From 207ab2802ac163eaa0e91a32cc3e55a97dc20673 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 25 Jun 2024 15:14:20 +0200 Subject: [PATCH 01/26] version++ --- matrix-sdk-android/build.gradle | 2 +- vector-app/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 d86f71b8a1..df8551f8b3 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -62,7 +62,7 @@ android { // that the app's state is completely cleared between tests. testInstrumentationRunnerArguments clearPackageData: 'true' - buildConfigField "String", "SDK_VERSION", "\"1.6.18\"" + buildConfigField "String", "SDK_VERSION", "\"1.6.20\"" buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\"" buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\"" diff --git a/vector-app/build.gradle b/vector-app/build.gradle index 829bc5f303..f6113744d6 100644 --- a/vector-app/build.gradle +++ b/vector-app/build.gradle @@ -37,7 +37,7 @@ ext.versionMinor = 6 // 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 = 18 +ext.versionPatch = 20 static def getGitTimestamp() { def cmd = 'git show -s --format=%ct' From dfb0fc31e19a62218738ba08ba5bbd8ea0ed946c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 25 Jun 2024 15:56:10 +0200 Subject: [PATCH 02/26] Use BuildTools 35.0.0 - part 2 --- tools/release/sign_apk.sh | 2 +- tools/release/sign_apk_unsafe.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/release/sign_apk.sh b/tools/release/sign_apk.sh index de5a22dd34..3e37dee3fb 100755 --- a/tools/release/sign_apk.sh +++ b/tools/release/sign_apk.sh @@ -17,7 +17,7 @@ PARAM_KEYSTORE_PATH=$1 PARAM_APK=$2 # Other params -BUILD_TOOLS_VERSION="31.0.0" +BUILD_TOOLS_VERSION="35.0.0" MIN_SDK_VERSION=21 echo "Signing APK with build-tools version ${BUILD_TOOLS_VERSION} for min SDK version ${MIN_SDK_VERSION}..." diff --git a/tools/release/sign_apk_unsafe.sh b/tools/release/sign_apk_unsafe.sh index a7536616e9..216f464266 100755 --- a/tools/release/sign_apk_unsafe.sh +++ b/tools/release/sign_apk_unsafe.sh @@ -23,7 +23,7 @@ PARAM_KS_PASS=$3 PARAM_KEY_PASS=$4 # Other params -BUILD_TOOLS_VERSION="31.0.0" +BUILD_TOOLS_VERSION="35.0.0" MIN_SDK_VERSION=21 echo "Signing APK with build-tools version ${BUILD_TOOLS_VERSION} for min SDK version ${MIN_SDK_VERSION}..." From 80904ee8471999a9f7bc957965abdb641c826fbe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 23:05:42 +0000 Subject: [PATCH 03/26] Bump io.element.android:wysiwyg from 2.37.3 to 2.37.4 Bumps [io.element.android:wysiwyg](https://github.com/matrix-org/matrix-wysiwyg) from 2.37.3 to 2.37.4. - [Changelog](https://github.com/matrix-org/matrix-rich-text-editor/blob/main/CHANGELOG.md) - [Commits](https://github.com/matrix-org/matrix-wysiwyg/compare/2.37.3...2.37.4) --- updated-dependencies: - dependency-name: io.element.android:wysiwyg dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 1f5b905250..f2f097d641 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -101,7 +101,7 @@ ext.libs = [ ], element : [ 'opusencoder' : "io.element.android:opusencoder:1.1.0", - 'wysiwyg' : "io.element.android:wysiwyg:2.37.3" + 'wysiwyg' : "io.element.android:wysiwyg:2.37.4" ], squareup : [ 'moshi' : "com.squareup.moshi:moshi:$moshi", From f2c970f1b46520c40eb8f1032fd153ca63e364b9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 26 Jun 2024 10:13:51 +0200 Subject: [PATCH 04/26] Run `bundle update` --- Gemfile.lock | 144 +++++++++++++++++++++++++++------------------------ 1 file changed, 75 insertions(+), 69 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 33ebbc1b70..866616ab41 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,29 +1,32 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (3.0.5) + CFPropertyList (3.0.7) + base64 + nkf rexml - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) - artifactory (3.0.15) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + artifactory (3.0.17) atomos (0.1.3) - aws-eventstream (1.2.0) - aws-partitions (1.619.0) - aws-sdk-core (3.132.0) - aws-eventstream (~> 1, >= 1.0.2) - aws-partitions (~> 1, >= 1.525.0) - aws-sigv4 (~> 1.1) + aws-eventstream (1.3.0) + aws-partitions (1.947.0) + aws-sdk-core (3.199.0) + aws-eventstream (~> 1, >= 1.3.0) + aws-partitions (~> 1, >= 1.651.0) + aws-sigv4 (~> 1.8) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.58.0) - aws-sdk-core (~> 3, >= 3.127.0) + aws-sdk-kms (1.87.0) + aws-sdk-core (~> 3, >= 3.199.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.114.0) - aws-sdk-core (~> 3, >= 3.127.0) + aws-sdk-s3 (1.154.0) + aws-sdk-core (~> 3, >= 3.199.0) aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.4) - aws-sigv4 (1.5.1) + aws-sigv4 (~> 1.8) + aws-sigv4 (1.8.0) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) + base64 (0.2.0) claide (1.1.0) claide-plugins (0.9.2) cork @@ -49,14 +52,14 @@ GEM octokit (~> 4.7) terminal-table (>= 1, < 4) declarative (0.0.20) - digest-crc (0.6.4) + digest-crc (0.6.5) rake (>= 12.0.0, < 14.0.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) dotenv (2.8.1) emoji_regex (3.2.3) - excon (0.92.4) - faraday (1.10.1) + excon (0.109.0) + faraday (1.10.3) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) faraday-excon (~> 1.1) @@ -74,7 +77,7 @@ GEM faraday-em_http (1.0.0) faraday-em_synchrony (1.0.0) faraday-excon (1.1.0) - faraday-http-cache (2.4.1) + faraday-http-cache (2.5.1) faraday (>= 0.8) faraday-httpclient (1.0.1) faraday-multipart (1.0.4) @@ -86,15 +89,15 @@ GEM faraday-retry (1.0.3) faraday_middleware (1.2.0) faraday (~> 1.0) - fastimage (2.2.6) - fastlane (2.209.0) + fastimage (2.3.1) + fastlane (2.221.1) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) aws-sdk-s3 (~> 1.0) babosa (>= 1.0.3, < 2.0.0) bundler (>= 1.12.0, < 3.0.0) - colored + colored (~> 1.2) commander (~> 4.6) dotenv (>= 2.1.1, < 3.0.0) emoji_regex (>= 0.1, < 4.0) @@ -106,33 +109,35 @@ GEM gh_inspector (>= 1.1.2, < 2.0.0) google-apis-androidpublisher_v3 (~> 0.3) google-apis-playcustomapp_v1 (~> 0.1) + google-cloud-env (>= 1.6.0, < 2.0.0) google-cloud-storage (~> 1.31) highline (~> 2.0) + http-cookie (~> 1.0.5) json (< 3.0.0) jwt (>= 2.1.0, < 3) mini_magick (>= 4.9.4, < 5.0.0) - multipart-post (~> 2.0.0) + multipart-post (>= 2.0.0, < 3.0.0) naturally (~> 2.2) - optparse (~> 0.1.1) + optparse (>= 0.1.1, < 1.0.0) plist (>= 3.1.0, < 4.0.0) rubyzip (>= 2.0.0, < 3.0.0) - security (= 0.1.3) + security (= 0.1.5) simctl (~> 1.6.3) terminal-notifier (>= 2.0.0, < 3.0.0) - terminal-table (>= 1.4.5, < 2.0.0) + terminal-table (~> 3) tty-screen (>= 0.6.3, < 1.0.0) tty-spinner (>= 0.8.0, < 1.0.0) word_wrap (~> 1.0.0) xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) - xcpretty-travis-formatter (>= 0.0.3) + xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) gh_inspector (1.1.3) - git (1.13.0) + git (1.19.1) addressable (~> 2.8) rchardet (~> 1.8) - google-apis-androidpublisher_v3 (0.25.0) - google-apis-core (>= 0.7, < 2.a) - google-apis-core (0.7.0) + google-apis-androidpublisher_v3 (0.54.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-core (0.11.3) addressable (~> 2.5, >= 2.5.1) googleauth (>= 0.16.2, < 2.a) httpclient (>= 2.8.1, < 3.a) @@ -140,101 +145,101 @@ GEM representable (~> 3.0) retriable (>= 2.0, < 4.a) rexml - webrick - google-apis-iamcredentials_v1 (0.13.0) - google-apis-core (>= 0.7, < 2.a) - google-apis-playcustomapp_v1 (0.10.0) - google-apis-core (>= 0.7, < 2.a) - google-apis-storage_v1 (0.17.0) - google-apis-core (>= 0.7, < 2.a) - google-cloud-core (1.6.0) - google-cloud-env (~> 1.0) + google-apis-iamcredentials_v1 (0.17.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-playcustomapp_v1 (0.13.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-storage_v1 (0.29.0) + google-apis-core (>= 0.11.0, < 2.a) + google-cloud-core (1.6.1) + google-cloud-env (>= 1.0, < 3.a) google-cloud-errors (~> 1.0) google-cloud-env (1.6.0) faraday (>= 0.17.3, < 3.0) - google-cloud-errors (1.2.0) - google-cloud-storage (1.38.0) + google-cloud-errors (1.3.1) + google-cloud-storage (1.45.0) addressable (~> 2.8) digest-crc (~> 0.4) google-apis-iamcredentials_v1 (~> 0.1) - google-apis-storage_v1 (~> 0.17.0) + google-apis-storage_v1 (~> 0.29.0) google-cloud-core (~> 1.6) googleauth (>= 0.16.2, < 2.a) mini_mime (~> 1.0) - googleauth (1.2.0) + googleauth (1.8.1) faraday (>= 0.17.3, < 3.a) jwt (>= 1.4, < 3.0) - memoist (~> 0.16) multi_json (~> 1.11) os (>= 0.9, < 2.0) signet (>= 0.16, < 2.a) highline (2.0.3) - http-cookie (1.0.5) + http-cookie (1.0.6) domain_name (~> 0.5) httpclient (2.8.3) - jmespath (1.6.1) - json (2.6.2) - jwt (2.4.1) + jmespath (1.6.2) + json (2.7.2) + jwt (2.8.2) + base64 kramdown (2.4.0) rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) - memoist (0.16.2) - mini_magick (4.11.0) - mini_mime (1.1.2) + mini_magick (4.13.1) + mini_mime (1.1.5) multi_json (1.15.0) - multipart-post (2.0.0) + multipart-post (2.4.1) nanaimo (0.3.0) nap (1.1.0) naturally (2.2.1) + nkf (0.2.0) no_proxy_fix (0.1.2) octokit (4.25.1) faraday (>= 1, < 3) sawyer (~> 0.9) open4 (1.3.4) - optparse (0.1.1) + optparse (0.5.0) os (1.1.4) - plist (3.6.0) - public_suffix (4.0.7) - rake (13.0.6) + plist (3.7.1) + public_suffix (5.1.1) + rake (13.2.1) rchardet (1.8.0) representable (3.2.0) declarative (< 0.1.0) trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.2.5) + rexml (3.2.9) + strscan rouge (2.0.7) ruby2_keywords (0.0.5) rubyzip (2.3.2) sawyer (0.9.2) addressable (>= 2.3.5) faraday (>= 0.17.3, < 3) - security (0.1.3) - signet (0.17.0) + security (0.1.5) + signet (0.18.0) addressable (~> 2.8) faraday (>= 0.17.5, < 3.a) jwt (>= 1.5, < 3.0) multi_json (~> 1.10) - simctl (1.6.8) + simctl (1.6.10) CFPropertyList naturally + strscan (3.1.0) terminal-notifier (2.0.0) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) trailblazer-option (0.1.2) tty-cursor (0.7.1) - tty-screen (0.8.1) + tty-screen (0.8.2) tty-spinner (0.9.3) tty-cursor (~> 0.7) uber (0.1.0) unf (0.1.4) unf_ext - unf_ext (0.0.8.2) - unicode-display_width (1.8.0) - webrick (1.7.0) + unf_ext (0.0.9.1) + unicode-display_width (2.5.0) word_wrap (1.0.0) - xcodeproj (1.22.0) + xcodeproj (1.24.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) @@ -248,6 +253,7 @@ GEM PLATFORMS universal-darwin-21 + universal-darwin-23 x86_64-darwin-20 x86_64-linux From 84b8d410d58416039d38249d52659f814c6debf5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 5 Jul 2024 16:17:09 +0200 Subject: [PATCH 05/26] Bump compile and target SDK to 34 --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index f2f097d641..2361ef9813 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ ext.versions = [ 'minSdk' : 21, - 'compileSdk' : 33, - 'targetSdk' : 33, + 'compileSdk' : 34, + 'targetSdk' : 34, 'sourceCompat' : JavaVersion.VERSION_11, 'targetCompat' : JavaVersion.VERSION_11, ] From 7ad3ccfc6024f6be90627686c61ef2056778ca5b Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 5 Jul 2024 17:58:25 +0200 Subject: [PATCH 06/26] Authenticated media : add versions check to HomeServerCapabilities --- .../homeserver/HomeServerCapabilities.kt | 4 +++ .../auth/version/HomeServerVersion.kt | 1 + .../sdk/internal/auth/version/Versions.kt | 10 +++++++ .../database/RealmSessionStoreMigration.kt | 4 ++- .../mapper/HomeServerCapabilitiesMapper.kt | 1 + .../database/migration/MigrateSessionTo055.kt | 30 +++++++++++++++++++ .../model/HomeServerCapabilitiesEntity.kt | 1 + .../GetHomeServerCapabilitiesTask.kt | 3 ++ 8 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo055.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt index ecd03288fc..101947f9d9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt @@ -95,6 +95,10 @@ data class HomeServerCapabilities( * If set to true, the SDK will not use the network constraint when configuring Worker for the WorkManager, provided in Wellknown. */ val disableNetworkConstraint: Boolean? = null, + /** + * True if the home server supports authenticated media. + */ + val canUseAuthenticatedMedia: Boolean = false, ) { enum class RoomCapabilitySupport { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/HomeServerVersion.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/HomeServerVersion.kt index d443d6e3c8..f683ae773b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/HomeServerVersion.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/HomeServerVersion.kt @@ -61,5 +61,6 @@ internal data class HomeServerVersion( val r0_6_1 = HomeServerVersion(major = 0, minor = 6, patch = 1) val v1_3_0 = HomeServerVersion(major = 1, minor = 3, patch = 0) val v1_4_0 = HomeServerVersion(major = 1, minor = 4, patch = 0) + val v1_11_0 = HomeServerVersion(major = 1, minor = 11, patch = 0) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt index 83186344bb..d819bef584 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt @@ -54,6 +54,7 @@ private const val FEATURE_ID_ACCESS_TOKEN = "m.id_access_token" private const val FEATURE_SEPARATE_ADD_AND_BIND = "m.separate_add_and_bind" private const val FEATURE_THREADS_MSC3440 = "org.matrix.msc3440" private const val FEATURE_THREADS_MSC3440_STABLE = "org.matrix.msc3440.stable" + @Deprecated("The availability of stable get_login_token is now exposed as a capability and part of login flow") private const val FEATURE_QR_CODE_LOGIN = "org.matrix.msc3882" private const val FEATURE_THREADS_MSC3771 = "org.matrix.msc3771" @@ -142,6 +143,15 @@ internal fun Versions.doesServerSupportLogoutDevices(): Boolean { return getMaxVersion() >= HomeServerVersion.r0_6_1 } +/** + * Indicate if the server supports MSC3916 : https://github.com/matrix-org/matrix-spec-proposals/pull/3916 + * + * @return true if authenticated media is supported + */ +internal fun Versions.doesServerSupportAuthenticatedMedia(): Boolean { + return getMaxVersion() >= HomeServerVersion.v1_11_0 +} + private fun Versions.getMaxVersion(): HomeServerVersion { return supportedVersions ?.mapNotNull { HomeServerVersion.parse(it) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt index 4a7064ebf5..e02ffc36c5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt @@ -71,6 +71,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo051 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo052 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo053 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo054 +import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo055 import org.matrix.android.sdk.internal.util.Normalizer import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration import javax.inject.Inject @@ -79,7 +80,7 @@ internal class RealmSessionStoreMigration @Inject constructor( private val normalizer: Normalizer ) : MatrixRealmMigration( dbName = "Session", - schemaVersion = 54L, + schemaVersion = 55L, ) { /** * Forces all RealmSessionStoreMigration instances to be equal. @@ -143,5 +144,6 @@ internal class RealmSessionStoreMigration @Inject constructor( if (oldVersion < 52) MigrateSessionTo052(realm).perform() if (oldVersion < 53) MigrateSessionTo053(realm).perform() if (oldVersion < 54) MigrateSessionTo054(realm).perform() + if (oldVersion < 55) MigrateSessionTo055(realm).perform() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt index 25af5be66d..8cdabaf150 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt @@ -51,6 +51,7 @@ internal object HomeServerCapabilitiesMapper { externalAccountManagementUrl = entity.externalAccountManagementUrl, authenticationIssuer = entity.authenticationIssuer, disableNetworkConstraint = entity.disableNetworkConstraint, + canUseAuthenticatedMedia = entity.canUseAuthenticatedMedia, ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo055.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo055.kt new file mode 100644 index 0000000000..77e8d7c868 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo055.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.internal.database.migration + +import io.realm.DynamicRealm +import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields +import org.matrix.android.sdk.internal.extensions.forceRefreshOfHomeServerCapabilities +import org.matrix.android.sdk.internal.util.database.RealmMigrator + +internal class MigrateSessionTo055(realm: DynamicRealm) : RealmMigrator(realm, 54) { + override fun doMigrate(realm: DynamicRealm) { + realm.schema.get("HomeServerCapabilitiesEntity") + ?.addField(HomeServerCapabilitiesEntityFields.CAN_USE_AUTHENTICATED_MEDIA, Boolean::class.java) + ?.forceRefreshOfHomeServerCapabilities() + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt index 3891948418..0096071d54 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt @@ -38,6 +38,7 @@ internal open class HomeServerCapabilitiesEntity( var externalAccountManagementUrl: String? = null, var authenticationIssuer: String? = null, var disableNetworkConstraint: Boolean? = null, + var canUseAuthenticatedMedia: Boolean = false, ) : RealmObject() { companion object diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt index f007f22366..7a7d140736 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt @@ -23,6 +23,7 @@ import org.matrix.android.sdk.api.auth.wellknown.WellknownResult import org.matrix.android.sdk.api.extensions.orTrue import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities import org.matrix.android.sdk.internal.auth.version.Versions +import org.matrix.android.sdk.internal.auth.version.doesServerSupportAuthenticatedMedia import org.matrix.android.sdk.internal.auth.version.doesServerSupportLogoutDevices import org.matrix.android.sdk.internal.auth.version.doesServerSupportQrCodeLogin import org.matrix.android.sdk.internal.auth.version.doesServerSupportRedactionOfRelatedEvents @@ -155,6 +156,8 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( getVersionResult.doesServerSupportRemoteToggleOfPushNotifications() homeServerCapabilitiesEntity.canRedactEventWithRelations = getVersionResult.doesServerSupportRedactionOfRelatedEvents() + homeServerCapabilitiesEntity.canUseAuthenticatedMedia = + getVersionResult.doesServerSupportAuthenticatedMedia() } if (getWellknownResult != null && getWellknownResult is WellknownResult.Prompt) { From da8c892f7a571a7f18e4108395c6b55f229a6607 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 9 Jul 2024 11:57:55 +0200 Subject: [PATCH 07/26] Authenticated media : makes usage of API when server supports it --- .../matrix/android/sdk/api/session/Session.kt | 5 ++ .../api/session/content/ContentUrlResolver.kt | 2 + .../internal/auth/login/DefaultLoginWizard.kt | 11 ++- .../network/AccessTokenInterceptor.kt | 3 +- .../network/httpclient/OkHttpClientUtil.kt | 9 +++ .../internal/session/DefaultFileService.kt | 23 +++++-- .../sdk/internal/session/DefaultSession.kt | 7 ++ .../content/DefaultContentUrlResolver.kt | 13 +++- .../GetHomeServerCapabilitiesTask.kt | 8 +-- .../session/media/AuthenticatedMediaAPI.kt | 45 ++++++++++++ .../DefaultIsAuthenticatedMediaSupported.kt | 45 ++++++++++++ .../session/media/GetPreviewUrlTask.kt | 4 +- .../session/media/GetRawPreviewUrlTask.kt | 2 +- .../media/IsAuthenticatedMediaSupported.kt | 21 ++++++ .../sdk/internal/session/media/MediaAPI.kt | 27 ++------ .../session/media/MediaAPIProvider.kt | 34 ++++++++++ .../sdk/internal/session/media/MediaModule.kt | 14 +++- .../session/media/UnauthenticatedMediaAPI.kt | 42 ++++++++++++ .../vector/app/core/di/ActiveSessionHolder.kt | 1 - .../im/vector/app/core/di/ImageManager.kt | 11 ++- .../core/glide/AuthenticatedGlideUrlLoader.kt | 68 +++++++++++++++++++ .../im/vector/app/core/glide/FactoryUrl.kt | 38 ----------- ...r.kt => ImageContentRendererDataLoader.kt} | 12 ++-- .../vector/app/core/glide/MyAppGlideModule.kt | 2 +- 24 files changed, 351 insertions(+), 96 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/AuthenticatedMediaAPI.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/DefaultIsAuthenticatedMediaSupported.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/IsAuthenticatedMediaSupported.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/MediaAPIProvider.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/UnauthenticatedMediaAPI.kt create mode 100644 vector/src/main/java/im/vector/app/core/glide/AuthenticatedGlideUrlLoader.kt delete mode 100644 vector/src/main/java/im/vector/app/core/glide/FactoryUrl.kt rename vector/src/main/java/im/vector/app/core/glide/{VectorGlideModelLoader.kt => ImageContentRendererDataLoader.kt} (91%) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt index cf0f4bdce0..9c94847b22 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt @@ -296,6 +296,11 @@ interface Session { */ fun getOkHttpClient(): OkHttpClient + /** + * Same as [getOkHttpClient] but will add the access token to the request. + */ + fun getAuthenticatedOkHttpClient(): OkHttpClient + /** * A global session listener to get notified for some events. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUrlResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUrlResolver.kt index 20f977e86e..3dd3712489 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUrlResolver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUrlResolver.kt @@ -61,6 +61,8 @@ interface ContentUrlResolver { */ fun resolveThumbnail(contentUrl: String?, width: Int, height: Int, method: ThumbnailMethod): String? + fun requiresAuthentication(resolvedUrl: String): Boolean + sealed class ResolvedMethod { data class GET(val url: String) : ResolvedMethod() data class POST(val url: String, val jsonBody: String) : ResolvedMethod() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt index 86341729ca..45e0fd072c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt @@ -35,6 +35,7 @@ import org.matrix.android.sdk.internal.auth.registration.RegisterAddThreePidTask import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.content.DefaultContentUrlResolver import org.matrix.android.sdk.internal.session.contentscanner.DisabledContentScannerService +import org.matrix.android.sdk.internal.session.media.IsAuthenticatedMediaSupported internal class DefaultLoginWizard( private val authAPI: AuthAPI, @@ -45,8 +46,14 @@ internal class DefaultLoginWizard( private var pendingSessionData: PendingSessionData = pendingSessionStore.getPendingSessionData() ?: error("Pending session data should exist here") private val getProfileTask: GetProfileTask = DefaultGetProfileTask( - authAPI, - DefaultContentUrlResolver(pendingSessionData.homeServerConnectionConfig, DisabledContentScannerService()) + authAPI = authAPI, + contentUrlResolver = DefaultContentUrlResolver( + homeServerConnectionConfig = pendingSessionData.homeServerConnectionConfig, + scannerService = DisabledContentScannerService(), + isAuthenticatedMediaSupported = object : IsAuthenticatedMediaSupported { + override fun invoke() = false + } + ) ) override suspend fun getProfileInfo(matrixId: String): LoginProfileInfo { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/AccessTokenInterceptor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/AccessTokenInterceptor.kt index a34606a6bb..fe27cea5ca 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/AccessTokenInterceptor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/AccessTokenInterceptor.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.network import okhttp3.Interceptor import okhttp3.Response +import org.matrix.android.sdk.internal.network.httpclient.addAuthenticationHeader import org.matrix.android.sdk.internal.network.token.AccessTokenProvider internal class AccessTokenInterceptor(private val accessTokenProvider: AccessTokenProvider) : Interceptor { @@ -28,7 +29,7 @@ internal class AccessTokenInterceptor(private val accessTokenProvider: AccessTok // Add the access token to all requests if it is set accessTokenProvider.getToken()?.let { token -> val newRequestBuilder = request.newBuilder() - newRequestBuilder.header(HttpHeaders.Authorization, "Bearer $token") + newRequestBuilder.addAuthenticationHeader(token) request = newRequestBuilder.build() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/httpclient/OkHttpClientUtil.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/httpclient/OkHttpClientUtil.kt index 1c395c2d61..aef2e63b2c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/httpclient/OkHttpClientUtil.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/httpclient/OkHttpClientUtil.kt @@ -17,9 +17,11 @@ package org.matrix.android.sdk.internal.network.httpclient import okhttp3.OkHttpClient +import okhttp3.Request import org.matrix.android.sdk.api.MatrixConfiguration import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig import org.matrix.android.sdk.internal.network.AccessTokenInterceptor +import org.matrix.android.sdk.internal.network.HttpHeaders import org.matrix.android.sdk.internal.network.interceptors.CurlLoggingInterceptor import org.matrix.android.sdk.internal.network.ssl.CertUtil import org.matrix.android.sdk.internal.network.token.AccessTokenProvider @@ -66,3 +68,10 @@ internal fun OkHttpClient.Builder.applyMatrixConfiguration(matrixConfiguration: return this } + +fun Request.Builder.addAuthenticationHeader(accessToken: String?): Request.Builder { + if (accessToken != null) { + header(HttpHeaders.Authorization, "Bearer $accessToken") + } + return this +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt index bbf260a3f1..217ef43821 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt @@ -34,8 +34,11 @@ import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt import org.matrix.android.sdk.api.session.file.FileService import org.matrix.android.sdk.api.util.md5 import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments +import org.matrix.android.sdk.internal.di.Authenticated import org.matrix.android.sdk.internal.di.SessionDownloadsDirectory import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificateWithProgress +import org.matrix.android.sdk.internal.network.httpclient.addAuthenticationHeader +import org.matrix.android.sdk.internal.network.token.AccessTokenProvider import org.matrix.android.sdk.internal.session.download.DownloadProgressInterceptor.Companion.DOWNLOAD_PROGRESS_INTERCEPTOR_HEADER import org.matrix.android.sdk.internal.util.file.AtomicFileCreator import org.matrix.android.sdk.internal.util.time.Clock @@ -54,6 +57,7 @@ internal class DefaultFileService @Inject constructor( private val okHttpClient: OkHttpClient, private val coroutineDispatchers: MatrixCoroutineDispatchers, private val clock: Clock, + @Authenticated private val accessTokenProvider: AccessTokenProvider, ) : FileService { // Legacy folder, will be deleted @@ -124,21 +128,26 @@ internal class DefaultFileService @Inject constructor( val cachedFiles = getFiles(url, fileName, mimeType, elementToDecrypt != null) if (!cachedFiles.file.exists()) { - val resolvedUrl = contentUrlResolver.resolveForDownload(url, elementToDecrypt) ?: throw IllegalArgumentException("url is null") + val resolvedMethod = contentUrlResolver.resolveForDownload(url, elementToDecrypt) ?: throw IllegalArgumentException("url is null") - val request = when (resolvedUrl) { + val request = when (resolvedMethod) { is ContentUrlResolver.ResolvedMethod.GET -> { - Request.Builder() - .url(resolvedUrl.url) + val requestBuilder = Request.Builder() + .url(resolvedMethod.url) .header(DOWNLOAD_PROGRESS_INTERCEPTOR_HEADER, url) - .build() + + if (contentUrlResolver.requiresAuthentication(resolvedMethod.url)) { + val accessToken = accessTokenProvider.getToken() + requestBuilder.addAuthenticationHeader(accessToken) + } + requestBuilder.build() } is ContentUrlResolver.ResolvedMethod.POST -> { Request.Builder() - .url(resolvedUrl.url) + .url(resolvedMethod.url) .header(DOWNLOAD_PROGRESS_INTERCEPTOR_HEADER, url) - .post(resolvedUrl.jsonBody.toRequestBody("application/json".toMediaType())) + .post(resolvedMethod.jsonBody.toRequestBody("application/json".toMediaType())) .build() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt index 992ea650cf..b2d5be2946 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt @@ -67,6 +67,7 @@ import org.matrix.android.sdk.api.util.appendParamToUrl import org.matrix.android.sdk.internal.auth.SSO_UIA_FALLBACK_PATH import org.matrix.android.sdk.internal.auth.SessionParamsStore import org.matrix.android.sdk.internal.database.tools.RealmDebugTools +import org.matrix.android.sdk.internal.di.Authenticated import org.matrix.android.sdk.internal.di.ContentScannerDatabase import org.matrix.android.sdk.internal.di.CryptoDatabase import org.matrix.android.sdk.internal.di.IdentityDatabase @@ -131,6 +132,8 @@ internal class DefaultSession @Inject constructor( private val eventStreamService: Lazy, @UnauthenticatedWithCertificate private val unauthenticatedWithCertificateOkHttpClient: Lazy, + @Authenticated + private val authenticatedOkHttpClient: Lazy, private val sessionState: SessionState, ) : Session, GlobalErrorHandler.Listener { @@ -234,6 +237,10 @@ internal class DefaultSession @Inject constructor( return unauthenticatedWithCertificateOkHttpClient.get() } + override fun getAuthenticatedOkHttpClient(): OkHttpClient { + return authenticatedOkHttpClient.get() + } + override fun addListener(listener: Session.Listener) { sessionListeners.addListener(listener) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUrlResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUrlResolver.kt index ad2b9d0905..dd277f6956 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUrlResolver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUrlResolver.kt @@ -25,16 +25,18 @@ import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt import org.matrix.android.sdk.internal.network.NetworkConstants import org.matrix.android.sdk.internal.session.contentscanner.ScanEncryptorUtils import org.matrix.android.sdk.internal.session.contentscanner.model.toJson +import org.matrix.android.sdk.internal.session.media.IsAuthenticatedMediaSupported import org.matrix.android.sdk.internal.util.ensureTrailingSlash import javax.inject.Inject internal class DefaultContentUrlResolver @Inject constructor( homeServerConnectionConfig: HomeServerConnectionConfig, - private val scannerService: ContentScannerService + private val scannerService: ContentScannerService, + private val isAuthenticatedMediaSupported: IsAuthenticatedMediaSupported, ) : ContentUrlResolver { private val baseUrl = homeServerConnectionConfig.homeServerUriBase.toString().ensureTrailingSlash() - + private val authenticatedMediaApiPath = baseUrl + NetworkConstants.URI_API_PREFIX_PATH_V1 + "media/" override val uploadUrl = baseUrl + NetworkConstants.URI_API_MEDIA_PREFIX_PATH_R0 + "upload" override fun resolveForDownload(contentUrl: String?, elementToDecrypt: ElementToDecrypt?): ContentUrlResolver.ResolvedMethod? { @@ -80,15 +82,20 @@ internal class DefaultContentUrlResolver @Inject constructor( } } + override fun requiresAuthentication(resolvedUrl: String): Boolean { + return resolvedUrl.startsWith(authenticatedMediaApiPath) + } + private fun resolve( contentUrl: String, toThumbnail: Boolean, params: String = "" ): String { var serverAndMediaId = contentUrl.removeMxcPrefix() - val apiPath = if (scannerService.isScannerEnabled()) { NetworkConstants.URI_API_PREFIX_PATH_MEDIA_PROXY_UNSTABLE + } else if (isAuthenticatedMediaSupported()) { + NetworkConstants.URI_API_PREFIX_PATH_V1 + "media/" } else { NetworkConstants.URI_API_MEDIA_PREFIX_PATH_R0 } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt index 7a7d140736..5e58443516 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt @@ -40,7 +40,8 @@ import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationManagerConfigExtractor import org.matrix.android.sdk.internal.session.media.GetMediaConfigResult -import org.matrix.android.sdk.internal.session.media.MediaAPI +import org.matrix.android.sdk.internal.session.media.MediaAPIProvider +import org.matrix.android.sdk.internal.session.media.UnauthenticatedMediaAPI import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction import org.matrix.android.sdk.internal.wellknown.GetWellknownTask @@ -56,7 +57,7 @@ internal interface GetHomeServerCapabilitiesTask : Task val homeServerCapabilitiesEntity = HomeServerCapabilitiesEntity.getOrCreate(realm) - doRequest = homeServerCapabilitiesEntity.lastUpdatedTimestamp + MIN_DELAY_BETWEEN_TWO_REQUEST_MILLIS < Date().time } } @@ -88,7 +88,7 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( val mediaConfig = runCatching { executeRequest(globalErrorReceiver) { - mediaAPI.getMediaConfig() + mediaAPIProvider.getMediaAPI().getMediaConfig() } }.getOrNull() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/AuthenticatedMediaAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/AuthenticatedMediaAPI.kt new file mode 100644 index 0000000000..baeb309cff --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/AuthenticatedMediaAPI.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 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 org.matrix.android.sdk.internal.session.media + +import org.matrix.android.sdk.api.util.JsonDict +import org.matrix.android.sdk.internal.network.NetworkConstants +import retrofit2.http.GET +import retrofit2.http.Query + +/** + * Implementation of the media repository API using the new Authenticated media API. + */ +internal interface AuthenticatedMediaAPI : MediaAPI { + /** + * Retrieve the configuration of the content repository + * Ref: https://spec.matrix.org/v1.11/client-server-api/#get_matrixclientv1mediaconfig + */ + @GET(NetworkConstants.URI_API_PREFIX_PATH_V1 + "media/config") + override suspend fun getMediaConfig(): GetMediaConfigResult + + /** + * Get information about a URL for the client. Typically this is called when a client + * sees a URL in a message and wants to render a preview for the user. + * Ref: https://spec.matrix.org/v1.11/client-server-api/#get_matrixclientv1mediapreview_url + * @param url Required. The URL to get a preview of. + * @param ts The preferred point in time to return a preview for. The server may return a newer version + * if it does not have the requested version available. + */ + @GET(NetworkConstants.URI_API_PREFIX_PATH_V1 + "media/preview_url") + override suspend fun getPreviewUrlData(@Query("url") url: String, @Query("ts") ts: Long?): JsonDict +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/DefaultIsAuthenticatedMediaSupported.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/DefaultIsAuthenticatedMediaSupported.kt new file mode 100644 index 0000000000..f2884c5cf7 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/DefaultIsAuthenticatedMediaSupported.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 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 org.matrix.android.sdk.internal.session.media + +import com.zhuinden.monarchy.Monarchy +import io.realm.Realm +import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntity +import org.matrix.android.sdk.internal.database.query.get +import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.session.SessionScope +import javax.inject.Inject + +@SessionScope +class DefaultIsAuthenticatedMediaSupported @Inject constructor( + @SessionDatabase private val monarchy: Monarchy, +) : IsAuthenticatedMediaSupported { + + private val canUseAuthenticatedMedia: Boolean by lazy { + canUseAuthenticatedMedia() + } + + override fun invoke(): Boolean { + return canUseAuthenticatedMedia + } + + private fun canUseAuthenticatedMedia(): Boolean { + return Realm.getInstance(monarchy.realmConfiguration).use { realm -> + HomeServerCapabilitiesEntity.get(realm)?.canUseAuthenticatedMedia ?: false + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetPreviewUrlTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetPreviewUrlTask.kt index a31f0d6065..fafd6f2753 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetPreviewUrlTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetPreviewUrlTask.kt @@ -41,7 +41,7 @@ internal interface GetPreviewUrlTask : Task { + + private val defaultClient = OkHttpClient() + + override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader { + return AuthenticatedGlideUrlLoader(context, defaultClient) + } + + override fun teardown() = Unit +} + +class AuthenticatedGlideUrlLoader( + context: Context, + private val defaultClient: OkHttpClient +) : + ModelLoader { + + private val activeSessionHolder = context.singletonEntryPoint().activeSessionHolder() + private val client: OkHttpClient + get() = activeSessionHolder.getSafeActiveSession() + ?.getAuthenticatedOkHttpClient() + ?: defaultClient + + private val callFactory = Call.Factory { request -> client.newCall(request) } + + override fun handles(model: GlideUrl): Boolean { + if (!activeSessionHolder.hasActiveSession()) return false + val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver() + val stringUrl = model.toStringUrl() + return contentUrlResolver.requiresAuthentication(stringUrl) + } + + override fun buildLoadData(model: GlideUrl, width: Int, height: Int, options: Options): ModelLoader.LoadData { + val fetcher = OkHttpStreamFetcher(callFactory, model) + return ModelLoader.LoadData(model, fetcher) + } +} + diff --git a/vector/src/main/java/im/vector/app/core/glide/FactoryUrl.kt b/vector/src/main/java/im/vector/app/core/glide/FactoryUrl.kt deleted file mode 100644 index d52d5814ad..0000000000 --- a/vector/src/main/java/im/vector/app/core/glide/FactoryUrl.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020 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.glide - -import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader -import com.bumptech.glide.load.model.GlideUrl -import com.bumptech.glide.load.model.ModelLoader -import com.bumptech.glide.load.model.ModelLoaderFactory -import com.bumptech.glide.load.model.MultiModelLoaderFactory -import im.vector.app.ActiveSessionDataSource -import okhttp3.OkHttpClient -import java.io.InputStream - -class FactoryUrl(private val activeSessionDataSource: ActiveSessionDataSource) : ModelLoaderFactory { - - override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader { - val client = activeSessionDataSource.currentValue?.orNull()?.getOkHttpClient() ?: OkHttpClient() - return OkHttpUrlLoader(client) - } - - override fun teardown() { - // Do nothing, this instance doesn't own the client. - } -} diff --git a/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt b/vector/src/main/java/im/vector/app/core/glide/ImageContentRendererDataLoader.kt similarity index 91% rename from vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt rename to vector/src/main/java/im/vector/app/core/glide/ImageContentRendererDataLoader.kt index 92c95d3062..6936a46d57 100644 --- a/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt +++ b/vector/src/main/java/im/vector/app/core/glide/ImageContentRendererDataLoader.kt @@ -37,10 +37,10 @@ import timber.log.Timber import java.io.IOException import java.io.InputStream -class VectorGlideModelLoaderFactory(private val context: Context) : ModelLoaderFactory { +class ImageContentRendererDataLoaderFactory(private val context: Context) : ModelLoaderFactory { override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader { - return VectorGlideModelLoader(context) + return ImageContentRendererDataLoader(context) } override fun teardown() { @@ -48,7 +48,7 @@ class VectorGlideModelLoaderFactory(private val context: Context) : ModelLoaderF } } -class VectorGlideModelLoader(private val context: Context) : +class ImageContentRendererDataLoader(private val context: Context) : ModelLoader { override fun handles(model: ImageContentRenderer.Data): Boolean { // Always handle @@ -56,11 +56,11 @@ class VectorGlideModelLoader(private val context: Context) : } override fun buildLoadData(model: ImageContentRenderer.Data, width: Int, height: Int, options: Options): ModelLoader.LoadData? { - return ModelLoader.LoadData(ObjectKey(model), VectorGlideDataFetcher(context, model, width, height)) + return ModelLoader.LoadData(ObjectKey(model), ImageContentRendererDataFetcher(context, model, width, height)) } } -class VectorGlideDataFetcher( +class ImageContentRendererDataFetcher( context: Context, private val data: ImageContentRenderer.Data, private val width: Int, @@ -71,8 +71,6 @@ class VectorGlideDataFetcher( private val localFilesHelper = LocalFilesHelper(context) private val activeSessionHolder = context.singletonEntryPoint().activeSessionHolder() - private val client = activeSessionHolder.getSafeActiveSession()?.getOkHttpClient() ?: OkHttpClient() - override fun getDataClass(): Class { return InputStream::class.java } diff --git a/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt b/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt index 59bffd95fd..67a79ca8b3 100644 --- a/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt +++ b/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt @@ -38,7 +38,7 @@ class MyAppGlideModule : AppGlideModule() { registry.append( ImageContentRenderer.Data::class.java, InputStream::class.java, - VectorGlideModelLoaderFactory(context) + ImageContentRendererDataLoaderFactory(context) ) registry.append( AvatarPlaceholder::class.java, From 19500a8cd97c4c99150a795992eff371cb8f407f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 15 Jul 2024 18:12:08 +0200 Subject: [PATCH 08/26] Upgrade a few dependencies and update the codebase Use fully qualified R classes Fix or ignore deprecation Update github actions and ensure JDK 17 is used Add group for paparazzi Fixes Lint issues Fix Jacoco configuration --- .github/workflows/build.yml | 18 +- .github/workflows/danger.yml | 2 +- .github/workflows/docs.yml | 2 +- .../workflows/gradle-wrapper-validation.yml | 2 +- .github/workflows/nightly.yml | 9 +- .github/workflows/post-pr.yml | 11 +- .github/workflows/quality.yml | 37 +- .../workflows/sync-from-external-sources.yml | 4 +- .github/workflows/tests.yml | 23 +- .github/workflows/update-gradle-wrapper.yml | 2 +- .github/workflows/validate-lfs.yml | 2 +- build.gradle | 4 +- coverage.gradle | 6 +- dependencies.gradle | 50 +-- dependencies_groups.gradle | 2 + docs/screenshot_testing.md | 2 +- docs/ui-tests.md | 4 +- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 43453 bytes gradle/wrapper/gradle-wrapper.properties | 5 +- library/attachment-viewer/build.gradle | 2 +- .../AttachmentViewerActivity.kt | 6 +- library/core-utils/build.gradle | 3 +- library/external/autocomplete/build.gradle | 2 +- .../autocomplete/Autocomplete.java | 1 - library/external/dialpad/build.gradle | 2 +- .../dialer/dialpadview/DialpadView.java | 1 - .../dialer/widget/ResizingTextEditText.java | 1 + library/external/jsonviewer/build.gradle | 2 +- .../realmfieldnameshelper/build.gradle | 4 +- library/external/span/build.gradle | 9 + .../textdrawable/TextDrawable.java | 11 +- library/multipicker/build.gradle | 2 +- library/ui-strings/build.gradle | 2 +- .../im/vector/lib/strings/CommonStrings.kt | 20 ++ .../src/main/res/values-fa/strings.xml | 4 +- .../src/main/res/values-zh-rCN/strings.xml | 4 +- library/ui-styles/build.gradle | 3 +- matrix-sdk-android-flow/build.gradle | 2 +- .../src/main/AndroidManifest.xml | 2 +- matrix-sdk-android/build.gradle | 13 +- .../android/sdk/common/CommonTestHelper.kt | 11 +- .../android/sdk/common/TestExtensions.kt | 6 +- .../sdk/internal/crypto/E2eeConfigTest.kt | 1 - .../crypto/gossiping/KeyShareTests.kt | 1 - .../database/TestRealmConfigurationFactory.kt | 2 - .../src/main/AndroidManifest.xml | 3 +- .../internal/crypto/store/RustCryptoStore.kt | 8 +- .../sdk/internal/di/WorkManagerProvider.kt | 6 +- .../db/RealmContentScannerStore.kt | 4 +- .../HomeServerCapabilitiesDataSource.kt | 4 +- .../identity/DefaultIdentityService.kt | 5 +- .../integrationmanager/IntegrationManager.kt | 5 +- .../pushrules/DefaultPushRuleService.kt | 4 +- .../session/room/DefaultRoomService.kt | 4 +- .../internal/session/room/RoomDataSource.kt | 4 +- .../accountdata/RoomAccountDataDataSource.kt | 4 +- .../session/room/draft/DraftRepository.kt | 4 +- .../location/DefaultLocationSharingService.kt | 12 +- .../DefaultRoomPushRuleService.kt | 6 +- .../room/poll/DefaultPollHistoryService.kt | 7 +- .../session/room/read/DefaultReadService.kt | 8 +- .../room/relation/DefaultRelationService.kt | 4 +- .../room/state/StateEventDataSource.kt | 6 +- .../room/summary/RoomSummaryDataSource.kt | 26 +- .../internal/session/user/UserDataSource.kt | 4 +- .../accountdata/UserAccountDataDataSource.kt | 4 +- .../internal/session/widgets/WidgetManager.kt | 11 +- .../android/sdk/internal/util/LruCache.kt | 2 +- .../network/ComputeUserAgentUseCaseTest.kt | 1 - .../DefaultLocationSharingServiceTest.kt | 19 +- tools/import_emojis.py | 7 +- tools/lint/lint.xml | 2 +- tools/release/download_github_artifacts.py | 4 +- vector-app/build.gradle | 12 +- vector-app/proguard-rules.pro | 13 + .../java/im/vector/app/CantVerifyTest.kt | 5 +- .../java/im/vector/app/RegistrationTest.kt | 5 +- .../im/vector/app/SecurityBootstrapTest.kt | 15 +- .../im/vector/app/VerificationTestBase.kt | 9 +- .../app/VerifySessionInteractiveTest.kt | 21 +- .../vector/app/VerifySessionNavigationTest.kt | 7 +- .../vector/app/VerifySessionPassphraseTest.kt | 11 +- .../app/espresso/tools/EspressoPreference.kt | 3 +- .../vector/app/ui/UiAllScreensSanityTest.kt | 6 +- .../im/vector/app/ui/robot/AnalyticsRobot.kt | 3 +- .../vector/app/ui/robot/CreateNewRoomRobot.kt | 5 +- .../im/vector/app/ui/robot/ElementRobot.kt | 9 +- .../vector/app/ui/robot/MessageMenuRobot.kt | 15 +- .../app/ui/robot/NewDirectMessageRobot.kt | 5 +- .../im/vector/app/ui/robot/NewRoomRobot.kt | 3 +- .../im/vector/app/ui/robot/OnboardingRobot.kt | 29 +- .../app/ui/robot/OnboardingServersRobot.kt | 13 +- .../im/vector/app/ui/robot/RoomDetailRobot.kt | 3 +- .../im/vector/app/ui/robot/RoomListRobot.kt | 3 +- .../vector/app/ui/robot/RoomSettingsRobot.kt | 17 +- .../robot/settings/SettingsAdvancedRobot.kt | 12 +- .../ui/robot/settings/SettingsGeneralRobot.kt | 20 +- .../ui/robot/settings/SettingsHelpRobot.kt | 8 +- .../ui/robot/settings/SettingsLegalsRobot.kt | 4 +- .../settings/SettingsNotificationsRobot.kt | 22 +- .../settings/SettingsPreferencesRobot.kt | 7 +- .../app/ui/robot/settings/SettingsRobot.kt | 22 +- .../robot/settings/SettingsSecurityRobot.kt | 12 +- .../app/ui/robot/space/SpaceCreateRobot.kt | 7 +- .../vector/app/ui/robot/space/SpaceRobot.kt | 3 +- .../app/ui/robot/space/SpaceSettingsRobot.kt | 7 +- .../features/debug/DebugPermissionActivity.kt | 5 +- vector-app/src/fdroid/AndroidManifest.xml | 4 + .../troubleshoot/TestAutoStartBoot.kt | 10 +- .../TestBackgroundRestrictions.kt | 12 +- .../troubleshoot/TestBatteryOptimization.kt | 10 +- .../app/fdroid/service/GuardAndroidService.kt | 4 +- .../troubleshoot/TestFirebaseToken.kt | 18 +- .../settings/troubleshoot/TestPlayServices.kt | 10 +- .../troubleshoot/TestTokenRegistration.kt | 12 +- .../im/vector/app/push/fcm/GoogleFcmHelper.kt | 4 +- .../fcm/VectorFirebaseMessagingService.kt | 3 +- .../im/vector/app/core/di/SingletonModule.kt | 4 +- vector-config/build.gradle | 2 +- vector/build.gradle | 5 +- .../java/im/vector/app/SleepViewAction.java | 6 +- .../FallbackBiometricDialogFragmentTests.kt | 4 +- vector/src/main/AndroidManifest.xml | 14 +- .../im/vector/app/core/animations/Konfetti.kt | 2 +- .../core/dialogs/ConfirmationDialogBuilder.kt | 3 +- .../app/core/dialogs/ExportKeysDialog.kt | 5 +- .../dialogs/GalleryOrCameraDialogHelper.kt | 14 +- .../app/core/dialogs/ManuallyVerifyDialog.kt | 7 +- .../app/core/dialogs/PhotoOrVideoDialog.kt | 13 +- .../dialogs/UnrecognizedCertificateDialog.kt | 27 +- .../app/core/epoxy/ExpandableTextItem.kt | 5 +- .../bottomsheet/BottomSheetActionItem.kt | 4 +- .../bottomsheet/BottomSheetRadioActionItem.kt | 7 +- .../bottomsheet/BottomSheetRoomPreviewItem.kt | 19 +- .../core/epoxy/profiles/ProfileActionItem.kt | 10 +- .../NotificationSettingsFooterItem.kt | 7 +- .../profiles/notifications/RadioButtonItem.kt | 7 +- .../vector/app/core/error/ErrorFormatter.kt | 91 ++--- .../core/error/ResourceLimitErrorFormatter.kt | 10 +- .../im/vector/app/core/extensions/EditText.kt | 5 +- .../im/vector/app/core/extensions/Fragment.kt | 22 +- .../im/vector/app/core/extensions/TextView.kt | 8 +- .../app/core/extensions/ViewExtensions.kt | 22 +- .../platform/BadgeFloatingActionButton.kt | 11 +- .../app/core/platform/ButtonStateView.kt | 8 +- .../app/core/platform/MaxHeightScrollView.kt | 5 +- .../core/platform/ScreenOrientationLocker.kt | 2 +- .../core/platform/SimpleFragmentActivity.kt | 1 + .../app/core/platform/VectorBaseActivity.kt | 24 +- .../core/platform/VectorBaseDialogFragment.kt | 3 +- .../app/core/platform/VectorBaseFragment.kt | 8 +- .../app/core/preference/KeywordPreference.kt | 9 +- .../app/core/preference/PushRulePreference.kt | 7 +- .../app/core/preference/VectorPreference.kt | 5 +- .../preference/VectorPreferenceCategory.kt | 3 +- .../core/preference/VectorSwitchPreference.kt | 3 +- .../vector/app/core/pushers/PushersManager.kt | 9 +- .../app/core/pushers/UnifiedPushHelper.kt | 18 +- .../im/vector/app/core/resources/BuildMeta.kt | 1 + .../core/services/VectorSyncAndroidService.kt | 6 +- .../app/core/ui/list/GenericButtonItem.kt | 4 +- .../app/core/ui/list/GenericFooterItem.kt | 2 +- .../app/core/ui/list/GenericHeaderItem.kt | 2 +- .../app/core/ui/list/GenericPillItem.kt | 2 +- .../app/core/ui/list/GenericWithValueItem.kt | 2 +- .../core/ui/views/BottomSheetActionButton.kt | 21 +- .../app/core/ui/views/CurrentCallsView.kt | 14 +- .../app/core/ui/views/JoinConferenceView.kt | 4 +- .../app/core/ui/views/KeysBackupBanner.kt | 17 +- .../app/core/ui/views/NotificationAreaView.kt | 19 +- .../app/core/ui/views/PasswordStrengthBar.kt | 4 +- .../core/ui/views/PresenceStateImageView.kt | 9 +- .../app/core/ui/views/ReadReceiptsView.kt | 22 +- .../app/core/ui/views/SendStateImageView.kt | 11 +- .../app/core/ui/views/ShieldImageView.kt | 29 +- .../app/core/ui/views/TypingMessageAvatar.kt | 3 +- .../java/im/vector/app/core/utils/Dialogs.kt | 14 +- .../utils/ExpandingBottomSheetBehavior.kt | 7 +- .../core/utils/ExternalApplicationsUtil.kt | 23 +- .../vector/app/core/utils/JsonViewerStyler.kt | 13 +- .../vector/app/core/utils/PermissionsTools.kt | 16 +- .../im/vector/app/core/utils/SystemUtils.kt | 12 +- .../im/vector/app/core/utils/TextUtils.kt | 10 +- .../im/vector/app/features/MainActivity.kt | 14 +- .../ui/consent/AnalyticsOptInFragment.kt | 6 +- .../attachments/AttachmentTypeSelectorView.kt | 17 +- .../preview/AttachmentsPreviewFragment.kt | 8 +- .../app/features/auth/PromptFragment.kt | 12 +- .../app/features/auth/ReAuthActivity.kt | 6 +- .../member/AutocompleteMemberController.kt | 4 +- .../member/AutocompleteMemberPresenter.kt | 6 +- .../features/call/CallControlsBottomSheet.kt | 15 +- .../app/features/call/CallControlsView.kt | 9 +- .../app/features/call/CallProximityManager.kt | 7 +- .../app/features/call/VectorCallActivity.kt | 59 ++-- .../features/call/audio/CallAudioManager.kt | 9 +- .../call/audio/DefaultAudioDeviceRouter.kt | 4 + .../features/call/conference/JitsiService.kt | 5 +- .../call/conference/RemoveJitsiWidgetView.kt | 6 +- .../call/conference/VectorJitsiActivity.kt | 20 +- .../features/call/dialpad/DialPadFragment.kt | 12 +- .../features/call/dialpad/PstnDialActivity.kt | 10 +- .../call/transfer/CallTransferActivity.kt | 6 +- .../im/vector/app/features/command/Command.kt | 79 +++-- .../features/consent/ConsentNotGivenHelper.kt | 10 +- .../contactsbook/ContactsBookController.kt | 8 +- .../contactsbook/ContactsBookViewModel.kt | 4 +- .../createdirect/CreateDirectRoomActivity.kt | 35 +- .../restore/KeysBackupRestoreActivity.kt | 15 +- .../KeysBackupRestoreFromKeyFragment.kt | 4 +- .../KeysBackupRestoreFromKeyViewModel.kt | 6 +- ...KeysBackupRestoreFromPassphraseFragment.kt | 8 +- ...eysBackupRestoreFromPassphraseViewModel.kt | 4 +- .../KeysBackupRestoreSharedViewModel.kt | 38 +- .../KeysBackupRestoreSuccessFragment.kt | 11 +- .../settings/KeysBackupManageActivity.kt | 13 +- .../settings/KeysBackupSettingsFragment.kt | 10 +- ...eysBackupSettingsRecyclerViewController.kt | 56 +-- .../setup/KeysBackupSetupActivity.kt | 41 ++- .../setup/KeysBackupSetupSharedViewModel.kt | 6 +- .../setup/KeysBackupSetupStep2Fragment.kt | 10 +- .../setup/KeysBackupSetupStep3Fragment.kt | 25 +- .../crypto/keysrequest/KeyRequestHandler.kt | 21 +- .../quads/SharedSecureStorageActivity.kt | 9 +- .../quads/SharedSecureStorageViewModel.kt | 22 +- .../quads/SharedSecuredStorageKeyFragment.kt | 4 +- .../SharedSecuredStoragePassphraseFragment.kt | 8 +- .../SharedSecuredStorageResetAllFragment.kt | 4 +- .../recover/BackupToQuadSMigrationTask.kt | 16 +- .../crypto/recover/BootstrapBottomSheet.kt | 35 +- .../recover/BootstrapConclusionFragment.kt | 12 +- .../BootstrapConfirmPassphraseFragment.kt | 10 +- .../recover/BootstrapCrossSigningTask.kt | 16 +- .../BootstrapEnterPassphraseFragment.kt | 10 +- .../crypto/recover/BootstrapErrorFragment.kt | 4 +- .../recover/BootstrapMigrateBackupFragment.kt | 18 +- .../BootstrapSaveRecoveryKeyFragment.kt | 10 +- .../BootstrapSetupRecoveryKeyFragment.kt | 6 +- .../recover/BootstrapSharedViewModel.kt | 14 +- .../crypto/recover/KeepItSafeDialog.kt | 11 +- .../IncomingVerificationRequestHandler.kt | 13 +- .../self/SelfVerificationBottomSheet.kt | 13 +- .../self/SelfVerificationController.kt | 79 ++--- .../self/SelfVerificationFragment.kt | 4 +- .../self/SelfVerificationViewModel.kt | 4 +- .../user/UserVerificationBottomSheet.kt | 20 +- .../user/UserVerificationController.kt | 47 +-- .../user/UserVerificationFragment.kt | 4 +- .../verification/user/VerificationEpoxyExt.kt | 111 +++--- .../features/devtools/RoomDevToolActivity.kt | 16 +- .../devtools/RoomDevToolRootController.kt | 8 +- .../devtools/RoomDevToolSendFormController.kt | 8 +- .../features/devtools/RoomDevToolViewModel.kt | 18 +- .../devtools/RoomStateListController.kt | 13 +- .../discovery/DiscoverySettingsController.kt | 62 ++-- .../discovery/DiscoverySettingsFragment.kt | 22 +- .../discovery/DiscoverySettingsViewModel.kt | 6 +- .../features/discovery/SettingsButtonItem.kt | 4 +- .../SettingsTextButtonSingleLineItem.kt | 8 +- .../change/SetIdentityServerFragment.kt | 27 +- .../change/SetIdentityServerViewModel.kt | 10 +- .../features/form/FormAdvancedToggleItem.kt | 2 +- .../grouplist/HomeSpaceSummaryItem.kt | 7 +- .../grouplist/NewHomeSpaceSummaryItem.kt | 10 +- .../app/features/home/AvatarRenderer.kt | 8 +- .../vector/app/features/home/HomeActivity.kt | 62 ++-- .../app/features/home/HomeDetailFragment.kt | 19 +- .../app/features/home/HomeDetailViewState.kt | 4 +- .../app/features/home/HomeDrawerFragment.kt | 7 +- .../features/home/InitSyncStepFormatter.kt | 20 +- .../features/home/NewHomeDetailFragment.kt | 15 +- .../home/NotificationPermissionManager.kt | 4 +- .../app/features/home/RoomListDisplayMode.kt | 8 +- .../app/features/home/ShortcutsHandler.kt | 6 +- .../detail/JoinReplacementRoomBottomSheet.kt | 4 +- .../home/room/detail/RoomDetailActivity.kt | 2 +- .../detail/RoomMessageTouchHelperCallback.kt | 3 +- .../room/detail/StartCallActionsHandler.kt | 32 +- .../home/room/detail/TimelineFragment.kt | 199 ++++++----- .../home/room/detail/TimelineViewModel.kt | 9 +- .../composer/MessageComposerFragment.kt | 39 ++- .../composer/MessageComposerViewModel.kt | 10 +- .../composer/PlainTextComposerLayout.kt | 13 +- .../detail/composer/RichTextComposerLayout.kt | 50 +-- .../detail/composer/link/SetLinkFragment.kt | 6 +- .../composer/voice/DraggableStateProcessor.kt | 3 +- .../voice/VoiceMessageRecorderView.kt | 5 +- .../composer/voice/VoiceMessageViews.kt | 21 +- .../composer/voice/VoiceRecorderFragment.kt | 4 +- .../home/room/detail/search/SearchFragment.kt | 3 +- .../detail/search/SearchResultController.kt | 6 +- .../room/detail/search/SearchResultItem.kt | 4 +- .../detail/timeline/MessageColorProvider.kt | 13 +- .../timeline/action/EventSharedAction.kt | 55 +-- .../action/MessageActionsEpoxyController.kt | 15 +- .../action/MessageActionsViewModel.kt | 26 +- .../edithistory/ViewEditHistoryBottomSheet.kt | 3 +- .../ViewEditHistoryEpoxyController.kt | 10 +- .../timeline/factory/DefaultItemFactory.kt | 6 +- .../timeline/factory/EncryptedItemFactory.kt | 17 +- .../timeline/factory/EncryptionItemFactory.kt | 20 +- .../factory/MergedHeaderItemFactory.kt | 8 +- .../timeline/factory/MessageItemFactory.kt | 11 +- .../factory/PollItemViewStateFactory.kt | 19 +- .../timeline/factory/RoomCreateItemFactory.kt | 6 +- .../factory/VerificationItemFactory.kt | 6 +- .../format/DisplayableEventFormatter.kt | 69 ++-- .../timeline/format/EventDetailsFormatter.kt | 6 +- .../timeline/format/NoticeEventFormatter.kt | 324 +++++++++--------- .../format/RoomHistoryVisibilityFormatter.kt | 18 +- .../helper/ContentUploadStateTrackerBinder.kt | 15 +- .../helper/MatrixItemColorProvider.kt | 2 +- .../helper/MessageItemAttributesFactory.kt | 4 +- .../helper/TimelineMediaSizeProvider.kt | 3 +- .../timeline/item/AbsBaseMessageItem.kt | 12 +- .../detail/timeline/item/AbsMessageItem.kt | 4 +- .../timeline/item/AbsMessageLocationItem.kt | 8 +- .../item/AbsMessageVoiceBroadcastItem.kt | 4 +- .../detail/timeline/item/BasedMergedItem.kt | 5 +- .../timeline/item/CallTileTimelineItem.kt | 75 ++-- .../timeline/item/MergedRoomCreationItem.kt | 47 +-- .../detail/timeline/item/MessageAudioItem.kt | 17 +- .../detail/timeline/item/MessageFileItem.kt | 2 +- .../MessageVoiceBroadcastListeningItem.kt | 5 +- .../MessageVoiceBroadcastRecordingItem.kt | 9 +- .../detail/timeline/item/MessageVoiceItem.kt | 15 +- .../detail/timeline/item/PollOptionView.kt | 11 +- .../timeline/item/VerificationRequestItem.kt | 15 +- .../reactions/ViewReactionsBottomSheet.kt | 3 +- .../reactions/ViewReactionsEpoxyController.kt | 4 +- .../DisplayReadReceiptsBottomSheet.kt | 4 +- .../timeline/render/EventTextRenderer.kt | 16 +- .../ProcessBodyOfReplyToEventUseCase.kt | 22 +- .../style/TimelineMessageLayoutFactory.kt | 3 +- .../detail/timeline/url/PreviewUrlView.kt | 4 +- .../detail/timeline/view/MessageBubbleView.kt | 28 +- .../detail/upgrade/MigrateRoomBottomSheet.kt | 18 +- .../detail/widget/RoomWidgetsBannerView.kt | 3 +- .../detail/widget/RoomWidgetsBottomSheet.kt | 6 +- .../detail/widget/RoomWidgetsController.kt | 8 +- .../room/filtered/FilteredRoomFooterItem.kt | 3 +- .../home/room/list/RoomCategoryItem.kt | 4 +- .../room/list/RoomListFooterController.kt | 4 +- .../home/room/list/RoomListFragment.kt | 28 +- .../home/room/list/RoomListSectionBuilder.kt | 28 +- .../home/room/list/RoomSummaryCenteredItem.kt | 2 +- .../home/room/list/RoomSummaryItem.kt | 2 +- .../home/room/list/RoomSummaryItemFactory.kt | 15 +- .../home/room/list/SectionHeaderAdapter.kt | 4 +- .../home/room/list/SpaceChildInfoItem.kt | 5 +- .../RoomListQuickActionsBottomSheet.kt | 6 +- .../RoomListQuickActionsEpoxyController.kt | 8 +- .../RoomListQuickActionsSharedAction.kt | 17 +- .../room/list/home/HomeRoomListFragment.kt | 17 +- .../room/list/home/HomeRoomListViewModel.kt | 13 +- .../room/list/home/header/HomeRoomFilter.kt | 10 +- .../home/header/HomeRoomsHeadersController.kt | 3 +- .../list/home/invites/InvitesViewModel.kt | 5 +- .../list/home/release/ReleaseNotesFragment.kt | 17 +- .../room/list/widget/NotifsFabMenuView.kt | 5 +- .../home/room/threads/ThreadsActivity.kt | 9 +- .../home/room/threads/ThreadsManager.kt | 10 +- .../room/threads/list/model/ThreadListItem.kt | 13 +- .../list/views/ThreadListBottomSheet.kt | 8 +- .../threads/list/views/ThreadListFragment.kt | 21 +- .../features/home/room/typing/TypingHelper.kt | 12 +- .../homeserver/ServerUrlsRepository.kt | 3 +- .../vector/app/features/html/PillImageSpan.kt | 19 +- .../app/features/html/PillsPostProcessor.kt | 3 +- .../vector/app/features/html/SpoilerSpan.kt | 7 +- .../invite/InviteUsersToRoomActivity.kt | 19 +- .../invite/InviteUsersToRoomViewModel.kt | 9 +- .../app/features/invite/VectorInviteView.kt | 5 +- .../app/features/link/LinkHandlerActivity.kt | 20 +- .../app/features/location/LocationDialog.kt | 8 +- .../location/LocationSharingFragment.kt | 10 +- .../location/LocationSharingViewState.kt | 6 +- .../features/location/MapLoadingErrorView.kt | 10 +- .../app/features/location/MapTilerMapView.kt | 15 +- .../live/LiveLocationEndedBannerView.kt | 7 +- .../live/LiveLocationRunningBannerView.kt | 11 +- .../map/LiveLocationBottomSheetController.kt | 4 +- .../live/map/LiveLocationMapViewActivity.kt | 4 +- .../live/map/LiveLocationMapViewFragment.kt | 6 +- .../location/live/map/LiveLocationUserItem.kt | 3 +- .../LiveLocationNotificationBuilder.kt | 5 +- .../option/LocationSharingOptionPickerView.kt | 3 +- .../option/LocationSharingOptionView.kt | 17 +- .../preview/LocationPreviewFragment.kt | 3 +- .../features/login/AbstractLoginFragment.kt | 24 +- .../app/features/login/LoginActivity.kt | 39 ++- .../features/login/LoginCaptchaFragment.kt | 8 +- .../app/features/login/LoginFragment.kt | 43 +-- .../LoginGenericTextInputFormFragment.kt | 36 +- .../login/LoginResetPasswordFragment.kt | 12 +- ...inResetPasswordMailConfirmationFragment.kt | 10 +- .../login/LoginServerSelectionFragment.kt | 4 +- .../login/LoginServerUrlFormFragment.kt | 21 +- .../LoginSignUpSignInSelectionFragment.kt | 15 +- .../app/features/login/LoginSplashFragment.kt | 10 +- .../app/features/login/LoginViewModel.kt | 6 +- .../login/LoginWaitForEmailFragment.kt | 4 +- .../app/features/login/LoginWebFragment.kt | 12 +- .../features/login/SocialLoginButtonsView.kt | 31 +- .../login/qr/QrCodeLoginHeaderView.kt | 11 +- .../qr/QrCodeLoginInstructionsFragment.kt | 12 +- .../login/qr/QrCodeLoginInstructionsView.kt | 9 +- .../login/qr/QrCodeLoginShowQrCodeFragment.kt | 16 +- .../login/qr/QrCodeLoginStatusFragment.kt | 43 +-- .../features/matrixto/MatrixToBottomSheet.kt | 4 +- .../matrixto/MatrixToBottomSheetViewModel.kt | 6 +- .../matrixto/MatrixToRoomSpaceFragment.kt | 24 +- .../features/matrixto/SpaceCardRenderer.kt | 16 +- .../features/media/BaseAttachmentProvider.kt | 4 +- .../features/media/ImageContentRenderer.kt | 10 +- .../vector/app/features/media/UCropHelper.kt | 7 +- .../media/VectorAttachmentViewerActivity.kt | 9 +- .../features/media/VideoContentRenderer.kt | 6 +- .../features/navigation/DefaultNavigator.kt | 10 +- .../notifications/NotifiableEventResolver.kt | 10 +- .../NotificationBroadcastReceiver.kt | 6 +- .../NotificationDrawerManager.kt | 2 +- .../notifications/NotificationUtils.kt | 118 ++++--- .../notifications/RoomGroupMessageCreator.kt | 11 +- .../SummaryGroupMessageCreator.kt | 23 +- .../features/onboarding/DirectLoginUseCase.kt | 4 +- .../features/onboarding/OnboardingActivity.kt | 4 +- .../onboarding/OnboardingVariantFactory.kt | 5 +- .../onboarding/OnboardingViewModel.kt | 3 +- .../onboarding/RegistrationActionHandler.kt | 3 +- .../ftueauth/AbstractFtueAuthFragment.kt | 18 +- .../onboarding/ftueauth/CaptchaWebview.kt | 8 +- .../FtueAuthAccountCreatedFragment.kt | 4 +- .../ftueauth/FtueAuthCaptchaFragment.kt | 6 +- .../ftueauth/FtueAuthCombinedLoginFragment.kt | 4 +- .../FtueAuthCombinedRegisterFragment.kt | 29 +- ...FtueAuthCombinedServerSelectionFragment.kt | 10 +- .../ftueauth/FtueAuthEmailEntryFragment.kt | 6 +- .../FtueAuthGenericTextInputFormFragment.kt | 36 +- .../FtueAuthLegacyWaitForEmailFragment.kt | 4 +- .../ftueauth/FtueAuthLoginFragment.kt | 49 +-- .../FtueAuthPhoneConfirmationFragment.kt | 6 +- .../ftueauth/FtueAuthPhoneEntryFragment.kt | 9 +- .../FtueAuthResetPasswordBreakerFragment.kt | 8 +- ...FtueAuthResetPasswordEmailEntryFragment.kt | 4 +- .../ftueauth/FtueAuthResetPasswordFragment.kt | 12 +- ...thResetPasswordMailConfirmationFragment.kt | 10 +- .../FtueAuthServerSelectionFragment.kt | 4 +- .../ftueauth/FtueAuthServerUrlFormFragment.kt | 21 +- .../FtueAuthSignUpSignInSelectionFragment.kt | 15 +- .../FtueAuthSplashCarouselFragment.kt | 4 +- .../ftueauth/FtueAuthSplashFragment.kt | 4 +- .../ftueauth/FtueAuthUseCaseFragment.kt | 19 +- .../onboarding/ftueauth/FtueAuthVariant.kt | 39 ++- .../ftueauth/FtueAuthWaitForEmailFragment.kt | 8 +- .../ftueauth/FtueAuthWebFragment.kt | 12 +- .../onboarding/ftueauth/FtueExtensions.kt | 2 +- .../onboarding/ftueauth/LoginErrorParser.kt | 8 +- .../ftueauth/LoginFieldsValidation.kt | 6 +- .../ftueauth/SplashCarouselStateFactory.kt | 31 +- .../ftueauth/terms/FtueAuthTermsFragment.kt | 3 +- .../features/permalink/PermalinkHandler.kt | 8 +- .../im/vector/app/features/pin/PinFragment.kt | 30 +- .../lockscreen/biometrics/BiometricHelper.kt | 5 +- .../pin/lockscreen/ui/LockScreenFragment.kt | 4 +- .../FallbackBiometricDialogFragment.kt | 14 +- .../lockscreen/views/LockScreenCodeView.kt | 2 +- .../poll/create/CreatePollController.kt | 15 +- .../poll/create/CreatePollFragment.kt | 15 +- .../app/features/popup/IncomingCallAlert.kt | 7 +- .../app/features/popup/PopupAlertManager.kt | 9 +- .../vector/app/features/popup/VectorAlert.kt | 3 +- .../features/qrcode/QrCodeScannerActivity.kt | 6 +- .../features/qrcode/QrCodeScannerFragment.kt | 6 +- .../features/rageshake/BugReportActivity.kt | 42 +-- .../app/features/rageshake/BugReporter.kt | 8 +- .../app/features/rageshake/RageShake.kt | 12 +- .../app/features/reactions/EmojiDrawView.kt | 8 +- .../reactions/EmojiReactionPickerActivity.kt | 5 +- .../reactions/EmojiSearchResultController.kt | 6 +- .../reactions/widget/ReactionButton.kt | 10 +- .../room/RequireActiveMembershipViewModel.kt | 8 +- .../VectorRoomDisplayNameFallbackProvider.kt | 17 +- .../features/roomdirectory/PublicRoomItem.kt | 4 +- .../roomdirectory/PublicRoomsController.kt | 4 +- .../roomdirectory/PublicRoomsFragment.kt | 3 +- .../createroom/CreateRoomController.kt | 42 +-- .../createroom/CreateRoomFragment.kt | 14 +- .../createroom/CreateSubSpaceController.kt | 25 +- .../createroom/RoomAliasErrorFormatter.kt | 8 +- .../picker/RoomDirectoryListCreator.kt | 2 +- .../picker/RoomDirectoryPickerController.kt | 21 +- .../picker/RoomDirectoryPickerFragment.kt | 4 +- .../picker/RoomDirectoryPickerViewModel.kt | 4 +- .../RoomPreviewNoPreviewFragment.kt | 17 +- .../RoomMemberProfileController.kt | 57 +-- .../RoomMemberProfileFragment.kt | 73 ++-- .../RoomMemberProfileViewModel.kt | 10 +- .../devices/DeviceListEpoxyController.kt | 29 +- .../devices/DeviceTrustInfoEpoxyController.kt | 17 +- .../powerlevel/EditPowerLevelDialogs.kt | 23 +- .../roomprofile/RoomProfileController.kt | 76 ++-- .../roomprofile/RoomProfileFragment.kt | 26 +- .../roomprofile/RoomProfileViewModel.kt | 4 +- .../roomprofile/alias/RoomAliasController.kt | 36 +- .../roomprofile/alias/RoomAliasFragment.kt | 26 +- .../RoomAliasBottomSheetSharedAction.kt | 13 +- .../banned/RoomBannedMemberListController.kt | 7 +- .../banned/RoomBannedMemberListFragment.kt | 12 +- .../banned/RoomBannedMemberListViewModel.kt | 4 +- .../members/RoomMemberListController.kt | 3 +- .../members/RoomMemberListFragment.kt | 12 +- .../members/RoomMemberListViewState.kt | 12 +- .../RoomNotificationSettingsController.kt | 10 +- .../RoomNotificationSettingsFragment.kt | 4 +- .../permissions/EditablePermission.kt | 48 +-- .../roomprofile/permissions/RoleFormatter.kt | 10 +- .../permissions/RoomPermissionsController.kt | 12 +- .../permissions/RoomPermissionsFragment.kt | 6 +- .../roomprofile/polls/RoomPollsFragment.kt | 6 +- .../polls/active/RoomActivePollsFragment.kt | 7 +- .../polls/detail/ui/RoomPollDetailFragment.kt | 6 +- .../polls/ended/RoomEndedPollsFragment.kt | 7 +- .../polls/list/ui/RoomPollsController.kt | 4 +- .../settings/RoomSettingsController.kt | 14 +- .../settings/RoomSettingsFragment.kt | 13 +- .../settings/RoomSettingsViewState.kt | 12 +- .../RoomHistoryVisibilityController.kt | 6 +- .../RoomJoinRuleAdvancedController.kt | 16 +- .../joinrule/RoomJoinRuleController.kt | 20 +- .../settings/joinrule/RoomJoinRuleFragment.kt | 16 +- .../settings/joinrule/SpaceJoinRuleItem.kt | 7 +- .../advanced/ChooseRestrictedController.kt | 8 +- .../RoomJoinRuleChooseRestrictedViewModel.kt | 6 +- .../uploads/RoomUploadsFragment.kt | 6 +- .../uploads/files/RoomUploadsFilesFragment.kt | 3 +- .../uploads/files/UploadsFileController.kt | 4 +- .../uploads/media/RoomUploadsMediaFragment.kt | 3 +- .../BackgroundSyncModeChooserDialog.kt | 5 +- .../features/settings/FontScalePreferences.kt | 16 +- .../app/features/settings/VectorLocale.kt | 18 +- .../features/settings/VectorPreferences.kt | 57 +-- .../settings/VectorSettingsActivity.kt | 5 +- .../VectorSettingsAdvancedSettingsFragment.kt | 5 +- .../settings/VectorSettingsBaseFragment.kt | 9 +- .../settings/VectorSettingsGeneralFragment.kt | 19 +- .../VectorSettingsHelpAboutFragment.kt | 3 +- .../settings/VectorSettingsPinFragment.kt | 5 +- .../VectorSettingsPreferencesFragment.kt | 11 +- .../settings/VectorSettingsRootFragment.kt | 3 +- .../VectorSettingsSecurityPrivacyFragment.kt | 52 +-- .../VectorSettingsVoiceVideoFragment.kt | 5 +- .../deactivation/DeactivateAccountFragment.kt | 6 +- .../CrossSigningSettingsController.kt | 23 +- .../CrossSigningSettingsFragment.kt | 10 +- .../CrossSigningSettingsViewModel.kt | 4 +- .../features/settings/devices/DeviceItem.kt | 5 +- ...ceVerificationInfoBottomSheetController.kt | 73 ++-- .../settings/devices/DevicesController.kt | 8 +- .../settings/devices/DevicesViewModel.kt | 6 +- .../devices/VectorSettingsDevicesFragment.kt | 13 +- .../devices/v2/SessionWarningInfoView.kt | 10 +- .../v2/VectorSettingsDevicesFragment.kt | 22 +- .../v2/details/SessionDetailsController.kt | 32 +- .../v2/details/SessionDetailsFragment.kt | 6 +- .../filter/DeviceManagerFilterBottomSheet.kt | 3 +- .../v2/list/OtherSessionsController.kt | 20 +- .../devices/v2/list/OtherSessionsView.kt | 3 +- .../v2/list/SecurityRecommendationView.kt | 13 +- .../devices/v2/list/SessionInfoView.kt | 38 +- .../devices/v2/list/SessionsListHeaderView.kt | 14 +- .../v2/list/SetDeviceTypeIconUseCase.kt | 9 +- .../v2/othersessions/OtherSessionsFragment.kt | 56 +-- ...OtherSessionsSecurityRecommendationView.kt | 18 +- .../SessionOverviewEntrySwitchView.kt | 9 +- .../v2/overview/SessionOverviewEntryView.kt | 7 +- .../v2/overview/SessionOverviewFragment.kt | 26 +- .../v2/rename/RenameSessionFragment.kt | 6 +- .../BuildConfirmSignoutDialogUseCase.kt | 10 +- .../devtools/AccountDataEpoxyController.kt | 6 +- .../settings/devtools/AccountDataFragment.kt | 13 +- .../settings/devtools/KeyRequestsFragment.kt | 3 +- .../font/FontScaleSettingController.kt | 6 +- .../HomeserverSettingsController.kt | 23 +- .../homeserver/HomeserverSettingsFragment.kt | 4 +- .../ignored/IgnoredUsersController.kt | 4 +- .../VectorSettingsIgnoredUsersFragment.kt | 14 +- .../labs/VectorSettingsLabsFragment.kt | 9 +- .../features/settings/legals/ElementLegals.kt | 8 +- .../settings/legals/LegalsController.kt | 16 +- .../settings/legals/LegalsFragment.kt | 4 +- .../settings/legals/LegalsViewModel.kt | 6 +- .../settings/locale/LocalePickerController.kt | 10 +- .../settings/locale/LocalePickerFragment.kt | 4 +- .../VectorSettingsNotificationFragment.kt | 20 +- ...torSettingsPushRuleNotificationFragment.kt | 6 +- ...sAdvancedNotificationPreferenceFragment.kt | 3 +- ...ctorSettingsDefaultNotificationFragment.kt | 3 +- ...sKeywordAndMentionsNotificationFragment.kt | 3 +- ...VectorSettingsOtherNotificationFragment.kt | 3 +- ...ttingsNotificationsTroubleshootFragment.kt | 16 +- .../settings/push/PushGateWayController.kt | 6 +- .../settings/push/PushGatewaysFragment.kt | 5 +- .../features/settings/push/PushRuleItem.kt | 9 +- .../settings/push/PushRulesController.kt | 4 +- .../settings/push/PushRulesFragment.kt | 3 +- .../threepids/ThreePidsSettingsController.kt | 38 +- .../threepids/ThreePidsSettingsFragment.kt | 22 +- .../threepids/ThreePidsSettingsViewModel.kt | 6 +- ...ficationTroubleshootRecyclerViewAdapter.kt | 10 +- .../troubleshoot/TestAccountSettings.kt | 10 +- .../TestAvailableUnifiedPushDistributors.kt | 11 +- .../TestCurrentUnifiedPushDistributor.kt | 6 +- .../troubleshoot/TestDeviceSettings.kt | 10 +- .../TestEndpointAsTokenRegistration.kt | 12 +- .../settings/troubleshoot/TestNotification.kt | 10 +- .../troubleshoot/TestPushFromPushGateway.kt | 12 +- .../troubleshoot/TestPushRulesSettings.kt | 10 +- .../troubleshoot/TestSystemSettings.kt | 14 +- .../troubleshoot/TestUnifiedPushEndpoint.kt | 8 +- .../troubleshoot/TestUnifiedPushGateway.kt | 6 +- .../features/share/IncomingShareController.kt | 4 +- .../features/share/IncomingShareFragment.kt | 12 +- .../signout/soft/SoftLogoutActivity.kt | 8 +- .../signout/soft/SoftLogoutController.kt | 20 +- .../signout/soft/SoftLogoutFragment.kt | 14 +- .../InviteRoomSpaceChooserBottomSheet.kt | 10 +- .../app/features/spaces/NewSpaceAddItem.kt | 2 +- .../spaces/NewSpaceSummaryController.kt | 4 +- .../features/spaces/NewSpaceSummaryItem.kt | 3 +- .../features/spaces/NewSubSpaceSummaryItem.kt | 3 +- .../features/spaces/SpaceCreationActivity.kt | 18 +- .../features/spaces/SpaceExploreActivity.kt | 4 +- .../app/features/spaces/SpaceInviteItem.kt | 3 +- .../features/spaces/SpaceSummaryController.kt | 4 +- .../create/ChoosePrivateSpaceTypeFragment.kt | 4 +- .../CreateSpaceAdd3pidInvitesFragment.kt | 8 +- .../create/CreateSpaceDefaultRoomsFragment.kt | 4 +- .../spaces/create/CreateSpaceViewModel.kt | 8 +- .../create/SpaceAdd3pidEpoxyController.kt | 22 +- .../create/SpaceDefaultRoomEpoxyController.kt | 20 +- .../create/SpaceDetailEpoxyController.kt | 12 +- .../spaces/create/WizardButtonView.kt | 10 +- .../explore/SpaceDirectoryController.kt | 27 +- .../spaces/explore/SpaceDirectoryFragment.kt | 27 +- .../spaces/invite/SpaceInviteBottomSheet.kt | 8 +- .../spaces/leave/SelectChildrenController.kt | 4 +- .../leave/SpaceLeaveAdvancedActivity.kt | 6 +- .../leave/SpaceLeaveAdvancedFragment.kt | 9 +- .../spaces/manage/RoomManageSelectionItem.kt | 5 +- .../spaces/manage/RoomSelectionItem.kt | 5 +- .../spaces/manage/SpaceAddRoomFragment.kt | 21 +- .../spaces/manage/SpaceManageActivity.kt | 4 +- .../manage/SpaceManageRoomsController.kt | 4 +- .../spaces/manage/SpaceManageRoomsFragment.kt | 8 +- .../spaces/manage/SpaceSettingsController.kt | 32 +- .../spaces/manage/SpaceSettingsFragment.kt | 13 +- .../spaces/people/SpacePeopleActivity.kt | 4 +- .../spaces/people/SpacePeopleFragment.kt | 7 +- .../people/SpacePeopleListController.kt | 26 +- .../spaces/preview/SpacePreviewController.kt | 7 +- .../spaces/preview/SpacePreviewFragment.kt | 4 +- .../spaces/share/ShareSpaceBottomSheet.kt | 14 +- .../app/features/terms/ReviewTermsActivity.kt | 4 +- .../app/features/terms/ReviewTermsFragment.kt | 12 +- .../app/features/terms/TermsController.kt | 4 +- .../features/themes/ActivityOtherThemes.kt | 2 +- .../vector/app/features/themes/ThemeUtils.kt | 2 +- .../app/features/usercode/UserCodeActivity.kt | 9 +- .../usercode/UserCodeSharedViewModel.kt | 16 +- .../userdirectory/UserDirectoryUserItem.kt | 2 +- .../userdirectory/UserListController.kt | 37 +- .../userdirectory/UserListFragment.kt | 7 +- .../userdirectory/UserListViewModel.kt | 4 +- .../app/features/voice/AudioWaveformView.kt | 21 +- .../views/VoiceBroadcastMetadataView.kt | 6 +- .../features/webview/VectorWebViewActivity.kt | 2 +- .../app/features/widgets/WidgetActivity.kt | 17 +- .../app/features/widgets/WidgetFragment.kt | 11 +- .../features/widgets/WidgetPostAPIHandler.kt | 28 +- .../app/features/widgets/WidgetViewState.kt | 6 +- .../RoomWidgetPermissionBottomSheet.kt | 12 +- .../RoomWidgetPermissionViewModel.kt | 18 +- .../widgets/webview/WebviewPermissionUtils.kt | 12 +- .../features/widgets/webview/WidgetWebView.kt | 3 +- .../signout/SignOutBottomSheetActionButton.kt | 4 +- .../SignOutBottomSheetDialogFragment.kt | 36 +- .../workers/signout/SignOutUiWorker.kt | 10 +- .../main/res/drawable/ic_presence_away.xml | 7 +- .../main/res/drawable/ic_presence_busy.xml | 7 +- .../main/res/drawable/ic_presence_offline.xml | 9 +- .../main/res/drawable/ic_presence_online.xml | 7 +- .../src/main/res/layout/activity_threads.xml | 3 +- .../src/main/res/layout/fragment_composer.xml | 4 +- .../res/layout/item_space_beta_header.xml | 1 - .../layout/vector_preference_chip_group.xml | 1 - .../app/core/pushers/PushersManagerTest.kt | 3 +- .../conference/jwt/JitsiJWTFactoryTest.kt | 1 - .../features/home/RoomsListViewModelTest.kt | 13 +- .../vector/app/features/home/UserColorTest.kt | 2 +- .../factory/PollItemViewStateFactoryTest.kt | 17 +- .../ProcessBodyOfReplyToEventUseCaseTest.kt | 26 +- .../onboarding/DirectLoginUseCaseTest.kt | 4 +- .../onboarding/OnboardingViewModelTest.kt | 3 +- .../RegistrationActionHandlerTest.kt | 3 +- .../ftueauth/LoginErrorParserTest.kt | 8 +- .../v2/list/SetDeviceTypeIconUseCaseTest.kt | 9 +- .../PaparazziExampleScreenshotTest.kt | 3 +- .../test/fakes/FakeFontScalePreferences.kt | 16 +- .../app/test/fixtures/BuildMetaFixture.kt | 1 + 711 files changed, 4776 insertions(+), 4296 deletions(-) create mode 100644 library/ui-strings/src/main/java/im/vector/lib/strings/CommonStrings.kt diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 116a604c10..d54a64ed34 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,12 +24,17 @@ jobs: group: ${{ github.ref == 'refs/heads/develop' && format('integration-tests-develop-{0}-{1}', matrix.target, github.sha) || format('build-debug-{0}-{1}', matrix.target, github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: # https://github.com/actions/checkout/issues/881 ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} + - name: Use JDK 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '17' - name: Configure gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/actions/setup-gradle@v3 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Assemble ${{ matrix.target }} debug apk @@ -48,12 +53,17 @@ jobs: group: ${{ github.ref == 'refs/head/main' && format('build-release-apk-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('build-release-apk-develop-{0}', github.sha) || format('build-debug-{0}', github.ref) }} cancel-in-progress: ${{ github.ref != 'refs/head/main' }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: # https://github.com/actions/checkout/issues/881 ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} + - name: Use JDK 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '17' - name: Configure gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/actions/setup-gradle@v3 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Assemble GPlay unsigned apk diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index 8358eae14b..5eb2f1af3c 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest name: Danger steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: | npm install --save-dev @babel/plugin-transform-flow-strip-types - name: Danger diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index a44872e0ef..1a27d491a0 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build docs run: ./gradlew dokkaHtml diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 7b68c0077d..2c13615738 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -10,5 +10,5 @@ jobs: runs-on: ubuntu-latest # No concurrency required, this is a prerequisite to other actions and should run every time. steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: gradle/wrapper-validation-action@v1 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 5ad3adc7d2..3a9465c1e9 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -15,13 +15,18 @@ jobs: name: Build and publish nightly Gplay APK to Firebase runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python 3.8 uses: actions/setup-python@v4 with: python-version: 3.8 + - name: Use JDK 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '17' - name: Configure gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/actions/setup-gradle@v3 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Install towncrier diff --git a/.github/workflows/post-pr.yml b/.github/workflows/post-pr.yml index 0245fcdd34..023945c4ee 100644 --- a/.github/workflows/post-pr.yml +++ b/.github/workflows/post-pr.yml @@ -39,17 +39,18 @@ jobs: api-level: [ 28 ] # No concurrency required, runs every time on a schedule. steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python 3.8 uses: actions/setup-python@v4 with: python-version: 3.8 - - uses: actions/setup-java@v3 + - name: Use JDK 17 + uses: actions/setup-java@v4 with: - distribution: 'adopt' - java-version: '11' + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '17' - name: Configure gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/actions/setup-gradle@v3 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Start synapse server diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 4b12594a68..c943cff5b6 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -7,7 +7,7 @@ on: # Enrich gradle.properties for CI/CD env: - GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -XX:MaxPermSize=512m -Dkotlin.daemon.jvm.options="-Xmx2g" -Dkotlin.incremental=false + GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError -XX:MaxMetaspaceSize=1g" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon jobs: @@ -15,7 +15,7 @@ jobs: name: Project Check Suite runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Run code quality check suite run: ./tools/check/check_code_quality.sh @@ -24,7 +24,16 @@ jobs: name: Knit runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + - name: Use JDK 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '17' + - name: Configure gradle + uses: gradle/actions/setup-gradle@v3 + with: + cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run knit run: | ./gradlew knitCheck $CI_GRADLE_ARG_PROPERTIES @@ -38,7 +47,16 @@ jobs: group: ${{ github.ref == 'refs/heads/main' && format('lint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('lint-develop-{0}', github.sha) || format('lint-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + - name: Use JDK 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '17' + - name: Configure gradle + uses: gradle/actions/setup-gradle@v3 + with: + cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run ktlint run: | ./gradlew ktlintCheck $CI_GRADLE_ARG_PROPERTIES --continue @@ -83,7 +101,16 @@ jobs: group: ${{ github.ref == 'refs/heads/main' && format('dep-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('dep-develop-{0}', github.sha) || format('dep-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + - name: Use JDK 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '17' + - name: Configure gradle + uses: gradle/actions/setup-gradle@v3 + with: + cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Dependency analysis run: ./gradlew dependencyCheckAnalyze $CI_GRADLE_ARG_PROPERTIES - name: Upload dependency analysis diff --git a/.github/workflows/sync-from-external-sources.yml b/.github/workflows/sync-from-external-sources.yml index ac8b8f1717..40dd71c3b0 100644 --- a/.github/workflows/sync-from-external-sources.yml +++ b/.github/workflows/sync-from-external-sources.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'element-hq/element-android' # No concurrency required, runs every time on a schedule. steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python 3.8 uses: actions/setup-python@v4 with: @@ -39,7 +39,7 @@ jobs: if: github.repository == 'element-hq/element-android' # No concurrency required, runs every time on a schedule. steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python 3.8 uses: actions/setup-python@v4 with: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1bb8366900..36a0365f84 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,21 +19,23 @@ jobs: timeout-minutes: 90 # We might need to increase it if the time for tests grows strategy: matrix: - api-level: [28] + api-level: [34] # Allow all jobs on main and develop. Just one per PR. concurrency: group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('unit-tests-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: lfs: true fetch-depth: 0 - - uses: actions/setup-java@v3 + - name: Use JDK 17 + uses: actions/setup-java@v4 with: - distribution: 'adopt' + distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - - uses: gradle/gradle-build-action@v2 + - name: Configure gradle + uses: gradle/actions/setup-gradle@v3 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} gradle-home-cache-cleanup: ${{ github.ref == 'refs/heads/develop' }} @@ -136,13 +138,14 @@ jobs: # group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('build-android-tests-{0}', github.ref) }} # cancel-in-progress: true # steps: -# - uses: actions/checkout@v3 -# - uses: actions/setup-java@v3 +# - uses: actions/checkout@v4 +# - name: Use JDK 17 +# uses: actions/setup-java@v4 # with: -# distribution: 'adopt' -# java-version: 11 +# distribution: 'temurin' # See 'Supported distributions' for available options +# java-version: '17' # - name: Configure gradle -# uses: gradle/gradle-build-action@v2 +# uses: gradle/actions/setup-gradle@v3 # with: # cache-read-only: ${{ github.ref != 'refs/heads/develop' }} # - name: Build Android Tests diff --git a/.github/workflows/update-gradle-wrapper.yml b/.github/workflows/update-gradle-wrapper.yml index 338e2b2c17..cb6f9e1c2c 100644 --- a/.github/workflows/update-gradle-wrapper.yml +++ b/.github/workflows/update-gradle-wrapper.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Update Gradle Wrapper uses: gradle-update/update-gradle-wrapper-action@v1 diff --git a/.github/workflows/validate-lfs.yml b/.github/workflows/validate-lfs.yml index 203ecb0481..c52e3e4f6a 100644 --- a/.github/workflows/validate-lfs.yml +++ b/.github/workflows/validate-lfs.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest name: Validate steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: lfs: 'true' diff --git a/build.gradle b/build.gradle index 71b94c2354..af6aa5e91b 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ buildscript { classpath 'com.google.gms:google-services:4.3.15' classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:4.0.0.2929' classpath 'com.google.android.gms:oss-licenses-plugin:0.10.6' - classpath "com.likethesalad.android:stem-plugin:2.4.1" + classpath "com.likethesalad.android:stem-plugin:2.9.0" classpath 'org.owasp:dependency-check-gradle:8.2.1' classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.8.10" classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0" @@ -45,7 +45,7 @@ plugins { // Detekt id "io.gitlab.arturbosch.detekt" version "1.22.0" // Ksp - id "com.google.devtools.ksp" version "1.8.10-1.0.9" + id "com.google.devtools.ksp" version "1.9.24-1.0.20" // Dependency Analysis id 'com.autonomousapps.dependency-analysis' version "1.20.0" diff --git a/coverage.gradle b/coverage.gradle index 421c500728..614dfe7e65 100644 --- a/coverage.gradle +++ b/coverage.gradle @@ -33,9 +33,9 @@ def initializeReport(report, projects, classExcludes) { ) } report.reports { - xml.enabled true - html.enabled true - csv.enabled false + xml.required = true + html.required = true + csv.required = false } gradle.projectsEvaluated { diff --git a/dependencies.gradle b/dependencies.gradle index 2361ef9813..14077987b2 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,38 +2,38 @@ ext.versions = [ 'minSdk' : 21, 'compileSdk' : 34, 'targetSdk' : 34, - 'sourceCompat' : JavaVersion.VERSION_11, - 'targetCompat' : JavaVersion.VERSION_11, + 'sourceCompat' : JavaVersion.VERSION_17, + 'targetCompat' : JavaVersion.VERSION_17, + 'jvmTarget' : "17", ] -def gradle = "7.4.2" +def gradle = "8.4.2" // Ref: https://kotlinlang.org/releases.html -def kotlin = "1.8.10" -def kotlinCoroutines = "1.6.4" -def dagger = "2.45" -def firebaseBom = "32.0.0" +def kotlin = "1.9.24" +def kotlinCoroutines = "1.8.1" +def dagger = "2.51.1" +def firebaseBom = "33.1.1" def appDistribution = "16.0.0-beta08" -def retrofit = "2.9.0" +def retrofit = "2.11.0" def markwon = "4.6.2" -def moshi = "1.14.0" -def lifecycle = "2.5.1" +def moshi = "1.15.1" +def lifecycle = "2.8.3" def flowBinding = "1.2.0" def flipper = "0.190.0" def epoxy = "5.0.0" -def mavericks = "3.0.7" -def glide = "4.15.1" +def mavericks = "3.0.9" +def glide = "4.16.0" def bigImageViewer = "1.8.1" def jjwt = "0.11.5" def vanniktechEmoji = "0.16.0" def sentry = "6.18.1" -// Use 1.6.0 alpha to fix issue with test -def fragment = "1.6.0-beta01" +def fragment = "1.8.1" // 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 -def espresso = "3.5.1" -def androidxTest = "1.5.0" -def androidxOrchestrator = "1.4.2" -def paparazzi = "1.2.0" +def mockk = "1.13.11" +def espresso = "3.6.1" +def androidxTest = "1.6.1" +def androidxOrchestrator = "1.5.0" +def paparazzi = "1.3.4" ext.libs = [ gradle : [ @@ -47,8 +47,8 @@ ext.libs = [ 'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines" ], androidx : [ - 'activity' : "androidx.activity:activity-ktx:1.7.2", - 'appCompat' : "androidx.appcompat:appcompat:1.6.1", + 'activity' : "androidx.activity:activity-ktx:1.9.0", + 'appCompat' : "androidx.appcompat:appcompat:1.7.0", 'biometric' : "androidx.biometric:biometric:1.1.0", 'core' : "androidx.core:core-ktx:1.10.1", 'recyclerview' : "androidx.recyclerview:recyclerview:1.3.0", @@ -76,11 +76,11 @@ ext.libs = [ 'espressoCore' : "androidx.test.espresso:espresso-core:$espresso", 'espressoContrib' : "androidx.test.espresso:espresso-contrib:$espresso", 'espressoIntents' : "androidx.test.espresso:espresso-intents:$espresso", - 'viewpager2' : "androidx.viewpager2:viewpager2:1.0.0", - 'transition' : "androidx.transition:transition:1.4.1", + 'viewpager2' : "androidx.viewpager2:viewpager2:1.1.0", + 'transition' : "androidx.transition:transition:1.5.0", ], google : [ - 'material' : "com.google.android.material:material:1.9.0", + 'material' : "com.google.android.material:material:1.12.0", 'firebaseBom' : "com.google.firebase:firebase-bom:$firebaseBom", 'messaging' : "com.google.firebase:firebase-messaging", 'appdistributionApi' : "com.google.firebase:firebase-appdistribution-api-ktx:$appDistribution", @@ -172,7 +172,7 @@ ext.libs = [ 'kluent' : "org.amshove.kluent:kluent-android:1.73", 'timberJunitRule' : "net.lachlanmckee:timber-junit-rule:1.0.1", 'junit' : "junit:junit:4.13.2", - 'robolectric' : "org.robolectric:robolectric:4.9", + 'robolectric' : "org.robolectric:robolectric:4.13", ] ] diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index f16ed4f809..0c76f0f3b9 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -96,6 +96,7 @@ ext.groups = [ 'com.google.auto.value', 'com.google.code.findbugs', 'com.google.code.gson', + 'com.google.crypto.tink', 'com.google.dagger', 'com.google.devtools.ksp', 'com.google.errorprone', @@ -141,6 +142,7 @@ ext.groups = [ 'commons-codec', 'commons-io', 'commons-logging', + 'dev.drewhamilton.poko', 'info.picocli', 'io.element.android', 'io.github.davidburstrom.contester', diff --git a/docs/screenshot_testing.md b/docs/screenshot_testing.md index 93b91cdf67..0445689305 100644 --- a/docs/screenshot_testing.md +++ b/docs/screenshot_testing.md @@ -62,7 +62,7 @@ class PaparazziExampleScreenshotTest { val view = paparazzi.inflate(R.layout.item_radio) // Bind data to the view - view.findViewById(R.id.actionTitle).text = paparazzi.resources.getString(R.string.room_settings_all_messages) + view.findViewById(R.id.actionTitle).text = paparazzi.resources.getString(CommonStrings.room_settings_all_messages) view.findViewById(R.id.radioIcon).setImageResource(R.drawable.ic_radio_on) // Record the bound view diff --git a/docs/ui-tests.md b/docs/ui-tests.md index d0b9db6818..b4aed278bc 100644 --- a/docs/ui-tests.md +++ b/docs/ui-tests.md @@ -179,7 +179,7 @@ class SettingsRobot { } fun advancedSettings(block: SettingsAdvancedRobot.() -> Unit) { - clickOn(R.string.settings_advanced_settings) + clickOn(CommonStrings.settings_advanced_settings) block(SettingsAdvancedRobot()) pressBack() } @@ -187,7 +187,7 @@ class SettingsRobot { class SettingsAdvancedRobot { fun toggleDeveloperMode() { - clickOn(R.string.settings_developer_mode_summary) + clickOn(CommonStrings.settings_developer_mode_summary) } } ``` diff --git a/gradle.properties b/gradle.properties index 682c94a916..8cde2fc687 100644 --- a/gradle.properties +++ b/gradle.properties @@ -42,4 +42,4 @@ signing.element.nightly.keyPassword=Secret # Customise the Lint version to use a more recent version than the one bundled with AGP # https://googlesamples.github.io/android-custom-lint-rules/usage/newer-lint.md.html -android.experimental.lint.version=8.3.0-alpha12 +android.experimental.lint.version=8.6.0-alpha08 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..e6441136f3d4ba8a0da8d277868979cfbc8ad796 100644 GIT binary patch literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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
NnX)EH+Nua)3Y(c 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 ScNgau(U?ep-K_E5zy1%ZQTdPn diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bc073f6761..515ab9d5f1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,8 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=312eb12875e1747e05c2f81a4789902d7e4ec5defbd1eefeaccc08acf096505d -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip +distributionSha256Sum=f8b4f4772d302c8ff580bc40d0f56e715de69b163546944f787c87abf209c961 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/library/attachment-viewer/build.gradle b/library/attachment-viewer/build.gradle index fc9495b113..812ea42f67 100644 --- a/library/attachment-viewer/build.gradle +++ b/library/attachment-viewer/build.gradle @@ -38,7 +38,7 @@ android { targetCompatibility versions.targetCompat } kotlinOptions { - jvmTarget = "11" + jvmTarget = versions.jvmTarget } buildFeatures { diff --git a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt index 21d96afb77..f691c75094 100644 --- a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt +++ b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt @@ -31,7 +31,6 @@ import android.view.WindowManager import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat -import androidx.core.view.GestureDetectorCompat import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.isVisible @@ -39,6 +38,7 @@ import androidx.core.view.updatePadding import androidx.transition.TransitionManager import androidx.viewpager2.widget.ViewPager2 import im.vector.lib.attachmentviewer.databinding.ActivityAttachmentViewerBinding +import im.vector.lib.ui.styles.R import java.lang.ref.WeakReference import kotlin.math.abs @@ -71,7 +71,7 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi private lateinit var swipeDismissHandler: SwipeToDismissHandler private lateinit var directionDetector: SwipeDirectionDetector private lateinit var scaleDetector: ScaleGestureDetector - private lateinit var gestureDetector: GestureDetectorCompat + private lateinit var gestureDetector: GestureDetector var currentPosition = 0 private set @@ -309,7 +309,7 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi ScaleGestureDetector(this, ScaleGestureDetector.SimpleOnScaleGestureListener()) private fun createGestureDetector() = - GestureDetectorCompat(this, object : GestureDetector.SimpleOnGestureListener() { + GestureDetector(this, object : GestureDetector.SimpleOnGestureListener() { override fun onSingleTapConfirmed(e: MotionEvent): Boolean { if (isImagePagerIdle) { handleSingleTap(e, isOverlayWasClicked) diff --git a/library/core-utils/build.gradle b/library/core-utils/build.gradle index d1e82fcb9a..cf9f5fbe37 100644 --- a/library/core-utils/build.gradle +++ b/library/core-utils/build.gradle @@ -28,7 +28,6 @@ android { targetSdk versions.targetSdk testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles "consumer-rules.pro" } buildTypes { @@ -44,7 +43,7 @@ android { } kotlinOptions { - jvmTarget = "11" + jvmTarget = versions.jvmTarget freeCompilerArgs += [ "-opt-in=kotlin.RequiresOptIn" ] diff --git a/library/external/autocomplete/build.gradle b/library/external/autocomplete/build.gradle index 39d4d4b19e..a076e4a836 100644 --- a/library/external/autocomplete/build.gradle +++ b/library/external/autocomplete/build.gradle @@ -17,7 +17,7 @@ android { } kotlinOptions { - jvmTarget = "11" + jvmTarget = versions.jvmTarget } } diff --git a/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/Autocomplete.java b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/Autocomplete.java index cf58146f14..4639abae96 100644 --- a/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/Autocomplete.java +++ b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/Autocomplete.java @@ -13,7 +13,6 @@ import android.util.Log; import android.util.TypedValue; import android.view.Gravity; -import android.view.Window; import android.view.WindowManager; import android.widget.EditText; import android.widget.PopupWindow; diff --git a/library/external/dialpad/build.gradle b/library/external/dialpad/build.gradle index e6f249f535..f76ee66b4c 100644 --- a/library/external/dialpad/build.gradle +++ b/library/external/dialpad/build.gradle @@ -17,7 +17,7 @@ android { } kotlinOptions { - jvmTarget = "11" + jvmTarget = versions.jvmTarget } } diff --git a/library/external/dialpad/src/main/java/com/android/dialer/dialpadview/DialpadView.java b/library/external/dialpad/src/main/java/com/android/dialer/dialpadview/DialpadView.java index 09079235af..edd4572c87 100644 --- a/library/external/dialpad/src/main/java/com/android/dialer/dialpadview/DialpadView.java +++ b/library/external/dialpad/src/main/java/com/android/dialer/dialpadview/DialpadView.java @@ -20,7 +20,6 @@ import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; -import android.graphics.drawable.Drawable; import android.os.Build; import android.text.Spannable; import android.text.TextUtils; diff --git a/library/external/dialpad/src/main/java/com/android/dialer/widget/ResizingTextEditText.java b/library/external/dialpad/src/main/java/com/android/dialer/widget/ResizingTextEditText.java index 216175981b..bb40a651ea 100644 --- a/library/external/dialpad/src/main/java/com/android/dialer/widget/ResizingTextEditText.java +++ b/library/external/dialpad/src/main/java/com/android/dialer/widget/ResizingTextEditText.java @@ -20,6 +20,7 @@ import android.content.res.TypedArray; import android.util.AttributeSet; import android.widget.EditText; + import com.android.dialer.dialpadview.R; import com.android.dialer.util.ViewUtil; diff --git a/library/external/jsonviewer/build.gradle b/library/external/jsonviewer/build.gradle index c501f583d0..22991d1a31 100644 --- a/library/external/jsonviewer/build.gradle +++ b/library/external/jsonviewer/build.gradle @@ -42,7 +42,7 @@ android { } kotlinOptions { - jvmTarget = "11" + jvmTarget = versions.jvmTarget } } diff --git a/library/external/realmfieldnameshelper/build.gradle b/library/external/realmfieldnameshelper/build.gradle index e051550210..79e66702dd 100644 --- a/library/external/realmfieldnameshelper/build.gradle +++ b/library/external/realmfieldnameshelper/build.gradle @@ -10,11 +10,11 @@ dependencies { task javadocJar(type: Jar, dependsOn: 'javadoc') { from javadoc.destinationDir - classifier = 'javadoc' + archiveClassifier = 'javadoc' } task sourcesJar(type: Jar, dependsOn: 'classes') { from sourceSets.main.allSource - classifier = 'sources' + archiveClassifier = 'sources' } sourceSets { diff --git a/library/external/span/build.gradle b/library/external/span/build.gradle index 05adbacb4d..2cf552ba7b 100644 --- a/library/external/span/build.gradle +++ b/library/external/span/build.gradle @@ -13,6 +13,15 @@ android { sourceSets { main.java.srcDirs += 'src/main/kotlin' } + + compileOptions { + sourceCompatibility versions.sourceCompat + targetCompatibility versions.targetCompat + } + + kotlinOptions { + jvmTarget = versions.jvmTarget + } } dependencies { diff --git a/library/external/textdrawable/src/main/java/com/amulyakhare/textdrawable/TextDrawable.java b/library/external/textdrawable/src/main/java/com/amulyakhare/textdrawable/TextDrawable.java index db42f8b764..c5e89b039b 100644 --- a/library/external/textdrawable/src/main/java/com/amulyakhare/textdrawable/TextDrawable.java +++ b/library/external/textdrawable/src/main/java/com/amulyakhare/textdrawable/TextDrawable.java @@ -1,6 +1,13 @@ package com.amulyakhare.textdrawable; -import android.graphics.*; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Typeface; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.shapes.OvalShape; import android.graphics.drawable.shapes.RectShape; @@ -313,4 +320,4 @@ public static interface IShapeBuilder { public TextDrawable buildRound(String text, int color); } -} \ No newline at end of file +} diff --git a/library/multipicker/build.gradle b/library/multipicker/build.gradle index c77a86a764..b4d682ff7e 100644 --- a/library/multipicker/build.gradle +++ b/library/multipicker/build.gradle @@ -43,7 +43,7 @@ android { } kotlinOptions { - jvmTarget = "11" + jvmTarget = versions.jvmTarget } } diff --git a/library/ui-strings/build.gradle b/library/ui-strings/build.gradle index b6e6de5c22..90efce02dc 100644 --- a/library/ui-strings/build.gradle +++ b/library/ui-strings/build.gradle @@ -19,7 +19,7 @@ android { } kotlinOptions { - jvmTarget = "11" + jvmTarget = versions.jvmTarget } } diff --git a/library/ui-strings/src/main/java/im/vector/lib/strings/CommonStrings.kt b/library/ui-strings/src/main/java/im/vector/lib/strings/CommonStrings.kt new file mode 100644 index 0000000000..c95209633d --- /dev/null +++ b/library/ui-strings/src/main/java/im/vector/lib/strings/CommonStrings.kt @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 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.lib.strings + +typealias CommonStrings = R.string +typealias CommonPlurals = R.plurals diff --git a/library/ui-strings/src/main/res/values-fa/strings.xml b/library/ui-strings/src/main/res/values-fa/strings.xml index 4be2e46ce7..d9e0e67c0a 100644 --- a/library/ui-strings/src/main/res/values-fa/strings.xml +++ b/library/ui-strings/src/main/res/values-fa/strings.xml @@ -1,5 +1,5 @@ - + دعوت %s ‫%1$s، %2$s را دعوت کرد %1$s دعوتتان کرد @@ -2966,4 +2966,4 @@ \n%s آغاز گپ به هر حال دعوت به هر حال - \ No newline at end of file + diff --git a/library/ui-strings/src/main/res/values-zh-rCN/strings.xml b/library/ui-strings/src/main/res/values-zh-rCN/strings.xml index 30fba77195..58000353b0 100644 --- a/library/ui-strings/src/main/res/values-zh-rCN/strings.xml +++ b/library/ui-strings/src/main/res/values-zh-rCN/strings.xml @@ -1,5 +1,5 @@ - + %s 的邀请 %1$s 邀请了 %2$s %1$s 邀请了你 @@ -2865,4 +2865,4 @@ 显示投票 切换引用 切换有序列表 - \ No newline at end of file + diff --git a/library/ui-styles/build.gradle b/library/ui-styles/build.gradle index c805153e1d..fde78695a9 100644 --- a/library/ui-styles/build.gradle +++ b/library/ui-styles/build.gradle @@ -29,7 +29,6 @@ android { targetSdk versions.targetSdk testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles "consumer-rules.pro" } buildTypes { @@ -45,7 +44,7 @@ android { } kotlinOptions { - jvmTarget = "11" + jvmTarget = versions.jvmTarget } buildFeatures { diff --git a/matrix-sdk-android-flow/build.gradle b/matrix-sdk-android-flow/build.gradle index 8b0fe5003d..8d108ec70a 100644 --- a/matrix-sdk-android-flow/build.gradle +++ b/matrix-sdk-android-flow/build.gradle @@ -28,7 +28,7 @@ android { targetCompatibility versions.targetCompat } kotlinOptions { - jvmTarget = "11" + jvmTarget = versions.jvmTarget } // publishNonDefault true diff --git a/matrix-sdk-android-flow/src/main/AndroidManifest.xml b/matrix-sdk-android-flow/src/main/AndroidManifest.xml index b2d3ea1235..8072ee00db 100644 --- a/matrix-sdk-android-flow/src/main/AndroidManifest.xml +++ b/matrix-sdk-android-flow/src/main/AndroidManifest.xml @@ -1,2 +1,2 @@ - + diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index df8551f8b3..5d1a9f1497 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -81,7 +81,7 @@ android { buildTypes { debug { if (project.hasProperty("coverage")) { - testCoverageEnabled = coverage == "true" + testCoverageEnabled = project.properties["coverage"] == "true" } // Set to true to log privacy or sensible data, such as token buildConfigField "boolean", "LOG_PRIVATE_DATA", project.property("vector.debugPrivateData") @@ -106,7 +106,7 @@ android { } kotlinOptions { - jvmTarget = "11" + jvmTarget = versions.jvmTarget freeCompilerArgs += [ // Disabled for now, there are too many errors. Could be handled in another dedicated PR // '-Xexplicit-api=strict', // or warning @@ -125,6 +125,15 @@ android { } } + buildFeatures { + buildConfig true + } + + packaging { + pickFirsts.add("META-INF/LICENSE.md") + pickFirsts.add("META-INF/LICENSE-notice.md") + pickFirsts.add("MANIFEST.MF") + } } static def gitRevision() { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt index 983e00b9ea..5cb7a30413 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt @@ -23,7 +23,6 @@ import androidx.test.internal.runner.junit4.statement.UiThreadStatement import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job import kotlinx.coroutines.cancel import kotlinx.coroutines.delay @@ -58,6 +57,7 @@ import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine +import kotlin.time.Duration.Companion.milliseconds /** * This class exposes methods to be used in common cases @@ -67,10 +67,9 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig: companion object { - @OptIn(ExperimentalCoroutinesApi::class) internal fun runSessionTest(context: Context, cryptoConfig: MXCryptoConfig? = null, autoSignoutOnClose: Boolean = true, block: suspend CoroutineScope.(CommonTestHelper) -> Unit) { val testHelper = CommonTestHelper(context, cryptoConfig) - return runTest(dispatchTimeoutMs = TestConstants.timeOutMillis) { + return runTest(timeout = TestConstants.timeOutMillis.milliseconds) { try { withContext(Dispatchers.Default) { block(testHelper) @@ -83,11 +82,10 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig: } } - @OptIn(ExperimentalCoroutinesApi::class) internal fun runCryptoTest(context: Context, cryptoConfig: MXCryptoConfig? = null, autoSignoutOnClose: Boolean = true, block: suspend CoroutineScope.(CryptoTestHelper, CommonTestHelper) -> Unit) { val testHelper = CommonTestHelper(context, cryptoConfig) val cryptoTestHelper = CryptoTestHelper(testHelper) - return runTest(dispatchTimeoutMs = TestConstants.timeOutMillis) { + return runTest(timeout = TestConstants.timeOutMillis.milliseconds) { try { withContext(Dispatchers.Default) { block(cryptoTestHelper, testHelper) @@ -100,11 +98,10 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig: } } - @OptIn(ExperimentalCoroutinesApi::class) internal fun runLongCryptoTest(context: Context, cryptoConfig: MXCryptoConfig? = null, autoSignoutOnClose: Boolean = true, block: suspend CoroutineScope.(CryptoTestHelper, CommonTestHelper) -> Unit) { val testHelper = CommonTestHelper(context, cryptoConfig) val cryptoTestHelper = CryptoTestHelper(testHelper) - return runTest(dispatchTimeoutMs = TestConstants.timeOutMillis * 4) { + return runTest(timeout = (TestConstants.timeOutMillis * 4).milliseconds) { try { withContext(Dispatchers.Default) { block(cryptoTestHelper, testHelper) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestExtensions.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestExtensions.kt index 8f89d42ac0..3202ffb2bb 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestExtensions.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestExtensions.kt @@ -37,10 +37,10 @@ suspend fun LiveData.first(timeout: Long = TestConstants.timeOutMillis, p withContext(Dispatchers.Main) { suspendCancellableCoroutine { continuation -> val observer = object : Observer { - override fun onChanged(data: T) { - if (predicate(data)) { + override fun onChanged(value: T) { + if (predicate(value)) { removeObserver(this) - continuation.resume(data) + continuation.resume(value) } } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeConfigTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeConfigTest.kt index 7979a1258d..10618eba05 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeConfigTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeConfigTest.kt @@ -26,7 +26,6 @@ import org.junit.runners.JUnit4 import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.session.crypto.MXCryptoError -import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt index 9b94553fd0..37192bd7d2 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt @@ -21,7 +21,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import junit.framework.TestCase.assertEquals import junit.framework.TestCase.assertNotNull -import junit.framework.TestCase.assertTrue import org.amshove.kluent.shouldBeEqualTo import org.junit.Assert import org.junit.Assert.assertNull diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/database/TestRealmConfigurationFactory.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/database/TestRealmConfigurationFactory.kt index fc5a017287..a769e866ce 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/database/TestRealmConfigurationFactory.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/database/TestRealmConfigurationFactory.kt @@ -27,11 +27,9 @@ import java.io.File import java.io.FileOutputStream import java.io.IOException import java.io.InputStream -import java.lang.IllegalStateException import java.util.Collections import java.util.Locale import java.util.concurrent.ConcurrentHashMap -import kotlin.Throws /** * Based on https://github.com/realm/realm-java/blob/master/realm/realm-library/src/testUtils/java/io/realm/TestRealmConfigurationFactory.java diff --git a/matrix-sdk-android/src/main/AndroidManifest.xml b/matrix-sdk-android/src/main/AndroidManifest.xml index 7f940d4e1c..bea4c15b43 100644 --- a/matrix-sdk-android/src/main/AndroidManifest.xml +++ b/matrix-sdk-android/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ - + diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/RustCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/RustCryptoStore.kt index bf9a5ebf13..6854449861 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/RustCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/RustCryptoStore.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.crypto.store import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import com.zhuinden.monarchy.Monarchy import io.realm.Realm import io.realm.RealmConfiguration @@ -280,7 +280,7 @@ internal class RustCryptoStore @Inject constructor( { entity -> myDeviceLastSeenInfoEntityMapper.map(entity) } ) - return Transformations.map(liveData) { + return liveData.map { it.firstOrNull().toOptional() } } @@ -351,7 +351,7 @@ internal class RustCryptoStore @Inject constructor( ) } ) - return Transformations.map(liveData) { + return liveData.map { it.firstOrNull() ?: GlobalCryptoConfig(false, false, false) } } @@ -372,7 +372,7 @@ internal class RustCryptoStore @Inject constructor( it.blacklistUnverifiedDevices } ) - return Transformations.map(liveData) { + return liveData.map { it.firstOrNull() ?: false } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt index fe021e76dd..9f0a7d04ac 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt @@ -84,10 +84,10 @@ internal class WorkManagerProvider @Inject constructor( workManager.enqueue(checkWorkerRequest) val checkWorkerLiveState = workManager.getWorkInfoByIdLiveData(checkWorkerRequest.id) val observer = object : Observer { - override fun onChanged(workInfo: WorkInfo?) { - if (workInfo?.state?.isFinished == true) { + override fun onChanged(value: WorkInfo) { + if (value.state.isFinished) { checkWorkerLiveState.removeObserver(this) - if (workInfo.state == WorkInfo.State.FAILED) { + if (value.state == WorkInfo.State.FAILED) { throw RuntimeException( "MatrixWorkerFactory is not being set on your worker configuration.\n" + "Makes sure to add it to a DelegatingWorkerFactory if you have your own factory or use it directly.\n" + diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/RealmContentScannerStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/RealmContentScannerStore.kt index 72dc15c1bd..05247f1539 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/RealmContentScannerStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/db/RealmContentScannerStore.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.session.contentscanner.db import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import com.zhuinden.monarchy.Monarchy import io.realm.Realm import io.realm.RealmConfiguration @@ -138,7 +138,7 @@ internal class RealmContentScannerStore @Inject constructor( entity.toModel() } ) - return Transformations.map(liveData) { + return liveData.map { it.firstOrNull().toOptional() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/HomeServerCapabilitiesDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/HomeServerCapabilitiesDataSource.kt index beb1e67e40..4d64344a24 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/HomeServerCapabilitiesDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/HomeServerCapabilitiesDataSource.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.session.homeserver import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import com.zhuinden.monarchy.Monarchy import io.realm.Realm import io.realm.kotlin.where @@ -46,7 +46,7 @@ internal class HomeServerCapabilitiesDataSource @Inject constructor( { realm: Realm -> realm.where() }, { HomeServerCapabilitiesMapper.map(it) } ) - return Transformations.map(liveData) { + return liveData.map { it.firstOrNull().toOptional() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/DefaultIdentityService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/DefaultIdentityService.kt index 30c7773a8e..391c7c1322 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/DefaultIdentityService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/DefaultIdentityService.kt @@ -84,7 +84,10 @@ internal class DefaultIdentityService @Inject constructor( private val sessionParams: SessionParams ) : IdentityService, SessionLifecycleObserver { - private val lifecycleOwner: LifecycleOwner = LifecycleOwner { lifecycleRegistry } + private val lifecycleOwner: LifecycleOwner = object : LifecycleOwner { + override val lifecycle: Lifecycle + get() = lifecycleRegistry + } private val lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(lifecycleOwner) private val listeners = mutableSetOf() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt index 7588037b46..d5cf8d6708 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt @@ -64,7 +64,10 @@ internal class IntegrationManager @Inject constructor( SessionLifecycleObserver { private val currentConfigs = ArrayList() - private val lifecycleOwner: LifecycleOwner = LifecycleOwner { lifecycleRegistry } + private val lifecycleOwner: LifecycleOwner = object : LifecycleOwner { + override val lifecycle: Lifecycle + get() = lifecycleRegistry + } private val lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(lifecycleOwner) private val listeners = HashSet() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/DefaultPushRuleService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/DefaultPushRuleService.kt index ace23f1fe5..cdbb8f16a3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/DefaultPushRuleService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushrules/DefaultPushRuleService.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.internal.session.pushrules import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import com.zhuinden.monarchy.Monarchy import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.pushrules.Action @@ -160,7 +160,7 @@ internal class DefaultPushRuleService @Inject constructor( result.pushRules.map(PushRuleEntity::ruleId).filter { !it.startsWith(".") } } ) - return Transformations.map(liveData) { results -> + return liveData.map { results -> results.firstOrNull().orEmpty().toSet() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt index 1c8b994b62..43a6adbcf7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.session.room import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import androidx.paging.PagedList import com.zhuinden.monarchy.Monarchy import org.matrix.android.sdk.api.session.events.model.Event @@ -242,7 +242,7 @@ internal class DefaultRoomService @Inject constructor( }, { it.asDomain() } ) - return Transformations.map(liveData) { results -> + return liveData.map { results -> results.firstOrNull().toOptional() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomDataSource.kt index bcbc53f95e..2ec0e73fef 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomDataSource.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.session.room import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import com.zhuinden.monarchy.Monarchy import io.realm.Realm import org.matrix.android.sdk.api.extensions.orFalse @@ -48,7 +48,7 @@ internal class RoomDataSource @Inject constructor( } ) - return Transformations.map(liveData) { results -> + return liveData.map { results -> results.firstOrNull().orFalse() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataDataSource.kt index 5196f004ea..99d68bf84f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataDataSource.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.session.room.accountdata import androidx.lifecycle.LiveData import androidx.lifecycle.MediatorLiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import com.zhuinden.monarchy.Monarchy import io.realm.Realm import io.realm.RealmQuery @@ -44,7 +44,7 @@ internal class RoomAccountDataDataSource @Inject constructor( } fun getLiveAccountDataEvent(roomId: String, type: String): LiveData> { - return Transformations.map(getLiveAccountDataEvents(roomId, setOf(type))) { + return getLiveAccountDataEvents(roomId, setOf(type)).map { it.firstOrNull().toOptional() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/draft/DraftRepository.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/draft/DraftRepository.kt index b672ef7e46..8b6ca10b12 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/draft/DraftRepository.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/draft/DraftRepository.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.session.room.draft import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import com.zhuinden.monarchy.Monarchy import io.realm.Realm import io.realm.kotlin.createObject @@ -72,7 +72,7 @@ internal class DraftRepository @Inject constructor( } } ) - return Transformations.map(liveData) { + return liveData.map { it.firstOrNull()?.firstOrNull().toOptional() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt index c36efa064f..897544b740 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.session.room.location import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import com.zhuinden.monarchy.Monarchy import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -119,13 +119,13 @@ internal class DefaultLocationSharingService @AssistedInject constructor( } override fun getLiveLocationShareSummary(beaconInfoEventId: String): LiveData> { - return Transformations.map( - monarchy.findAllMappedWithChanges( + return monarchy + .findAllMappedWithChanges( { LiveLocationShareAggregatedSummaryEntity.where(it, roomId = roomId, eventId = beaconInfoEventId) }, liveLocationShareAggregatedSummaryMapper ) - ) { - it.firstOrNull().toOptional() - } + .map { + it.firstOrNull().toOptional() + } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/DefaultRoomPushRuleService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/DefaultRoomPushRuleService.kt index d46100a3a8..31e07def63 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/DefaultRoomPushRuleService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/DefaultRoomPushRuleService.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.session.room.notification import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import com.zhuinden.monarchy.Monarchy import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -42,7 +42,7 @@ internal class DefaultRoomPushRuleService @AssistedInject constructor( } override fun getLiveRoomNotificationState(): LiveData { - return Transformations.map(getPushRuleForRoom()) { + return getPushRuleForRoom().map { it?.toRoomNotificationState() ?: RoomNotificationState.ALL_MESSAGES } } @@ -60,7 +60,7 @@ internal class DefaultRoomPushRuleService @AssistedInject constructor( result.toRoomPushRule() } ) - return Transformations.map(liveData) { results -> + return liveData.map { results -> results.firstOrNull() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/poll/DefaultPollHistoryService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/poll/DefaultPollHistoryService.kt index 28a857e6fa..90cd71d376 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/poll/DefaultPollHistoryService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/poll/DefaultPollHistoryService.kt @@ -17,7 +17,8 @@ package org.matrix.android.sdk.internal.session.room.poll import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map +import androidx.lifecycle.switchMap import com.zhuinden.monarchy.Monarchy import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -112,7 +113,7 @@ internal class DefaultPollHistoryService @AssistedInject constructor( override fun getPollEvents(): LiveData> { val pollHistoryStatusLiveData = getPollHistoryStatus() - return Transformations.switchMap(pollHistoryStatusLiveData) { results -> + return pollHistoryStatusLiveData.switchMap { results -> val oldestTimestamp = results.firstOrNull()?.oldestTimestampTargetReachedMs ?: clock.epochMillis() getPollStartEventsAfter(oldestTimestamp) } @@ -132,7 +133,7 @@ internal class DefaultPollHistoryService @AssistedInject constructor( } ) - return Transformations.map(eventsLiveData) { events -> + return eventsLiveData.map { events -> events.filter { it.root.getClearType() in EventType.POLL_START.values } .distinctBy { it.eventId } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/DefaultReadService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/DefaultReadService.kt index 73b7ae05fe..c12b622334 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/DefaultReadService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/DefaultReadService.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.session.room.read import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import com.zhuinden.monarchy.Monarchy import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -94,7 +94,7 @@ internal class DefaultReadService @AssistedInject constructor( { ReadMarkerEntity.where(it, roomId) }, { it.eventId } ) - return Transformations.map(liveRealmData) { + return liveRealmData.map { it.firstOrNull().toOptional() } } @@ -104,7 +104,7 @@ internal class DefaultReadService @AssistedInject constructor( { ReadReceiptEntity.where(it, roomId = roomId, userId = userId, threadId = threadId) }, { it.eventId } ) - return Transformations.map(liveRealmData) { + return liveRealmData.map { it.firstOrNull().toOptional() } } @@ -125,7 +125,7 @@ internal class DefaultReadService @AssistedInject constructor( { ReadReceiptsSummaryEntity.where(it, eventId) }, { readReceiptsSummaryMapper.map(it) } ) - return Transformations.map(liveRealmData) { + return liveRealmData.map { it.firstOrNull().orEmpty() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt index 190dcf7472..f89eb46a05 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.internal.session.room.relation import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import com.zhuinden.monarchy.Monarchy import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -163,7 +163,7 @@ internal class DefaultRelationService @AssistedInject constructor( { EventAnnotationsSummaryEntity.where(it, roomId, eventId) }, { it.asDomain() } ) - return Transformations.map(liveData) { results -> + return liveData.map { results -> results.firstOrNull().toOptional() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/StateEventDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/StateEventDataSource.kt index 9971ce3ccc..723d604ad4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/StateEventDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/StateEventDataSource.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.session.room.state import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import com.zhuinden.monarchy.Monarchy import io.realm.Realm import io.realm.RealmQuery @@ -52,7 +52,7 @@ internal class StateEventDataSource @Inject constructor( { realm -> buildStateEventQuery(realm, roomId, setOf(eventType), stateKey) }, { it.root?.asDomain() } ) - return Transformations.map(liveData) { results -> + return liveData.map { results -> results.firstOrNull().toOptional() } } @@ -72,7 +72,7 @@ internal class StateEventDataSource @Inject constructor( { realm -> buildStateEventQuery(realm, roomId, eventTypes, stateKey) }, { it.root?.asDomain() } ) - return Transformations.map(liveData) { results -> + return liveData.map { results -> results.filterNotNull() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt index d27fe72709..cc19b484b3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt @@ -19,7 +19,8 @@ package org.matrix.android.sdk.internal.session.room.summary import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map +import androidx.lifecycle.switchMap import androidx.paging.LivePagedListBuilder import androidx.paging.PagedList import com.zhuinden.monarchy.Monarchy @@ -84,7 +85,7 @@ internal class RoomSummaryDataSource @Inject constructor( { realm -> RoomSummaryEntity.where(realm, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) }, { roomSummaryMapper.map(it) } ) - return Transformations.map(liveData) { results -> + return liveData.map { results -> results.firstOrNull().toOptional() } } @@ -113,7 +114,7 @@ internal class RoomSummaryDataSource @Inject constructor( { realm -> LocalRoomSummaryEntity.where(realm, roomId) }, { localRoomSummaryMapper.map(it) } ) - return Transformations.map(liveData) { results -> + return liveData.map { results -> results.firstOrNull().toOptional() } } @@ -165,7 +166,7 @@ internal class RoomSummaryDataSource @Inject constructor( roomSummaryMapper.map(it) } ) - return Transformations.map(liveData) { results -> + return liveData.map { results -> results.firstOrNull().toOptional() } } @@ -292,7 +293,7 @@ internal class RoomSummaryDataSource @Inject constructor( val liveRooms = monarchy.findAllManagedWithChanges { roomSummariesQuery(it, queryParams) } - return Transformations.map(liveRooms) { + return liveRooms.map { it.realmResults.where().count().toInt() } } @@ -387,7 +388,7 @@ internal class RoomSummaryDataSource @Inject constructor( // and switch map to listen those? val mediatorLiveData = HierarchyLiveDataHelper(spaceId, memberShips, this).liveData() - return Transformations.switchMap(mediatorLiveData) { allIds -> + return mediatorLiveData.switchMap { allIds -> monarchy.findAllMappedWithChanges( { it.where() @@ -412,15 +413,16 @@ internal class RoomSummaryDataSource @Inject constructor( } fun getFlattenOrphanRoomsLive(): LiveData> { - return Transformations.map( - getRoomSummariesLive(roomSummaryQueryParams { + return getRoomSummariesLive( + roomSummaryQueryParams { memberships = Membership.activeMemberships() excludeType = listOf(RoomType.SPACE) roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS - }) - ) { - it.filter { isOrphan(it) } - } + } + ) + .map { + it.filter { isOrphan(it) } + } } private fun isOrphan(roomSummary: RoomSummary): Boolean { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserDataSource.kt index 98108008fe..316f5b9805 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserDataSource.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.session.user import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import androidx.paging.DataSource import androidx.paging.LivePagedListBuilder import androidx.paging.PagedList @@ -73,7 +73,7 @@ internal class UserDataSource @Inject constructor( { UserEntity.where(it, userId) }, { it.asDomain() } ) - return Transformations.map(liveData) { results -> + return liveData.map { results -> results.firstOrNull().toOptional() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataDataSource.kt index 01f5d9f708..a99d779ef9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataDataSource.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.session.user.accountdata import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import com.zhuinden.monarchy.Monarchy import io.realm.Realm import io.realm.RealmQuery @@ -42,7 +42,7 @@ internal class UserAccountDataDataSource @Inject constructor( } fun getLiveAccountDataEvent(type: String): LiveData> { - return Transformations.map(getLiveAccountDataEvents(setOf(type))) { + return getLiveAccountDataEvents(setOf(type)).map { it.firstOrNull().toOptional() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt index 37a329af34..7359fdbd91 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt @@ -20,7 +20,7 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.map import org.matrix.android.sdk.api.query.QueryStateEventValue import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.Session @@ -57,7 +57,10 @@ internal class WidgetManager @Inject constructor( IntegrationManagerService.Listener, SessionLifecycleObserver { - private val lifecycleOwner: LifecycleOwner = LifecycleOwner { lifecycleRegistry } + private val lifecycleOwner: LifecycleOwner = object : LifecycleOwner { + override val lifecycle: Lifecycle + get() = lifecycleRegistry + } private val lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(lifecycleOwner) override fun onSessionStarted(session: Session) { @@ -82,7 +85,7 @@ internal class WidgetManager @Inject constructor( eventTypes = setOf(EventType.STATE_ROOM_WIDGET, EventType.STATE_ROOM_WIDGET_LEGACY), stateKey = widgetId ) - return Transformations.map(liveWidgetEvents) { widgetEvents -> + return liveWidgetEvents.map { widgetEvents -> widgetEvents.mapEventsToWidgets(widgetTypes, excludedTypes) } } @@ -141,7 +144,7 @@ internal class WidgetManager @Inject constructor( excludedTypes: Set? = null ): LiveData> { val widgetsAccountData = userAccountDataDataSource.getLiveAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS) - return Transformations.map(widgetsAccountData) { + return widgetsAccountData.map { it.getOrNull()?.mapToWidgets(widgetTypes, excludedTypes).orEmpty() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/LruCache.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/LruCache.kt index 0998601db6..cd5164d8a2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/LruCache.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/LruCache.kt @@ -19,6 +19,6 @@ package org.matrix.android.sdk.internal.util import androidx.collection.LruCache @Suppress("NULLABLE_TYPE_PARAMETER_AGAINST_NOT_NULL_TYPE_PARAMETER") -internal inline fun LruCache.getOrPut(key: K, defaultValue: () -> V): V { +internal inline fun LruCache.getOrPut(key: K, defaultValue: () -> V): V { return get(key) ?: defaultValue().also { put(key, it) } } diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/network/ComputeUserAgentUseCaseTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/network/ComputeUserAgentUseCaseTest.kt index 2170371cde..174806bb11 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/network/ComputeUserAgentUseCaseTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/network/ComputeUserAgentUseCaseTest.kt @@ -29,7 +29,6 @@ import org.junit.Test import org.matrix.android.sdk.BuildConfig import org.matrix.android.sdk.api.util.getApplicationInfoCompat import org.matrix.android.sdk.api.util.getPackageInfoCompat -import java.lang.Exception private const val A_PACKAGE_NAME = "org.matrix.sdk" private const val AN_APP_NAME = "Element" diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingServiceTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingServiceTest.kt index 5c27562c9c..660fb1411b 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingServiceTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingServiceTest.kt @@ -16,17 +16,12 @@ package org.matrix.android.sdk.internal.session.room.location -import androidx.arch.core.util.Function -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.Transformations import io.mockk.coEvery import io.mockk.coVerify -import io.mockk.every import io.mockk.just import io.mockk.mockk import io.mockk.mockkStatic import io.mockk.runs -import io.mockk.slot import io.mockk.unmockkAll import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest @@ -37,7 +32,6 @@ import org.junit.Test import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary import org.matrix.android.sdk.api.util.Cancelable -import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.toOptional import org.matrix.android.sdk.internal.database.mapper.LiveLocationShareAggregatedSummaryMapper import org.matrix.android.sdk.internal.database.model.livelocation.LiveLocationShareAggregatedSummaryEntity @@ -262,25 +256,14 @@ internal class DefaultLocationSharingServiceTest { endOfLiveTimestampMillis = 123, lastLocationDataContent = null ) - fakeMonarchy.givenWhere() .givenEqualTo(LiveLocationShareAggregatedSummaryEntityFields.ROOM_ID, A_ROOM_ID) .givenEqualTo(LiveLocationShareAggregatedSummaryEntityFields.EVENT_ID, AN_EVENT_ID) - val liveData = fakeMonarchy.givenFindAllMappedWithChangesReturns( + fakeMonarchy.givenFindAllMappedWithChangesReturns( realmEntities = listOf(entity), mappedResult = listOf(summary), fakeLiveLocationShareAggregatedSummaryMapper ) - val mapper = slot, Optional>>() - every { - Transformations.map( - liveData, - capture(mapper) - ) - } answers { - val value = secondArg, Optional>>().apply(listOf(summary)) - MutableLiveData(value) - } val result = defaultLocationSharingService.getLiveLocationShareSummary(AN_EVENT_ID).value diff --git a/tools/import_emojis.py b/tools/import_emojis.py index 66bcd45015..97e9d02534 100755 --- a/tools/import_emojis.py +++ b/tools/import_emojis.py @@ -1,11 +1,10 @@ #!/usr/bin/env python3 -from collections import OrderedDict - -import requests import json -import re import os +import re +import requests from bs4 import BeautifulSoup +from collections import OrderedDict # A list of words to not capitalize in emoji-names capitalization_exclude = {'with', 'a', 'at', 'of', 'for', 'and', 'over', 'the', 'off', 'on', 'out', 'in', 'but', 'or'} diff --git a/tools/lint/lint.xml b/tools/lint/lint.xml index 467b32bacd..1cb3b8d442 100644 --- a/tools/lint/lint.xml +++ b/tools/lint/lint.xml @@ -11,7 +11,7 @@ - + diff --git a/tools/release/download_github_artifacts.py b/tools/release/download_github_artifacts.py index 8bc0c2d9c9..fddc120762 100755 --- a/tools/release/download_github_artifacts.py +++ b/tools/release/download_github_artifacts.py @@ -18,10 +18,10 @@ import argparse import json import os -# Run `pip3 install requests` if not installed yet -import requests # Run `pip3 install re` if not installed yet import re +# Run `pip3 install requests` if not installed yet +import requests # This script downloads artifacts from GitHub. # Ref: https://docs.github.com/en/rest/actions/artifacts#get-an-artifact diff --git a/vector-app/build.gradle b/vector-app/build.gradle index f6113744d6..342930c44f 100644 --- a/vector-app/build.gradle +++ b/vector-app/build.gradle @@ -250,7 +250,7 @@ android { resValue "string", "app_name", "Element - dbg" if (project.hasProperty("coverage")) { - testCoverageEnabled = coverage == "true" + testCoverageEnabled = project.coverage == "true" } } @@ -342,7 +342,7 @@ android { } } - lintOptions { + lint { lintConfig file("../tools/lint/lint.xml") checkDependencies true @@ -355,7 +355,7 @@ android { } kotlinOptions { - jvmTarget = "11" + jvmTarget = versions.jvmTarget freeCompilerArgs += [ "-opt-in=kotlin.RequiresOptIn", // Fixes false positive "This is an internal Mavericks API. It is not intended for external use." @@ -370,6 +370,7 @@ android { buildFeatures { viewBinding true + buildConfig true } } @@ -377,6 +378,7 @@ dependencies { implementation project(':vector') implementation project(':vector-config') implementation project(':library:core-utils') + implementation project(':library:ui-strings') debugImplementation project(':library:external:span') debugImplementation project(':library:ui-styles') implementation libs.dagger.hilt @@ -393,7 +395,7 @@ dependencies { debugImplementation 'com.facebook.soloader:soloader:0.10.5' debugImplementation "com.kgurgul.flipper:flipper-realm-android:2.2.0" - gplayImplementation "com.google.android.gms:play-services-location:21.0.1" + gplayImplementation "com.google.android.gms:play-services-location:21.3.0" // UnifiedPush gplay flavor only gplayImplementation platform(libs.google.firebaseBom) gplayImplementation(libs.google.messaging) { @@ -409,7 +411,7 @@ dependencies { nightlyImplementation libs.google.appdistribution // OSS License, gplay flavor only - gplayImplementation 'com.google.android.gms:play-services-oss-licenses:17.0.1' + gplayImplementation 'com.google.android.gms:play-services-oss-licenses:17.1.0' kapt libs.dagger.hiltCompiler ksp libs.airbnb.epoxyProcessor diff --git a/vector-app/proguard-rules.pro b/vector-app/proguard-rules.pro index 57559bf7b4..6e8afc44e3 100644 --- a/vector-app/proguard-rules.pro +++ b/vector-app/proguard-rules.pro @@ -80,3 +80,16 @@ # JNA -keep class com.sun.jna.** { *; } -keep class * implements com.sun.jna.** { *; } + +# New +-dontwarn com.google.appengine.api.urlfetch.** +-dontwarn com.google.common.io.LimitInputStream +-dontwarn com.google.firebase.analytics.connector.AnalyticsConnector +-dontwarn com.google.javascript.jscomp.** +-dontwarn com.likethesalad.android.templates.provider.api.TemplatesProvider +-dontwarn com.yahoo.platform.yui.compressor.** +-dontwarn java.awt.** +-dontwarn org.apache.velocity.** +-dontwarn org.commonmark.ext.gfm.strikethrough.Strikethrough +-dontwarn org.mozilla.javascript.** +-dontwarn org.slf4j.** diff --git a/vector-app/src/androidTest/java/im/vector/app/CantVerifyTest.kt b/vector-app/src/androidTest/java/im/vector/app/CantVerifyTest.kt index 6f9d6cdde9..506842f845 100644 --- a/vector-app/src/androidTest/java/im/vector/app/CantVerifyTest.kt +++ b/vector-app/src/androidTest/java/im/vector/app/CantVerifyTest.kt @@ -26,6 +26,7 @@ import androidx.test.filters.LargeTest import com.adevinta.android.barista.internal.viewaction.SleepViewAction import im.vector.app.features.MainActivity import im.vector.app.ui.robot.ElementRobot +import im.vector.lib.strings.CommonStrings import org.junit.Rule import org.junit.Test import org.junit.rules.RuleChain @@ -61,7 +62,7 @@ class CantVerifyTest { val activity = EspressoHelper.getCurrentActivity()!! Espresso.onView(ViewMatchers.isRoot()) - .perform(waitForView(ViewMatchers.withText(R.string.crosssigning_cannot_verify_this_session))) + .perform(waitForView(ViewMatchers.withText(CommonStrings.crosssigning_cannot_verify_this_session))) // check that the text is correct val popup = activity.findViewById(com.tapadoo.alerter.R.id.llAlertBackground)!! @@ -73,7 +74,7 @@ class CantVerifyTest { Espresso.onView(ViewMatchers.isRoot()).perform(SleepViewAction.sleep(2000)) - Espresso.onView(ViewMatchers.withText(R.string.bottom_sheet_setup_secure_backup_title)) + Espresso.onView(ViewMatchers.withText(CommonStrings.bottom_sheet_setup_secure_backup_title)) .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) } } diff --git a/vector-app/src/androidTest/java/im/vector/app/RegistrationTest.kt b/vector-app/src/androidTest/java/im/vector/app/RegistrationTest.kt index 68a4d27deb..0b5af5b432 100644 --- a/vector-app/src/androidTest/java/im/vector/app/RegistrationTest.kt +++ b/vector-app/src/androidTest/java/im/vector/app/RegistrationTest.kt @@ -31,6 +31,7 @@ import androidx.test.filters.LargeTest import im.vector.app.features.MainActivity import im.vector.app.features.analytics.ui.consent.AnalyticsOptInActivity import im.vector.app.features.home.HomeActivity +import im.vector.lib.strings.CommonStrings import org.hamcrest.CoreMatchers.not import org.junit.Ignore import org.junit.Rule @@ -55,7 +56,7 @@ class RegistrationTest { // Check splashscreen is there onView(withId(R.id.loginSplashSubmit)) .check(matches(isDisplayed())) - .check(matches(withText(R.string.login_splash_submit))) + .check(matches(withText(CommonStrings.login_splash_submit))) // Click on get started onView(withId(R.id.loginSplashSubmit)) @@ -64,7 +65,7 @@ class RegistrationTest { // Check that homeserver options are shown onView(withId(R.id.loginServerTitle)) .check(matches(isDisplayed())) - .check(matches(withText(R.string.login_server_title))) + .check(matches(withText(CommonStrings.login_server_title))) // Chose custom server onView(withId(R.id.loginServerChoiceOther)) diff --git a/vector-app/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt b/vector-app/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt index e5286e43ea..d7deeebbd8 100644 --- a/vector-app/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt +++ b/vector-app/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt @@ -42,6 +42,7 @@ import im.vector.app.core.utils.getMatrixInstance import im.vector.app.features.MainActivity import im.vector.app.features.crypto.recover.SetupMode import im.vector.app.features.home.HomeActivity +import im.vector.lib.strings.CommonStrings import org.hamcrest.CoreMatchers.not import org.junit.Before import org.junit.Ignore @@ -109,7 +110,7 @@ class SecurityBootstrapTest : VerificationTestBase() { .perform(click()) onView(isRoot()) - .perform(waitForView(withText(R.string.bootstrap_info_text_2))) + .perform(waitForView(withText(CommonStrings.bootstrap_info_text_2))) // test back onView(isRoot()).perform(pressBack()) @@ -124,7 +125,7 @@ class SecurityBootstrapTest : VerificationTestBase() { .perform(click()) onView(isRoot()) - .perform(waitForView(withText(R.string.bootstrap_info_text_2))) + .perform(waitForView(withText(CommonStrings.bootstrap_info_text_2))) onView(withId(R.id.ssss_passphrase_enter_edittext)) .perform(typeText("person woman man camera tv")) @@ -139,7 +140,7 @@ class SecurityBootstrapTest : VerificationTestBase() { onView(withId(R.id.bootstrapSubmit)) .perform(closeSoftKeyboard(), click()) - onView(withText(R.string.passphrase_passphrase_does_not_match)).check(matches(isDisplayed())) + onView(withText(CommonStrings.passphrase_passphrase_does_not_match)).check(matches(isDisplayed())) onView(withId(R.id.ssss_passphrase_enter_edittext)) .perform(replaceText("person woman man camera tv")) @@ -148,7 +149,7 @@ class SecurityBootstrapTest : VerificationTestBase() { .perform(closeSoftKeyboard(), click()) onView(withId(R.id.bottomSheetScrollView)) - .perform(waitForView(withText(R.string.bottom_sheet_save_your_recovery_key_content))) + .perform(waitForView(withText(CommonStrings.bottom_sheet_save_your_recovery_key_content))) intending(hasAction(Intent.ACTION_SEND)).respondWith(ActivityResult(Activity.RESULT_OK, null)) @@ -156,12 +157,12 @@ class SecurityBootstrapTest : VerificationTestBase() { .perform(click()) // Dismiss dialog - onView(withText(R.string.ok)).inRoot(RootMatchers.isDialog()).perform(click()) + onView(withText(CommonStrings.ok)).inRoot(RootMatchers.isDialog()).perform(click()) onView(withId(R.id.bottomSheetScrollView)) - .perform(waitForView(withText(R.string.bottom_sheet_save_your_recovery_key_content))) + .perform(waitForView(withText(CommonStrings.bottom_sheet_save_your_recovery_key_content))) - onView(withText(R.string._continue)).perform(click()) + onView(withText(CommonStrings._continue)).perform(click()) // Assert that all is configured val crossSigningInitialized = runBlockingTest { diff --git a/vector-app/src/androidTest/java/im/vector/app/VerificationTestBase.kt b/vector-app/src/androidTest/java/im/vector/app/VerificationTestBase.kt index 48549a93dd..8cdbfb830f 100644 --- a/vector-app/src/androidTest/java/im/vector/app/VerificationTestBase.kt +++ b/vector-app/src/androidTest/java/im/vector/app/VerificationTestBase.kt @@ -27,6 +27,7 @@ import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.features.home.HomeActivity import im.vector.app.ui.robot.AnalyticsRobot import im.vector.app.ui.robot.OnboardingRobot +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DelicateCoroutinesApi @@ -184,18 +185,18 @@ abstract class VerificationTestBase { Espresso.onView(ViewMatchers.isRoot()) .perform(waitForView(ViewMatchers.withId(R.id.bottomSheetFragmentContainer))) - Espresso.onView(ViewMatchers.withText(R.string.verification_verify_identity)) + Espresso.onView(ViewMatchers.withText(CommonStrings.verification_verify_identity)) .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) // 4S is not setup so passphrase option should be hidden Espresso.onView(ViewMatchers.withId(R.id.bottomSheetVerificationRecyclerView)) - .check(ViewAssertions.matches(CoreMatchers.not(ViewMatchers.hasDescendant(ViewMatchers.withText(R.string.verification_cannot_access_other_session))))) + .check(ViewAssertions.matches(CoreMatchers.not(ViewMatchers.hasDescendant(ViewMatchers.withText(CommonStrings.verification_cannot_access_other_session))))) Espresso.onView(ViewMatchers.withId(R.id.bottomSheetVerificationRecyclerView)) - .check(ViewAssertions.matches(ViewMatchers.hasDescendant(ViewMatchers.withText(R.string.verification_verify_with_another_device)))) + .check(ViewAssertions.matches(ViewMatchers.hasDescendant(ViewMatchers.withText(CommonStrings.verification_verify_with_another_device)))) Espresso.onView(ViewMatchers.withId(R.id.bottomSheetVerificationRecyclerView)) - .check(ViewAssertions.matches(ViewMatchers.hasDescendant(ViewMatchers.withText(R.string.bad_passphrase_key_reset_all_action)))) + .check(ViewAssertions.matches(ViewMatchers.hasDescendant(ViewMatchers.withText(CommonStrings.bad_passphrase_key_reset_all_action)))) return uiSession } diff --git a/vector-app/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt b/vector-app/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt index 72892112dd..c9b8857ed8 100644 --- a/vector-app/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt +++ b/vector-app/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt @@ -31,6 +31,7 @@ import androidx.test.filters.LargeTest import im.vector.app.core.utils.getMatrixInstance import im.vector.app.features.MainActivity import im.vector.app.ui.robot.ElementRobot +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.test.runTest import org.amshove.kluent.internal.assertEquals import org.junit.After @@ -117,13 +118,13 @@ class VerifySessionInteractiveTest : VerificationTestBase() { onView(withId(R.id.bottomSheetVerificationRecyclerView)) .perform( actionOnItem( - hasDescendant(withText(R.string.verification_verify_with_another_device)), + hasDescendant(withText(CommonStrings.verification_verify_with_another_device)), click() ) ) onView(withId(R.id.bottomSheetVerificationRecyclerView)) - .check(matches(hasDescendant(withText(R.string.verification_request_was_sent)))) + .check(matches(hasDescendant(withText(CommonStrings.verification_request_was_sent)))) val txId = runBlockingTest { otherRequest.await().transactionId @@ -139,9 +140,9 @@ class VerifySessionInteractiveTest : VerificationTestBase() { } onView(withId(R.id.bottomSheetVerificationRecyclerView)) - .perform(waitForView(hasDescendant(withText(R.string.verification_scan_self_notice)))) + .perform(waitForView(hasDescendant(withText(CommonStrings.verification_scan_self_notice)))) onView(withId(R.id.bottomSheetVerificationRecyclerView)) - .perform(waitForView(hasDescendant(withText(R.string.verification_scan_self_emoji_subtitle)))) + .perform(waitForView(hasDescendant(withText(CommonStrings.verification_scan_self_emoji_subtitle)))) // there should be the QR code also onView(withId(R.id.bottomSheetVerificationRecyclerView)) @@ -151,16 +152,16 @@ class VerifySessionInteractiveTest : VerificationTestBase() { onView(withId(R.id.bottomSheetVerificationRecyclerView)) .perform( actionOnItem( - hasDescendant(withText(R.string.verification_scan_self_emoji_subtitle)), + hasDescendant(withText(CommonStrings.verification_scan_self_emoji_subtitle)), click() ) ) onView(withId(R.id.bottomSheetVerificationRecyclerView)) - .perform(waitForView(hasDescendant(withText(R.string.verification_sas_do_not_match)))) + .perform(waitForView(hasDescendant(withText(CommonStrings.verification_sas_do_not_match)))) onView(withId(R.id.bottomSheetVerificationRecyclerView)) - .perform(waitForView(hasDescendant(withText(R.string.verification_sas_match)))) + .perform(waitForView(hasDescendant(withText(CommonStrings.verification_sas_match)))) // check that the code matches val uiCode = runBlockingTest { @@ -190,19 +191,19 @@ class VerifySessionInteractiveTest : VerificationTestBase() { onView(withId(R.id.bottomSheetVerificationRecyclerView)) .perform( actionOnItem( - hasDescendant(withText(R.string.verification_sas_match)), + hasDescendant(withText(CommonStrings.verification_sas_match)), click() ) ) onView(withId(R.id.bottomSheetVerificationRecyclerView)) - .perform(waitForView(hasDescendant(withText(R.string.verification_conclusion_ok_notice)))) + .perform(waitForView(hasDescendant(withText(CommonStrings.verification_conclusion_ok_notice)))) // click on done onView(withId(R.id.bottomSheetVerificationRecyclerView)) .perform( actionOnItem( - hasDescendant(withText(R.string.done)), + hasDescendant(withText(CommonStrings.done)), click() ) ) diff --git a/vector-app/src/androidTest/java/im/vector/app/VerifySessionNavigationTest.kt b/vector-app/src/androidTest/java/im/vector/app/VerifySessionNavigationTest.kt index 2bb37e4711..496c8bab8e 100644 --- a/vector-app/src/androidTest/java/im/vector/app/VerifySessionNavigationTest.kt +++ b/vector-app/src/androidTest/java/im/vector/app/VerifySessionNavigationTest.kt @@ -31,6 +31,7 @@ import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.features.MainActivity import im.vector.app.features.home.HomeActivity import im.vector.app.ui.robot.ElementRobot +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.test.runTest import org.junit.After import org.junit.Before @@ -102,13 +103,13 @@ class VerifySessionNavigationTest : VerificationTestBase() { Espresso.onView(ViewMatchers.withId(R.id.bottomSheetVerificationRecyclerView)) .perform( RecyclerViewActions.actionOnItem( - ViewMatchers.hasDescendant(ViewMatchers.withText(R.string.verification_verify_with_another_device)), + ViewMatchers.hasDescendant(ViewMatchers.withText(CommonStrings.verification_verify_with_another_device)), ViewActions.click() ) ) Espresso.onView(ViewMatchers.withId(R.id.bottomSheetVerificationRecyclerView)) - .check(ViewAssertions.matches(ViewMatchers.hasDescendant(ViewMatchers.withText(R.string.verification_request_was_sent)))) + .check(ViewAssertions.matches(ViewMatchers.hasDescendant(ViewMatchers.withText(CommonStrings.verification_request_was_sent)))) val txId = runBlockingTest { otherRequest.await().transactionId @@ -127,7 +128,7 @@ class VerifySessionNavigationTest : VerificationTestBase() { .perform(waitForView(ViewMatchers.withId(R.id.bottomSheetFragmentContainer))) Espresso.onView(ViewMatchers.withId(R.id.bottomSheetVerificationRecyclerView)) - .check(ViewAssertions.matches(ViewMatchers.hasDescendant(ViewMatchers.withText(R.string.verification_verify_with_another_device)))) + .check(ViewAssertions.matches(ViewMatchers.hasDescendant(ViewMatchers.withText(CommonStrings.verification_verify_with_another_device)))) runBlockingTest { otherGetCancelledRequest.await() diff --git a/vector-app/src/androidTest/java/im/vector/app/VerifySessionPassphraseTest.kt b/vector-app/src/androidTest/java/im/vector/app/VerifySessionPassphraseTest.kt index f54d619772..cf3f056276 100644 --- a/vector-app/src/androidTest/java/im/vector/app/VerifySessionPassphraseTest.kt +++ b/vector-app/src/androidTest/java/im/vector/app/VerifySessionPassphraseTest.kt @@ -43,6 +43,7 @@ import im.vector.app.features.crypto.recover.Params import im.vector.app.features.crypto.recover.SetupMode import im.vector.app.features.home.HomeActivity import im.vector.app.ui.robot.AnalyticsRobot +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.runBlocking import org.junit.Before import org.junit.Ignore @@ -148,17 +149,17 @@ class VerifySessionPassphraseTest : VerificationTestBase() { onView(isRoot()) .perform(waitForView(withId(R.id.bottomSheetFragmentContainer))) - onView(withText(R.string.verification_verify_identity)) + onView(withText(CommonStrings.verification_verify_identity)) .check(matches(isDisplayed())) // 4S is setup so passphrase option should be visible onView(withId(R.id.bottomSheetVerificationRecyclerView)) - .check(matches((hasDescendant(withText(R.string.verification_cannot_access_other_session))))) + .check(matches((hasDescendant(withText(CommonStrings.verification_cannot_access_other_session))))) onView(withId(R.id.bottomSheetVerificationRecyclerView)) .perform( actionOnItem( - hasDescendant(withText(R.string.verification_cannot_access_other_session)), + hasDescendant(withText(CommonStrings.verification_cannot_access_other_session)), click() ) ) @@ -178,14 +179,14 @@ class VerifySessionPassphraseTest : VerificationTestBase() { withIdlingResource(activityIdlingResource(HomeActivity::class.java)) { System.out.println("*** passphrase 1.1") onView(withId(R.id.bottomSheetVerificationRecyclerView)) - .perform(waitForView(hasDescendant(withText(R.string.verification_conclusion_ok_notice)))) + .perform(waitForView(hasDescendant(withText(CommonStrings.verification_conclusion_ok_notice)))) } // click on done onView(withId(R.id.bottomSheetVerificationRecyclerView)) .perform( actionOnItem( - hasDescendant(withText(R.string.done)), + hasDescendant(withText(CommonStrings.done)), click() ) ) diff --git a/vector-app/src/androidTest/java/im/vector/app/espresso/tools/EspressoPreference.kt b/vector-app/src/androidTest/java/im/vector/app/espresso/tools/EspressoPreference.kt index 19dc1d391c..6b2116dda4 100644 --- a/vector-app/src/androidTest/java/im/vector/app/espresso/tools/EspressoPreference.kt +++ b/vector-app/src/androidTest/java/im/vector/app/espresso/tools/EspressoPreference.kt @@ -30,13 +30,12 @@ import androidx.test.espresso.matcher.ViewMatchers.isFocusable import androidx.test.espresso.matcher.ViewMatchers.withClassName import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText -import im.vector.app.R import org.hamcrest.Matchers.allOf import org.hamcrest.Matchers.instanceOf import org.hamcrest.Matchers.`is` fun clickOnPreference(@StringRes textResId: Int) { - onView(withId(R.id.recycler_view)) + onView(withId(androidx.preference.R.id.recycler_view)) .perform( actionOnItem( allOf( diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt b/vector-app/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt index 3439bcfced..2e22dfc289 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt @@ -23,13 +23,13 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.GrantPermissionRule -import im.vector.app.R import im.vector.app.espresso.tools.ScreenshotFailureRule import im.vector.app.features.MainActivity import im.vector.app.getString import im.vector.app.ui.robot.ElementRobot import im.vector.app.ui.robot.settings.labs.LabFeaturesPreferences import im.vector.app.ui.robot.withDeveloperMode +import im.vector.lib.strings.CommonStrings import org.junit.Rule import org.junit.Test import org.junit.rules.RuleChain @@ -55,7 +55,7 @@ class UiAllScreensSanityTest { InstrumentationRegistry.getInstrumentation() .targetContext .resources - .getBoolean(R.bool.settings_labs_new_app_layout_default) + .getBoolean(im.vector.app.config.R.bool.settings_labs_new_app_layout_default) ) ) @@ -151,7 +151,7 @@ class UiAllScreensSanityTest { advancedSettings { crawlDeveloperOptions() } } roomList { - openRoom(getString(R.string.room_displayname_empty_room)) { + openRoom(getString(CommonStrings.room_displayname_empty_room)) { val message = "Test view source" postMessage(message) openMessageMenu(message) { diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/AnalyticsRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/AnalyticsRobot.kt index 86b110ce87..a4d1c02ef8 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/AnalyticsRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/AnalyticsRobot.kt @@ -23,6 +23,7 @@ import im.vector.app.R import im.vector.app.espresso.tools.waitUntilActivityVisible import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.features.analytics.ui.consent.AnalyticsOptInActivity +import im.vector.lib.strings.CommonStrings class AnalyticsRobot { @@ -38,7 +39,7 @@ class AnalyticsRobot { waitUntilActivityVisible { waitUntilViewVisible(withId(R.id.title)) } - assertDisplayed(R.id.title, R.string.analytics_opt_in_title) + assertDisplayed(R.id.title, CommonStrings.analytics_opt_in_title) if (optIn) { clickOn(R.id.submit) } else { diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt index 854dd0ce0f..a336e3ceef 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt @@ -29,6 +29,7 @@ import im.vector.app.R import im.vector.app.espresso.tools.waitUntilActivityVisible import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.features.home.room.detail.RoomDetailActivity +import im.vector.lib.strings.CommonStrings import org.hamcrest.CoreMatchers.allOf class CreateNewRoomRobot( @@ -39,7 +40,7 @@ class CreateNewRoomRobot( createdRoom = true BaristaListAssertions.assertListItemCount(R.id.createRoomForm, 12) roomName?.let { - onView(allOf(withId(R.id.formTextInputTextInputEditText), withHint(R.string.create_room_name_hint))) + onView(allOf(withId(R.id.formTextInputTextInputEditText), withHint(CommonStrings.create_room_name_hint))) .perform(replaceText(roomName)) closeSoftKeyboard() } @@ -53,7 +54,7 @@ class CreateNewRoomRobot( fun crawl() { // Room access bottom sheet - BaristaClickInteractions.clickOn(R.string.room_settings_room_access_private_title) + BaristaClickInteractions.clickOn(CommonStrings.room_settings_room_access_private_title) pressBack() } } diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt index 8f1df52863..506477b959 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt @@ -49,6 +49,7 @@ import im.vector.app.ui.robot.settings.labs.LabFeature import im.vector.app.ui.robot.settings.labs.LabFeaturesPreferences import im.vector.app.ui.robot.space.SpaceRobot import im.vector.app.withIdlingResource +import im.vector.lib.strings.CommonStrings import timber.log.Timber class ElementRobot( @@ -100,7 +101,7 @@ class ElementRobot( openActionBarOverflowOrOptionsMenu( ApplicationProvider.getApplicationContext() ) - clickOn(R.string.home_layout_preferences) + clickOn(CommonStrings.home_layout_preferences) waitUntilDialogVisible(withId(R.id.home_layout_settings_recents)) block(LayoutPreferencesRobot()) @@ -149,7 +150,7 @@ class ElementRobot( LabFeature.THREAD_MESSAGES -> { settings(shouldGoBack = false) { labs(shouldGoBack = false) { - onView(withText(R.string.labs_enable_thread_messages)) + onView(withText(CommonStrings.labs_enable_thread_messages)) .check(ViewAssertions.matches(isDisplayed())) .perform(ViewActions.closeSoftKeyboard(), click()) } @@ -185,9 +186,9 @@ class ElementRobot( onView(withId((R.id.avatar))) .perform(click()) waitUntilActivityVisible { - clickOn(R.string.settings_general_title) + clickOn(CommonStrings.settings_general_title) } - clickOnPreference(R.string.action_sign_out) + clickOnPreference(CommonStrings.action_sign_out) } else { clickOn(R.id.groupToolbarAvatarImageView) clickOn(R.id.homeDrawerHeaderSignoutView) diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt index 01a9ec02dc..2ab35c9fbd 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt @@ -29,6 +29,7 @@ import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet import im.vector.app.features.reactions.EmojiReactionPickerActivity import im.vector.app.interactWithSheet +import im.vector.lib.strings.CommonStrings import java.lang.Thread.sleep class MessageMenuRobot( @@ -36,7 +37,7 @@ class MessageMenuRobot( ) { fun viewSource() { - clickOn(R.string.view_source) + clickOn(CommonStrings.view_source) // wait for library sleep(1000) pressBack() @@ -44,8 +45,8 @@ class MessageMenuRobot( } fun editHistory() { - clickOn(R.string.message_view_edit_history) - interactWithSheet(withText(R.string.message_edits), openState = BottomSheetBehavior.STATE_COLLAPSED) { + clickOn(CommonStrings.message_view_edit_history) + interactWithSheet(withText(CommonStrings.message_edits), openState = BottomSheetBehavior.STATE_COLLAPSED) { pressBack() } autoClosed = true @@ -57,7 +58,7 @@ class MessageMenuRobot( } fun addReactionFromEmojiPicker() { - clickOn(R.string.message_add_reaction) + clickOn(CommonStrings.message_add_reaction) // Wait for emoji to load, it's async now waitUntilActivityVisible { closeSoftKeyboard() @@ -69,17 +70,17 @@ class MessageMenuRobot( } fun edit() { - clickOn(R.string.edit) + clickOn(CommonStrings.edit) autoClosed = true } fun replyInThread() { - clickOn(R.string.reply_in_thread) + clickOn(CommonStrings.reply_in_thread) autoClosed = true } fun viewInRoom() { - clickOn(R.string.view_in_room) + clickOn(CommonStrings.view_in_room) autoClosed = true } } diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/NewDirectMessageRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/NewDirectMessageRobot.kt index 34c43c73f7..3a8d0db27d 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/NewDirectMessageRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/NewDirectMessageRobot.kt @@ -20,16 +20,17 @@ import androidx.test.espresso.Espresso import androidx.test.espresso.matcher.ViewMatchers import im.vector.app.R import im.vector.app.waitForView +import im.vector.lib.strings.CommonStrings class NewDirectMessageRobot { fun verifyQrCodeButton() { Espresso.onView(ViewMatchers.withId(R.id.userListRecyclerView)) - .perform(waitForView(ViewMatchers.withText(R.string.qr_code))) + .perform(waitForView(ViewMatchers.withText(CommonStrings.qr_code))) } fun verifyInviteFriendsButton() { Espresso.onView(ViewMatchers.withId(R.id.userListRecyclerView)) - .perform(waitForView(ViewMatchers.withText(R.string.invite_friends))) + .perform(waitForView(ViewMatchers.withText(CommonStrings.invite_friends))) } } diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/NewRoomRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/NewRoomRobot.kt index 0cea26d5cc..525dd06cd1 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/NewRoomRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/NewRoomRobot.kt @@ -24,6 +24,7 @@ import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.features.DefaultVectorFeatures import im.vector.app.features.VectorFeatures import im.vector.app.ui.robot.settings.labs.LabFeaturesPreferences +import im.vector.lib.strings.CommonStrings class NewRoomRobot( var createdRoom: Boolean = false, @@ -32,7 +33,7 @@ class NewRoomRobot( private val features: VectorFeatures = DefaultVectorFeatures() fun createNewRoom(block: CreateNewRoomRobot.() -> Unit) { - clickOn(R.string.create_new_room) + clickOn(CommonStrings.create_new_room) waitUntilViewVisible(withId(R.id.createRoomForm)) val createNewRoomRobot = CreateNewRoomRobot() block(createNewRoomRobot) diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt index 72abbbf804..70894f9700 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt @@ -31,6 +31,7 @@ import im.vector.app.R import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.features.DefaultVectorFeatures import im.vector.app.waitForView +import im.vector.lib.strings.CommonStrings class OnboardingRobot { private val defaultVectorFeatures = DefaultVectorFeatures() @@ -46,7 +47,7 @@ class OnboardingRobot { // TODO https://github.com/element-hq/element-android/issues/6652 } else { clickOn(R.id.loginSplashSubmit) - assertDisplayed(R.id.useCaseHeaderTitle, R.string.ftue_auth_use_case_title) + assertDisplayed(R.id.useCaseHeaderTitle, CommonStrings.ftue_auth_use_case_title) clickOn(R.id.useCaseOptionOne) OnboardingServersRobot().crawlSignUp() pressBack() @@ -71,27 +72,27 @@ class OnboardingRobot { initSession(true, userId, password, homeServerUrl) } - waitUntilViewVisible(withText(R.string.ftue_account_created_congratulations_title)) + waitUntilViewVisible(withText(CommonStrings.ftue_account_created_congratulations_title)) if (defaultVectorFeatures.isOnboardingPersonalizeEnabled()) { - clickOn(R.string.ftue_account_created_personalize) + clickOn(CommonStrings.ftue_account_created_personalize) - waitUntilViewVisible(withText(R.string.ftue_display_name_title)) + waitUntilViewVisible(withText(CommonStrings.ftue_display_name_title)) writeTo(R.id.displayNameInput, "UI automation") - clickOn(R.string.ftue_personalize_submit) + clickOn(CommonStrings.ftue_personalize_submit) - waitUntilViewVisible(withText(R.string.ftue_profile_picture_title)) - clickOn(R.string.ftue_personalize_skip_this_step) + waitUntilViewVisible(withText(CommonStrings.ftue_profile_picture_title)) + clickOn(CommonStrings.ftue_personalize_skip_this_step) - waitUntilViewVisible(withText(R.string.ftue_personalize_complete_title)) - clickOn(R.string.ftue_personalize_lets_go) + waitUntilViewVisible(withText(CommonStrings.ftue_personalize_complete_title)) + clickOn(CommonStrings.ftue_personalize_lets_go) } else { - clickOn(R.string.ftue_account_created_take_me_home) + clickOn(CommonStrings.ftue_account_created_take_me_home) } } private fun createAccountViaCombinedRegister(homeServerUrl: String, userId: String, password: String) { waitUntilViewVisible(withId(R.id.loginSplashSubmit)) - assertDisplayed(R.id.loginSplashSubmit, R.string.login_splash_create_account) + assertDisplayed(R.id.loginSplashSubmit, CommonStrings.login_splash_create_account) clickOn(R.id.loginSplashSubmit) clickOn(R.id.useCaseOptionOne) @@ -117,7 +118,7 @@ class OnboardingRobot { private fun loginViaCombinedLogin(homeServerUrl: String, userId: String, password: String) { waitUntilViewVisible(withId(R.id.loginSplashSubmit)) - assertDisplayed(R.id.loginSplashSubmit, R.string.login_splash_create_account) + assertDisplayed(R.id.loginSplashSubmit, CommonStrings.login_splash_create_account) clickOn(R.id.loginSplashAlreadyHaveAccount) waitUntilViewVisible(withId(R.id.loginRoot)) @@ -139,14 +140,14 @@ class OnboardingRobot { homeServerUrl: String ) { waitUntilViewVisible(withId(R.id.loginSplashSubmit)) - assertDisplayed(R.id.loginSplashSubmit, R.string.login_splash_create_account) + assertDisplayed(R.id.loginSplashSubmit, CommonStrings.login_splash_create_account) if (createAccount) { clickOn(R.id.loginSplashSubmit) clickOn(R.id.useCaseOptionOne) } else { clickOn(R.id.loginSplashAlreadyHaveAccount) } - assertDisplayed(R.id.loginServerTitle, R.string.login_server_title) + assertDisplayed(R.id.loginServerTitle, CommonStrings.login_server_title) // Chose custom server clickOn(R.id.loginServerChoiceOther) // Enter local synapse diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/OnboardingServersRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/OnboardingServersRobot.kt index 050e5ab5c0..e4f20307c0 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/OnboardingServersRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/OnboardingServersRobot.kt @@ -23,11 +23,12 @@ import com.adevinta.android.barista.interaction.BaristaClickInteractions import com.adevinta.android.barista.interaction.BaristaEditTextInteractions import im.vector.app.R import im.vector.app.espresso.tools.waitUntilViewVisible +import im.vector.lib.strings.CommonStrings class OnboardingServersRobot { fun crawlSignUp() { - BaristaVisibilityAssertions.assertDisplayed(R.id.loginServerTitle, R.string.login_server_title) + BaristaVisibilityAssertions.assertDisplayed(R.id.loginServerTitle, CommonStrings.login_server_title) crawlMatrixServer(isSignUp = true) crawlEmsServer() crawlOtherServer(isSignUp = true) @@ -35,7 +36,7 @@ class OnboardingServersRobot { } fun crawlSignIn() { - BaristaVisibilityAssertions.assertDisplayed(R.id.loginServerTitle, R.string.login_server_title) + BaristaVisibilityAssertions.assertDisplayed(R.id.loginServerTitle, CommonStrings.login_server_title) crawlMatrixServer(isSignUp = false) crawlEmsServer() crawlOtherServer(isSignUp = false) @@ -49,7 +50,7 @@ class OnboardingServersRobot { BaristaClickInteractions.clickOn(R.id.loginServerUrlFormSubmit) waitUntilViewVisible(ViewMatchers.withId(R.id.loginSignupSigninTitle)) BaristaVisibilityAssertions.assertDisplayed(R.id.loginSignupSigninText, "Connect to chat.mozilla.org") - BaristaVisibilityAssertions.assertDisplayed(R.id.loginSignupSigninSubmit, R.string.login_signin_sso) + BaristaVisibilityAssertions.assertDisplayed(R.id.loginSignupSigninSubmit, CommonStrings.login_signin_sso) Espresso.pressBack() BaristaEditTextInteractions.writeTo(R.id.loginServerUrlFormHomeServerUrl, "https://matrix.org") @@ -62,14 +63,14 @@ class OnboardingServersRobot { private fun crawlEmsServer() { BaristaClickInteractions.clickOn(R.id.loginServerChoiceEms) waitUntilViewVisible(ViewMatchers.withId(R.id.loginServerUrlFormTitle)) - BaristaVisibilityAssertions.assertDisplayed(R.id.loginServerUrlFormTitle, R.string.login_connect_to_modular) + BaristaVisibilityAssertions.assertDisplayed(R.id.loginServerUrlFormTitle, CommonStrings.login_connect_to_modular) BaristaEditTextInteractions.writeTo(R.id.loginServerUrlFormHomeServerUrl, "https://one.ems.host") BaristaClickInteractions.clickOn(R.id.loginServerUrlFormSubmit) waitUntilViewVisible(ViewMatchers.withId(R.id.loginSignupSigninTitle)) BaristaVisibilityAssertions.assertDisplayed(R.id.loginSignupSigninText, "one.ems.host") - BaristaVisibilityAssertions.assertDisplayed(R.id.loginSignupSigninSubmit, R.string.login_signin_sso) + BaristaVisibilityAssertions.assertDisplayed(R.id.loginSignupSigninSubmit, CommonStrings.login_signin_sso) Espresso.pressBack() Espresso.pressBack() } @@ -91,7 +92,7 @@ class OnboardingServersRobot { private fun crawlSignInWithMatrixId() { BaristaClickInteractions.clickOn(R.id.loginServerIKnowMyIdSubmit) waitUntilViewVisible(ViewMatchers.withId(R.id.loginTitle)) - BaristaVisibilityAssertions.assertDisplayed(R.id.loginTitle, R.string.login_signin_matrix_id_title) + BaristaVisibilityAssertions.assertDisplayed(R.id.loginTitle, CommonStrings.login_signin_matrix_id_title) Espresso.pressBack() } } diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt index 6436080599..682f9ac3f8 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt @@ -39,6 +39,7 @@ import im.vector.app.features.home.room.detail.timeline.reactions.ViewReactionsB import im.vector.app.features.reactions.data.EmojiDataSource import im.vector.app.interactWithSheet import im.vector.app.withRetry +import im.vector.lib.strings.CommonStrings import java.lang.Thread.sleep class RoomDetailRobot { @@ -93,7 +94,7 @@ class RoomDetailRobot { // Open reactions longClickReaction(quickReaction) // wait for bottom sheet - interactWithSheet(withText(R.string.reactions), openState = BottomSheetBehavior.STATE_COLLAPSED) { + interactWithSheet(withText(CommonStrings.reactions), openState = BottomSheetBehavior.STATE_COLLAPSED) { pressBack() } println("Room Detail Robot: Open reaction from emoji picker") diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt index cbc46f15e7..c00c75cec8 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt @@ -36,6 +36,7 @@ import im.vector.app.features.home.room.list.home.header.HomeRoomFilter import im.vector.app.features.roomdirectory.RoomDirectoryActivity import im.vector.app.ui.robot.settings.labs.LabFeaturesPreferences import im.vector.app.waitForView +import im.vector.lib.strings.CommonStrings class RoomListRobot(private val labsPreferences: LabFeaturesPreferences) { @@ -55,7 +56,7 @@ class RoomListRobot(private val labsPreferences: LabFeaturesPreferences) { onView(withId(R.id.roomListView)) .perform( RecyclerViewActions.actionOnItem( - hasDescendant(withText(R.string.room_displayname_empty_room)), + hasDescendant(withText(CommonStrings.room_displayname_empty_room)), ViewActions.longClick() ) ) diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomSettingsRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomSettingsRobot.kt index 62c34e1b66..86f14bca68 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomSettingsRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/RoomSettingsRobot.kt @@ -29,6 +29,7 @@ import im.vector.app.espresso.tools.waitUntilActivityVisible import im.vector.app.espresso.tools.waitUntilDialogVisible import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.features.roommemberprofile.RoomMemberProfileActivity +import im.vector.lib.strings.CommonStrings class RoomSettingsRobot { @@ -58,8 +59,8 @@ class RoomSettingsRobot { // Uploads clickListItem(R.id.matrixProfileRecyclerView, 10) // File tab - clickOn(R.string.uploads_files_title) - waitUntilViewVisible(withText(R.string.uploads_media_title)) + clickOn(CommonStrings.uploads_files_title) + waitUntilViewVisible(withText(CommonStrings.uploads_media_title)) pressBack() waitUntilViewVisible(withId(R.id.matrixProfileRecyclerView)) @@ -74,19 +75,19 @@ class RoomSettingsRobot { // Room addresses clickListItem(R.id.matrixProfileRecyclerView, 16) - waitUntilViewVisible(withText(R.string.room_alias_published_alias_title)) + waitUntilViewVisible(withText(CommonStrings.room_alias_published_alias_title)) pressBack() // Room permissions clickListItem(R.id.matrixProfileRecyclerView, 18) - waitUntilViewVisible(withText(R.string.room_permissions_change_room_avatar)) - clickOn(R.string.room_permissions_change_room_avatar) + waitUntilViewVisible(withText(CommonStrings.room_permissions_change_room_avatar)) + clickOn(CommonStrings.room_permissions_change_room_avatar) waitUntilDialogVisible(withId(android.R.id.button2)) clickDialogNegativeButton() - waitUntilViewVisible(withText(R.string.room_permissions_title)) + waitUntilViewVisible(withText(CommonStrings.room_permissions_title)) // Toggle - clickOn(R.string.show_advanced) - clickOn(R.string.hide_advanced) + clickOn(CommonStrings.show_advanced) + clickOn(CommonStrings.hide_advanced) pressBack() // Menu share diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsAdvancedRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsAdvancedRobot.kt index 4aeb8903dd..d579bf23de 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsAdvancedRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsAdvancedRobot.kt @@ -19,31 +19,31 @@ package im.vector.app.ui.robot.settings import androidx.test.espresso.Espresso.pressBack import androidx.test.espresso.matcher.ViewMatchers.withText import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn -import im.vector.app.R import im.vector.app.espresso.tools.clickOnPreference import im.vector.app.espresso.tools.waitUntilViewVisible +import im.vector.lib.strings.CommonStrings class SettingsAdvancedRobot { fun crawl() { - clickOnPreference(R.string.settings_notifications_targets) + clickOnPreference(CommonStrings.settings_notifications_targets) pressBack() - clickOnPreference(R.string.settings_push_rules) + clickOnPreference(CommonStrings.settings_push_rules) pressBack() } fun toggleDeveloperMode() { - clickOn(R.string.settings_developer_mode_summary) + clickOn(CommonStrings.settings_developer_mode_summary) } fun crawlDeveloperOptions() { - clickOnPreference(R.string.settings_account_data) + clickOnPreference(CommonStrings.settings_account_data) waitUntilViewVisible(withText("m.push_rules")) clickOn("m.push_rules") pressBack() pressBack() - clickOnPreference(R.string.settings_key_requests) + clickOnPreference(CommonStrings.settings_key_requests) pressBack() } } diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsGeneralRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsGeneralRobot.kt index 9082eaa889..6bcdd9a299 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsGeneralRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsGeneralRobot.kt @@ -20,32 +20,32 @@ import androidx.test.espresso.Espresso.pressBack import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogPositiveButton -import im.vector.app.R import im.vector.app.espresso.tools.clickOnPreference +import im.vector.lib.strings.CommonStrings class SettingsGeneralRobot { fun crawl() { - clickOn(R.string.settings_profile_picture) + clickOn(CommonStrings.settings_profile_picture) clickDialogPositiveButton() - clickOn(R.string.settings_display_name) + clickOn(CommonStrings.settings_display_name) clickDialogNegativeButton() - clickOn(R.string.settings_password) + clickOn(CommonStrings.settings_password) clickDialogNegativeButton() - clickOn(R.string.settings_emails_and_phone_numbers_title) + clickOn(CommonStrings.settings_emails_and_phone_numbers_title) pressBack() - clickOn(R.string.settings_discovery_manage) - clickOn(R.string.add_identity_server) + clickOn(CommonStrings.settings_discovery_manage) + clickOn(CommonStrings.add_identity_server) pressBack() pressBack() // Homeserver - clickOnPreference(R.string.settings_home_server) + clickOnPreference(CommonStrings.settings_home_server) pressBack() // Identity server - clickOnPreference(R.string.settings_identity_server) + clickOnPreference(CommonStrings.settings_identity_server) pressBack() // Deactivate account - clickOnPreference(R.string.settings_deactivate_my_account) + clickOnPreference(CommonStrings.settings_deactivate_my_account) pressBack() } } diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsHelpRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsHelpRobot.kt index cf0c997d80..e7258e2aae 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsHelpRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsHelpRobot.kt @@ -20,14 +20,14 @@ class SettingsHelpRobot { fun crawl() { /* - clickOn(R.string.settings_app_info_link_title) + clickOn(CommonStrings.settings_app_info_link_title) Cannot go back... pressBack() - clickOn(R.string.settings_copyright) + clickOn(CommonStrings.settings_copyright) pressBack() - clickOn(R.string.settings_app_term_conditions) + clickOn(CommonStrings.settings_app_term_conditions) pressBack() - clickOn(R.string.settings_privacy_policy) + clickOn(CommonStrings.settings_privacy_policy) pressBack() */ } diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsLegalsRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsLegalsRobot.kt index 842471752a..5d166f1d87 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsLegalsRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsLegalsRobot.kt @@ -18,12 +18,12 @@ package im.vector.app.ui.robot.settings import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogPositiveButton -import im.vector.app.R +import im.vector.lib.strings.CommonStrings class SettingsLegalsRobot { fun crawl() { - clickOn(R.string.settings_third_party_notices) + clickOn(CommonStrings.settings_third_party_notices) clickDialogPositiveButton() } } diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsNotificationsRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsNotificationsRobot.kt index 5858e78a2a..e6711c9a7a 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsNotificationsRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsNotificationsRobot.kt @@ -19,39 +19,39 @@ package im.vector.app.ui.robot.settings import androidx.test.espresso.Espresso.pressBack import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn -import im.vector.app.R import im.vector.app.espresso.tools.clickOnPreference +import im.vector.lib.strings.CommonStrings class SettingsNotificationsRobot { fun crawl() { - clickOn(R.string.settings_notification_default) + clickOn(CommonStrings.settings_notification_default) pressBack() - clickOn(R.string.settings_notification_mentions_and_keywords) + clickOn(CommonStrings.settings_notification_mentions_and_keywords) // TODO Test adding a keyword? pressBack() - clickOn(R.string.settings_notification_other) + clickOn(CommonStrings.settings_notification_other) pressBack() /* - clickOn(R.string.settings_noisy_notifications_preferences) + clickOn(CommonStrings.settings_noisy_notifications_preferences) TODO Cannot go back pressBack() - clickOn(R.string.settings_silent_notifications_preferences) + clickOn(CommonStrings.settings_silent_notifications_preferences) pressBack() - clickOn(R.string.settings_call_notifications_preferences) + clickOn(CommonStrings.settings_call_notifications_preferences) pressBack() */ // Email notification. No Emails are configured so we show go to the screen to add email - clickOnPreference(R.string.settings_notification_emails_no_emails) - assertDisplayed(R.string.settings_emails_and_phone_numbers_title) + clickOnPreference(CommonStrings.settings_notification_emails_no_emails) + assertDisplayed(CommonStrings.settings_emails_and_phone_numbers_title) pressBack() // Display the notification method change dialog - clickOnPreference(R.string.settings_notification_method) + clickOnPreference(CommonStrings.settings_notification_method) pressBack() - clickOnPreference(R.string.settings_notification_troubleshoot) + clickOnPreference(CommonStrings.settings_notification_troubleshoot) // Give time for the tests to perform Thread.sleep(12_000) pressBack() diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsPreferencesRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsPreferencesRobot.kt index 126cfafa18..4bdce129a6 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsPreferencesRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsPreferencesRobot.kt @@ -23,16 +23,17 @@ import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton import im.vector.app.R import im.vector.app.espresso.tools.waitUntilViewVisible +import im.vector.lib.strings.CommonStrings class SettingsPreferencesRobot { fun crawl() { - clickOn(R.string.settings_interface_language) + clickOn(CommonStrings.settings_interface_language) waitUntilViewVisible(withText("Dansk (Danmark)")) pressBack() - clickOn(R.string.settings_theme) + clickOn(CommonStrings.settings_theme) clickDialogNegativeButton() - clickOn(R.string.font_size) + clickOn(CommonStrings.font_size) waitUntilViewVisible(withId(R.id.fons_scale_recycler)) pressBack() } diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsRobot.kt index 1697fe078d..f5e1e480b1 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsRobot.kt @@ -17,8 +17,8 @@ package im.vector.app.ui.robot.settings import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn -import im.vector.app.R import im.vector.app.clickOnAndGoBack +import im.vector.lib.strings.CommonStrings class SettingsRobot { @@ -29,45 +29,45 @@ class SettingsRobot { } fun general(block: SettingsGeneralRobot.() -> Unit) { - clickOnAndGoBack(R.string.settings_general_title) { block(SettingsGeneralRobot()) } + clickOnAndGoBack(CommonStrings.settings_general_title) { block(SettingsGeneralRobot()) } } fun notifications(block: SettingsNotificationsRobot.() -> Unit) { - clickOnAndGoBack(R.string.settings_notifications) { block(SettingsNotificationsRobot()) } + clickOnAndGoBack(CommonStrings.settings_notifications) { block(SettingsNotificationsRobot()) } } fun preferences(block: SettingsPreferencesRobot.() -> Unit) { - clickOnAndGoBack(R.string.settings_preferences) { block(SettingsPreferencesRobot()) } + clickOnAndGoBack(CommonStrings.settings_preferences) { block(SettingsPreferencesRobot()) } } fun voiceAndVideo(block: () -> Unit = {}) { - clickOnAndGoBack(R.string.preference_voice_and_video) { block() } + clickOnAndGoBack(CommonStrings.preference_voice_and_video) { block() } } fun securityAndPrivacy(block: SettingsSecurityRobot.() -> Unit) { - clickOnAndGoBack(R.string.settings_security_and_privacy) { block(SettingsSecurityRobot()) } + clickOnAndGoBack(CommonStrings.settings_security_and_privacy) { block(SettingsSecurityRobot()) } } fun labs(shouldGoBack: Boolean = true, block: () -> Unit = {}) { if (shouldGoBack) { - clickOnAndGoBack(R.string.room_settings_labs_pref_title) { block() } + clickOnAndGoBack(CommonStrings.room_settings_labs_pref_title) { block() } } else { - clickOn(R.string.room_settings_labs_pref_title) + clickOn(CommonStrings.room_settings_labs_pref_title) block() } } fun advancedSettings(block: SettingsAdvancedRobot.() -> Unit) { - clickOnAndGoBack(R.string.settings_advanced_settings) { + clickOnAndGoBack(CommonStrings.settings_advanced_settings) { block(SettingsAdvancedRobot()) } } fun helpAndAbout(block: SettingsHelpRobot.() -> Unit) { - clickOnAndGoBack(R.string.preference_root_help_about) { block(SettingsHelpRobot()) } + clickOnAndGoBack(CommonStrings.preference_root_help_about) { block(SettingsHelpRobot()) } } fun legals(block: SettingsLegalsRobot.() -> Unit) { - clickOnAndGoBack(R.string.preference_root_legals) { block(SettingsLegalsRobot()) } + clickOnAndGoBack(CommonStrings.preference_root_legals) { block(SettingsLegalsRobot()) } } } diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsSecurityRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsSecurityRobot.kt index 841c99e1b5..41895dcb21 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsSecurityRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsSecurityRobot.kt @@ -17,27 +17,27 @@ package im.vector.app.ui.robot.settings import androidx.test.espresso.Espresso -import im.vector.app.R import im.vector.app.espresso.tools.clickOnPreference +import im.vector.lib.strings.CommonStrings class SettingsSecurityRobot { fun crawl() { - clickOnPreference(R.string.settings_active_sessions_show_all) + clickOnPreference(CommonStrings.settings_active_sessions_show_all) Espresso.pressBack() - clickOnPreference(R.string.encryption_message_recovery) + clickOnPreference(CommonStrings.encryption_message_recovery) // TODO go deeper here Espresso.pressBack() /* Cannot exit - clickOnPreference(R.string.encryption_export_e2e_room_keys) + clickOnPreference(CommonStrings.encryption_export_e2e_room_keys) pressBack() */ - clickOnPreference(R.string.settings_opt_in_of_analytics) + clickOnPreference(CommonStrings.settings_opt_in_of_analytics) Espresso.pressBack() - clickOnPreference(R.string.settings_ignored_users) + clickOnPreference(CommonStrings.settings_ignored_users) Espresso.pressBack() } } diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt index ad6d5e5df3..0f8b5d5709 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceCreateRobot.kt @@ -32,6 +32,7 @@ import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.features.home.HomeActivity import im.vector.app.features.home.room.detail.RoomDetailActivity import im.vector.app.features.spaces.manage.SpaceManageActivity +import im.vector.lib.strings.CommonStrings class SpaceCreateRobot { @@ -39,7 +40,7 @@ class SpaceCreateRobot { // public clickOn(R.id.publicButton) waitUntilViewVisible(withId(R.id.recyclerView)) - onView(ViewMatchers.withHint(R.string.create_room_name_hint)).perform(ViewActions.replaceText(name)) + onView(ViewMatchers.withHint(CommonStrings.create_room_name_hint)).perform(ViewActions.replaceText(name)) clickOn(R.id.nextButton) waitUntilViewVisible(withId(R.id.recyclerView)) pressBack() @@ -68,7 +69,7 @@ class SpaceCreateRobot { onView(withId(R.id.roomList)) .perform( RecyclerViewActions.actionOnItem( - ViewMatchers.hasDescendant(withText(R.string.room_displayname_empty_room)), + ViewMatchers.hasDescendant(withText(CommonStrings.room_displayname_empty_room)), click() ).atPosition(0) ) @@ -81,7 +82,7 @@ class SpaceCreateRobot { fun createPublicSpace(spaceName: String) { clickOn(R.id.publicButton) waitUntilViewVisible(withId(R.id.recyclerView)) - onView(ViewMatchers.withHint(R.string.create_room_name_hint)).perform(ViewActions.replaceText(spaceName)) + onView(ViewMatchers.withHint(CommonStrings.create_room_name_hint)).perform(ViewActions.replaceText(spaceName)) clickOn(R.id.nextButton) waitUntilViewVisible(withId(R.id.recyclerView)) clickOn(R.id.nextButton) diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceRobot.kt index e8ff58ba6a..6ce7aad238 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceRobot.kt @@ -31,6 +31,7 @@ import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.features.DefaultVectorFeatures import im.vector.app.features.VectorFeatures import im.vector.app.ui.robot.settings.labs.LabFeaturesPreferences +import im.vector.lib.strings.CommonStrings import org.hamcrest.Matchers class SpaceRobot(private val labsPreferences: LabFeaturesPreferences) { @@ -54,7 +55,7 @@ class SpaceRobot(private val labsPreferences: LabFeaturesPreferences) { } } else { openDrawer() - clickOn(R.string.create_space) + clickOn(CommonStrings.create_space) } block(SpaceCreateRobot()) } diff --git a/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceSettingsRobot.kt b/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceSettingsRobot.kt index dcd003da98..90a2df1fe8 100644 --- a/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceSettingsRobot.kt +++ b/vector-app/src/androidTest/java/im/vector/app/ui/robot/space/SpaceSettingsRobot.kt @@ -25,13 +25,14 @@ import im.vector.app.R import im.vector.app.espresso.tools.waitUntilActivityVisible import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleActivity +import im.vector.lib.strings.CommonStrings class SpaceSettingsRobot { fun crawl() { Espresso.onView(ViewMatchers.withId(R.id.roomSettingsRecyclerView)) .perform( RecyclerViewActions.actionOnItem( - ViewMatchers.hasDescendant(ViewMatchers.withText(R.string.room_settings_space_access_title)), + ViewMatchers.hasDescendant(ViewMatchers.withText(CommonStrings.room_settings_space_access_title)), ViewActions.click() ) ) @@ -45,7 +46,7 @@ class SpaceSettingsRobot { Espresso.onView(ViewMatchers.withId(R.id.roomSettingsRecyclerView)) .perform( RecyclerViewActions.actionOnItem( - ViewMatchers.hasDescendant(ViewMatchers.withText(R.string.space_settings_manage_rooms)), + ViewMatchers.hasDescendant(ViewMatchers.withText(CommonStrings.space_settings_manage_rooms)), ViewActions.click() ) ) @@ -56,7 +57,7 @@ class SpaceSettingsRobot { Espresso.onView(ViewMatchers.withId(R.id.roomSettingsRecyclerView)) .perform( RecyclerViewActions.actionOnItem( - ViewMatchers.hasDescendant(ViewMatchers.withText(R.string.space_settings_permissions_title)), + ViewMatchers.hasDescendant(ViewMatchers.withText(CommonStrings.space_settings_permissions_title)), ViewActions.click() ) ) diff --git a/vector-app/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt b/vector-app/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt index 2b1b66e672..419d2dcde5 100644 --- a/vector-app/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt @@ -31,6 +31,7 @@ import im.vector.app.core.utils.onPermissionDeniedSnackbar import im.vector.app.core.utils.registerForPermissionsResult import im.vector.application.R import im.vector.application.databinding.ActivityDebugPermissionBinding +import im.vector.lib.strings.CommonStrings import timber.log.Timber @AndroidEntryPoint @@ -111,9 +112,9 @@ class DebugPermissionActivity : VectorBaseActivity + + + diff --git a/vector-app/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestAutoStartBoot.kt b/vector-app/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestAutoStartBoot.kt index ce1263c67b..4b62a4e024 100644 --- a/vector-app/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestAutoStartBoot.kt +++ b/vector-app/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestAutoStartBoot.kt @@ -15,10 +15,10 @@ */ package im.vector.app.fdroid.features.settings.troubleshoot -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.troubleshoot.TroubleshootTest +import im.vector.lib.strings.CommonStrings import javax.inject.Inject /** @@ -28,16 +28,16 @@ class TestAutoStartBoot @Inject constructor( private val vectorPreferences: VectorPreferences, private val stringProvider: StringProvider ) : - TroubleshootTest(R.string.settings_troubleshoot_test_service_boot_title) { + TroubleshootTest(CommonStrings.settings_troubleshoot_test_service_boot_title) { override fun perform(testParameters: TestParameters) { if (vectorPreferences.autoStartOnBoot()) { - description = stringProvider.getString(R.string.settings_troubleshoot_test_service_boot_success) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_service_boot_success) status = TestStatus.SUCCESS quickFix = null } else { - description = stringProvider.getString(R.string.settings_troubleshoot_test_service_boot_failed) - quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_service_boot_quickfix) { + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_service_boot_failed) + quickFix = object : TroubleshootQuickFix(CommonStrings.settings_troubleshoot_test_service_boot_quickfix) { override fun doFix() { vectorPreferences.setAutoStartOnBoot(true) manager?.retry(testParameters) diff --git a/vector-app/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestBackgroundRestrictions.kt b/vector-app/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestBackgroundRestrictions.kt index a14d3b5c8a..fe4847b541 100644 --- a/vector-app/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestBackgroundRestrictions.kt +++ b/vector-app/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestBackgroundRestrictions.kt @@ -19,16 +19,16 @@ import android.net.ConnectivityManager import androidx.core.content.getSystemService import androidx.core.net.ConnectivityManagerCompat import androidx.fragment.app.FragmentActivity -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.settings.troubleshoot.TroubleshootTest +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class TestBackgroundRestrictions @Inject constructor( private val context: FragmentActivity, private val stringProvider: StringProvider ) : - TroubleshootTest(R.string.settings_troubleshoot_test_bg_restricted_title) { + TroubleshootTest(CommonStrings.settings_troubleshoot_test_bg_restricted_title) { override fun perform(testParameters: TestParameters) { context.getSystemService()!!.apply { @@ -40,7 +40,7 @@ class TestBackgroundRestrictions @Inject constructor( // Background data usage is blocked for this app. Wherever possible, // the app should also use less data in the foreground. description = stringProvider.getString( - R.string.settings_troubleshoot_test_bg_restricted_failed, + CommonStrings.settings_troubleshoot_test_bg_restricted_failed, "RESTRICT_BACKGROUND_STATUS_ENABLED" ) status = TestStatus.FAILED @@ -50,7 +50,7 @@ class TestBackgroundRestrictions @Inject constructor( // The app is whitelisted. Wherever possible, // the app should use less data in the foreground and background. description = stringProvider.getString( - R.string.settings_troubleshoot_test_bg_restricted_success, + CommonStrings.settings_troubleshoot_test_bg_restricted_success, "RESTRICT_BACKGROUND_STATUS_WHITELISTED" ) status = TestStatus.SUCCESS @@ -60,7 +60,7 @@ class TestBackgroundRestrictions @Inject constructor( // Data Saver is disabled. Since the device is connected to a // metered network, the app should use less data wherever possible. description = stringProvider.getString( - R.string.settings_troubleshoot_test_bg_restricted_success, + CommonStrings.settings_troubleshoot_test_bg_restricted_success, "RESTRICT_BACKGROUND_STATUS_DISABLED" ) status = TestStatus.SUCCESS @@ -70,7 +70,7 @@ class TestBackgroundRestrictions @Inject constructor( } else { // The device is not on a metered network. // Use data as required to perform syncs, downloads, and updates. - description = stringProvider.getString(R.string.settings_troubleshoot_test_bg_restricted_success, "") + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_bg_restricted_success, "") status = TestStatus.SUCCESS quickFix = null } diff --git a/vector-app/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestBatteryOptimization.kt b/vector-app/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestBatteryOptimization.kt index 075432c9d2..8057e1279c 100644 --- a/vector-app/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestBatteryOptimization.kt +++ b/vector-app/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestBatteryOptimization.kt @@ -16,26 +16,26 @@ package im.vector.app.fdroid.features.settings.troubleshoot import androidx.fragment.app.FragmentActivity -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.isIgnoringBatteryOptimizations import im.vector.app.core.utils.requestDisablingBatteryOptimization import im.vector.app.features.settings.troubleshoot.TroubleshootTest +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class TestBatteryOptimization @Inject constructor( private val context: FragmentActivity, private val stringProvider: StringProvider -) : TroubleshootTest(R.string.settings_troubleshoot_test_battery_title) { +) : TroubleshootTest(CommonStrings.settings_troubleshoot_test_battery_title) { override fun perform(testParameters: TestParameters) { if (context.isIgnoringBatteryOptimizations()) { - description = stringProvider.getString(R.string.settings_troubleshoot_test_battery_success) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_battery_success) status = TestStatus.SUCCESS quickFix = null } else { - description = stringProvider.getString(R.string.settings_troubleshoot_test_battery_failed) - quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_battery_quickfix) { + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_battery_failed) + quickFix = object : TroubleshootQuickFix(CommonStrings.settings_troubleshoot_test_battery_quickfix) { override fun doFix() { requestDisablingBatteryOptimization(context, testParameters.activityResultLauncher) } diff --git a/vector-app/src/fdroid/java/im/vector/app/fdroid/service/GuardAndroidService.kt b/vector-app/src/fdroid/java/im/vector/app/fdroid/service/GuardAndroidService.kt index f46b8f9820..685ea74029 100644 --- a/vector-app/src/fdroid/java/im/vector/app/fdroid/service/GuardAndroidService.kt +++ b/vector-app/src/fdroid/java/im/vector/app/fdroid/service/GuardAndroidService.kt @@ -17,9 +17,9 @@ package im.vector.app.fdroid.service import android.content.Intent import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.services.VectorAndroidService import im.vector.app.features.notifications.NotificationUtils +import im.vector.lib.strings.CommonStrings import javax.inject.Inject /** @@ -34,7 +34,7 @@ class GuardAndroidService : VectorAndroidService() { @Inject lateinit var notificationUtils: NotificationUtils override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - val notificationSubtitleRes = R.string.notification_listening_for_notifications + val notificationSubtitleRes = CommonStrings.notification_listening_for_notifications val notification = notificationUtils.buildForegroundServiceNotification(notificationSubtitleRes, false) startForeground(NotificationUtils.NOTIFICATION_ID_FOREGROUND_SERVICE, notification) return START_STICKY diff --git a/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestFirebaseToken.kt b/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestFirebaseToken.kt index 8e7e4f43cc..a5365611a2 100644 --- a/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestFirebaseToken.kt +++ b/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestFirebaseToken.kt @@ -17,11 +17,11 @@ package im.vector.app.gplay.features.settings.troubleshoot 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.lib.strings.CommonStrings import timber.log.Timber import javax.inject.Inject @@ -32,7 +32,7 @@ class TestFirebaseToken @Inject constructor( private val context: FragmentActivity, private val stringProvider: StringProvider, private val fcmHelper: FcmHelper, -) : TroubleshootTest(R.string.settings_troubleshoot_test_fcm_title) { +) : TroubleshootTest(CommonStrings.settings_troubleshoot_test_fcm_title) { override fun perform(testParameters: TestParameters) { status = TestStatus.RUNNING @@ -43,28 +43,28 @@ class TestFirebaseToken @Inject constructor( // Can't find where this constant is (not documented -or deprecated in docs- and all obfuscated) description = when (val errorMsg = task.exception?.localizedMessage ?: "Unknown") { "SERVICE_NOT_AVAILABLE" -> { - stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_service_not_available, errorMsg) + stringProvider.getString(CommonStrings.settings_troubleshoot_test_fcm_failed_service_not_available, errorMsg) } "TOO_MANY_REGISTRATIONS" -> { - stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_too_many_registration, errorMsg) + stringProvider.getString(CommonStrings.settings_troubleshoot_test_fcm_failed_too_many_registration, errorMsg) } "ACCOUNT_MISSING" -> { - quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_fcm_failed_account_missing_quick_fix) { + quickFix = object : TroubleshootQuickFix(CommonStrings.settings_troubleshoot_test_fcm_failed_account_missing_quick_fix) { override fun doFix() { startAddGoogleAccountIntent(context, testParameters.activityResultLauncher) } } - stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_account_missing, errorMsg) + stringProvider.getString(CommonStrings.settings_troubleshoot_test_fcm_failed_account_missing, errorMsg) } else -> { - stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed, errorMsg) + stringProvider.getString(CommonStrings.settings_troubleshoot_test_fcm_failed, errorMsg) } } status = TestStatus.FAILED } else { task.result?.let { token -> val tok = token.take(8) + "********************" - description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_success, tok) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_fcm_success, tok) Timber.e("Retrieved FCM token success [$tok].") // Ensure it is well store in our local storage fcmHelper.storeFcmToken(token) @@ -73,7 +73,7 @@ class TestFirebaseToken @Inject constructor( } } } catch (e: Throwable) { - description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed, e.localizedMessage) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_fcm_failed, e.localizedMessage) status = TestStatus.FAILED } } diff --git a/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPlayServices.kt b/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPlayServices.kt index 3ebcceb3fb..644ef0295d 100644 --- a/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPlayServices.kt +++ b/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPlayServices.kt @@ -18,9 +18,9 @@ package im.vector.app.gplay.features.settings.troubleshoot import androidx.fragment.app.FragmentActivity import com.google.android.gms.common.ConnectionResult import com.google.android.gms.common.GoogleApiAvailability -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.settings.troubleshoot.TroubleshootTest +import im.vector.lib.strings.CommonStrings import timber.log.Timber import javax.inject.Inject @@ -31,18 +31,18 @@ class TestPlayServices @Inject constructor( private val context: FragmentActivity, private val stringProvider: StringProvider ) : - TroubleshootTest(R.string.settings_troubleshoot_test_play_services_title) { + TroubleshootTest(CommonStrings.settings_troubleshoot_test_play_services_title) { override fun perform(testParameters: TestParameters) { val apiAvailability = GoogleApiAvailability.getInstance() val resultCode = apiAvailability.isGooglePlayServicesAvailable(context) if (resultCode == ConnectionResult.SUCCESS) { quickFix = null - description = stringProvider.getString(R.string.settings_troubleshoot_test_play_services_success) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_play_services_success) status = TestStatus.SUCCESS } else { if (apiAvailability.isUserResolvableError(resultCode)) { - quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_play_services_quickfix) { + quickFix = object : TroubleshootQuickFix(CommonStrings.settings_troubleshoot_test_play_services_quickfix) { override fun doFix() { apiAvailability.getErrorDialog(context, resultCode, 9000 /*hey does the magic number*/)?.show() } @@ -50,7 +50,7 @@ class TestPlayServices @Inject constructor( Timber.e("Play Services apk error $resultCode -> ${apiAvailability.getErrorString(resultCode)}.") } - description = stringProvider.getString(R.string.settings_troubleshoot_test_play_services_failed, apiAvailability.getErrorString(resultCode)) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_play_services_failed, apiAvailability.getErrorString(resultCode)) status = TestStatus.FAILED } } diff --git a/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt b/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt index 313073da4d..d850b01364 100644 --- a/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt +++ b/vector-app/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt @@ -20,12 +20,12 @@ import androidx.lifecycle.Observer import androidx.lifecycle.lifecycleScope 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.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.pushers.PusherState @@ -41,7 +41,7 @@ class TestTokenRegistration @Inject constructor( private val activeSessionHolder: ActiveSessionHolder, private val fcmHelper: FcmHelper, ) : - TroubleshootTest(R.string.settings_troubleshoot_test_token_registration_title) { + TroubleshootTest(CommonStrings.settings_troubleshoot_test_token_registration_title) { override fun perform(testParameters: TestParameters) { // Check if we have a registered pusher for this token @@ -58,10 +58,10 @@ class TestTokenRegistration @Inject constructor( } if (pushers.isEmpty()) { description = stringProvider.getString( - R.string.settings_troubleshoot_test_token_registration_failed, - stringProvider.getString(R.string.sas_error_unknown) + CommonStrings.settings_troubleshoot_test_token_registration_failed, + stringProvider.getString(CommonStrings.sas_error_unknown) ) - quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_token_registration_quick_fix) { + quickFix = object : TroubleshootQuickFix(CommonStrings.settings_troubleshoot_test_token_registration_quick_fix) { override fun doFix() { context.lifecycleScope.launch(Dispatchers.IO) { val workId = pushersManager.enqueueRegisterPusherWithFcmKey(fcmToken) @@ -80,7 +80,7 @@ class TestTokenRegistration @Inject constructor( status = TestStatus.FAILED } else { - description = stringProvider.getString(R.string.settings_troubleshoot_test_token_registration_success) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_token_registration_success) status = TestStatus.SUCCESS } } diff --git a/vector-app/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt b/vector-app/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt index 676cd0258f..0f2ce770c2 100755 --- a/vector-app/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt +++ b/vector-app/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt @@ -23,12 +23,12 @@ import com.google.android.gms.common.ConnectionResult import com.google.android.gms.common.GoogleApiAvailability import com.google.firebase.messaging.FirebaseMessaging import dagger.hilt.android.qualifiers.ApplicationContext -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.DefaultPreferences import im.vector.app.core.dispatchers.CoroutineDispatchers import im.vector.app.core.pushers.FcmHelper import im.vector.app.core.pushers.PushersManager +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import timber.log.Timber @@ -84,7 +84,7 @@ class GoogleFcmHelper @Inject constructor( Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed") } } else { - Toast.makeText(context, R.string.no_valid_google_play_services_apk, Toast.LENGTH_SHORT).show() + Toast.makeText(context, CommonStrings.no_valid_google_play_services_apk, Toast.LENGTH_SHORT).show() Timber.e("No valid Google Play Services found. Cannot use FCM.") } } diff --git a/vector-app/src/gplay/java/im/vector/app/push/fcm/VectorFirebaseMessagingService.kt b/vector-app/src/gplay/java/im/vector/app/push/fcm/VectorFirebaseMessagingService.kt index 7a7f14d690..f6aa5b154f 100644 --- a/vector-app/src/gplay/java/im/vector/app/push/fcm/VectorFirebaseMessagingService.kt +++ b/vector-app/src/gplay/java/im/vector/app/push/fcm/VectorFirebaseMessagingService.kt @@ -19,7 +19,6 @@ package im.vector.app.push.fcm import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage import dagger.hilt.android.AndroidEntryPoint -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.PushParser @@ -70,7 +69,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { pushKey = token, gateway = mdmService.getData( mdmData = MdmData.DefaultPushGatewayUrl, - defaultValue = getString(R.string.pusher_http_url), + defaultValue = getString(im.vector.app.config.R.string.pusher_http_url), ), ) } diff --git a/vector-app/src/main/java/im/vector/app/core/di/SingletonModule.kt b/vector-app/src/main/java/im/vector/app/core/di/SingletonModule.kt index 9c173268cc..97150cbfc6 100644 --- a/vector-app/src/main/java/im/vector/app/core/di/SingletonModule.kt +++ b/vector-app/src/main/java/im/vector/app/core/di/SingletonModule.kt @@ -64,6 +64,7 @@ import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.ui.SharedPreferencesUiStateRepository import im.vector.app.features.ui.UiStateRepository import im.vector.application.BuildConfig +import im.vector.application.R import im.vector.lib.core.utils.timer.Clock import im.vector.lib.core.utils.timer.DefaultClock import kotlinx.coroutines.CoroutineScope @@ -225,9 +226,10 @@ import javax.inject.Singleton @Provides @Singleton - fun providesBuildMeta() = BuildMeta( + fun providesBuildMeta(context: Context) = BuildMeta( isDebug = BuildConfig.DEBUG, applicationId = BuildConfig.APPLICATION_ID, + applicationName = context.getString(R.string.app_name), lowPrivacyLoggingEnabled = Config.LOW_PRIVACY_LOG_ENABLE, versionName = BuildConfig.VERSION_NAME, gitRevision = BuildConfig.GIT_REVISION, diff --git a/vector-config/build.gradle b/vector-config/build.gradle index 771e51f357..f509fab32d 100644 --- a/vector-config/build.gradle +++ b/vector-config/build.gradle @@ -18,6 +18,6 @@ android { } kotlinOptions { - jvmTarget = "11" + jvmTarget = versions.jvmTarget } } diff --git a/vector/build.gradle b/vector/build.gradle index dc8eb0641e..57effb23fa 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -69,7 +69,7 @@ android { buildTypes { debug { if (project.hasProperty("coverage")) { - testCoverageEnabled = coverage == "true" + testCoverageEnabled = project.properties["coverage"] == "true" } } } @@ -80,7 +80,7 @@ android { } kotlinOptions { - jvmTarget = "11" + jvmTarget = versions.jvmTarget freeCompilerArgs += [ "-opt-in=kotlin.RequiresOptIn", // Fixes false positive "This is an internal Mavericks API. It is not intended for external use." @@ -104,6 +104,7 @@ android { buildFeatures { viewBinding true + buildConfig true } } diff --git a/vector/src/androidTest/java/im/vector/app/SleepViewAction.java b/vector/src/androidTest/java/im/vector/app/SleepViewAction.java index 8623f24756..981c2f3bb3 100644 --- a/vector/src/androidTest/java/im/vector/app/SleepViewAction.java +++ b/vector/src/androidTest/java/im/vector/app/SleepViewAction.java @@ -16,6 +16,8 @@ package im.vector.app; +import static androidx.test.espresso.matcher.ViewMatchers.isRoot; + import android.view.View; import androidx.test.espresso.UiController; @@ -23,8 +25,6 @@ import org.hamcrest.Matcher; -import static androidx.test.espresso.matcher.ViewMatchers.isRoot; - public class SleepViewAction { public static ViewAction sleep(final long millis) { @@ -46,4 +46,4 @@ public void perform(final UiController uiController, final View view) { } }; } -} \ No newline at end of file +} diff --git a/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/ui/fallbackprompt/FallbackBiometricDialogFragmentTests.kt b/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/ui/fallbackprompt/FallbackBiometricDialogFragmentTests.kt index 3781535f72..2d7825090c 100644 --- a/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/ui/fallbackprompt/FallbackBiometricDialogFragmentTests.kt +++ b/vector/src/androidTest/java/im/vector/app/features/pin/lockscreen/ui/fallbackprompt/FallbackBiometricDialogFragmentTests.kt @@ -80,7 +80,7 @@ class FallbackBiometricDialogFragmentTests { fragmentScenario.moveToState(Lifecycle.State.RESUMED) // Espresso wasn't fast enough to catch this value authFlow.tryEmit(true) - fragment.requireView().statusText() shouldBeEqualTo context.getString(R.string.lockscreen_fingerprint_success) + fragment.requireView().statusText() shouldBeEqualTo context.getString(im.vector.lib.ui.styles.R.string.lockscreen_fingerprint_success) } latch.await() } @@ -95,7 +95,7 @@ class FallbackBiometricDialogFragmentTests { fragment.authenticationFlow = authFlow fragmentScenario.moveToState(Lifecycle.State.RESUMED) authFlow.tryEmit(false) - fragment.requireView().statusText() shouldBeEqualTo context.getString(R.string.lockscreen_fingerprint_not_recognized) + fragment.requireView().statusText() shouldBeEqualTo context.getString(im.vector.lib.ui.styles.R.string.lockscreen_fingerprint_not_recognized) latch.countDown() } latch.await() diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index 1b9bfaf802..6fed67e7da 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -41,8 +41,20 @@ + + + + + + + + + + + + - + diff --git a/vector/src/main/java/im/vector/app/core/animations/Konfetti.kt b/vector/src/main/java/im/vector/app/core/animations/Konfetti.kt index 882891810b..3f4bc0f1bb 100644 --- a/vector/src/main/java/im/vector/app/core/animations/Konfetti.kt +++ b/vector/src/main/java/im/vector/app/core/animations/Konfetti.kt @@ -19,7 +19,7 @@ package im.vector.app.core.animations import android.content.Context import androidx.annotation.ColorInt import androidx.core.content.ContextCompat -import im.vector.app.R +import im.vector.lib.ui.styles.R import nl.dionsegijn.konfetti.core.Angle import nl.dionsegijn.konfetti.core.Party import nl.dionsegijn.konfetti.core.Position diff --git a/vector/src/main/java/im/vector/app/core/dialogs/ConfirmationDialogBuilder.kt b/vector/src/main/java/im/vector/app/core/dialogs/ConfirmationDialogBuilder.kt index 01d369b019..6c7e73f7ed 100644 --- a/vector/src/main/java/im/vector/app/core/dialogs/ConfirmationDialogBuilder.kt +++ b/vector/src/main/java/im/vector/app/core/dialogs/ConfirmationDialogBuilder.kt @@ -22,6 +22,7 @@ import androidx.core.view.isVisible import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.databinding.DialogConfirmationWithReasonBinding +import im.vector.lib.strings.CommonStrings object ConfirmationDialogBuilder { @@ -58,7 +59,7 @@ object ConfirmationDialogBuilder { ?.takeIf { it.isNotBlank() } confirmation(reason) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } } diff --git a/vector/src/main/java/im/vector/app/core/dialogs/ExportKeysDialog.kt b/vector/src/main/java/im/vector/app/core/dialogs/ExportKeysDialog.kt index d0de7e6a3f..defcd11a6b 100644 --- a/vector/src/main/java/im/vector/app/core/dialogs/ExportKeysDialog.kt +++ b/vector/src/main/java/im/vector/app/core/dialogs/ExportKeysDialog.kt @@ -22,6 +22,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.core.platform.SimpleTextWatcher import im.vector.app.databinding.DialogExportE2eKeysBinding +import im.vector.lib.strings.CommonStrings class ExportKeysDialog { @@ -29,7 +30,7 @@ class ExportKeysDialog { val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_export_e2e_keys, null) val views = DialogExportE2eKeysBinding.bind(dialogLayout) val builder = MaterialAlertDialogBuilder(activity) - .setTitle(R.string.encryption_export_room_keys) + .setTitle(CommonStrings.encryption_export_room_keys) .setView(dialogLayout) val textWatcher = object : SimpleTextWatcher() { @@ -45,7 +46,7 @@ class ExportKeysDialog { } else -> { views.exportDialogSubmit.isEnabled = false - views.exportDialogTilConfirm.error = activity.getString(R.string.passphrase_passphrase_does_not_match) + views.exportDialogTilConfirm.error = activity.getString(CommonStrings.passphrase_passphrase_does_not_match) } } } diff --git a/vector/src/main/java/im/vector/app/core/dialogs/GalleryOrCameraDialogHelper.kt b/vector/src/main/java/im/vector/app/core/dialogs/GalleryOrCameraDialogHelper.kt index cec43dfc08..58bb2d6778 100644 --- a/vector/src/main/java/im/vector/app/core/dialogs/GalleryOrCameraDialogHelper.kt +++ b/vector/src/main/java/im/vector/app/core/dialogs/GalleryOrCameraDialogHelper.kt @@ -22,7 +22,6 @@ import androidx.core.net.toUri import androidx.fragment.app.Fragment import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.yalantis.ucrop.UCrop -import im.vector.app.R import im.vector.app.core.dialogs.GalleryOrCameraDialogHelper.Listener import im.vector.app.core.extensions.insertBeforeLast import im.vector.app.core.extensions.registerStartForActivityResult @@ -35,6 +34,7 @@ import im.vector.app.features.media.createUCropWithDefaultSettings import im.vector.lib.core.utils.timer.Clock import im.vector.lib.multipicker.MultiPicker import im.vector.lib.multipicker.entity.MultiPickerImageType +import im.vector.lib.strings.CommonStrings import java.io.File /** @@ -62,7 +62,7 @@ class GalleryOrCameraDialogHelper( if (allGranted) { doOpenCamera() } else if (deniedPermanently) { - activity.onPermissionDeniedDialog(R.string.denied_permission_camera) + activity.onPermissionDeniedDialog(CommonStrings.denied_permission_camera) } } @@ -95,7 +95,7 @@ class GalleryOrCameraDialogHelper( private fun startUCrop(image: MultiPickerImageType) { val destinationFile = File(activity.cacheDir, image.displayName.insertBeforeLast("_e_${clock.epochMillis()}")) val uri = image.contentUri - createUCropWithDefaultSettings(colorProvider, uri, destinationFile.toUri(), fragment.getString(R.string.rotate_and_crop_screen_title)) + createUCropWithDefaultSettings(colorProvider, uri, destinationFile.toUri(), fragment.getString(CommonStrings.rotate_and_crop_screen_title)) .withAspectRatio(1f, 1f) .getIntent(activity) .let { uCropActivityResultLauncher.launch(it) } @@ -108,16 +108,16 @@ class GalleryOrCameraDialogHelper( fun show() { MaterialAlertDialogBuilder(activity) - .setTitle(R.string.attachment_type_dialog_title) + .setTitle(CommonStrings.attachment_type_dialog_title) .setItems( arrayOf( - fragment.getString(R.string.attachment_type_camera), - fragment.getString(R.string.attachment_type_gallery) + fragment.getString(CommonStrings.attachment_type_camera), + fragment.getString(CommonStrings.attachment_type_gallery) ) ) { _, which -> onAvatarTypeSelected(if (which == 0) Type.Camera else Type.Gallery) } - .setPositiveButton(R.string.action_cancel, null) + .setPositiveButton(CommonStrings.action_cancel, null) .show() } diff --git a/vector/src/main/java/im/vector/app/core/dialogs/ManuallyVerifyDialog.kt b/vector/src/main/java/im/vector/app/core/dialogs/ManuallyVerifyDialog.kt index f3923fc4e0..291b525f95 100644 --- a/vector/src/main/java/im/vector/app/core/dialogs/ManuallyVerifyDialog.kt +++ b/vector/src/main/java/im/vector/app/core/dialogs/ManuallyVerifyDialog.kt @@ -20,6 +20,7 @@ import android.app.Activity import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.databinding.DialogDeviceVerifyBinding +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.getFingerprintHumanReadable import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo @@ -29,12 +30,12 @@ object ManuallyVerifyDialog { val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_device_verify, null) val views = DialogDeviceVerifyBinding.bind(dialogLayout) val builder = MaterialAlertDialogBuilder(activity) - .setTitle(R.string.cross_signing_verify_by_text) + .setTitle(CommonStrings.cross_signing_verify_by_text) .setView(dialogLayout) - .setPositiveButton(R.string.encryption_information_verify) { _, _ -> + .setPositiveButton(CommonStrings.encryption_information_verify) { _, _ -> onVerified() } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) views.encryptedDeviceInfoDeviceName.text = cryptoDeviceInfo.displayName() views.encryptedDeviceInfoDeviceId.text = cryptoDeviceInfo.deviceId diff --git a/vector/src/main/java/im/vector/app/core/dialogs/PhotoOrVideoDialog.kt b/vector/src/main/java/im/vector/app/core/dialogs/PhotoOrVideoDialog.kt index 9effa4c489..ccd203f79c 100644 --- a/vector/src/main/java/im/vector/app/core/dialogs/PhotoOrVideoDialog.kt +++ b/vector/src/main/java/im/vector/app/core/dialogs/PhotoOrVideoDialog.kt @@ -22,6 +22,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.databinding.DialogPhotoOrVideoBinding import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings class PhotoOrVideoDialog( private val activity: Activity, @@ -52,12 +53,12 @@ class PhotoOrVideoDialog( views.dialogPhotoOrVideoPhoto.isChecked = true MaterialAlertDialogBuilder(activity) - .setTitle(R.string.option_take_photo_video) + .setTitle(CommonStrings.option_take_photo_video) .setView(dialogLayout) - .setPositiveButton(R.string._continue) { _, _ -> + .setPositiveButton(CommonStrings._continue) { _, _ -> submit(views, vectorPreferences, listener) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } } @@ -98,13 +99,13 @@ class PhotoOrVideoDialog( views.dialogPhotoOrVideoAlwaysAsk.isChecked = currentMode == VectorPreferences.TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK MaterialAlertDialogBuilder(activity) - .setTitle(R.string.option_take_photo_video) + .setTitle(CommonStrings.option_take_photo_video) .setView(dialogLayout) - .setPositiveButton(R.string.action_save) { _, _ -> + .setPositiveButton(CommonStrings.action_save) { _, _ -> submitSettings(views) listener.onUpdated() } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } diff --git a/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt b/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt index df50175f87..1414113746 100644 --- a/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt +++ b/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt @@ -21,6 +21,7 @@ import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.resources.StringProvider import im.vector.app.databinding.DialogSslFingerprintBinding +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.network.ssl.Fingerprint import timber.log.Timber import javax.inject.Inject @@ -121,37 +122,37 @@ class UnrecognizedCertificateDialog @Inject constructor( val inflater = activity.layoutInflater val layout = inflater.inflate(R.layout.dialog_ssl_fingerprint, null) val views = DialogSslFingerprintBinding.bind(layout) - views.sslFingerprintTitle.text = stringProvider.getString(R.string.ssl_fingerprint_hash, unrecognizedFingerprint.hashType.toString()) + views.sslFingerprintTitle.text = stringProvider.getString(CommonStrings.ssl_fingerprint_hash, unrecognizedFingerprint.hashType.toString()) views.sslFingerprint.text = unrecognizedFingerprint.displayableHexRepr if (userId != null) { views.sslUserId.text = stringProvider.getString( - R.string.generic_label_and_value, - stringProvider.getString(R.string.username), + CommonStrings.generic_label_and_value, + stringProvider.getString(CommonStrings.username), userId ) } else { views.sslUserId.text = stringProvider.getString( - R.string.generic_label_and_value, - stringProvider.getString(R.string.hs_url), + CommonStrings.generic_label_and_value, + stringProvider.getString(CommonStrings.hs_url), homeServerUrl ) } if (existing) { if (homeServerConnectionConfigHasFingerprints) { - views.sslExplanation.text = stringProvider.getString(R.string.ssl_expected_existing_expl) + views.sslExplanation.text = stringProvider.getString(CommonStrings.ssl_expected_existing_expl) } else { - views.sslExplanation.text = stringProvider.getString(R.string.ssl_unexpected_existing_expl) + views.sslExplanation.text = stringProvider.getString(CommonStrings.ssl_unexpected_existing_expl) } } else { - views.sslExplanation.text = stringProvider.getString(R.string.ssl_cert_new_account_expl) + views.sslExplanation.text = stringProvider.getString(CommonStrings.ssl_cert_new_account_expl) } builder.setView(layout) - builder.setTitle(R.string.ssl_could_not_verify) - builder.setPositiveButton(R.string.ssl_trust) { _, _ -> + builder.setTitle(CommonStrings.ssl_could_not_verify) + builder.setPositiveButton(CommonStrings.ssl_trust) { _, _ -> callback.onAccept() } if (existing) { - builder.setNegativeButton(R.string.ssl_remain_offline) { _, _ -> + builder.setNegativeButton(CommonStrings.ssl_remain_offline) { _, _ -> if (userId != null) { var f = ignoredFingerprints[userId] if (f == null) { @@ -162,9 +163,9 @@ class UnrecognizedCertificateDialog @Inject constructor( } callback.onIgnore() } - builder.setNeutralButton(R.string.ssl_logout_account) { _, _ -> callback.onReject() } + builder.setNeutralButton(CommonStrings.ssl_logout_account) { _, _ -> callback.onReject() } } else { - builder.setNegativeButton(R.string.action_cancel) { _, _ -> callback.onReject() } + builder.setNegativeButton(CommonStrings.action_cancel) { _, _ -> callback.onReject() } } builder.setOnDismissListener { diff --git a/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt index 07a4a2f4e1..8d11e92f1a 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt @@ -27,6 +27,7 @@ import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R import im.vector.app.core.extensions.copyOnLongClick +import im.vector.lib.strings.CommonStrings @EpoxyModelClass abstract class ExpandableTextItem : VectorEpoxyModel(R.layout.item_expandable_textview) { @@ -76,7 +77,7 @@ abstract class ExpandableTextItem : VectorEpoxyModel( holder.content.ellipsize = null holder.arrow.setImageResource(R.drawable.ic_expand_less) - holder.arrow.contentDescription = holder.view.context.getString(R.string.merged_events_collapse) + holder.arrow.contentDescription = holder.view.context.getString(CommonStrings.merged_events_collapse) isExpanded = true } @@ -88,7 +89,7 @@ abstract class ExpandableTextItem : VectorEpoxyModel( holder.content.ellipsize = TextUtils.TruncateAt.END holder.arrow.setImageResource(R.drawable.ic_expand_more) - holder.arrow.contentDescription = holder.view.context.getString(R.string.merged_events_expand) + holder.arrow.contentDescription = holder.view.context.getString(CommonStrings.merged_events_expand) isExpanded = false } diff --git a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetActionItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetActionItem.kt index 0656726e7d..2769c995a1 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetActionItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetActionItem.kt @@ -82,9 +82,9 @@ abstract class BottomSheetActionItem : VectorEpoxyModel(R. } holder.title.text = title val titleTintColor = if (destructive) { - ThemeUtils.getColor(holder.view.context, R.attr.colorError) + ThemeUtils.getColor(holder.view.context, com.google.android.material.R.attr.colorError) } else { - ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_primary) + ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_primary) } val iconTintColor = if (destructive) { - ThemeUtils.getColor(holder.view.context, R.attr.colorError) + ThemeUtils.getColor(holder.view.context, com.google.android.material.R.attr.colorError) } else { - ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary) + ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary) } holder.title.setTextColor(titleTintColor) holder.subtitle.setTextOrHide(subtitle) @@ -118,7 +118,7 @@ abstract class ProfileActionItem : VectorEpoxyModel(R. val tintColorSecondary = if (destructive) { titleTintColor } else { - ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary) + ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary) } holder.editable.setImageResource(editableRes) ImageViewCompat.setImageTintList(holder.editable, ColorStateList.valueOf(tintColorSecondary)) diff --git a/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/NotificationSettingsFooterItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/NotificationSettingsFooterItem.kt index 203a10a6fe..a8a8081b44 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/NotificationSettingsFooterItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/NotificationSettingsFooterItem.kt @@ -24,6 +24,7 @@ import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel import im.vector.app.core.extensions.setTextWithColoredPart +import im.vector.lib.strings.CommonStrings @EpoxyModelClass abstract class NotificationSettingsFooterItem : VectorEpoxyModel(R.layout.item_notifications_footer) { @@ -36,14 +37,14 @@ abstract class NotificationSettingsFooterItem : VectorEpoxyModel(R.layout.item_radio) { @@ -55,11 +56,11 @@ abstract class RadioButtonItem : VectorEpoxyModel(R.layo } if (selected) { - holder.radioImage.setAttributeTintedImageResource(R.drawable.ic_radio_on, R.attr.colorPrimary) - holder.radioImage.contentDescription = holder.view.context.getString(R.string.a11y_checked) + holder.radioImage.setAttributeTintedImageResource(R.drawable.ic_radio_on, com.google.android.material.R.attr.colorPrimary) + holder.radioImage.contentDescription = holder.view.context.getString(CommonStrings.a11y_checked) } else { holder.radioImage.setImageDrawable(ContextCompat.getDrawable(holder.view.context, R.drawable.ic_radio_off)) - holder.radioImage.contentDescription = holder.view.context.getString(R.string.a11y_unchecked) + holder.radioImage.contentDescription = holder.view.context.getString(CommonStrings.a11y_unchecked) } } diff --git a/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt b/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt index 84f866d1f3..1980c1508c 100644 --- a/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt +++ b/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt @@ -17,13 +17,14 @@ package im.vector.app.core.error import android.content.ActivityNotFoundException -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.call.dialpad.DialPadLookup import im.vector.app.features.roomprofile.polls.RoomPollsLoadingError import im.vector.app.features.voice.VoiceFailure import im.vector.app.features.voicebroadcast.VoiceBroadcastFailure import im.vector.app.features.voicebroadcast.VoiceBroadcastFailure.RecordingError +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.api.failure.MatrixIdFailure @@ -52,66 +53,66 @@ class DefaultErrorFormatter @Inject constructor( is Failure.NetworkConnection -> { when (throwable.ioException) { is SocketTimeoutException -> - stringProvider.getString(R.string.error_network_timeout) + stringProvider.getString(CommonStrings.error_network_timeout) is SSLPeerUnverifiedException -> - stringProvider.getString(R.string.login_error_ssl_peer_unverified) + stringProvider.getString(CommonStrings.login_error_ssl_peer_unverified) is SSLException -> - stringProvider.getString(R.string.login_error_ssl_other) + stringProvider.getString(CommonStrings.login_error_ssl_other) else -> // TODO Check network state, airplane mode, etc. - stringProvider.getString(R.string.error_no_network) + stringProvider.getString(CommonStrings.error_no_network) } } is Failure.ServerError -> { when { throwable.error.code == MatrixError.M_CONSENT_NOT_GIVEN -> { // Special case for terms and conditions - stringProvider.getString(R.string.error_terms_not_accepted) + stringProvider.getString(CommonStrings.error_terms_not_accepted) } throwable.isInvalidPassword() -> { - stringProvider.getString(R.string.auth_invalid_login_param) + stringProvider.getString(CommonStrings.auth_invalid_login_param) } throwable.error.code == MatrixError.M_USER_IN_USE -> { - stringProvider.getString(R.string.login_signup_error_user_in_use) + stringProvider.getString(CommonStrings.login_signup_error_user_in_use) } throwable.error.code == MatrixError.M_BAD_JSON -> { - stringProvider.getString(R.string.login_error_bad_json) + stringProvider.getString(CommonStrings.login_error_bad_json) } throwable.error.code == MatrixError.M_NOT_JSON -> { - stringProvider.getString(R.string.login_error_not_json) + stringProvider.getString(CommonStrings.login_error_not_json) } throwable.error.code == MatrixError.M_THREEPID_DENIED -> { - stringProvider.getString(R.string.login_error_threepid_denied) + stringProvider.getString(CommonStrings.login_error_threepid_denied) } throwable.isLimitExceededError() -> { limitExceededError(throwable.error) } throwable.error.code == MatrixError.M_TOO_LARGE -> { - stringProvider.getString(R.string.error_file_too_big_simple) + stringProvider.getString(CommonStrings.error_file_too_big_simple) } throwable.error.code == MatrixError.M_THREEPID_NOT_FOUND -> { - stringProvider.getString(R.string.login_reset_password_error_not_found) + stringProvider.getString(CommonStrings.login_reset_password_error_not_found) } throwable.error.code == MatrixError.M_USER_DEACTIVATED -> { - stringProvider.getString(R.string.auth_invalid_login_deactivated_account) + stringProvider.getString(CommonStrings.auth_invalid_login_deactivated_account) } throwable.error.code == MatrixError.M_THREEPID_IN_USE && throwable.error.message == "Email is already in use" -> { - stringProvider.getString(R.string.account_email_already_used_error) + stringProvider.getString(CommonStrings.account_email_already_used_error) } throwable.error.code == MatrixError.M_THREEPID_IN_USE && throwable.error.message == "MSISDN is already in use" -> { - stringProvider.getString(R.string.account_phone_number_already_used_error) + stringProvider.getString(CommonStrings.account_phone_number_already_used_error) } throwable.error.code == MatrixError.M_THREEPID_AUTH_FAILED -> { - stringProvider.getString(R.string.error_threepid_auth_failed) + stringProvider.getString(CommonStrings.error_threepid_auth_failed) } throwable.error.code == MatrixError.M_UNKNOWN && throwable.error.message == "Not allowed to join this room" -> { - stringProvider.getString(R.string.room_error_access_unauthorized) + stringProvider.getString(CommonStrings.room_error_access_unauthorized) } throwable.isMissingEmailVerification() -> { - stringProvider.getString(R.string.auth_reset_password_error_unverified) + stringProvider.getString(CommonStrings.auth_reset_password_error_unverified) } else -> { throwable.error.message.takeIf { it.isNotEmpty() } @@ -123,46 +124,46 @@ class DefaultErrorFormatter @Inject constructor( when (throwable.httpCode) { HttpURLConnection.HTTP_NOT_FOUND -> // homeserver not found - stringProvider.getString(R.string.login_error_no_homeserver_found) + stringProvider.getString(CommonStrings.login_error_no_homeserver_found) HttpURLConnection.HTTP_UNAUTHORIZED -> // uia errors? - stringProvider.getString(R.string.error_unauthorized) + stringProvider.getString(CommonStrings.error_unauthorized) else -> throwable.localizedMessage } } is DialPadLookup.Failure.NumberIsYours -> - stringProvider.getString(R.string.cannot_call_yourself) + stringProvider.getString(CommonStrings.cannot_call_yourself) is DialPadLookup.Failure.NoResult -> - stringProvider.getString(R.string.call_dial_pad_lookup_error) + stringProvider.getString(CommonStrings.call_dial_pad_lookup_error) is MatrixIdFailure.InvalidMatrixId -> - stringProvider.getString(R.string.login_signin_matrix_id_error_invalid_matrix_id) + stringProvider.getString(CommonStrings.login_signin_matrix_id_error_invalid_matrix_id) is VoiceFailure -> voiceMessageError(throwable) is VoiceBroadcastFailure -> voiceBroadcastMessageError(throwable) - is RoomPollsLoadingError -> stringProvider.getString(R.string.room_polls_loading_error) + is RoomPollsLoadingError -> stringProvider.getString(CommonStrings.room_polls_loading_error) is ActivityNotFoundException -> - stringProvider.getString(R.string.error_no_external_application_found) + stringProvider.getString(CommonStrings.error_no_external_application_found) else -> throwable.localizedMessage } - ?: stringProvider.getString(R.string.unknown_error) + ?: stringProvider.getString(CommonStrings.unknown_error) } private fun voiceMessageError(throwable: VoiceFailure): String { return when (throwable) { - is VoiceFailure.UnableToPlay -> stringProvider.getString(R.string.error_voice_message_unable_to_play) - is VoiceFailure.UnableToRecord -> stringProvider.getString(R.string.error_voice_message_unable_to_record) - is VoiceFailure.VoiceBroadcastInProgress -> stringProvider.getString(R.string.error_voice_message_broadcast_in_progress) + is VoiceFailure.UnableToPlay -> stringProvider.getString(CommonStrings.error_voice_message_unable_to_play) + is VoiceFailure.UnableToRecord -> stringProvider.getString(CommonStrings.error_voice_message_unable_to_record) + is VoiceFailure.VoiceBroadcastInProgress -> stringProvider.getString(CommonStrings.error_voice_message_broadcast_in_progress) } } private fun voiceBroadcastMessageError(throwable: VoiceBroadcastFailure): String { return when (throwable) { - RecordingError.BlockedBySomeoneElse -> stringProvider.getString(R.string.error_voice_broadcast_blocked_by_someone_else_message) - RecordingError.NoPermission -> stringProvider.getString(R.string.error_voice_broadcast_permission_denied_message) - RecordingError.UserAlreadyBroadcasting -> stringProvider.getString(R.string.error_voice_broadcast_already_in_progress_message) + RecordingError.BlockedBySomeoneElse -> stringProvider.getString(CommonStrings.error_voice_broadcast_blocked_by_someone_else_message) + RecordingError.NoPermission -> stringProvider.getString(CommonStrings.error_voice_broadcast_permission_denied_message) + RecordingError.UserAlreadyBroadcasting -> stringProvider.getString(CommonStrings.error_voice_broadcast_already_in_progress_message) is VoiceBroadcastFailure.ListeningError.UnableToPlay, - is VoiceBroadcastFailure.ListeningError.PrepareMediaPlayerError -> stringProvider.getString(R.string.error_voice_broadcast_unable_to_play) - is VoiceBroadcastFailure.ListeningError.UnableToDecrypt -> stringProvider.getString(R.string.error_voice_broadcast_unable_to_decrypt) + is VoiceBroadcastFailure.ListeningError.PrepareMediaPlayerError -> stringProvider.getString(CommonStrings.error_voice_broadcast_unable_to_play) + is VoiceBroadcastFailure.ListeningError.UnableToDecrypt -> stringProvider.getString(CommonStrings.error_voice_broadcast_unable_to_decrypt) } } @@ -170,25 +171,25 @@ class DefaultErrorFormatter @Inject constructor( val delay = error.retryAfterMillis return if (delay == null) { - stringProvider.getString(R.string.login_error_limit_exceeded) + stringProvider.getString(CommonStrings.login_error_limit_exceeded) } else { // Ensure at least 1 second val delaySeconds = delay.toInt() / 1000 + 1 - stringProvider.getQuantityString(R.plurals.login_error_limit_exceeded_retry_after, delaySeconds, delaySeconds) + stringProvider.getQuantityString(CommonPlurals.login_error_limit_exceeded_retry_after, delaySeconds, delaySeconds) } } private fun identityServerError(identityServiceError: IdentityServiceError): String { return stringProvider.getString( when (identityServiceError) { - IdentityServiceError.OutdatedIdentityServer -> R.string.identity_server_error_outdated_identity_server - IdentityServiceError.OutdatedHomeServer -> R.string.identity_server_error_outdated_home_server - IdentityServiceError.NoIdentityServerConfigured -> R.string.identity_server_error_no_identity_server_configured - IdentityServiceError.TermsNotSignedException -> R.string.identity_server_error_terms_not_signed - IdentityServiceError.BulkLookupSha256NotSupported -> R.string.identity_server_error_bulk_sha256_not_supported - IdentityServiceError.BindingError -> R.string.identity_server_error_binding_error - IdentityServiceError.NoCurrentBindingError -> R.string.identity_server_error_no_current_binding_error - IdentityServiceError.UserConsentNotProvided -> R.string.identity_server_user_consent_not_provided + IdentityServiceError.OutdatedIdentityServer -> CommonStrings.identity_server_error_outdated_identity_server + IdentityServiceError.OutdatedHomeServer -> CommonStrings.identity_server_error_outdated_home_server + IdentityServiceError.NoIdentityServerConfigured -> CommonStrings.identity_server_error_no_identity_server_configured + IdentityServiceError.TermsNotSignedException -> CommonStrings.identity_server_error_terms_not_signed + IdentityServiceError.BulkLookupSha256NotSupported -> CommonStrings.identity_server_error_bulk_sha256_not_supported + IdentityServiceError.BindingError -> CommonStrings.identity_server_error_binding_error + IdentityServiceError.NoCurrentBindingError -> CommonStrings.identity_server_error_no_current_binding_error + IdentityServiceError.UserConsentNotProvided -> CommonStrings.identity_server_user_consent_not_provided } ) } diff --git a/vector/src/main/java/im/vector/app/core/error/ResourceLimitErrorFormatter.kt b/vector/src/main/java/im/vector/app/core/error/ResourceLimitErrorFormatter.kt index cfe9d2db58..c8d46bb545 100644 --- a/vector/src/main/java/im/vector/app/core/error/ResourceLimitErrorFormatter.kt +++ b/vector/src/main/java/im/vector/app/core/error/ResourceLimitErrorFormatter.kt @@ -19,7 +19,7 @@ package im.vector.app.core.error import android.content.Context import androidx.annotation.StringRes import androidx.core.text.HtmlCompat -import im.vector.app.R +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span import org.matrix.android.sdk.api.failure.MatrixError @@ -28,10 +28,10 @@ class ResourceLimitErrorFormatter(private val context: Context) { // 'hard' if the logged in user has been locked out, 'soft' if they haven't sealed class Mode(@StringRes val mauErrorRes: Int, @StringRes val defaultErrorRes: Int, @StringRes val contactRes: Int) { // User can still send message (will be used in a near future) - object Soft : Mode(R.string.resource_limit_soft_mau, R.string.resource_limit_soft_default, R.string.resource_limit_soft_contact) + object Soft : Mode(CommonStrings.resource_limit_soft_mau, CommonStrings.resource_limit_soft_default, CommonStrings.resource_limit_soft_contact) // User cannot send message anymore - object Hard : Mode(R.string.resource_limit_hard_mau, R.string.resource_limit_hard_default, R.string.resource_limit_hard_contact) + object Hard : Mode(CommonStrings.resource_limit_hard_mau, CommonStrings.resource_limit_hard_default, CommonStrings.resource_limit_hard_contact) } fun format( @@ -50,7 +50,7 @@ class ResourceLimitErrorFormatter(private val context: Context) { val contactFullString = context.getString(mode.contactRes, contactSubString) HtmlCompat.fromHtml(contactFullString, HtmlCompat.FROM_HTML_MODE_LEGACY) } else { - val contactSubString = context.getString(R.string.resource_limit_contact_admin) + val contactSubString = context.getString(CommonStrings.resource_limit_contact_admin) context.getString(mode.contactRes, contactSubString) } return span { @@ -64,7 +64,7 @@ class ResourceLimitErrorFormatter(private val context: Context) { * Create a HTML link with a uri. */ private fun uriAsLink(uri: String): String { - val contactStr = context.getString(R.string.resource_limit_contact_admin) + val contactStr = context.getString(CommonStrings.resource_limit_contact_admin) return "$contactStr" } } diff --git a/vector/src/main/java/im/vector/app/core/extensions/EditText.kt b/vector/src/main/java/im/vector/app/core/extensions/EditText.kt index 2e2c8429d0..f48531b7d5 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/EditText.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/EditText.kt @@ -24,12 +24,11 @@ import android.view.View import android.view.inputmethod.EditorInfo import android.widget.EditText import androidx.annotation.DrawableRes -import im.vector.app.R import im.vector.app.core.platform.SimpleTextWatcher fun EditText.setupAsSearch( - @DrawableRes searchIconRes: Int = R.drawable.ic_home_search, - @DrawableRes clearIconRes: Int = R.drawable.ic_x_gray + @DrawableRes searchIconRes: Int = im.vector.lib.ui.styles.R.drawable.ic_home_search, + @DrawableRes clearIconRes: Int = im.vector.lib.ui.styles.R.drawable.ic_x_gray ) { addTextChangedListener(object : SimpleTextWatcher() { override fun afterTextChanged(s: Editable) { diff --git a/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt b/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt index f3aef54062..2c7bf6ca7b 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt @@ -23,8 +23,8 @@ import androidx.activity.result.ActivityResult import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.fragment.app.Fragment -import im.vector.app.R import im.vector.app.core.utils.selectTxtFileToWrite +import im.vector.lib.strings.CommonStrings import java.text.SimpleDateFormat import java.util.Date import java.util.Locale @@ -168,26 +168,34 @@ fun Fragment.getAllChildFragments(): List { // Define a missing constant const val POP_BACK_STACK_EXCLUSIVE = 0 -fun Fragment.queryExportKeys(userId: String, activityResultLauncher: ActivityResultLauncher) { +fun Fragment.queryExportKeys( + userId: String, + applicationName: String, + activityResultLauncher: ActivityResultLauncher, +) { val timestamp = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date()) - val appName = getString(R.string.app_name).replace(" ", "-") + val appName = applicationName.replace(" ", "-") selectTxtFileToWrite( activity = requireActivity(), activityResultLauncher = activityResultLauncher, defaultFileName = "$appName-megolm-export-$userId-${timestamp}.txt", - chooserHint = getString(R.string.keys_backup_setup_step1_manual_export) + chooserHint = getString(CommonStrings.keys_backup_setup_step1_manual_export) ) } -fun Activity.queryExportKeys(userId: String, activityResultLauncher: ActivityResultLauncher) { +fun Activity.queryExportKeys( + userId: String, + applicationName: String, + activityResultLauncher: ActivityResultLauncher, +) { val timestamp = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date()) - val appName = getString(R.string.app_name).replace(" ", "-") + val appName = applicationName.replace(" ", "-") selectTxtFileToWrite( activity = this, activityResultLauncher = activityResultLauncher, defaultFileName = "$appName-megolm-export-$userId-${timestamp}.txt", - chooserHint = getString(R.string.keys_backup_setup_step1_manual_export) + chooserHint = getString(CommonStrings.keys_backup_setup_step1_manual_export) ) } diff --git a/vector/src/main/java/im/vector/app/core/extensions/TextView.kt b/vector/src/main/java/im/vector/app/core/extensions/TextView.kt index 3c453d854d..b0454149b0 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/TextView.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/TextView.kt @@ -32,10 +32,10 @@ import androidx.annotation.StringRes import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.DrawableCompat import androidx.core.view.isVisible -import im.vector.app.R import im.vector.app.core.platform.showOptimizedSnackbar import im.vector.app.core.utils.copyToClipboard import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings /** * Set a text in the TextView, or set visibility to GONE if the text is null. @@ -63,7 +63,7 @@ fun TextView.setTextOrHide(newText: CharSequence?, hideWhenBlank: Boolean = true fun TextView.setTextWithColoredPart( @StringRes fullTextRes: Int, @StringRes coloredTextRes: Int, - @AttrRes colorAttribute: Int = R.attr.colorPrimary, + @AttrRes colorAttribute: Int = com.google.android.material.R.attr.colorPrimary, underline: Boolean = false, onClick: (() -> Unit)? = null ) { @@ -85,7 +85,7 @@ fun TextView.setTextWithColoredPart( fun TextView.setTextWithColoredPart( fullText: String, coloredPart: String, - @AttrRes colorAttribute: Int = R.attr.colorPrimary, + @AttrRes colorAttribute: Int = com.google.android.material.R.attr.colorPrimary, underline: Boolean = true, onClick: (() -> Unit)? = null ) { @@ -146,7 +146,7 @@ fun TextView.copyOnLongClick() { ?.text ?.let { text -> copyToClipboard(view.context, text, false) - view.showOptimizedSnackbar(view.resources.getString(R.string.copied_to_clipboard)) + view.showOptimizedSnackbar(view.resources.getString(CommonStrings.copied_to_clipboard)) } true } diff --git a/vector/src/main/java/im/vector/app/core/extensions/ViewExtensions.kt b/vector/src/main/java/im/vector/app/core/extensions/ViewExtensions.kt index 55ad5294d9..0db48a97c2 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/ViewExtensions.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/ViewExtensions.kt @@ -27,37 +27,17 @@ import android.widget.ImageView import androidx.annotation.AttrRes import androidx.annotation.ColorInt import androidx.annotation.DrawableRes -import androidx.appcompat.widget.SearchView import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.DrawableCompat -import androidx.core.view.ViewCompat import androidx.core.view.isVisible import androidx.transition.ChangeBounds import androidx.transition.Fade import androidx.transition.Transition import androidx.transition.TransitionManager import androidx.transition.TransitionSet -import im.vector.app.R import im.vector.app.core.animations.SimpleTransitionListener import im.vector.app.features.themes.ThemeUtils -/** - * Remove left margin of a SearchView. - */ -fun SearchView.withoutLeftMargin() { - (findViewById(R.id.search_edit_frame))?.let { - val searchEditFrameParams = it.layoutParams as ViewGroup.MarginLayoutParams - searchEditFrameParams.leftMargin = 0 - it.layoutParams = searchEditFrameParams - } - - (findViewById(R.id.search_mag_icon))?.let { - val searchIconParams = it.layoutParams as ViewGroup.MarginLayoutParams - searchIconParams.leftMargin = 0 - it.layoutParams = searchIconParams - } -} - fun EditText.hidePassword() { inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD } @@ -104,7 +84,7 @@ fun View.setAttributeBackground(@AttrRes attributeId: Int) { * Inspired from https://stackoverflow.com/a/64597532/1472514. Safer to call the 2 available API. */ fun View.giveAccessibilityFocus() { - ViewCompat.performAccessibilityAction(this, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null) + performAccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null) sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED) } diff --git a/vector/src/main/java/im/vector/app/core/platform/BadgeFloatingActionButton.kt b/vector/src/main/java/im/vector/app/core/platform/BadgeFloatingActionButton.kt index e2adc0993a..264af39f9e 100644 --- a/vector/src/main/java/im/vector/app/core/platform/BadgeFloatingActionButton.kt +++ b/vector/src/main/java/im/vector/app/core/platform/BadgeFloatingActionButton.kt @@ -28,7 +28,6 @@ import android.text.TextPaint import android.util.AttributeSet import androidx.core.content.res.use import com.google.android.material.floatingactionbutton.FloatingActionButton -import im.vector.app.R import kotlin.math.PI import kotlin.math.cos import kotlin.math.max @@ -135,11 +134,11 @@ class BadgeFloatingActionButton @JvmOverloads constructor( @SuppressWarnings("Recycle") private fun initAttrs(attrs: AttributeSet) { - context.obtainStyledAttributes(attrs, R.styleable.BadgeFloatingActionButton).use { - counterBackgroundColor = it.getColor(R.styleable.BadgeFloatingActionButton_badgeBackgroundColor, 0) - counterTextPadding = it.getDimension(R.styleable.BadgeFloatingActionButton_badgeTextPadding, 0f) - counterTextSize = it.getDimension(R.styleable.BadgeFloatingActionButton_badgeTextSize, 14f) - counterTextColor = it.getColor(R.styleable.BadgeFloatingActionButton_badgeTextColor, Color.WHITE) + context.obtainStyledAttributes(attrs, im.vector.lib.ui.styles.R.styleable.BadgeFloatingActionButton).use { + counterBackgroundColor = it.getColor(im.vector.lib.ui.styles.R.styleable.BadgeFloatingActionButton_badgeBackgroundColor, 0) + counterTextPadding = it.getDimension(im.vector.lib.ui.styles.R.styleable.BadgeFloatingActionButton_badgeTextPadding, 0f) + counterTextSize = it.getDimension(im.vector.lib.ui.styles.R.styleable.BadgeFloatingActionButton_badgeTextSize, 14f) + counterTextColor = it.getColor(im.vector.lib.ui.styles.R.styleable.BadgeFloatingActionButton_badgeTextColor, Color.WHITE) } } diff --git a/vector/src/main/java/im/vector/app/core/platform/ButtonStateView.kt b/vector/src/main/java/im/vector/app/core/platform/ButtonStateView.kt index 128591fd96..b36b21129a 100755 --- a/vector/src/main/java/im/vector/app/core/platform/ButtonStateView.kt +++ b/vector/src/main/java/im/vector/app/core/platform/ButtonStateView.kt @@ -61,12 +61,12 @@ class ButtonStateView @JvmOverloads constructor(context: Context, attrs: Attribu // Read attributes context.theme.obtainStyledAttributes( attrs, - R.styleable.ButtonStateView, + im.vector.lib.ui.styles.R.styleable.ButtonStateView, 0, 0 ) .apply { try { - if (getBoolean(R.styleable.ButtonStateView_bsv_use_flat_button, true)) { + if (getBoolean(im.vector.lib.ui.styles.R.styleable.ButtonStateView_bsv_use_flat_button, true)) { button = views.buttonStateButtonFlat views.buttonStateButtonBig.isVisible = false } else { @@ -74,8 +74,8 @@ class ButtonStateView @JvmOverloads constructor(context: Context, attrs: Attribu views.buttonStateButtonFlat.isVisible = false } - button.text = getString(R.styleable.ButtonStateView_bsv_button_text) - views.buttonStateLoaded.setImageDrawable(getDrawable(R.styleable.ButtonStateView_bsv_loaded_image_src)) + button.text = getString(im.vector.lib.ui.styles.R.styleable.ButtonStateView_bsv_button_text) + views.buttonStateLoaded.setImageDrawable(getDrawable(im.vector.lib.ui.styles.R.styleable.ButtonStateView_bsv_loaded_image_src)) } finally { recycle() } diff --git a/vector/src/main/java/im/vector/app/core/platform/MaxHeightScrollView.kt b/vector/src/main/java/im/vector/app/core/platform/MaxHeightScrollView.kt index da15d4413d..2701ef75fe 100644 --- a/vector/src/main/java/im/vector/app/core/platform/MaxHeightScrollView.kt +++ b/vector/src/main/java/im/vector/app/core/platform/MaxHeightScrollView.kt @@ -20,7 +20,6 @@ import android.content.Context import android.util.AttributeSet import androidx.core.content.withStyledAttributes import androidx.core.widget.NestedScrollView -import im.vector.app.R private const val DEFAULT_MAX_HEIGHT = 200 @@ -35,8 +34,8 @@ class MaxHeightScrollView @JvmOverloads constructor(context: Context, attrs: Att init { if (attrs != null) { - context.withStyledAttributes(attrs, R.styleable.MaxHeightScrollView) { - maxHeight = getDimensionPixelSize(R.styleable.MaxHeightScrollView_maxHeight, DEFAULT_MAX_HEIGHT) + context.withStyledAttributes(attrs, im.vector.lib.ui.styles.R.styleable.MaxHeightScrollView) { + maxHeight = getDimensionPixelSize(im.vector.lib.ui.styles.R.styleable.MaxHeightScrollView_maxHeight, DEFAULT_MAX_HEIGHT) } } } diff --git a/vector/src/main/java/im/vector/app/core/platform/ScreenOrientationLocker.kt b/vector/src/main/java/im/vector/app/core/platform/ScreenOrientationLocker.kt index 37a0352dc6..651e6c35b7 100644 --- a/vector/src/main/java/im/vector/app/core/platform/ScreenOrientationLocker.kt +++ b/vector/src/main/java/im/vector/app/core/platform/ScreenOrientationLocker.kt @@ -20,7 +20,7 @@ import android.annotation.SuppressLint import android.content.pm.ActivityInfo import android.content.res.Resources import androidx.appcompat.app.AppCompatActivity -import im.vector.app.R +import im.vector.lib.ui.styles.R import javax.inject.Inject class ScreenOrientationLocker @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/core/platform/SimpleFragmentActivity.kt b/vector/src/main/java/im/vector/app/core/platform/SimpleFragmentActivity.kt index 794d5c7886..2599e322bc 100644 --- a/vector/src/main/java/im/vector/app/core/platform/SimpleFragmentActivity.kt +++ b/vector/src/main/java/im/vector/app/core/platform/SimpleFragmentActivity.kt @@ -78,6 +78,7 @@ abstract class SimpleFragmentActivity : VectorBaseActivity() { super.hideWaitingView() } + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() { if (waitingView!!.isVisible) { // ignore 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 5bdd960e00..a4dd00f74a 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 @@ -16,6 +16,7 @@ package im.vector.app.core.platform +import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.os.Build @@ -91,6 +92,7 @@ import im.vector.app.features.settings.VectorLocaleProvider import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.themes.ActivityOtherThemes import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @@ -253,7 +255,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver if (vectorPreferences.isNewAppLayoutEnabled()) { tryOrNull { // Add to XML theme when feature flag is removed - val toolbarBackground = MaterialColors.getColor(views.root, R.attr.vctr_toolbar_background) + val toolbarBackground = MaterialColors.getColor(views.root, im.vector.lib.ui.styles.R.attr.vctr_toolbar_background) window.statusBarColor = toolbarBackground window.navigationBarColor = toolbarBackground } @@ -321,20 +323,20 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver private fun handleInitialSyncRequest(initialSyncRequest: GlobalError.InitialSyncRequest) { MaterialAlertDialogBuilder(this) - .setTitle(R.string.initial_sync_request_title) + .setTitle(CommonStrings.initial_sync_request_title) .setMessage( getString( - R.string.initial_sync_request_content, getString( + CommonStrings.initial_sync_request_content, getString( when (initialSyncRequest.reason) { - InitialSyncRequestReason.IGNORED_USERS_LIST_CHANGE -> R.string.initial_sync_request_reason_unignored_users + InitialSyncRequestReason.IGNORED_USERS_LIST_CHANGE -> CommonStrings.initial_sync_request_reason_unignored_users } ) ) ) - .setPositiveButton(R.string.ok) { _, _ -> + .setPositiveButton(CommonStrings.ok) { _, _ -> MainActivity.restartApp(this, MainActivityArgs(clearCache = true)) } - .setNegativeButton(R.string.later, null) + .setNegativeButton(CommonStrings.later, null) .show() } @@ -478,9 +480,9 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver // New API instead of SYSTEM_UI_FLAG_IMMERSIVE window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE // New API instead of FLAG_TRANSLUCENT_STATUS - window.statusBarColor = ContextCompat.getColor(this, im.vector.lib.attachmentviewer.R.color.half_transparent_status_bar) + window.statusBarColor = ContextCompat.getColor(this, im.vector.lib.ui.styles.R.color.half_transparent_status_bar) // New API instead of FLAG_TRANSLUCENT_NAVIGATION - window.navigationBarColor = ContextCompat.getColor(this, im.vector.lib.attachmentviewer.R.color.half_transparent_status_bar) + window.navigationBarColor = ContextCompat.getColor(this, im.vector.lib.ui.styles.R.color.half_transparent_status_bar) } else { @Suppress("DEPRECATION") window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE @@ -502,6 +504,8 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver } } + @SuppressLint("MissingSuperCall") + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() { onBackPressed(false) } @@ -646,9 +650,9 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver fun notImplemented(message: String = "") { if (message.isNotBlank()) { - toast(getString(R.string.not_implemented) + ": $message") + toast(getString(CommonStrings.not_implemented) + ": $message") } else { - toast(getString(R.string.not_implemented)) + toast(getString(CommonStrings.not_implemented)) } } diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseDialogFragment.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseDialogFragment.kt index 34e233aa7a..68a919c0ae 100644 --- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseDialogFragment.kt +++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseDialogFragment.kt @@ -30,7 +30,6 @@ import androidx.lifecycle.repeatOnLifecycle import androidx.viewbinding.ViewBinding import com.airbnb.mvrx.MavericksView import dagger.hilt.android.EntryPointAccessors -import im.vector.app.R import im.vector.app.core.di.ActivityEntryPoint import im.vector.app.core.extensions.singletonEntryPoint import im.vector.app.core.extensions.toMvRxBundle @@ -126,7 +125,7 @@ abstract class VectorBaseDialogFragment : DialogFragment(), Ma // This ensures that invalidate() is called for static screens that don't // subscribe to a ViewModel. postInvalidate() - requireDialog().window?.setWindowAnimations(R.style.Animation_AppCompat_Dialog) + requireDialog().window?.setWindowAnimations(androidx.appcompat.R.style.Animation_AppCompat_Dialog) } protected fun setArguments(args: Parcelable? = null) { diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt index b57f288c09..05f2506ff1 100644 --- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt +++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt @@ -41,7 +41,6 @@ import com.bumptech.glide.util.Util.assertMainThread import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.EntryPointAccessors -import im.vector.app.R import im.vector.app.core.di.ActivityEntryPoint import im.vector.app.core.dialogs.UnrecognizedCertificateDialog import im.vector.app.core.error.ErrorFormatter @@ -52,6 +51,7 @@ import im.vector.app.core.utils.ToolbarConfig import im.vector.app.features.analytics.AnalyticsTracker import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.navigation.Navigator +import im.vector.lib.strings.CommonStrings import im.vector.lib.ui.styles.dialogs.MaterialProgressDialog import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -251,7 +251,7 @@ abstract class VectorBaseFragment : Fragment(), MavericksView protected fun showLoadingDialog(message: CharSequence? = null) { progress?.dismiss() progress = MaterialProgressDialog(requireContext()) - .show(message ?: getString(R.string.please_wait)) + .show(message ?: getString(CommonStrings.please_wait)) } protected fun dismissLoadingDialog() { @@ -314,9 +314,9 @@ abstract class VectorBaseFragment : Fragment(), MavericksView protected fun displayErrorDialog(throwable: Throwable) { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(errorFormatter.toHumanReadable(throwable)) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } diff --git a/vector/src/main/java/im/vector/app/core/preference/KeywordPreference.kt b/vector/src/main/java/im/vector/app/core/preference/KeywordPreference.kt index 8ec9012367..583eb72f99 100644 --- a/vector/src/main/java/im/vector/app/core/preference/KeywordPreference.kt +++ b/vector/src/main/java/im/vector/app/core/preference/KeywordPreference.kt @@ -30,6 +30,7 @@ import com.google.android.material.textfield.TextInputLayout import im.vector.app.R import im.vector.app.core.epoxy.addTextChangedListenerOnce import im.vector.app.core.platform.SimpleTextWatcher +import im.vector.lib.strings.CommonStrings class KeywordPreference : VectorPreference { @@ -131,13 +132,13 @@ class KeywordPreference : VectorPreference { val keyword = s.toString().trim() val errorMessage = when { keyword.startsWith(".") -> { - context.getString(R.string.settings_notification_keyword_contains_dot) + context.getString(CommonStrings.settings_notification_keyword_contains_dot) } keyword.contains("\\") -> { - context.getString(R.string.settings_notification_keyword_contains_invalid_character, "\\") + context.getString(CommonStrings.settings_notification_keyword_contains_invalid_character, "\\") } keyword.contains("/") -> { - context.getString(R.string.settings_notification_keyword_contains_invalid_character, "/") + context.getString(CommonStrings.settings_notification_keyword_contains_invalid_character, "/") } else -> null } @@ -151,7 +152,7 @@ class KeywordPreference : VectorPreference { } private fun addChipToGroup(keyword: String, chipGroup: ChipGroup) { - val chip = Chip(context, null, R.attr.vctr_keyword_style) + val chip = Chip(context, null, im.vector.lib.ui.styles.R.attr.vctr_keyword_style) chip.text = keyword chipGroup.addView(chip) diff --git a/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt b/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt index c0ff80a0e7..f9e26f7b21 100644 --- a/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt +++ b/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt @@ -23,6 +23,7 @@ import android.widget.RadioGroup import androidx.preference.PreferenceViewHolder import im.vector.app.R import im.vector.app.features.settings.notifications.NotificationIndex +import im.vector.lib.strings.CommonStrings class PushRulePreference : VectorPreference { @@ -58,9 +59,9 @@ class PushRulePreference : VectorPreference { private fun refreshSummary() { summary = context.getString( when (index) { - NotificationIndex.OFF -> R.string.notification_off - NotificationIndex.SILENT -> R.string.notification_silent - NotificationIndex.NOISY, null -> R.string.notification_noisy + NotificationIndex.OFF -> CommonStrings.notification_off + NotificationIndex.SILENT -> CommonStrings.notification_silent + NotificationIndex.NOISY, null -> CommonStrings.notification_noisy } ) } diff --git a/vector/src/main/java/im/vector/app/core/preference/VectorPreference.kt b/vector/src/main/java/im/vector/app/core/preference/VectorPreference.kt index 2dd6f058d7..b8fd5b856b 100755 --- a/vector/src/main/java/im/vector/app/core/preference/VectorPreference.kt +++ b/vector/src/main/java/im/vector/app/core/preference/VectorPreference.kt @@ -31,7 +31,6 @@ import androidx.core.animation.doOnEnd import androidx.core.widget.ImageViewCompat import androidx.preference.Preference import androidx.preference.PreferenceViewHolder -import im.vector.app.R import im.vector.app.features.themes.ThemeUtils import org.matrix.android.sdk.api.extensions.orFalse import timber.log.Timber @@ -108,7 +107,7 @@ open class VectorPreference : Preference { val icon = holder.findViewById(android.R.id.icon) as? ImageView icon?.let { - val color = ThemeUtils.getColor(context, R.attr.vctr_content_secondary) + val color = ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary) ImageViewCompat.setImageTintList(it, ColorStateList.valueOf(color)) } } @@ -117,7 +116,7 @@ open class VectorPreference : Preference { currentHighlightAnimator?.cancel() if (isHighlighted) { val colorFrom = Color.TRANSPARENT - val colorTo = ThemeUtils.getColor(itemView.context, R.attr.colorPrimary) + val colorTo = ThemeUtils.getColor(itemView.context, com.google.android.material.R.attr.colorPrimary) currentHighlightAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo).apply { duration = 250 // milliseconds addUpdateListener { animator -> diff --git a/vector/src/main/java/im/vector/app/core/preference/VectorPreferenceCategory.kt b/vector/src/main/java/im/vector/app/core/preference/VectorPreferenceCategory.kt index d074f0afd9..29ee66eac1 100644 --- a/vector/src/main/java/im/vector/app/core/preference/VectorPreferenceCategory.kt +++ b/vector/src/main/java/im/vector/app/core/preference/VectorPreferenceCategory.kt @@ -23,7 +23,6 @@ import android.view.ViewGroup import android.widget.TextView import androidx.preference.PreferenceCategory import androidx.preference.PreferenceViewHolder -import im.vector.app.R import im.vector.app.features.themes.ThemeUtils /** @@ -48,7 +47,7 @@ class VectorPreferenceCategory : PreferenceCategory { val titleTextView = holder.findViewById(android.R.id.title) as? TextView titleTextView?.setTypeface(null, Typeface.BOLD) - titleTextView?.setTextColor(ThemeUtils.getColor(context, R.attr.vctr_content_primary)) + titleTextView?.setTextColor(ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_content_primary)) // "isIconSpaceReserved = false" does not work for preference category, so remove the padding if (!isIconSpaceReserved) { diff --git a/vector/src/main/java/im/vector/app/core/preference/VectorSwitchPreference.kt b/vector/src/main/java/im/vector/app/core/preference/VectorSwitchPreference.kt index 635cbff568..3aadb6aa25 100644 --- a/vector/src/main/java/im/vector/app/core/preference/VectorSwitchPreference.kt +++ b/vector/src/main/java/im/vector/app/core/preference/VectorSwitchPreference.kt @@ -26,7 +26,6 @@ import android.widget.TextView import androidx.core.animation.doOnEnd import androidx.preference.PreferenceViewHolder import androidx.preference.SwitchPreference -import im.vector.app.R import im.vector.app.features.themes.ThemeUtils /** @@ -66,7 +65,7 @@ class VectorSwitchPreference : SwitchPreference { val itemView = holder.itemView if (isHighlighted) { val colorFrom = Color.TRANSPARENT - val colorTo = ThemeUtils.getColor(itemView.context, R.attr.colorControlHighlight) + val colorTo = ThemeUtils.getColor(itemView.context, com.google.android.material.R.attr.colorControlHighlight) currentHighlightAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo).apply { duration = 250 // milliseconds addUpdateListener { animator -> diff --git a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt index 1f2441622d..09fbdb3e61 100644 --- a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt @@ -16,7 +16,6 @@ package im.vector.app.core.pushers -import im.vector.app.R import im.vector.app.core.device.GetDeviceInfoUseCase import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.resources.AppNameProvider @@ -46,7 +45,7 @@ class PushersManager @Inject constructor( currentSession.pushersService().testPush( unifiedPushHelper.getPushGateway() ?: return, - stringProvider.getString(R.string.pusher_app_id), + stringProvider.getString(im.vector.app.config.R.string.pusher_app_id), unifiedPushHelper.getEndpointOrToken().orEmpty(), TEST_EVENT_ID ) @@ -55,7 +54,7 @@ class PushersManager @Inject constructor( suspend fun enqueueRegisterPusherWithFcmKey(pushKey: String): UUID { return enqueueRegisterPusher( pushKey = pushKey, - gateway = mdmService.getData(MdmData.DefaultPushGatewayUrl, stringProvider.getString(R.string.pusher_http_url)) + gateway = mdmService.getData(MdmData.DefaultPushGatewayUrl, stringProvider.getString(im.vector.app.config.R.string.pusher_http_url)) ) } @@ -73,7 +72,7 @@ class PushersManager @Inject constructor( gateway: String ) = HttpPusher( pushkey = pushKey, - appId = stringProvider.getString(R.string.pusher_app_id), + appId = stringProvider.getString(im.vector.app.config.R.string.pusher_app_id), profileTag = DEFAULT_PUSHER_FILE_TAG + "_" + abs(activeSessionHolder.getActiveSession().myUserId.hashCode()), lang = localeProvider.current().language, appDisplayName = appNameProvider.getAppName(), @@ -110,7 +109,7 @@ class PushersManager @Inject constructor( suspend fun unregisterPusher(pushKey: String) { val currentSession = activeSessionHolder.getSafeActiveSession() ?: return - currentSession.pushersService().removeHttpPusher(pushKey, stringProvider.getString(R.string.pusher_app_id)) + currentSession.pushersService().removeHttpPusher(pushKey, stringProvider.getString(im.vector.app.config.R.string.pusher_app_id)) } companion object { 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 5b6d91e354..e3ddaa1bb1 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 @@ -21,11 +21,11 @@ import androidx.annotation.MainThread import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.getApplicationLabel import im.vector.app.features.mdm.MdmData import im.vector.app.features.mdm.MdmService +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.cache.CacheStrategy import org.matrix.android.sdk.api.failure.Failure @@ -52,9 +52,9 @@ class UnifiedPushHelper @Inject constructor( ) { val internalDistributorName = stringProvider.getString( if (fcmHelper.isFirebaseAvailable()) { - R.string.unifiedpush_distributor_fcm_fallback + CommonStrings.unifiedpush_distributor_fcm_fallback } else { - R.string.unifiedpush_distributor_background_sync + CommonStrings.unifiedpush_distributor_background_sync } ) @@ -68,7 +68,7 @@ class UnifiedPushHelper @Inject constructor( } MaterialAlertDialogBuilder(context) - .setTitle(stringProvider.getString(R.string.unifiedpush_getdistributors_dialog_title)) + .setTitle(stringProvider.getString(CommonStrings.unifiedpush_getdistributors_dialog_title)) .setItems(distributorsName.toTypedArray()) { _, which -> val distributor = distributors[which] onDistributorSelected(distributor) @@ -105,14 +105,14 @@ class UnifiedPushHelper @Inject constructor( unifiedPushStore.storePushGateway( gateway = mdmService.getData( mdmData = MdmData.DefaultPushGatewayUrl, - defaultValue = stringProvider.getString(R.string.pusher_http_url), + defaultValue = stringProvider.getString(im.vector.app.config.R.string.pusher_http_url), ) ) onDoneRunnable?.run() return } // else, unifiedpush, and pushkey is an endpoint - val gateway = stringProvider.getString(R.string.default_push_gateway_http_url) + val gateway = stringProvider.getString(im.vector.app.config.R.string.default_push_gateway_http_url) val parsed = URL(endpoint) val port = if (parsed.port != -1) { ":${parsed.port}" @@ -153,8 +153,8 @@ class UnifiedPushHelper @Inject constructor( fun getCurrentDistributorName(): String { return when { - isEmbeddedDistributor() -> stringProvider.getString(R.string.unifiedpush_distributor_fcm_fallback) - isBackgroundSync() -> stringProvider.getString(R.string.unifiedpush_distributor_background_sync) + isEmbeddedDistributor() -> stringProvider.getString(CommonStrings.unifiedpush_distributor_fcm_fallback) + isBackgroundSync() -> stringProvider.getString(CommonStrings.unifiedpush_distributor_background_sync) else -> context.getApplicationLabel(UnifiedPush.getDistributor(context)) } } @@ -196,7 +196,7 @@ class UnifiedPushHelper @Inject constructor( return if (isEmbeddedDistributor()) { mdmService.getData( mdmData = MdmData.DefaultPushGatewayUrl, - defaultValue = stringProvider.getString(R.string.pusher_http_url), + defaultValue = stringProvider.getString(im.vector.app.config.R.string.pusher_http_url), ) } else { unifiedPushStore.getPushGateway() diff --git a/vector/src/main/java/im/vector/app/core/resources/BuildMeta.kt b/vector/src/main/java/im/vector/app/core/resources/BuildMeta.kt index ddc6f992a9..2e150df215 100644 --- a/vector/src/main/java/im/vector/app/core/resources/BuildMeta.kt +++ b/vector/src/main/java/im/vector/app/core/resources/BuildMeta.kt @@ -19,6 +19,7 @@ package im.vector.app.core.resources data class BuildMeta( val isDebug: Boolean, val applicationId: String, + val applicationName: String, val lowPrivacyLoggingEnabled: Boolean, val versionName: String, val gitRevision: String, diff --git a/vector/src/main/java/im/vector/app/core/services/VectorSyncAndroidService.kt b/vector/src/main/java/im/vector/app/core/services/VectorSyncAndroidService.kt index 5fa263ff7b..67a9c3b0ce 100644 --- a/vector/src/main/java/im/vector/app/core/services/VectorSyncAndroidService.kt +++ b/vector/src/main/java/im/vector/app/core/services/VectorSyncAndroidService.kt @@ -31,13 +31,13 @@ import androidx.work.WorkRequest import androidx.work.Worker import androidx.work.WorkerParameters import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.startForegroundCompat import im.vector.app.core.platform.PendingIntentCompat import im.vector.app.features.notifications.NotificationUtils import im.vector.app.features.settings.BackgroundSyncMode import im.vector.lib.core.utils.timer.Clock import im.vector.lib.core.utils.timer.DefaultClock +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.session.sync.job.SyncAndroidService import timber.log.Timber @@ -94,9 +94,9 @@ class VectorSyncAndroidService : SyncAndroidService() { override fun onStart(isInitialSync: Boolean) { val notificationSubtitleRes = if (isInitialSync) { - R.string.notification_initial_sync + CommonStrings.notification_initial_sync } else { - R.string.notification_listening_for_notifications + CommonStrings.notification_listening_for_notifications } val notification = notificationUtils.buildForegroundServiceNotification(notificationSubtitleRes, false) startForegroundCompat(NotificationUtils.NOTIFICATION_ID_FOREGROUND_SERVICE, notification) diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericButtonItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericButtonItem.kt index a3b6b40616..0252f48c65 100644 --- a/vector/src/main/java/im/vector/app/core/ui/list/GenericButtonItem.kt +++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericButtonItem.kt @@ -62,7 +62,7 @@ abstract class GenericButtonItem : VectorEpoxyModel(R. override fun bind(holder: Holder) { super.bind(holder) holder.button.text = text - val textColor = textColor ?: ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_primary) + val textColor = textColor ?: ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_primary) holder.button.setTextColor(textColor) if (iconRes != null) { holder.button.setIconResource(iconRes!!) @@ -75,7 +75,7 @@ abstract class GenericButtonItem : VectorEpoxyModel(R. holder.button.setTypeface(null, textStyle) holder.button.rippleColor = if (highlight) { - ContextCompat.getColorStateList(holder.view.context, R.color.mtrl_btn_text_btn_ripple_color) + ContextCompat.getColorStateList(holder.view.context, com.google.android.material.R.color.mtrl_btn_text_btn_ripple_color) } else { null } diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericFooterItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericFooterItem.kt index a41ea0153c..89df091dfa 100644 --- a/vector/src/main/java/im/vector/app/core/ui/list/GenericFooterItem.kt +++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericFooterItem.kt @@ -65,7 +65,7 @@ abstract class GenericFooterItem : VectorEpoxyModel(R. if (textColor != null) { holder.text.setTextColor(textColor!!) } else { - holder.text.setTextColor(ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary)) + holder.text.setTextColor(ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary)) } holder.view.onClick(itemClickAction) diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericHeaderItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericHeaderItem.kt index 2123b4c639..322c088784 100644 --- a/vector/src/main/java/im/vector/app/core/ui/list/GenericHeaderItem.kt +++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericHeaderItem.kt @@ -44,7 +44,7 @@ abstract class GenericHeaderItem : VectorEpoxyModel(R. if (textColor != null) { holder.text.setTextColor(textColor!!) } else { - holder.text.setTextColor(ThemeUtils.getColor(holder.view.context, R.attr.vctr_notice_text_color)) + holder.text.setTextColor(ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_notice_text_color)) } } diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt index 2a321ac4b0..f7d2b786a9 100644 --- a/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt +++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt @@ -73,7 +73,7 @@ abstract class GenericPillItem : VectorEpoxyModel(R.layo holder.imageView.isVisible = false } if (tintIcon) { - val iconTintColor = ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary) + val iconTintColor = ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary) ImageViewCompat.setImageTintList(holder.imageView, ColorStateList.valueOf(iconTintColor)) } else { ImageViewCompat.setImageTintList(holder.imageView, null) diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericWithValueItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericWithValueItem.kt index 8b82bf4684..ed9dcef4a2 100644 --- a/vector/src/main/java/im/vector/app/core/ui/list/GenericWithValueItem.kt +++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericWithValueItem.kt @@ -77,7 +77,7 @@ abstract class GenericWithValueItem : VectorEpoxyModel { - resources.getString(R.string.call_ringing) + resources.getString(CommonStrings.call_ringing) } is CallState.Answering -> { - resources.getString(R.string.call_connecting) + resources.getString(CommonStrings.call_connecting) } else -> { - resources.getString(R.string.call_one_active, formattedDuration) + resources.getString(CommonStrings.call_one_active, formattedDuration) } } } else { - resources.getQuantityString(R.plurals.call_active_status, calls.size, calls.size) + resources.getQuantityString(CommonPlurals.call_active_status, calls.size, calls.size) } - views.currentCallsInfo.text = resources.getString(R.string.call_tap_to_return, tapToReturnFormat) + views.currentCallsInfo.text = resources.getString(CommonStrings.call_tap_to_return, tapToReturnFormat) } } diff --git a/vector/src/main/java/im/vector/app/core/ui/views/JoinConferenceView.kt b/vector/src/main/java/im/vector/app/core/ui/views/JoinConferenceView.kt index fa1e2c1403..5ef9aa4cfd 100644 --- a/vector/src/main/java/im/vector/app/core/ui/views/JoinConferenceView.kt +++ b/vector/src/main/java/im/vector/app/core/ui/views/JoinConferenceView.kt @@ -46,8 +46,8 @@ class JoinConferenceView @JvmOverloads constructor( super.onAttachedToWindow() views = ViewJoinConferenceBinding.bind(this) views?.joinConferenceButton?.setOnClickListener { onJoinClicked?.invoke() } - val colorFrom = ContextCompat.getColor(context, R.color.palette_element_green) - val colorTo = ContextCompat.getColor(context, R.color.join_conference_animated_color) + val colorFrom = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.palette_element_green) + val colorTo = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.join_conference_animated_color) // Animate button color to highlight backgroundAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo).apply { repeatMode = ValueAnimator.REVERSE diff --git a/vector/src/main/java/im/vector/app/core/ui/views/KeysBackupBanner.kt b/vector/src/main/java/im/vector/app/core/ui/views/KeysBackupBanner.kt index f0a42dd78d..7127d606d1 100755 --- a/vector/src/main/java/im/vector/app/core/ui/views/KeysBackupBanner.kt +++ b/vector/src/main/java/im/vector/app/core/ui/views/KeysBackupBanner.kt @@ -24,6 +24,7 @@ import androidx.core.view.isVisible import im.vector.app.R import im.vector.app.databinding.ViewKeysBackupBannerBinding import im.vector.app.features.workers.signout.BannerState +import im.vector.lib.strings.CommonStrings import timber.log.Timber /** @@ -113,9 +114,9 @@ class KeysBackupBanner @JvmOverloads constructor( } else { isVisible = true - views.viewKeysBackupBannerText1.setText(R.string.secure_backup_banner_setup_line1) + views.viewKeysBackupBannerText1.setText(CommonStrings.secure_backup_banner_setup_line1) views.viewKeysBackupBannerText2.isVisible = true - views.viewKeysBackupBannerText2.setText(R.string.secure_backup_banner_setup_line2) + views.viewKeysBackupBannerText2.setText(CommonStrings.secure_backup_banner_setup_line2) views.viewKeysBackupBannerCloseGroup.isVisible = true } } @@ -126,9 +127,9 @@ class KeysBackupBanner @JvmOverloads constructor( } else { isVisible = true - views.viewKeysBackupBannerText1.setText(R.string.keys_backup_banner_recover_line1) + views.viewKeysBackupBannerText1.setText(CommonStrings.keys_backup_banner_recover_line1) views.viewKeysBackupBannerText2.isVisible = true - views.viewKeysBackupBannerText2.setText(R.string.keys_backup_banner_recover_line2) + views.viewKeysBackupBannerText2.setText(CommonStrings.keys_backup_banner_recover_line2) views.viewKeysBackupBannerCloseGroup.isVisible = true } } @@ -139,18 +140,18 @@ class KeysBackupBanner @JvmOverloads constructor( } else { isVisible = true - views.viewKeysBackupBannerText1.setText(R.string.keys_backup_banner_update_line1) + views.viewKeysBackupBannerText1.setText(CommonStrings.keys_backup_banner_update_line1) views.viewKeysBackupBannerText2.isVisible = true - views.viewKeysBackupBannerText2.setText(R.string.keys_backup_banner_update_line2) + views.viewKeysBackupBannerText2.setText(CommonStrings.keys_backup_banner_update_line2) views.viewKeysBackupBannerCloseGroup.isVisible = true } } private fun renderBackingUp() { isVisible = true - views.viewKeysBackupBannerText1.setText(R.string.secure_backup_banner_setup_line1) + views.viewKeysBackupBannerText1.setText(CommonStrings.secure_backup_banner_setup_line1) views.viewKeysBackupBannerText2.isVisible = true - views.viewKeysBackupBannerText2.setText(R.string.keys_backup_banner_in_progress) + views.viewKeysBackupBannerText2.setText(CommonStrings.keys_backup_banner_in_progress) views.viewKeysBackupBannerLoading.isVisible = true } diff --git a/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt b/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt index b298a6d4d5..292be69d4f 100644 --- a/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt +++ b/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt @@ -30,6 +30,7 @@ import im.vector.app.core.error.ResourceLimitErrorFormatter import im.vector.app.core.utils.DimensionConverter import im.vector.app.databinding.ViewNotificationAreaBinding import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span import me.saket.bettermovementmethod.BetterLinkMovementMethod import org.matrix.android.sdk.api.failure.MatrixError @@ -100,19 +101,19 @@ class NotificationAreaView @JvmOverloads constructor( views.roomNotificationIcon.setImageDrawable(null) val message = span { italic { - +resources.getString(R.string.room_do_not_have_permission_to_post) + +resources.getString(CommonStrings.room_do_not_have_permission_to_post) } } views.roomNotificationMessage.text = message - views.roomNotificationMessage.setTextColor(ThemeUtils.getColor(context, R.attr.vctr_content_secondary)) + views.roomNotificationMessage.setTextColor(ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary)) } private fun renderUnsupportedAlgorithm(e2eState: State.UnsupportedAlgorithm) { visibility = View.VISIBLE views.roomNotificationIcon.setImageResource(R.drawable.ic_warning_badge) val text = if (e2eState.canRestore) { - R.string.room_unsupported_e2e_algorithm_as_admin - } else R.string.room_unsupported_e2e_algorithm + CommonStrings.room_unsupported_e2e_algorithm_as_admin + } else CommonStrings.room_unsupported_e2e_algorithm val message = span { italic { +resources.getString(text) @@ -122,7 +123,7 @@ class NotificationAreaView @JvmOverloads constructor( delegate?.onMisconfiguredEncryptionClicked() } views.roomNotificationMessage.text = message - views.roomNotificationMessage.setTextColor(ThemeUtils.getColor(context, R.attr.vctr_content_secondary)) + views.roomNotificationMessage.setTextColor(ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary)) } private fun renderResourceLimitExceededError(state: State.ResourceLimitExceededError) { @@ -131,10 +132,10 @@ class NotificationAreaView @JvmOverloads constructor( val formatterMode: ResourceLimitErrorFormatter.Mode val backgroundColor: Int if (state.isSoft) { - backgroundColor = R.color.soft_resource_limit_exceeded + backgroundColor = im.vector.lib.ui.styles.R.color.soft_resource_limit_exceeded formatterMode = ResourceLimitErrorFormatter.Mode.Soft } else { - backgroundColor = R.color.hard_resource_limit_exceeded + backgroundColor = im.vector.lib.ui.styles.R.color.hard_resource_limit_exceeded formatterMode = ResourceLimitErrorFormatter.Mode.Hard } val message = resourceLimitErrorFormatter.format(state.matrixError, formatterMode, clickable = true) @@ -149,9 +150,9 @@ class NotificationAreaView @JvmOverloads constructor( visibility = View.VISIBLE views.roomNotificationIcon.setImageResource(R.drawable.ic_warning_badge) val message = span { - +resources.getString(R.string.room_tombstone_versioned_description) + +resources.getString(CommonStrings.room_tombstone_versioned_description) +"\n" - span(resources.getString(R.string.room_tombstone_continuation_link)) { + span(resources.getString(CommonStrings.room_tombstone_continuation_link)) { textDecorationLine = "underline" onClick = { delegate?.onTombstoneEventClicked() } } diff --git a/vector/src/main/java/im/vector/app/core/ui/views/PasswordStrengthBar.kt b/vector/src/main/java/im/vector/app/core/ui/views/PasswordStrengthBar.kt index eb5b05e79b..7fd77458dc 100644 --- a/vector/src/main/java/im/vector/app/core/ui/views/PasswordStrengthBar.kt +++ b/vector/src/main/java/im/vector/app/core/ui/views/PasswordStrengthBar.kt @@ -20,8 +20,8 @@ import android.util.AttributeSet import android.widget.LinearLayout import androidx.annotation.IntRange import androidx.core.content.ContextCompat -import im.vector.app.R import im.vector.app.databinding.ViewPasswordStrengthBarBinding +import im.vector.lib.ui.styles.R /** * A password strength bar custom widget. @@ -87,7 +87,7 @@ class PasswordStrengthBar @JvmOverloads constructor( } init { - inflate(context, R.layout.view_password_strength_bar, this) + inflate(context, im.vector.app.R.layout.view_password_strength_bar, this) views = ViewPasswordStrengthBarBinding.bind(this) orientation = HORIZONTAL strength = 0 diff --git a/vector/src/main/java/im/vector/app/core/ui/views/PresenceStateImageView.kt b/vector/src/main/java/im/vector/app/core/ui/views/PresenceStateImageView.kt index 0176901bfb..f70b982579 100644 --- a/vector/src/main/java/im/vector/app/core/ui/views/PresenceStateImageView.kt +++ b/vector/src/main/java/im/vector/app/core/ui/views/PresenceStateImageView.kt @@ -21,6 +21,7 @@ import android.util.AttributeSet import androidx.appcompat.widget.AppCompatImageView import androidx.core.view.isVisible import im.vector.app.R +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.presence.model.PresenceEnum import org.matrix.android.sdk.api.session.presence.model.UserPresence @@ -39,19 +40,19 @@ class PresenceStateImageView @JvmOverloads constructor( when (userPresence?.presence) { PresenceEnum.ONLINE -> { setImageResource(R.drawable.ic_presence_online) - contentDescription = context.getString(R.string.a11y_presence_online) + contentDescription = context.getString(CommonStrings.a11y_presence_online) } PresenceEnum.UNAVAILABLE -> { setImageResource(R.drawable.ic_presence_away) - contentDescription = context.getString(R.string.a11y_presence_unavailable) + contentDescription = context.getString(CommonStrings.a11y_presence_unavailable) } PresenceEnum.OFFLINE -> { setImageResource(R.drawable.ic_presence_offline) - contentDescription = context.getString(R.string.a11y_presence_offline) + contentDescription = context.getString(CommonStrings.a11y_presence_offline) } PresenceEnum.BUSY -> { setImageResource(R.drawable.ic_presence_busy) - contentDescription = context.getString(R.string.a11y_presence_busy) + contentDescription = context.getString(CommonStrings.a11y_presence_busy) } null -> Unit } diff --git a/vector/src/main/java/im/vector/app/core/ui/views/ReadReceiptsView.kt b/vector/src/main/java/im/vector/app/core/ui/views/ReadReceiptsView.kt index db5dae5222..aff7b18677 100644 --- a/vector/src/main/java/im/vector/app/core/ui/views/ReadReceiptsView.kt +++ b/vector/src/main/java/im/vector/app/core/ui/views/ReadReceiptsView.kt @@ -27,6 +27,8 @@ import im.vector.app.databinding.ViewReadReceiptsBinding import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.item.ReadReceiptData import im.vector.app.features.home.room.detail.timeline.item.toMatrixItem +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings private const val MAX_RECEIPT_DISPLAYED = 3 @@ -49,7 +51,7 @@ class ReadReceiptsView @JvmOverloads constructor( private fun setupView() { inflate(context, R.layout.view_read_receipts, this) - contentDescription = context.getString(R.string.a11y_view_read_receipts) + contentDescription = context.getString(CommonStrings.a11y_view_read_receipts) } fun render(readReceipts: List, avatarRenderer: AvatarRenderer) { @@ -68,7 +70,7 @@ class ReadReceiptsView @JvmOverloads constructor( if (readReceipts.size > MAX_RECEIPT_DISPLAYED) { views.receiptMore.visibility = View.VISIBLE views.receiptMore.text = context.getString( - R.string.x_plus, readReceipts.size - MAX_RECEIPT_DISPLAYED + CommonStrings.x_plus, readReceipts.size - MAX_RECEIPT_DISPLAYED ) } else { views.receiptMore.visibility = View.GONE @@ -76,34 +78,34 @@ class ReadReceiptsView @JvmOverloads constructor( contentDescription = when (readReceipts.size) { 1 -> if (displayNames.size == 1) { - context.getString(R.string.one_user_read, displayNames[0]) + context.getString(CommonStrings.one_user_read, displayNames[0]) } else { - context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size) + context.resources.getQuantityString(CommonPlurals.fallback_users_read, readReceipts.size) } 2 -> if (displayNames.size == 2) { - context.getString(R.string.two_users_read, displayNames[0], displayNames[1]) + context.getString(CommonStrings.two_users_read, displayNames[0], displayNames[1]) } else { - context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size) + context.resources.getQuantityString(CommonPlurals.fallback_users_read, readReceipts.size) } 3 -> if (displayNames.size == 3) { - context.getString(R.string.three_users_read, displayNames[0], displayNames[1], displayNames[2]) + context.getString(CommonStrings.three_users_read, displayNames[0], displayNames[1], displayNames[2]) } else { - context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size) + context.resources.getQuantityString(CommonPlurals.fallback_users_read, readReceipts.size) } else -> if (displayNames.size >= 2) { val qty = readReceipts.size - 2 context.resources.getQuantityString( - R.plurals.two_and_some_others_read, + CommonPlurals.two_and_some_others_read, qty, displayNames[0], displayNames[1], qty ) } else { - context.resources.getQuantityString(R.plurals.fallback_users_read, readReceipts.size) + context.resources.getQuantityString(CommonPlurals.fallback_users_read, readReceipts.size) } } } diff --git a/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt b/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt index 77b0204783..bc5ef75669 100644 --- a/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt +++ b/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt @@ -24,6 +24,7 @@ import androidx.core.view.isInvisible import im.vector.app.R import im.vector.app.features.home.room.detail.timeline.item.SendStateDecoration import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings class SendStateImageView @JvmOverloads constructor( context: Context, @@ -41,20 +42,20 @@ class SendStateImageView @JvmOverloads constructor( isInvisible = when (sendState) { SendStateDecoration.SENDING_NON_MEDIA -> { setImageResource(R.drawable.ic_sending_message) - imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(context, R.attr.vctr_content_tertiary)) - contentDescription = context.getString(R.string.event_status_a11y_sending) + imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_content_tertiary)) + contentDescription = context.getString(CommonStrings.event_status_a11y_sending) false } SendStateDecoration.SENT -> { setImageResource(R.drawable.ic_message_sent) - imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(context, R.attr.vctr_content_tertiary)) - contentDescription = context.getString(R.string.event_status_a11y_sent) + imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_content_tertiary)) + contentDescription = context.getString(CommonStrings.event_status_a11y_sent) false } SendStateDecoration.FAILED -> { setImageResource(R.drawable.ic_sending_message_failed) imageTintList = null - contentDescription = context.getString(R.string.event_status_a11y_failed) + contentDescription = context.getString(CommonStrings.event_status_a11y_failed) false } SendStateDecoration.SENDING_MEDIA, diff --git a/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt b/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt index 34714d97d0..aac9bc5dfd 100644 --- a/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt +++ b/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt @@ -23,6 +23,7 @@ import androidx.appcompat.widget.AppCompatImageView import androidx.core.view.isVisible import im.vector.app.R import im.vector.app.features.home.room.detail.timeline.item.E2EDecoration +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.session.crypto.model.UserVerificationLevel @@ -46,14 +47,14 @@ class ShieldImageView @JvmOverloads constructor( fun renderDeviceShield(roomEncryptionTrustLevel: RoomEncryptionTrustLevel?, borderLess: Boolean = false) { when (roomEncryptionTrustLevel) { null -> { - contentDescription = context.getString(R.string.a11y_trust_level_warning) + contentDescription = context.getString(CommonStrings.a11y_trust_level_warning) setImageResource( if (borderLess) R.drawable.ic_shield_warning_no_border else R.drawable.ic_shield_warning ) } RoomEncryptionTrustLevel.Default -> { - contentDescription = context.getString(R.string.a11y_trust_level_default) + contentDescription = context.getString(CommonStrings.a11y_trust_level_default) setImageResource( if (borderLess) R.drawable.ic_shield_unknown_no_border else R.drawable.ic_shield_unknown @@ -68,28 +69,28 @@ class ShieldImageView @JvmOverloads constructor( when (roomEncryptionTrustLevel) { RoomEncryptionTrustLevel.Default -> { - contentDescription = context.getString(R.string.a11y_trust_level_default) + contentDescription = context.getString(CommonStrings.a11y_trust_level_default) setImageResource( if (borderLess) R.drawable.ic_shield_black_no_border else R.drawable.ic_shield_black ) } RoomEncryptionTrustLevel.Warning -> { - contentDescription = context.getString(R.string.a11y_trust_level_warning) + contentDescription = context.getString(CommonStrings.a11y_trust_level_warning) setImageResource( if (borderLess) R.drawable.ic_shield_warning_no_border else R.drawable.ic_shield_warning ) } RoomEncryptionTrustLevel.Trusted -> { - contentDescription = context.getString(R.string.a11y_trust_level_trusted) + contentDescription = context.getString(CommonStrings.a11y_trust_level_trusted) setImageResource( if (borderLess) R.drawable.ic_shield_trusted_no_border else R.drawable.ic_shield_trusted ) } RoomEncryptionTrustLevel.E2EWithUnsupportedAlgorithm -> { - contentDescription = context.getString(R.string.a11y_trust_level_trusted) + contentDescription = context.getString(CommonStrings.a11y_trust_level_trusted) setImageResource(R.drawable.ic_warning_badge) } null -> Unit @@ -100,23 +101,23 @@ class ShieldImageView @JvmOverloads constructor( isVisible = true when (decoration) { E2EDecoration.WARN_IN_CLEAR -> { - contentDescription = context.getString(R.string.unencrypted) + contentDescription = context.getString(CommonStrings.unencrypted) setImageResource(R.drawable.ic_shield_warning) } E2EDecoration.WARN_SENT_BY_UNVERIFIED -> { - contentDescription = context.getString(R.string.encrypted_unverified) + contentDescription = context.getString(CommonStrings.encrypted_unverified) setImageResource(R.drawable.ic_shield_warning) } E2EDecoration.WARN_SENT_BY_UNKNOWN -> { - contentDescription = context.getString(R.string.encrypted_unverified) + contentDescription = context.getString(CommonStrings.encrypted_unverified) setImageResource(R.drawable.ic_shield_warning) } E2EDecoration.WARN_SENT_BY_DELETED_SESSION -> { - contentDescription = context.getString(R.string.encrypted_unverified) + contentDescription = context.getString(CommonStrings.encrypted_unverified) setImageResource(R.drawable.ic_shield_warning) } E2EDecoration.WARN_UNSAFE_KEY -> { - contentDescription = context.getString(R.string.key_authenticity_not_guaranteed) + contentDescription = context.getString(CommonStrings.key_authenticity_not_guaranteed) setImageResource( R.drawable.ic_shield_gray ) @@ -133,7 +134,7 @@ class ShieldImageView @JvmOverloads constructor( isVisible = userVerificationLevel != null when (userVerificationLevel) { UserVerificationLevel.VERIFIED_ALL_DEVICES_TRUSTED -> { - contentDescription = context.getString(R.string.a11y_trust_level_trusted) + contentDescription = context.getString(CommonStrings.a11y_trust_level_trusted) setImageResource( if (borderLess) R.drawable.ic_shield_trusted_no_border else R.drawable.ic_shield_trusted @@ -141,14 +142,14 @@ class ShieldImageView @JvmOverloads constructor( } UserVerificationLevel.UNVERIFIED_BUT_WAS_PREVIOUSLY, UserVerificationLevel.VERIFIED_WITH_DEVICES_UNTRUSTED -> { - contentDescription = context.getString(R.string.a11y_trust_level_warning) + contentDescription = context.getString(CommonStrings.a11y_trust_level_warning) setImageResource( if (borderLess) R.drawable.ic_shield_warning_no_border else R.drawable.ic_shield_warning ) } UserVerificationLevel.WAS_NEVER_VERIFIED -> { - contentDescription = context.getString(R.string.a11y_trust_level_default) + contentDescription = context.getString(CommonStrings.a11y_trust_level_default) setImageResource( if (borderLess) R.drawable.ic_shield_black_no_border else R.drawable.ic_shield_black diff --git a/vector/src/main/java/im/vector/app/core/ui/views/TypingMessageAvatar.kt b/vector/src/main/java/im/vector/app/core/ui/views/TypingMessageAvatar.kt index 1f78584a6b..ee362e7be1 100644 --- a/vector/src/main/java/im/vector/app/core/ui/views/TypingMessageAvatar.kt +++ b/vector/src/main/java/im/vector/app/core/ui/views/TypingMessageAvatar.kt @@ -22,7 +22,6 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.LinearLayout -import im.vector.app.R import im.vector.app.features.home.AvatarRenderer import org.matrix.android.sdk.api.session.room.sender.SenderInfo import org.matrix.android.sdk.api.util.toMatrixItem @@ -38,7 +37,7 @@ class TypingMessageAvatar @JvmOverloads constructor( } private val typingAvatarSize by lazy(LazyThreadSafetyMode.NONE) { - context.resources.getDimension(R.dimen.typing_avatar_size).toInt() + context.resources.getDimension(im.vector.lib.ui.styles.R.dimen.typing_avatar_size).toInt() } fun render(typingUsers: List, avatarRenderer: AvatarRenderer) { diff --git a/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt b/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt index c9bd4e54b0..bb04be7fe4 100644 --- a/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt +++ b/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt @@ -22,8 +22,8 @@ import android.webkit.WebView import android.webkit.WebViewClient import android.widget.TextView import com.google.android.material.dialog.MaterialAlertDialogBuilder -import im.vector.app.R import im.vector.app.features.discovery.ServerAndPolicies +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.link import me.gujun.android.span.span @@ -51,12 +51,12 @@ fun Context.showIdentityServerConsentDialog( ) { // Build the message val content = span { - +getString(R.string.identity_server_consent_dialog_content_3) + +getString(CommonStrings.identity_server_consent_dialog_content_3) +"\n\n" if (identityServerWithTerms?.policies?.isNullOrEmpty() == false) { span { textStyle = "bold" - text = getString(R.string.settings_privacy_policy) + text = getString(CommonStrings.settings_privacy_policy) } identityServerWithTerms.policies.forEach { +"\n • " @@ -65,15 +65,15 @@ fun Context.showIdentityServerConsentDialog( } +"\n\n" } - +getString(R.string.identity_server_consent_dialog_content_question) + +getString(CommonStrings.identity_server_consent_dialog_content_question) } MaterialAlertDialogBuilder(this) - .setTitle(getString(R.string.identity_server_consent_dialog_title_2, identityServerWithTerms?.serverUrl.orEmpty())) + .setTitle(getString(CommonStrings.identity_server_consent_dialog_title_2, identityServerWithTerms?.serverUrl.orEmpty())) .setMessage(content) - .setPositiveButton(R.string.action_agree) { _, _ -> + .setPositiveButton(CommonStrings.action_agree) { _, _ -> consentCallBack.invoke() } - .setNegativeButton(R.string.action_not_now, null) + .setNegativeButton(CommonStrings.action_not_now, null) .show() .apply { // Make the link(s) clickable. Must be called after show() diff --git a/vector/src/main/java/im/vector/app/core/utils/ExpandingBottomSheetBehavior.kt b/vector/src/main/java/im/vector/app/core/utils/ExpandingBottomSheetBehavior.kt index 47326bca76..7834d6a014 100644 --- a/vector/src/main/java/im/vector/app/core/utils/ExpandingBottomSheetBehavior.kt +++ b/vector/src/main/java/im/vector/app/core/utils/ExpandingBottomSheetBehavior.kt @@ -204,6 +204,7 @@ class ExpandingBottomSheetBehavior : CoordinatorLayout.Behavior { if (useScrimView && scrimView == null) { val scrimView = View(parent.context) scrimView.setBackgroundColor(scrimViewColor) + @Suppress("DEPRECATION") scrimView.translationZ = scrimViewTranslationZ * child.resources.displayMetrics.scaledDensity scrimView.isVisible = false val params = CoordinatorLayout.LayoutParams( @@ -488,7 +489,7 @@ class ExpandingBottomSheetBehavior : CoordinatorLayout.Behavior { } private fun isLayouting(child: V): Boolean { - return child.parent != null && child.parent.isLayoutRequested && ViewCompat.isAttachedToWindow(child) + return child.parent != null && child.parent.isLayoutRequested && child.isAttachedToWindow } private fun getTopOffsetForState(state: State): Int { @@ -639,7 +640,7 @@ class ExpandingBottomSheetBehavior : CoordinatorLayout.Behavior { } // Request to apply insets as soon as the view is attached to a window. - if (ViewCompat.isAttachedToWindow(view)) { + if (view.isAttachedToWindow) { ViewCompat.requestApplyInsets(view) } else { view.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { @@ -790,7 +791,7 @@ class ExpandingBottomSheetBehavior : CoordinatorLayout.Behavior { this.targetState = state if (!isContinueSettlingRunnablePosted) { - ViewCompat.postOnAnimation(view, continueSettlingRunnable) + view.postOnAnimation(continueSettlingRunnable) isContinueSettlingRunnablePosted = true } } diff --git a/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt b/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt index 23641bd170..cc68441ab5 100644 --- a/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt +++ b/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt @@ -43,6 +43,7 @@ import androidx.core.content.getSystemService import im.vector.app.R import im.vector.app.features.notifications.NotificationUtils import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import okio.buffer @@ -119,7 +120,7 @@ fun openUrlInChromeCustomTab( .build() .launchUrl(context, Uri.parse(url)) } catch (activityNotFoundException: ActivityNotFoundException) { - context.toast(R.string.error_no_external_application_found) + context.toast(CommonStrings.error_no_external_application_found) } } @@ -145,7 +146,7 @@ fun openFileSelection( activity.startActivityForResult(fileIntent, requestCode) } } catch (activityNotFoundException: ActivityNotFoundException) { - activity.toast(R.string.error_no_external_application_found) + activity.toast(CommonStrings.error_no_external_application_found) } } @@ -223,7 +224,7 @@ fun shareMedia(context: Context, file: File, mediaMimeType: String?) { val chooserIntent = ShareCompat.IntentBuilder(context) .setType(mediaMimeType) .setStream(mediaUri) - .setChooserTitle(R.string.action_share) + .setChooserTitle(CommonStrings.action_share) .createChooserIntent() context.safeStartActivity(chooserIntent) @@ -233,7 +234,7 @@ fun shareText(context: Context, text: String) { val chooserIntent = ShareCompat.IntentBuilder(context) .setType("text/plain") .setText(text) - .setChooserTitle(R.string.action_share) + .setChooserTitle(CommonStrings.action_share) .createChooserIntent() context.safeStartActivity(chooserIntent) @@ -243,7 +244,7 @@ fun Context.safeStartActivity(intent: Intent) { try { startActivity(intent) } catch (activityNotFoundException: ActivityNotFoundException) { - toast(R.string.error_no_external_application_found) + toast(CommonStrings.error_no_external_application_found) } } @@ -286,8 +287,8 @@ suspend fun saveMedia( val uri = context.contentResolver.insert(externalContentUri, values) if (uri == null) { - Toast.makeText(context, R.string.error_saving_media_file, Toast.LENGTH_LONG).show() - throw IllegalStateException(context.getString(R.string.error_saving_media_file)) + Toast.makeText(context, CommonStrings.error_saving_media_file, Toast.LENGTH_LONG).show() + throw IllegalStateException(context.getString(CommonStrings.error_saving_media_file)) } else { val source = file.inputStream().source().buffer() context.contentResolver.openOutputStream(uri)?.sink()?.buffer()?.let { sink -> @@ -320,8 +321,8 @@ private fun saveMediaLegacy( ) { val state = Environment.getExternalStorageState() if (Environment.MEDIA_MOUNTED != state) { - context.toast(context.getString(R.string.error_saving_media_file)) - throw IllegalStateException(context.getString(R.string.error_saving_media_file)) + context.toast(context.getString(CommonStrings.error_saving_media_file)) + throw IllegalStateException(context.getString(CommonStrings.error_saving_media_file)) } val dest = when { @@ -354,7 +355,7 @@ private fun saveMediaLegacy( addToGallery(savedFile, mediaMimeType, context) } } catch (error: Throwable) { - context.toast(context.getString(R.string.error_saving_media_file)) + context.toast(context.getString(CommonStrings.error_saving_media_file)) throw error } } @@ -412,7 +413,7 @@ fun selectTxtFileToWrite( try { activityResultLauncher.launch(chooserIntent) } catch (activityNotFoundException: ActivityNotFoundException) { - activity.toast(R.string.error_no_external_application_found) + activity.toast(CommonStrings.error_no_external_application_found) } } diff --git a/vector/src/main/java/im/vector/app/core/utils/JsonViewerStyler.kt b/vector/src/main/java/im/vector/app/core/utils/JsonViewerStyler.kt index 070b382e99..dc81e44277 100644 --- a/vector/src/main/java/im/vector/app/core/utils/JsonViewerStyler.kt +++ b/vector/src/main/java/im/vector/app/core/utils/JsonViewerStyler.kt @@ -16,17 +16,16 @@ package im.vector.app.core.utils -import im.vector.app.R import im.vector.app.core.resources.ColorProvider import org.billcarsonfr.jsonviewer.JSonViewerStyleProvider fun createJSonViewerStyleProvider(colorProvider: ColorProvider): JSonViewerStyleProvider { return JSonViewerStyleProvider( - keyColor = colorProvider.getColorFromAttribute(R.attr.colorPrimary), - secondaryColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary), - stringColor = colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color), - baseColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_primary), - booleanColor = colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color), - numberColor = colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color) + keyColor = colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary), + secondaryColor = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary), + stringColor = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_notice_text_color), + baseColor = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary), + booleanColor = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_notice_text_color), + numberColor = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_notice_text_color) ) } diff --git a/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt b/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt index a287626671..9f61a52671 100644 --- a/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt +++ b/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt @@ -28,8 +28,8 @@ import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import com.google.android.material.dialog.MaterialAlertDialogBuilder -import im.vector.app.R import im.vector.app.core.platform.VectorBaseActivity +import im.vector.lib.strings.CommonStrings // Permissions sets val PERMISSIONS_EMPTY = emptyList() @@ -119,13 +119,13 @@ fun checkPermissions( // display the dialog with the info text. Do not do it if no system dialog will // be displayed MaterialAlertDialogBuilder(activity) - .setTitle(R.string.permissions_rationale_popup_title) + .setTitle(CommonStrings.permissions_rationale_popup_title) .setMessage(rationaleMessage) .setCancelable(false) - .setPositiveButton(R.string.ok) { _, _ -> + .setPositiveButton(CommonStrings.ok) { _, _ -> activityResultLauncher.launch(missingPermissions.toTypedArray()) } - .setNegativeButton(R.string.action_not_now, null) + .setNegativeButton(CommonStrings.action_not_now, null) .show() } else { // some permissions are not granted, ask permissions @@ -162,18 +162,18 @@ private fun permissionsDeniedPermanently( } fun VectorBaseActivity<*>.onPermissionDeniedSnackbar(@StringRes rationaleMessage: Int) { - showSnackbar(getString(rationaleMessage), R.string.settings) { + showSnackbar(getString(rationaleMessage), CommonStrings.settings) { openAppSettingsPage(this) } } fun FragmentActivity.onPermissionDeniedDialog(@StringRes rationaleMessage: Int) { MaterialAlertDialogBuilder(this) - .setTitle(R.string.missing_permissions_title) + .setTitle(CommonStrings.missing_permissions_title) .setMessage(rationaleMessage) - .setPositiveButton(R.string.open_settings) { _, _ -> + .setPositiveButton(CommonStrings.open_settings) { _, _ -> openAppSettingsPage(this) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } diff --git a/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt b/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt index 20eda102e2..3f55b7d352 100644 --- a/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt +++ b/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt @@ -32,8 +32,8 @@ import androidx.annotation.RequiresApi import androidx.annotation.StringRes import androidx.core.content.getSystemService import androidx.fragment.app.Fragment -import im.vector.app.R import im.vector.app.features.notifications.NotificationUtils +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.util.getApplicationInfoCompat /** @@ -98,7 +98,7 @@ fun requestDisablingBatteryOptimization(activity: Activity, activityResultLaunch * @param showToast true to also show a Toast to the user * @param toastMessage content of the toast message as a String resource */ -fun copyToClipboard(context: Context, text: CharSequence, showToast: Boolean = true, @StringRes toastMessage: Int = R.string.copied_to_clipboard) { +fun copyToClipboard(context: Context, text: CharSequence, showToast: Boolean = true, @StringRes toastMessage: Int = CommonStrings.copied_to_clipboard) { CopyToClipboardUseCase(context).execute(text) if (showToast) { context.toast(toastMessage) @@ -141,7 +141,7 @@ fun startAddGoogleAccountIntent(context: Context, activityResultLauncher: Activi try { activityResultLauncher.launch(intent) } catch (activityNotFoundException: ActivityNotFoundException) { - context.toast(R.string.error_no_external_application_found) + context.toast(CommonStrings.error_no_external_application_found) } } @@ -152,7 +152,7 @@ fun startInstallFromSourceIntent(context: Context, activityResultLauncher: Activ try { activityResultLauncher.launch(intent) } catch (activityNotFoundException: ActivityNotFoundException) { - context.toast(R.string.error_no_external_application_found) + context.toast(CommonStrings.error_no_external_application_found) } } @@ -183,7 +183,7 @@ fun startSharePlainTextIntent( context.startActivity(intent) } } catch (activityNotFoundException: ActivityNotFoundException) { - context.toast(R.string.error_no_external_application_found) + context.toast(CommonStrings.error_no_external_application_found) } } @@ -194,7 +194,7 @@ fun startImportTextFromFileIntent(context: Context, activityResultLauncher: Acti try { activityResultLauncher.launch(intent) } catch (activityNotFoundException: ActivityNotFoundException) { - context.toast(R.string.error_no_external_application_found) + context.toast(CommonStrings.error_no_external_application_found) } } diff --git a/vector/src/main/java/im/vector/app/core/utils/TextUtils.kt b/vector/src/main/java/im/vector/app/core/utils/TextUtils.kt index db42df92e7..a73fb5bb25 100644 --- a/vector/src/main/java/im/vector/app/core/utils/TextUtils.kt +++ b/vector/src/main/java/im/vector/app/core/utils/TextUtils.kt @@ -16,11 +16,12 @@ package im.vector.app.core.utils +import android.annotation.SuppressLint import android.content.Context import android.os.Build import android.text.format.Formatter -import im.vector.app.R import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import org.threeten.bp.Duration import java.util.TreeMap @@ -75,6 +76,7 @@ object TextUtils { } } + @SuppressLint("DefaultLocale") fun formatDuration(duration: Duration): String { val hours = getHours(duration) val minutes = getMinutes(duration) @@ -135,17 +137,17 @@ object TextUtils { private fun appendHours(getString: ((Int) -> String), builder: StringBuilder, hours: Int) { builder.append(hours) - builder.append(getString(R.string.time_unit_hour_short)) + builder.append(getString(CommonStrings.time_unit_hour_short)) } private fun appendMinutes(getString: ((Int) -> String), builder: StringBuilder, minutes: Int) { builder.append(minutes) - builder.append(getString(R.string.time_unit_minute_short)) + builder.append(getString(CommonStrings.time_unit_minute_short)) } private fun appendSeconds(getString: ((Int) -> String), builder: StringBuilder, seconds: Int) { builder.append(seconds) - builder.append(getString(R.string.time_unit_second_short)) + builder.append(getString(CommonStrings.time_unit_second_short)) } private fun getHours(duration: Duration): Int = duration.toHours().toInt() diff --git a/vector/src/main/java/im/vector/app/features/MainActivity.kt b/vector/src/main/java/im/vector/app/features/MainActivity.kt index 0f0ac83903..1fa2a68941 100644 --- a/vector/src/main/java/im/vector/app/features/MainActivity.kt +++ b/vector/src/main/java/im/vector/app/features/MainActivity.kt @@ -29,7 +29,6 @@ import com.airbnb.mvrx.viewModel import com.bumptech.glide.Glide import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.startSyncing import im.vector.app.core.extensions.vectorStore import im.vector.app.core.platform.VectorBaseActivity @@ -57,6 +56,7 @@ import im.vector.app.features.start.StartAppViewState import im.vector.app.features.themes.ActivityOtherThemes import im.vector.app.features.ui.UiStateRepository import im.vector.lib.core.utils.compat.getParcelableExtraCompat +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -161,7 +161,7 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity private fun renderState(state: StartAppViewState) { if (state.mayBeLongToProcess) { - views.status.setText(R.string.updating_your_data) + views.status.setText(CommonStrings.updating_your_data) } views.status.isVisible = state.mayBeLongToProcess } @@ -338,15 +338,15 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity ) { if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) { MaterialAlertDialogBuilder(this) - .setTitle(R.string.dialog_title_error) - .setMessage(R.string.sign_out_failed_dialog_message) - .setPositiveButton(R.string.sign_out_anyway) { _, _ -> + .setTitle(CommonStrings.dialog_title_error) + .setMessage(CommonStrings.sign_out_failed_dialog_message) + .setPositiveButton(CommonStrings.sign_out_anyway) { _, _ -> signout(session, onboardingStore, ignoreServerError = true) } - .setNeutralButton(R.string.global_retry) { _, _ -> + .setNeutralButton(CommonStrings.global_retry) { _, _ -> signout(session, onboardingStore, ignoreServerError = false) } - .setNegativeButton(R.string.action_cancel) { _, _ -> startNextActivityAndFinish(ignoreClearCredentials = true) } + .setNegativeButton(CommonStrings.action_cancel) { _, _ -> startNextActivityAndFinish(ignoreClearCredentials = true) } .setCancelable(false) .show() } diff --git a/vector/src/main/java/im/vector/app/features/analytics/ui/consent/AnalyticsOptInFragment.kt b/vector/src/main/java/im/vector/app/features/analytics/ui/consent/AnalyticsOptInFragment.kt index fbeeab9ec3..3e2c076543 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/ui/consent/AnalyticsOptInFragment.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/ui/consent/AnalyticsOptInFragment.kt @@ -22,13 +22,13 @@ import android.view.View import android.view.ViewGroup import com.airbnb.mvrx.activityViewModel import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.setTextWithColoredPart import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.openUrlInChromeCustomTab import im.vector.app.databinding.FragmentAnalyticsOptinBinding import im.vector.app.features.analytics.AnalyticsConfig +import im.vector.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint @@ -63,8 +63,8 @@ class AnalyticsOptInFragment : private fun setupLink() { views.subtitle.setTextWithColoredPart( - fullTextRes = R.string.analytics_opt_in_content, - coloredTextRes = R.string.analytics_opt_in_content_link, + fullTextRes = CommonStrings.analytics_opt_in_content, + coloredTextRes = CommonStrings.analytics_opt_in_content_link, onClick = { openUrlInChromeCustomTab(requireContext(), null, analyticsConfig.policyLink) } diff --git a/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt b/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt index 55805a0728..952c720174 100644 --- a/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt +++ b/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt @@ -37,6 +37,7 @@ import im.vector.app.R import im.vector.app.core.epoxy.onClick import im.vector.app.databinding.ViewAttachmentTypeSelectorBinding import im.vector.app.features.attachments.AttachmentTypeSelectorView.Callback +import im.vector.lib.strings.CommonStrings import kotlin.math.max private const val ANIMATION_DURATION = 250 @@ -214,14 +215,14 @@ class AttachmentTypeSelectorView( private companion object { private val attachmentTooltipLabels: Map = AttachmentType.values().associateWith { when (it) { - AttachmentType.CAMERA -> R.string.tooltip_attachment_photo - AttachmentType.GALLERY -> R.string.tooltip_attachment_gallery - AttachmentType.FILE -> R.string.tooltip_attachment_file - AttachmentType.STICKER -> R.string.tooltip_attachment_sticker - AttachmentType.CONTACT -> R.string.tooltip_attachment_contact - AttachmentType.POLL -> R.string.tooltip_attachment_poll - AttachmentType.LOCATION -> R.string.tooltip_attachment_location - AttachmentType.VOICE_BROADCAST -> R.string.tooltip_attachment_voice_broadcast + AttachmentType.CAMERA -> CommonStrings.tooltip_attachment_photo + AttachmentType.GALLERY -> CommonStrings.tooltip_attachment_gallery + AttachmentType.FILE -> CommonStrings.tooltip_attachment_file + AttachmentType.STICKER -> CommonStrings.tooltip_attachment_sticker + AttachmentType.CONTACT -> CommonStrings.tooltip_attachment_contact + AttachmentType.POLL -> CommonStrings.tooltip_attachment_poll + AttachmentType.LOCATION -> CommonStrings.tooltip_attachment_location + AttachmentType.VOICE_BROADCAST -> CommonStrings.tooltip_attachment_voice_broadcast } } } diff --git a/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt b/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt index 5f7776bc95..81cfb0c9e6 100644 --- a/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt @@ -53,6 +53,8 @@ import im.vector.app.core.utils.attachSnapHelperWithListener import im.vector.app.databinding.FragmentAttachmentsPreviewBinding import im.vector.app.features.media.createUCropWithDefaultSettings import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.content.ContentAttachmentData @@ -152,9 +154,9 @@ class AttachmentsPreviewFragment : val nbImages = state.attachments.count { it.type == ContentAttachmentData.Type.IMAGE } val nbVideos = state.attachments.count { it.type == ContentAttachmentData.Type.VIDEO } return when { - nbVideos == 0 -> resources.getQuantityString(R.plurals.send_images_with_original_size, nbImages) - nbImages == 0 -> resources.getQuantityString(R.plurals.send_videos_with_original_size, nbVideos) - else -> getString(R.string.send_images_and_video_with_original_size) + nbVideos == 0 -> resources.getQuantityString(CommonPlurals.send_images_with_original_size, nbImages) + nbImages == 0 -> resources.getQuantityString(CommonPlurals.send_videos_with_original_size, nbVideos) + else -> getString(CommonStrings.send_images_and_video_with_original_size) } } diff --git a/vector/src/main/java/im/vector/app/features/auth/PromptFragment.kt b/vector/src/main/java/im/vector/app/features/auth/PromptFragment.kt index 38f098612b..b4aa9f52ab 100644 --- a/vector/src/main/java/im/vector/app/features/auth/PromptFragment.kt +++ b/vector/src/main/java/im/vector/app/features/auth/PromptFragment.kt @@ -23,9 +23,9 @@ import android.view.ViewGroup import androidx.core.view.isVisible import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState -import im.vector.app.R import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentReauthConfirmBinding +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.data.LoginFlowTypes class PromptFragment : VectorBaseFragment() { @@ -51,7 +51,7 @@ class PromptFragment : VectorBaseFragment() { val password = views.passwordField.text.toString() if (password.isBlank()) { // Prompt to enter something - views.passwordFieldTil.error = getString(R.string.error_empty_field_your_password) + views.passwordFieldTil.error = getString(CommonStrings.error_empty_field_your_password) } else { views.passwordFieldTil.error = null viewModel.handle(ReAuthActions.ReAuthWithPass(password)) @@ -67,11 +67,11 @@ class PromptFragment : VectorBaseFragment() { when (it.flowType) { LoginFlowTypes.SSO -> { views.passwordFieldTil.isVisible = false - views.reAuthConfirmButton.text = getString(R.string.auth_login_sso) + views.reAuthConfirmButton.text = getString(CommonStrings.auth_login_sso) } LoginFlowTypes.PASSWORD -> { views.passwordFieldTil.isVisible = true - views.reAuthConfirmButton.text = getString(R.string._continue) + views.reAuthConfirmButton.text = getString(CommonStrings._continue) } else -> { // This login flow is not supported, you should use web? @@ -82,10 +82,10 @@ class PromptFragment : VectorBaseFragment() { when (it.flowType) { LoginFlowTypes.SSO -> { views.genericErrorText.isVisible = true - views.genericErrorText.text = getString(R.string.authentication_error) + views.genericErrorText.text = getString(CommonStrings.authentication_error) } LoginFlowTypes.PASSWORD -> { - views.passwordFieldTil.error = getString(R.string.authentication_error) + views.passwordFieldTil.error = getString(CommonStrings.authentication_error) } else -> { // nop diff --git a/vector/src/main/java/im/vector/app/features/auth/ReAuthActivity.kt b/vector/src/main/java/im/vector/app/features/auth/ReAuthActivity.kt index 3f0b49e9f1..bfdc4d8099 100644 --- a/vector/src/main/java/im/vector/app/features/auth/ReAuthActivity.kt +++ b/vector/src/main/java/im/vector/app/features/auth/ReAuthActivity.kt @@ -30,10 +30,10 @@ import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.addFragment import im.vector.app.core.platform.SimpleFragmentActivity import im.vector.app.core.utils.openUrlInChromeCustomTab +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.auth.AuthenticationService import org.matrix.android.sdk.api.auth.data.LoginFlowTypes @@ -63,12 +63,12 @@ class ReAuthActivity : SimpleFragmentActivity() { private val sharedViewModel: ReAuthViewModel by viewModel() - // override fun getTitleRes() = R.string.re_authentication_activity_title + // override fun getTitleRes() = CommonStrings.re_authentication_activity_title override fun initUiAndData() { super.initUiAndData() - val title = intent.extras?.getString(EXTRA_REASON_TITLE) ?: getString(R.string.re_authentication_activity_title) + val title = intent.extras?.getString(EXTRA_REASON_TITLE) ?: getString(CommonStrings.re_authentication_activity_title) supportActionBar?.setTitle(title) ?: run { setTitle(title) } // val authArgs = intent.getParcelableExtra(Mavericks.KEY_ARG) diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberController.kt b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberController.kt index d6f177da0e..5ef3cca74e 100644 --- a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberController.kt +++ b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberController.kt @@ -18,11 +18,11 @@ package im.vector.app.features.autocomplete.member import android.content.Context import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.features.autocomplete.AutocompleteClickListener import im.vector.app.features.autocomplete.autocompleteHeaderItem import im.vector.app.features.autocomplete.autocompleteMatrixItem import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.util.toEveryoneInRoomMatrixItem import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject @@ -89,7 +89,7 @@ class AutocompleteMemberController @Inject constructor(private val context: Cont everyone.roomSummary.let { room -> id(room.roomId) matrixItem(room.toEveryoneInRoomMatrixItem()) - subName(host.context.getString(R.string.room_message_notify_everyone)) + subName(host.context.getString(CommonStrings.room_message_notify_everyone)) avatarRenderer(host.avatarRenderer) clickListener { host.listener?.onItemClick(everyone) } } diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt index 0f337470f3..87dfc2ef1f 100644 --- a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt +++ b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt @@ -21,9 +21,9 @@ import androidx.recyclerview.widget.RecyclerView import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.features.autocomplete.AutocompleteClickListener import im.vector.app.features.autocomplete.RecyclerViewPresenter +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.events.model.Event @@ -124,7 +124,7 @@ class AutocompleteMemberPresenter @AssistedInject constructor( private fun createMembersHeader() = AutocompleteMemberItem.Header( ID_HEADER_MEMBERS, - context.getString(R.string.room_message_autocomplete_users) + context.getString(CommonStrings.room_message_autocomplete_users) ) private fun createMemberItems(queryParams: RoomMemberQueryParams) = @@ -139,7 +139,7 @@ class AutocompleteMemberPresenter @AssistedInject constructor( private fun createEveryoneHeader() = AutocompleteMemberItem.Header( ID_HEADER_EVERYONE, - context.getString(R.string.room_message_autocomplete_notification) + context.getString(CommonStrings.room_message_autocomplete_notification) ) private fun createEveryoneItem(query: CharSequence?) = diff --git a/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt b/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt index 11a43bcd0c..d148485ffe 100644 --- a/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt @@ -28,6 +28,7 @@ import im.vector.app.R import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.databinding.BottomSheetCallControlsBinding import im.vector.app.features.VectorFeatures +import im.vector.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint @@ -80,15 +81,15 @@ class CallControlsBottomSheet : VectorBaseBottomSheetDialogFragment if (isVideoCall) { - if (checkPermissions(PERMISSIONS_FOR_VIDEO_IP_CALL, this, permissionCameraLauncher, R.string.permissions_rationale_msg_camera_and_audio)) { + if (checkPermissions(PERMISSIONS_FOR_VIDEO_IP_CALL, this, permissionCameraLauncher, CommonStrings.permissions_rationale_msg_camera_and_audio)) { setupRenderersIfNeeded() } } else { - if (checkPermissions(PERMISSIONS_FOR_AUDIO_IP_CALL, this, permissionCameraLauncher, R.string.permissions_rationale_msg_record_audio)) { + if (checkPermissions(PERMISSIONS_FOR_AUDIO_IP_CALL, this, permissionCameraLauncher, CommonStrings.permissions_rationale_msg_record_audio)) { setupRenderersIfNeeded() } } @@ -176,9 +177,9 @@ class VectorCallActivity : bindToScreenCaptureService() } - override fun onNewIntent(intent: Intent?) { + override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) - intent?.takeIf { it.hasExtra(Mavericks.KEY_ARG) } + intent.takeIf { it.hasExtra(Mavericks.KEY_ARG) } ?.let { intent.getParcelableExtraCompat(Mavericks.KEY_ARG) } ?.let { callViewModel.handle(VectorCallViewActions.SwitchCall(it)) @@ -189,12 +190,13 @@ class VectorCallActivity : override fun getMenuRes() = R.menu.vector_call override fun onUserLeaveHint() { + super.onUserLeaveHint() enterPictureInPictureIfRequired() } + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() { if (!enterPictureInPictureIfRequired()) { - @Suppress("DEPRECATION") super.onBackPressed() } } @@ -203,7 +205,10 @@ class VectorCallActivity : if (!it.isVideoCall) { false } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val aspectRatio = Rational(resources.getDimensionPixelSize(R.dimen.call_pip_width), resources.getDimensionPixelSize(R.dimen.call_pip_height)) + val aspectRatio = Rational( + resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.call_pip_width), + resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.call_pip_height) + ) val params = PictureInPictureParams.Builder() .setAspectRatio(aspectRatio) .build() @@ -287,14 +292,14 @@ class VectorCallActivity : views.fullscreenRenderer.isVisible = false views.pipRendererWrapper.isVisible = false views.callInfoGroup.isVisible = true - toolbar?.setSubtitle(R.string.call_ringing) + toolbar?.setSubtitle(CommonStrings.call_ringing) configureCallInfo(state) } is CallState.Answering -> { views.fullscreenRenderer.isVisible = false views.pipRendererWrapper.isVisible = false views.callInfoGroup.isVisible = true - toolbar?.setSubtitle(R.string.call_connecting) + toolbar?.setSubtitle(CommonStrings.call_connecting) configureCallInfo(state) } is CallState.Connected -> { @@ -307,23 +312,23 @@ class VectorCallActivity : views.callInfoGroup.isVisible = true configureCallInfo(state, blurAvatar = true) if (state.isRemoteOnHold) { - views.callActionText.setText(R.string.call_resume_action) + views.callActionText.setText(CommonStrings.call_resume_action) views.callActionText.isVisible = true views.callActionText.setOnClickListener { callViewModel.handle(VectorCallViewActions.ToggleHoldResume) } - toolbar?.setSubtitle(R.string.call_held_by_you) + toolbar?.setSubtitle(CommonStrings.call_held_by_you) } else { views.callActionText.isInvisible = true state.callInfo?.opponentUserItem?.let { - toolbar?.subtitle = getString(R.string.call_held_by_user, it.getBestName()) + toolbar?.subtitle = getString(CommonStrings.call_held_by_user, it.getBestName()) } } } else if (state.transferee !is VectorCallViewState.TransfereeState.NoTransferee) { val transfereeName = if (state.transferee is VectorCallViewState.TransfereeState.KnownTransferee) { state.transferee.name } else { - getString(R.string.call_transfer_unknown_person) + getString(CommonStrings.call_transfer_unknown_person) } - views.callActionText.text = getString(R.string.call_transfer_transfer_to_title, transfereeName) + views.callActionText.text = getString(CommonStrings.call_transfer_transfer_to_title, transfereeName) views.callActionText.isVisible = true views.callActionText.setOnClickListener { callViewModel.handle(VectorCallViewActions.TransferCall) } configureCallInfo(state) @@ -346,14 +351,14 @@ class VectorCallActivity : views.pipRendererWrapper.isVisible = false views.callInfoGroup.isVisible = true configureCallInfo(state) - toolbar?.setSubtitle(R.string.call_connecting) + toolbar?.setSubtitle(CommonStrings.call_connecting) } } is CallState.Ended -> { views.fullscreenRenderer.isVisible = false views.pipRendererWrapper.isVisible = false views.callInfoGroup.isVisible = true - toolbar?.setSubtitle(R.string.call_ended) + toolbar?.setSubtitle(CommonStrings.call_ended) configureCallInfo(state) } else -> { @@ -412,10 +417,10 @@ class VectorCallActivity : } when (callState.reason) { EndCallReason.USER_BUSY -> { - showEndCallDialog(R.string.call_ended_user_busy_title, R.string.call_ended_user_busy_description) + showEndCallDialog(CommonStrings.call_ended_user_busy_title, CommonStrings.call_ended_user_busy_description) } EndCallReason.INVITE_TIMEOUT -> { - showEndCallDialog(R.string.call_ended_invite_timeout_title, R.string.call_error_user_not_responding) + showEndCallDialog(CommonStrings.call_ended_invite_timeout_title, CommonStrings.call_error_user_not_responding) } else -> { finish() @@ -427,7 +432,7 @@ class VectorCallActivity : MaterialAlertDialogBuilder(this) .setTitle(title) .setMessage(description) - .setNegativeButton(R.string.ok, null) + .setNegativeButton(CommonStrings.ok, null) .setOnDismissListener { finish() } @@ -436,17 +441,17 @@ class VectorCallActivity : private fun configureCallInfo(state: VectorCallViewState, blurAvatar: Boolean = false) { state.callInfo?.opponentUserItem?.let { - val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen_blur) + val colorFilter = ContextCompat.getColor(this, im.vector.lib.ui.styles.R.color.bg_call_screen_blur) avatarRenderer.renderBlur(it, views.bgCallView, sampling = 20, rounded = false, colorFilter = colorFilter, addPlaceholder = false) if (state.transferee is VectorCallViewState.TransfereeState.NoTransferee) { views.participantNameText.setTextOrHide(null) toolbar?.title = if (state.isVideoCall) { - getString(R.string.video_call_with_participant, it.getBestName()) + getString(CommonStrings.video_call_with_participant, it.getBestName()) } else { - getString(R.string.audio_call_with_participant, it.getBestName()) + getString(CommonStrings.audio_call_with_participant, it.getBestName()) } } else { - views.participantNameText.setTextOrHide(getString(R.string.call_transfer_consulting_with, it.getBestName())) + views.participantNameText.setTextOrHide(getString(CommonStrings.call_transfer_consulting_with, it.getBestName())) } if (blurAvatar) { avatarRenderer.renderBlur(it, views.otherMemberAvatar, sampling = 2, rounded = true, colorFilter = colorFilter, addPlaceholder = true) @@ -458,7 +463,7 @@ class VectorCallActivity : views.otherKnownCallLayout.isVisible = false } else { val otherCall = callManager.getCallById(state.otherKnownCallInfo.callId) - val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen_blur) + val colorFilter = ContextCompat.getColor(this, im.vector.lib.ui.styles.R.color.bg_call_screen_blur) avatarRenderer.renderBlur( matrixItem = state.otherKnownCallInfo.opponentUserItem, imageView = views.otherKnownCallAvatarView, @@ -550,7 +555,7 @@ class VectorCallActivity : val callId = withState(callViewModel) { it.callId } navigator.openCallTransfer(this, callTransferActivityResultLauncher, callId) } - is VectorCallViewEvents.FailToTransfer -> showSnackbar(getString(R.string.call_transfer_failure)) + is VectorCallViewEvents.FailToTransfer -> showSnackbar(getString(CommonStrings.call_transfer_failure)) is VectorCallViewEvents.ShowScreenSharingPermissionDialog -> handleShowScreenSharingPermissionDialog() is VectorCallViewEvents.StopScreenSharingService -> handleStopScreenSharingService() else -> Unit @@ -573,9 +578,9 @@ class VectorCallActivity : Timber.tag(loggerTag.value).d("onErrorTimoutConnect $turn") // TODO ask to use default stun, etc... MaterialAlertDialogBuilder(this) - .setTitle(R.string.call_failed_no_connection) - .setMessage(R.string.call_failed_no_connection_description) - .setNegativeButton(R.string.ok) { _, _ -> + .setTitle(CommonStrings.call_failed_no_connection) + .setMessage(CommonStrings.call_failed_no_connection_description) + .setNegativeButton(CommonStrings.ok) { _, _ -> callViewModel.handle(VectorCallViewActions.EndCall) } .show() diff --git a/vector/src/main/java/im/vector/app/features/call/audio/CallAudioManager.kt b/vector/src/main/java/im/vector/app/features/call/audio/CallAudioManager.kt index 6577d0374d..dfdfe8b93f 100644 --- a/vector/src/main/java/im/vector/app/features/call/audio/CallAudioManager.kt +++ b/vector/src/main/java/im/vector/app/features/call/audio/CallAudioManager.kt @@ -23,6 +23,7 @@ import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.core.content.getSystemService import im.vector.app.R +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orFalse import timber.log.Timber import java.util.concurrent.Executors @@ -34,10 +35,10 @@ class CallAudioManager(private val context: Context, val configChange: (() -> Un private var audioDeviceRouter: AudioDeviceRouter? = null sealed class Device(@StringRes val titleRes: Int, @DrawableRes val drawableRes: Int) { - object Phone : Device(R.string.sound_device_phone, R.drawable.ic_sound_device_phone) - object Speaker : Device(R.string.sound_device_speaker, R.drawable.ic_sound_device_speaker) - object Headset : Device(R.string.sound_device_headset, R.drawable.ic_sound_device_headphone) - data class WirelessHeadset(val name: String?) : Device(R.string.sound_device_wireless_headset, R.drawable.ic_sound_device_wireless) + object Phone : Device(CommonStrings.sound_device_phone, R.drawable.ic_sound_device_phone) + object Speaker : Device(CommonStrings.sound_device_speaker, R.drawable.ic_sound_device_speaker) + object Headset : Device(CommonStrings.sound_device_headset, R.drawable.ic_sound_device_headphone) + data class WirelessHeadset(val name: String?) : Device(CommonStrings.sound_device_wireless_headset, R.drawable.ic_sound_device_wireless) } enum class Mode { diff --git a/vector/src/main/java/im/vector/app/features/call/audio/DefaultAudioDeviceRouter.kt b/vector/src/main/java/im/vector/app/features/call/audio/DefaultAudioDeviceRouter.kt index 7251c2d423..d3591b77fc 100644 --- a/vector/src/main/java/im/vector/app/features/call/audio/DefaultAudioDeviceRouter.kt +++ b/vector/src/main/java/im/vector/app/features/call/audio/DefaultAudioDeviceRouter.kt @@ -32,6 +32,7 @@ class DefaultAudioDeviceRouter( private var focusRequestCompat: AudioFocusRequestCompat? = null override fun setAudioRoute(device: CallAudioManager.Device) { + @Suppress("DEPRECATION") audioManager.isSpeakerphoneOn = device is CallAudioManager.Device.Speaker setBluetoothAudioRoute(device is CallAudioManager.Device.WirelessHeadset) } @@ -44,6 +45,7 @@ class DefaultAudioDeviceRouter( AudioManagerCompat.abandonAudioFocusRequest(audioManager, it) } focusRequestCompat = null + @Suppress("DEPRECATION") audioManager.isSpeakerphoneOn = false setBluetoothAudioRoute(false) return true @@ -79,10 +81,12 @@ class DefaultAudioDeviceRouter( */ private fun setBluetoothAudioRoute(enabled: Boolean) { if (enabled) { + @Suppress("DEPRECATION") audioManager.startBluetoothSco() audioManager.isBluetoothScoOn = true } else { audioManager.isBluetoothScoOn = false + @Suppress("DEPRECATION") audioManager.stopBluetoothSco() } } diff --git a/vector/src/main/java/im/vector/app/features/call/conference/JitsiService.kt b/vector/src/main/java/im/vector/app/features/call/conference/JitsiService.kt index 9ce2d6bf2d..41c188b913 100644 --- a/vector/src/main/java/im/vector/app/features/call/conference/JitsiService.kt +++ b/vector/src/main/java/im/vector/app/features/call/conference/JitsiService.kt @@ -16,7 +16,6 @@ package im.vector.app.features.call.conference -import im.vector.app.R import im.vector.app.core.network.await import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.ensureProtocol @@ -57,7 +56,7 @@ class JitsiService @Inject constructor( } private val jitsiWidgetDataFactory by lazy { - JitsiWidgetDataFactory(stringProvider.getString(R.string.preferred_jitsi_domain)) { widget -> + JitsiWidgetDataFactory(stringProvider.getString(im.vector.app.config.R.string.preferred_jitsi_domain)) { widget -> session.widgetService().getWidgetComputedUrl(widget, themeProvider.isLightTheme()) } } @@ -70,7 +69,7 @@ class JitsiService @Inject constructor( ?.jitsiServer ?.preferredDomain } - val jitsiDomain = preferredJitsiDomain ?: stringProvider.getString(R.string.preferred_jitsi_domain) + val jitsiDomain = preferredJitsiDomain ?: stringProvider.getString(im.vector.app.config.R.string.preferred_jitsi_domain) val jitsiAuth = getJitsiAuth(jitsiDomain) val confId = createConferenceId(roomId, jitsiAuth) diff --git a/vector/src/main/java/im/vector/app/features/call/conference/RemoveJitsiWidgetView.kt b/vector/src/main/java/im/vector/app/features/call/conference/RemoveJitsiWidgetView.kt index 656c0029eb..3bb9269c2e 100644 --- a/vector/src/main/java/im/vector/app/features/call/conference/RemoveJitsiWidgetView.kt +++ b/vector/src/main/java/im/vector/app/features/call/conference/RemoveJitsiWidgetView.kt @@ -152,11 +152,11 @@ import kotlin.math.absoluteValue val iconTintColor: Int val bgColor: Int if (activated) { - bgColor = ContextCompat.getColor(context, R.color.palette_vermilion) - iconTintColor = ContextCompat.getColor(context, R.color.palette_white) + bgColor = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.palette_vermilion) + iconTintColor = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.palette_white) } else { bgColor = ContextCompat.getColor(context, android.R.color.transparent) - iconTintColor = ContextCompat.getColor(context, R.color.palette_vermilion) + iconTintColor = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.palette_vermilion) } removeJitsiHangupContainer.setBackgroundColor(bgColor) ImageViewCompat.setImageTintList(removeJitsiHangupIcon, ColorStateList.valueOf(iconTintColor)) diff --git a/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt b/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt index 1f5770a6fb..ea25b42669 100644 --- a/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt +++ b/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt @@ -16,6 +16,7 @@ package im.vector.app.features.call.conference +import android.annotation.SuppressLint import android.content.Context import android.content.Intent import android.content.pm.PackageManager @@ -37,10 +38,10 @@ import com.airbnb.mvrx.viewModel import com.facebook.react.modules.core.PermissionListener import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.databinding.ActivityJitsiBinding import im.vector.lib.core.utils.compat.getParcelableExtraCompat +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.jitsi.meet.sdk.BroadcastIntentHelper import org.jitsi.meet.sdk.JitsiMeet @@ -130,12 +131,15 @@ class VectorJitsiActivity : VectorBaseActivity(), JitsiMee // Activity lifecycle methods // + @Suppress("OVERRIDE_DEPRECATION") override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { @Suppress("DEPRECATION") super.onActivityResult(requestCode, resultCode, data) JitsiMeetActivityDelegate.onActivityResult(this, requestCode, resultCode, data) } + @Suppress("OVERRIDE_DEPRECATION") + @SuppressLint("MissingSuperCall") override fun onBackPressed() { JitsiMeetActivityDelegate.onBackPressed() } @@ -154,12 +158,12 @@ class VectorJitsiActivity : VectorBaseActivity(), JitsiMee private fun handleConfirmSwitching(action: JitsiCallViewEvents.ConfirmSwitchingConference) { MaterialAlertDialogBuilder(this) - .setTitle(R.string.dialog_title_warning) - .setMessage(R.string.jitsi_leave_conf_to_join_another_one_content) - .setPositiveButton(R.string.action_switch) { _, _ -> + .setTitle(CommonStrings.dialog_title_warning) + .setMessage(CommonStrings.jitsi_leave_conf_to_join_another_one_content) + .setPositiveButton(CommonStrings.action_switch) { _, _ -> jitsiViewModel.handle(JitsiCallViewActions.SwitchTo(action.args, false)) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } @@ -191,7 +195,7 @@ class VectorJitsiActivity : VectorBaseActivity(), JitsiMee } private fun handleFailJoining() { - Toast.makeText(this, getString(R.string.error_jitsi_join_conf), Toast.LENGTH_LONG).show() + Toast.makeText(this, getString(CommonStrings.error_jitsi_join_conf), Toast.LENGTH_LONG).show() finish() } @@ -217,11 +221,11 @@ class VectorJitsiActivity : VectorBaseActivity(), JitsiMee jitsiMeetView?.join(jitsiMeetConferenceOptions) } - override fun onNewIntent(intent: Intent?) { + override fun onNewIntent(intent: Intent) { JitsiMeetActivityDelegate.onNewIntent(intent) // Is it a switch to another conf? - intent?.takeIf { it.hasExtra(Mavericks.KEY_ARG) } + intent.takeIf { it.hasExtra(Mavericks.KEY_ARG) } ?.let { intent.getParcelableExtraCompat(Mavericks.KEY_ARG) } ?.let { jitsiViewModel.handle(JitsiCallViewActions.SwitchTo(it, true)) diff --git a/vector/src/main/java/im/vector/app/features/call/dialpad/DialPadFragment.kt b/vector/src/main/java/im/vector/app/features/call/dialpad/DialPadFragment.kt index 05337e2064..2862164aae 100644 --- a/vector/src/main/java/im/vector/app/features/call/dialpad/DialPadFragment.kt +++ b/vector/src/main/java/im/vector/app/features/call/dialpad/DialPadFragment.kt @@ -16,6 +16,7 @@ package im.vector.app.features.call.dialpad +import android.annotation.SuppressLint import android.content.ClipboardManager import android.content.Context import android.content.res.ColorStateList @@ -37,7 +38,7 @@ import androidx.core.widget.ImageViewCompat import androidx.fragment.app.Fragment import com.android.dialer.dialpadview.DialpadView import com.android.dialer.dialpadview.DigitsEditText -import im.vector.app.R +import com.android.dialer.dialpadview.R import im.vector.app.core.extensions.singletonEntryPoint import im.vector.app.features.analytics.AnalyticsTracker import im.vector.app.features.analytics.plan.MobileScreen @@ -70,6 +71,7 @@ class DialPadFragment : Fragment(), TextWatcher { analyticsTracker.screen(MobileScreen(screenName = MobileScreen.ScreenName.Dialpad)) } + @SuppressLint("WrongThread") override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -77,14 +79,14 @@ class DialPadFragment : Fragment(), TextWatcher { ): View { initArgs(savedInstanceState) val view = inflater.inflate(R.layout.dialpad_fragment, container, false) - view.setBackgroundColor(ThemeUtils.getColor(requireContext(), R.attr.backgroundColor)) + view.setBackgroundColor(ThemeUtils.getColor(requireContext(), com.google.android.material.R.attr.backgroundColor)) val dialpadView = view.findViewById(R.id.dialpad_view) as DialpadView dialpadView.findViewById(R.id.dialpad_key_voicemail).isVisible = false digits = dialpadView.digits as DigitsEditText digits.isCursorVisible = cursorVisible digits.inputType = InputType.TYPE_CLASS_PHONE digits.keyListener = DialerKeyListener.getInstance() - digits.setTextColor(ThemeUtils.getColor(requireContext(), R.attr.vctr_content_primary)) + digits.setTextColor(ThemeUtils.getColor(requireContext(), im.vector.lib.ui.styles.R.attr.vctr_content_primary)) digits.addTextChangedListener(PhoneNumberFormattingTextWatcher(if (formatAsYouType) regionCode else "")) digits.addTextChangedListener(this) dialpadView.findViewById(R.id.zero).setOnClickListener { keyPressed(KeyEvent.KEYCODE_0, "0") } @@ -119,7 +121,7 @@ class DialPadFragment : Fragment(), TextWatcher { clear() true } - val tintColor = ThemeUtils.getColor(requireContext(), R.attr.vctr_content_secondary) + val tintColor = ThemeUtils.getColor(requireContext(), im.vector.lib.ui.styles.R.attr.vctr_content_secondary) ImageViewCompat.setImageTintList(dialpadView.deleteButton, ColorStateList.valueOf(tintColor)) } else { dialpadView.deleteButton.isVisible = false @@ -190,7 +192,7 @@ class DialPadFragment : Fragment(), TextWatcher { fun clear() { if (::digits.isInitialized) { - digits.setText("") + digits.text = null } } diff --git a/vector/src/main/java/im/vector/app/features/call/dialpad/PstnDialActivity.kt b/vector/src/main/java/im/vector/app/features/call/dialpad/PstnDialActivity.kt index 1a7571598e..eb290afac2 100644 --- a/vector/src/main/java/im/vector/app/features/call/dialpad/PstnDialActivity.kt +++ b/vector/src/main/java/im/vector/app/features/call/dialpad/PstnDialActivity.kt @@ -22,11 +22,11 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.addFragment import im.vector.app.core.platform.SimpleFragmentActivity import im.vector.app.features.call.webrtc.WebRtcCallManager import im.vector.app.features.createdirect.DirectRoomHelper +import im.vector.lib.strings.CommonStrings import im.vector.lib.ui.styles.dialogs.MaterialProgressDialog import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.Session @@ -41,7 +41,7 @@ class PstnDialActivity : SimpleFragmentActivity() { private var progress: AppCompatDialog? = null - override fun getTitleRes(): Int = R.string.call + override fun getTitleRes(): Int = CommonStrings.call override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -89,7 +89,7 @@ class PstnDialActivity : SimpleFragmentActivity() { private fun showLoadingDialog() { progress?.dismiss() progress = MaterialProgressDialog(this) - .show(getString(R.string.please_wait)) + .show(getString(CommonStrings.please_wait)) } private fun dismissLoadingDialog() { @@ -98,9 +98,9 @@ class PstnDialActivity : SimpleFragmentActivity() { private fun displayErrorDialog(throwable: Throwable) { MaterialAlertDialogBuilder(this) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(errorFormatter.toHumanReadable(throwable)) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } } diff --git a/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt b/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt index ae168c5f92..5ab6288965 100644 --- a/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt +++ b/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt @@ -24,10 +24,10 @@ import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.viewModel import com.google.android.material.tabs.TabLayoutMediator import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.databinding.ActivityCallTransferBinding import im.vector.lib.core.utils.compat.getParcelableCompat +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize @Parcelize @@ -61,8 +61,8 @@ class CallTransferActivity : VectorBaseActivity() { TabLayoutMediator(views.callTransferTabLayout, views.callTransferViewPager) { tab, position -> when (position) { - CallTransferPagerAdapter.USER_LIST_INDEX -> tab.text = getString(R.string.call_transfer_users_tab_title) - CallTransferPagerAdapter.DIAL_PAD_INDEX -> tab.text = getString(R.string.call_dial_pad_title) + CallTransferPagerAdapter.USER_LIST_INDEX -> tab.text = getString(CommonStrings.call_transfer_users_tab_title) + CallTransferPagerAdapter.DIAL_PAD_INDEX -> tab.text = getString(CommonStrings.call_dial_pad_title) } }.attach() setupToolbar(views.callTransferToolbar) diff --git a/vector/src/main/java/im/vector/app/features/command/Command.kt b/vector/src/main/java/im/vector/app/features/command/Command.kt index b112751f68..eabaacd9e7 100644 --- a/vector/src/main/java/im/vector/app/features/command/Command.kt +++ b/vector/src/main/java/im/vector/app/features/command/Command.kt @@ -17,7 +17,7 @@ package im.vector.app.features.command import androidx.annotation.StringRes -import im.vector.app.R +import im.vector.lib.strings.CommonStrings /** * Defines the command line operations. @@ -32,43 +32,46 @@ enum class Command( val isDevCommand: Boolean, val isThreadCommand: Boolean ) { - CRASH_APP("/crash", null, "", R.string.command_description_crash_application, true, true), - EMOTE("/me", null, "", R.string.command_description_emote, false, true), - BAN_USER("/ban", null, " [reason]", R.string.command_description_ban_user, false, false), - UNBAN_USER("/unban", null, " [reason]", R.string.command_description_unban_user, false, false), - IGNORE_USER("/ignore", null, " [reason]", R.string.command_description_ignore_user, false, true), - UNIGNORE_USER("/unignore", null, "", R.string.command_description_unignore_user, false, true), - SET_USER_POWER_LEVEL("/op", null, " []", R.string.command_description_op_user, false, false), - RESET_USER_POWER_LEVEL("/deop", null, "", R.string.command_description_deop_user, false, false), - ROOM_NAME("/roomname", null, "", R.string.command_description_room_name, false, false), - INVITE("/invite", null, " [reason]", R.string.command_description_invite_user, false, false), - JOIN_ROOM("/join", arrayOf("/j", "/goto"), " [reason]", R.string.command_description_join_room, false, false), - PART("/part", null, "[]", R.string.command_description_part_room, false, false), - TOPIC("/topic", null, "", R.string.command_description_topic, false, false), - REMOVE_USER("/remove", arrayOf("/kick"), " [reason]", R.string.command_description_remove_user, false, false), - CHANGE_DISPLAY_NAME("/nick", null, "", R.string.command_description_nick, false, false), - CHANGE_DISPLAY_NAME_FOR_ROOM("/myroomnick", arrayOf("/roomnick"), "", R.string.command_description_nick_for_room, false, false), - ROOM_AVATAR("/roomavatar", null, "", R.string.command_description_room_avatar, true /* User has to know the mxc url */, false), - CHANGE_AVATAR_FOR_ROOM("/myroomavatar", null, "", R.string.command_description_avatar_for_room, true /* User has to know the mxc url */, false), - MARKDOWN("/markdown", null, "", R.string.command_description_markdown, false, false), - RAINBOW("/rainbow", null, "", R.string.command_description_rainbow, false, true), - RAINBOW_EMOTE("/rainbowme", null, "", R.string.command_description_rainbow_emote, false, true), - DEVTOOLS("/devtools", null, "", R.string.command_description_devtools, true, false), - CLEAR_SCALAR_TOKEN("/clear_scalar_token", null, "", R.string.command_description_clear_scalar_token, false, false), - SPOILER("/spoiler", null, "", R.string.command_description_spoiler, false, true), - SHRUG("/shrug", null, "", R.string.command_description_shrug, false, true), - LENNY("/lenny", null, "", R.string.command_description_lenny, false, true), - PLAIN("/plain", null, "", R.string.command_description_plain, false, true), - WHOIS("/whois", null, "", R.string.command_description_whois, false, true), - DISCARD_SESSION("/discardsession", null, "", R.string.command_description_discard_session, false, false), - CONFETTI("/confetti", null, "", R.string.command_confetti, false, false), - SNOWFALL("/snowfall", null, "", R.string.command_snow, false, false), - CREATE_SPACE("/createspace", null, " *", R.string.command_description_create_space, true, false), - ADD_TO_SPACE("/addToSpace", null, "spaceId", R.string.command_description_add_to_space, true, false), - JOIN_SPACE("/joinSpace", null, "spaceId", R.string.command_description_join_space, true, false), - LEAVE_ROOM("/leave", null, "", R.string.command_description_leave_room, true, false), - UPGRADE_ROOM("/upgraderoom", null, "newVersion", R.string.command_description_upgrade_room, true, false), - TABLE_FLIP("/tableflip", null, "", R.string.command_description_table_flip, false, true); + CRASH_APP("/crash", null, "", CommonStrings.command_description_crash_application, true, true), + EMOTE("/me", null, "", CommonStrings.command_description_emote, false, true), + BAN_USER("/ban", null, " [reason]", CommonStrings.command_description_ban_user, false, false), + UNBAN_USER("/unban", null, " [reason]", CommonStrings.command_description_unban_user, false, false), + IGNORE_USER("/ignore", null, " [reason]", CommonStrings.command_description_ignore_user, false, true), + UNIGNORE_USER("/unignore", null, "", CommonStrings.command_description_unignore_user, false, true), + SET_USER_POWER_LEVEL("/op", null, " []", CommonStrings.command_description_op_user, false, false), + RESET_USER_POWER_LEVEL("/deop", null, "", CommonStrings.command_description_deop_user, false, false), + ROOM_NAME("/roomname", null, "", CommonStrings.command_description_room_name, false, false), + INVITE("/invite", null, " [reason]", CommonStrings.command_description_invite_user, false, false), + JOIN_ROOM("/join", arrayOf("/j", "/goto"), " [reason]", CommonStrings.command_description_join_room, false, false), + PART("/part", null, "[]", CommonStrings.command_description_part_room, false, false), + TOPIC("/topic", null, "", CommonStrings.command_description_topic, false, false), + REMOVE_USER("/remove", arrayOf("/kick"), " [reason]", CommonStrings.command_description_remove_user, false, false), + CHANGE_DISPLAY_NAME("/nick", null, "", CommonStrings.command_description_nick, false, false), + CHANGE_DISPLAY_NAME_FOR_ROOM("/myroomnick", arrayOf("/roomnick"), "", CommonStrings.command_description_nick_for_room, false, false), + ROOM_AVATAR("/roomavatar", null, "", CommonStrings.command_description_room_avatar, true /* User has to know the mxc url */, false), + CHANGE_AVATAR_FOR_ROOM( + "/myroomavatar", null, "", + CommonStrings.command_description_avatar_for_room, true /* User has to know the mxc url */, false + ), + MARKDOWN("/markdown", null, "", CommonStrings.command_description_markdown, false, false), + RAINBOW("/rainbow", null, "", CommonStrings.command_description_rainbow, false, true), + RAINBOW_EMOTE("/rainbowme", null, "", CommonStrings.command_description_rainbow_emote, false, true), + DEVTOOLS("/devtools", null, "", CommonStrings.command_description_devtools, true, false), + CLEAR_SCALAR_TOKEN("/clear_scalar_token", null, "", CommonStrings.command_description_clear_scalar_token, false, false), + SPOILER("/spoiler", null, "", CommonStrings.command_description_spoiler, false, true), + SHRUG("/shrug", null, "", CommonStrings.command_description_shrug, false, true), + LENNY("/lenny", null, "", CommonStrings.command_description_lenny, false, true), + PLAIN("/plain", null, "", CommonStrings.command_description_plain, false, true), + WHOIS("/whois", null, "", CommonStrings.command_description_whois, false, true), + DISCARD_SESSION("/discardsession", null, "", CommonStrings.command_description_discard_session, false, false), + CONFETTI("/confetti", null, "", CommonStrings.command_confetti, false, false), + SNOWFALL("/snowfall", null, "", CommonStrings.command_snow, false, false), + CREATE_SPACE("/createspace", null, " *", CommonStrings.command_description_create_space, true, false), + ADD_TO_SPACE("/addToSpace", null, "spaceId", CommonStrings.command_description_add_to_space, true, false), + JOIN_SPACE("/joinSpace", null, "spaceId", CommonStrings.command_description_join_space, true, false), + LEAVE_ROOM("/leave", null, "", CommonStrings.command_description_leave_room, true, false), + UPGRADE_ROOM("/upgraderoom", null, "newVersion", CommonStrings.command_description_upgrade_room, true, false), + TABLE_FLIP("/tableflip", null, "", CommonStrings.command_description_table_flip, false, true); val allAliases = arrayOf(command, *aliases.orEmpty()) diff --git a/vector/src/main/java/im/vector/app/features/consent/ConsentNotGivenHelper.kt b/vector/src/main/java/im/vector/app/features/consent/ConsentNotGivenHelper.kt index d2bb6b78b0..bfe3da4913 100644 --- a/vector/src/main/java/im/vector/app/features/consent/ConsentNotGivenHelper.kt +++ b/vector/src/main/java/im/vector/app/features/consent/ConsentNotGivenHelper.kt @@ -18,11 +18,11 @@ package im.vector.app.features.consent import android.app.Activity import com.google.android.material.dialog.MaterialAlertDialogBuilder -import im.vector.app.R import im.vector.app.core.dialogs.DialogLocker import im.vector.app.core.platform.Restorable import im.vector.app.features.webview.VectorWebViewActivity import im.vector.app.features.webview.WebViewMode +import im.vector.lib.strings.CommonStrings class ConsentNotGivenHelper( private val activity: Activity, @@ -40,9 +40,9 @@ class ConsentNotGivenHelper( fun displayDialog(consentUri: String, homeServerHost: String) { dialogLocker.displayDialog { MaterialAlertDialogBuilder(activity) - .setTitle(R.string.settings_app_term_conditions) - .setMessage(activity.getString(R.string.dialog_user_consent_content, homeServerHost)) - .setPositiveButton(R.string.dialog_user_consent_submit) { _, _ -> + .setTitle(CommonStrings.settings_app_term_conditions) + .setMessage(activity.getString(CommonStrings.dialog_user_consent_content, homeServerHost)) + .setPositiveButton(CommonStrings.dialog_user_consent_submit) { _, _ -> openWebViewActivity(consentUri) } } @@ -53,7 +53,7 @@ class ConsentNotGivenHelper( * ========================================================================================== */ private fun openWebViewActivity(consentUri: String) { - val intent = VectorWebViewActivity.getIntent(activity, consentUri, activity.getString(R.string.settings_app_term_conditions), WebViewMode.CONSENT) + val intent = VectorWebViewActivity.getIntent(activity, consentUri, activity.getString(CommonStrings.settings_app_term_conditions), WebViewMode.CONSENT) activity.startActivity(intent) } } diff --git a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookController.kt b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookController.kt index 6113755159..a501c36602 100644 --- a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookController.kt +++ b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookController.kt @@ -21,7 +21,6 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized -import im.vector.app.R import im.vector.app.core.contacts.MappedContact import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem @@ -29,6 +28,7 @@ import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.identity.ThreePid import javax.inject.Inject @@ -61,7 +61,7 @@ class ContactsBookController @Inject constructor( val host = this loadingItem { id("loading") - loadingText(host.stringProvider.getString(R.string.loading_contact_book)) + loadingText(host.stringProvider.getString(CommonStrings.loading_contact_book)) } } @@ -131,9 +131,9 @@ class ContactsBookController @Inject constructor( private fun renderEmptyState(hasSearch: Boolean) { val host = this val noResultRes = if (hasSearch) { - R.string.no_result_placeholder + CommonStrings.no_result_placeholder } else { - R.string.empty_contact_book + CommonStrings.empty_contact_book } noResultItem { id("noResult") diff --git a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewModel.kt b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewModel.kt index 402fc40c9a..67b511fa64 100644 --- a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewModel.kt @@ -22,7 +22,6 @@ import com.airbnb.mvrx.Success import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.contacts.ContactsDataSource import im.vector.app.core.contacts.MappedContact import im.vector.app.core.di.MavericksAssistedViewModelFactory @@ -30,6 +29,7 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.features.discovery.fetchIdentityServerWithTerms +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.Session @@ -170,7 +170,7 @@ class ContactsBookViewModel @AssistedInject constructor( private fun handleUserConsentRequest() { viewModelScope.launch { val event = try { - val result = session.fetchIdentityServerWithTerms(stringProvider.getString(R.string.resources_language)) + val result = session.fetchIdentityServerWithTerms(stringProvider.getString(CommonStrings.resources_language)) ContactsBookViewEvents.OnPoliciesRetrieved(result) } catch (throwable: Throwable) { ContactsBookViewEvents.Failure(throwable) diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt index faf4374d93..97e71c7940 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt @@ -53,6 +53,7 @@ import im.vector.app.features.userdirectory.UserListFragment import im.vector.app.features.userdirectory.UserListFragmentArgs import im.vector.app.features.userdirectory.UserListSharedAction import im.vector.app.features.userdirectory.UserListSharedActionViewModel +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.failure.Failure @@ -91,7 +92,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { views.container, UserListFragment::class.java, UserListFragmentArgs( - title = getString(R.string.fab_menu_create_chat), + title = getString(CommonStrings.fab_menu_create_chat), menuResId = R.menu.vector_create_direct_room, submitMenuItemId = R.id.action_create_direct_room, single3pidSelection = true, @@ -105,11 +106,11 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { viewModel.observeViewEvents { when (it) { CreateDirectRoomViewEvents.InvalidCode -> { - Toast.makeText(this, R.string.invalid_qr_code_uri, Toast.LENGTH_SHORT).show() + Toast.makeText(this, CommonStrings.invalid_qr_code_uri, Toast.LENGTH_SHORT).show() finish() } CreateDirectRoomViewEvents.DmSelf -> { - Toast.makeText(this, R.string.cannot_dm_self, Toast.LENGTH_SHORT).show() + Toast.makeText(this, CommonStrings.cannot_dm_self, Toast.LENGTH_SHORT).show() finish() } } @@ -121,7 +122,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { viewModel.handle(CreateDirectRoomAction.QrScannedAction(it.result)) } is QrCodeScannerEvents.ParseFailed -> { - Toast.makeText(this, R.string.qr_code_not_scanned, Toast.LENGTH_SHORT).show() + Toast.makeText(this, CommonStrings.qr_code_not_scanned, Toast.LENGTH_SHORT).show() finish() } else -> Unit @@ -131,7 +132,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { private fun openAddByQrCode() { if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this, permissionCameraLauncher)) { - val args = QrScannerArgs(showExtraButtons = false, R.string.add_by_qr_code) + val args = QrScannerArgs(showExtraButtons = false, CommonStrings.add_by_qr_code) addFragment(views.container, QrCodeScannerFragment::class.java, args) } } @@ -147,16 +148,16 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { if (allGranted) { doOnPostResume { addFragmentToBackstack(views.container, ContactsBookFragment::class.java) } } else if (deniedPermanently) { - onPermissionDeniedSnackbar(R.string.permissions_denied_add_contact) + onPermissionDeniedSnackbar(CommonStrings.permissions_denied_add_contact) } } private val permissionCameraLauncher = registerForPermissionsResult { allGranted, deniedPermanently -> if (allGranted) { - val args = QrScannerArgs(showExtraButtons = false, R.string.add_by_qr_code) + val args = QrScannerArgs(showExtraButtons = false, CommonStrings.add_by_qr_code) addFragment(views.container, QrCodeScannerFragment::class.java, args) } else if (deniedPermanently) { - onPermissionDeniedSnackbar(R.string.permissions_denied_qr_code) + onPermissionDeniedSnackbar(CommonStrings.permissions_denied_qr_code) } } @@ -166,12 +167,12 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { viewModel.handle(CreateDirectRoomAction.PrepareRoomWithSelectedUsers(action.selections)) } else { MaterialAlertDialogBuilder(this) - .setTitle(R.string.dialog_title_confirmation) - .setMessage(getString(R.string.create_room_unknown_users_dialog_content, unknownUsers.joinToString("\n • ", " • ") { it.getMxId() })) - .setPositiveButton(R.string.create_room_unknown_users_dialog_submit) { _, _ -> + .setTitle(CommonStrings.dialog_title_confirmation) + .setMessage(getString(CommonStrings.create_room_unknown_users_dialog_content, unknownUsers.joinToString("\n • ", " • ") { it.getMxId() })) + .setPositiveButton(CommonStrings.create_room_unknown_users_dialog_submit) { _, _ -> viewModel.handle(CreateDirectRoomAction.PrepareRoomWithSelectedUsers(action.selections)) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } } @@ -186,7 +187,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { } private fun renderCreationLoading() { - updateWaitingView(WaitingViewData(getString(R.string.creating_direct_room))) + updateWaitingView(WaitingViewData(getString(CommonStrings.creating_direct_room))) } private fun renderCreationFailure(error: Throwable) { @@ -197,21 +198,21 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { } is CreateRoomFailure.CreatedWithFederationFailure -> { MaterialAlertDialogBuilder(this) - .setMessage(getString(R.string.create_room_federation_error, error.matrixError.message)) + .setMessage(getString(CommonStrings.create_room_federation_error, error.matrixError.message)) .setCancelable(false) - .setPositiveButton(R.string.ok) { _, _ -> finish() } + .setPositiveButton(CommonStrings.ok) { _, _ -> finish() } .show() } else -> { val message = if (error is Failure.ServerError && error.httpCode == HttpURLConnection.HTTP_INTERNAL_ERROR /*500*/) { // This error happen if the invited userId does not exist. - getString(R.string.create_room_dm_failure) + getString(CommonStrings.create_room_dm_failure) } else { errorFormatter.toHumanReadable(error) } MaterialAlertDialogBuilder(this) .setMessage(message) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt index 931b42ea2a..ae3de1cfbb 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt @@ -21,7 +21,6 @@ import android.content.Intent import com.airbnb.mvrx.viewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.addFragmentToBackstack import im.vector.app.core.extensions.observeEvent import im.vector.app.core.extensions.registerStartForActivityResult @@ -30,6 +29,7 @@ import im.vector.app.core.platform.SimpleFragmentActivity import im.vector.app.features.crypto.quads.SharedSecureStorageActivity import im.vector.app.features.workers.signout.ServerBackupStatusAction import im.vector.app.features.workers.signout.ServerBackupStatusViewModel +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME @AndroidEntryPoint @@ -43,11 +43,12 @@ class KeysBackupRestoreActivity : SimpleFragmentActivity() { } } - override fun getTitleRes() = R.string.title_activity_keys_backup_restore + override fun getTitleRes() = CommonStrings.title_activity_keys_backup_restore private lateinit var viewModel: KeysBackupRestoreSharedViewModel private val serverBackupStatusViewModel: ServerBackupStatusViewModel by viewModel() + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() { hideWaitingView() @Suppress("DEPRECATION") @@ -73,10 +74,10 @@ class KeysBackupRestoreActivity : SimpleFragmentActivity() { viewModel.keyVersionResultError.observeEvent(this) { message -> MaterialAlertDialogBuilder(this) - .setTitle(R.string.unknown_error) + .setTitle(CommonStrings.unknown_error) .setMessage(message) .setCancelable(false) - .setPositiveButton(R.string.ok) { _, _ -> + .setPositiveButton(CommonStrings.ok) { _, _ -> // nop finish() } @@ -100,10 +101,10 @@ class KeysBackupRestoreActivity : SimpleFragmentActivity() { } KeysBackupRestoreSharedViewModel.NAVIGATE_FAILED_TO_LOAD_4S -> { MaterialAlertDialogBuilder(this) - .setTitle(R.string.unknown_error) - .setMessage(R.string.error_failed_to_import_keys) + .setTitle(CommonStrings.unknown_error) + .setMessage(CommonStrings.error_failed_to_import_keys) .setCancelable(false) - .setPositiveButton(R.string.ok) { _, _ -> + .setPositiveButton(CommonStrings.ok) { _, _ -> // nop launch4SActivity() } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyFragment.kt index 9a3d37eed7..806ac9a529 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyFragment.kt @@ -23,11 +23,11 @@ import android.view.ViewGroup import android.view.inputmethod.EditorInfo import androidx.core.widget.doOnTextChanged import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.startImportTextFromFileIntent import im.vector.app.databinding.FragmentKeysBackupRestoreFromKeyBinding +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.tryOrNull @AndroidEntryPoint @@ -73,7 +73,7 @@ class KeysBackupRestoreFromKeyFragment : private fun onRestoreFromKey() { val value = viewModel.recoveryCode.value if (value.isNullOrBlank()) { - viewModel.recoveryCodeErrorText.value = context?.getString(R.string.keys_backup_recovery_code_empty_error_message) + viewModel.recoveryCodeErrorText.value = context?.getString(CommonStrings.keys_backup_recovery_code_empty_error_message) } else { viewModel.recoverKeys(sharedViewModel) } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyViewModel.kt index 539a9e746e..4f7ebda842 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyViewModel.kt @@ -18,9 +18,9 @@ package im.vector.app.features.crypto.keysbackup.restore import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import im.vector.app.R import im.vector.app.core.platform.WaitingViewData import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.crypto.keysbackup.BackupUtils @@ -40,14 +40,14 @@ class KeysBackupRestoreFromKeyViewModel @Inject constructor( } fun recoverKeys(sharedViewModel: KeysBackupRestoreSharedViewModel) { - sharedViewModel.loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.loading))) + sharedViewModel.loadingEvent.postValue(WaitingViewData(stringProvider.getString(CommonStrings.loading))) recoveryCodeErrorText.value = null viewModelScope.launch(Dispatchers.IO) { try { val recoveryKey = BackupUtils.recoveryKeyFromBase58(recoveryCode.value!!) sharedViewModel.recoverUsingBackupRecoveryKey(recoveryKey) } catch (failure: Throwable) { - recoveryCodeErrorText.postValue(stringProvider.getString(R.string.keys_backup_recovery_code_error_decrypt)) + recoveryCodeErrorText.postValue(stringProvider.getString(CommonStrings.keys_backup_recovery_code_error_decrypt)) } } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseFragment.kt index cf98bc7e4d..534e54d842 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseFragment.kt @@ -25,9 +25,9 @@ import android.view.inputmethod.EditorInfo import androidx.core.text.set import androidx.core.widget.doOnTextChanged import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentKeysBackupRestoreFromPassphraseBinding +import im.vector.lib.strings.CommonStrings @AndroidEntryPoint class KeysBackupRestoreFromPassphraseFragment : @@ -66,8 +66,8 @@ class KeysBackupRestoreFromPassphraseFragment : } private fun spannableStringForHelperText(): SpannableString { - val clickableText = getString(R.string.keys_backup_restore_use_recovery_key) - val helperText = getString(R.string.keys_backup_restore_with_passphrase_helper_with_link, clickableText) + val clickableText = getString(CommonStrings.keys_backup_restore_use_recovery_key) + val helperText = getString(CommonStrings.keys_backup_restore_with_passphrase_helper_with_link, clickableText) val spanString = SpannableString(helperText) @@ -92,7 +92,7 @@ class KeysBackupRestoreFromPassphraseFragment : private fun onRestoreBackup() { val value = viewModel.passphrase.value if (value.isNullOrBlank()) { - viewModel.passphraseErrorText.value = getString(R.string.passphrase_empty_error_message) + viewModel.passphraseErrorText.value = getString(CommonStrings.passphrase_empty_error_message) } else { viewModel.recoverKeys(sharedViewModel) } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseViewModel.kt index 81d3c64dec..fb7ca45556 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromPassphraseViewModel.kt @@ -18,8 +18,8 @@ package im.vector.app.features.crypto.keysbackup.restore import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import im.vector.app.R import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import javax.inject.Inject @@ -44,7 +44,7 @@ class KeysBackupRestoreFromPassphraseViewModel @Inject constructor( try { sharedViewModel.recoverUsingBackupPass(passphrase.value!!) } catch (failure: Throwable) { - passphraseErrorText.postValue(stringProvider.getString(R.string.keys_backup_passphrase_error_decrypt)) + passphraseErrorText.postValue(stringProvider.getString(CommonStrings.keys_backup_passphrase_error_decrypt)) } } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt index 46ef811807..42f3f3f03d 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt @@ -19,11 +19,11 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import im.vector.app.R import im.vector.app.core.platform.WaitingViewData import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.LiveEvent import im.vector.app.features.session.coroutineScope +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -95,8 +95,8 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( is StepProgressListener.Step.ComputingKey -> { loadingEvent.postValue( WaitingViewData( - stringProvider.getString(R.string.keys_backup_restoring_waiting_message) + - "\n" + stringProvider.getString(R.string.keys_backup_restoring_computing_key_waiting_message), + stringProvider.getString(CommonStrings.keys_backup_restoring_waiting_message) + + "\n" + stringProvider.getString(CommonStrings.keys_backup_restoring_computing_key_waiting_message), step.progress, step.total ) @@ -105,8 +105,8 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( is StepProgressListener.Step.DownloadingKey -> { loadingEvent.postValue( WaitingViewData( - stringProvider.getString(R.string.keys_backup_restoring_waiting_message) + - "\n" + stringProvider.getString(R.string.keys_backup_restoring_downloading_backup_waiting_message), + stringProvider.getString(CommonStrings.keys_backup_restoring_waiting_message) + + "\n" + stringProvider.getString(CommonStrings.keys_backup_restoring_downloading_backup_waiting_message), isIndeterminate = true ) ) @@ -117,16 +117,16 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( if (step.progress == 0) { loadingEvent.postValue( WaitingViewData( - stringProvider.getString(R.string.keys_backup_restoring_waiting_message) + - "\n" + stringProvider.getString(R.string.keys_backup_restoring_importing_keys_waiting_message), + stringProvider.getString(CommonStrings.keys_backup_restoring_waiting_message) + + "\n" + stringProvider.getString(CommonStrings.keys_backup_restoring_importing_keys_waiting_message), isIndeterminate = true ) ) } else { loadingEvent.postValue( WaitingViewData( - stringProvider.getString(R.string.keys_backup_restoring_waiting_message) + - "\n" + stringProvider.getString(R.string.keys_backup_restoring_importing_keys_waiting_message), + stringProvider.getString(CommonStrings.keys_backup_restoring_waiting_message) + + "\n" + stringProvider.getString(CommonStrings.keys_backup_restoring_importing_keys_waiting_message), step.progress, step.total ) @@ -137,16 +137,16 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( if (step.progress == 0) { loadingEvent.postValue( WaitingViewData( - stringProvider.getString(R.string.keys_backup_restoring_waiting_message) + - "\n" + stringProvider.getString(R.string.keys_backup_restoring_importing_keys_waiting_message), + stringProvider.getString(CommonStrings.keys_backup_restoring_waiting_message) + + "\n" + stringProvider.getString(CommonStrings.keys_backup_restoring_importing_keys_waiting_message), isIndeterminate = true ) ) } else { loadingEvent.postValue( WaitingViewData( - stringProvider.getString(R.string.keys_backup_restoring_waiting_message) + - "\n" + stringProvider.getString(R.string.keys_backup_restoring_importing_keys_waiting_message), + stringProvider.getString(CommonStrings.keys_backup_restoring_waiting_message) + + "\n" + stringProvider.getString(CommonStrings.keys_backup_restoring_importing_keys_waiting_message), step.progress, step.total ) @@ -160,13 +160,13 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( private suspend fun getLatestVersion() { val keysBackup = session.cryptoService().keysBackupService() - loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.keys_backup_restore_is_getting_backup_version))) + loadingEvent.postValue(WaitingViewData(stringProvider.getString(CommonStrings.keys_backup_restore_is_getting_backup_version))) try { val version = keysBackup.getCurrentVersion()?.toKeysVersionResult() if (version?.version == null) { loadingEvent.postValue(null) - _keyVersionResultError.postValue(LiveEvent(stringProvider.getString(R.string.keys_backup_get_version_error, ""))) + _keyVersionResultError.postValue(LiveEvent(stringProvider.getString(CommonStrings.keys_backup_get_version_error, ""))) return } @@ -205,7 +205,7 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( loadingEvent.postValue(null) } catch (failure: Throwable) { loadingEvent.postValue(null) - _keyVersionResultError.postValue(LiveEvent(stringProvider.getString(R.string.keys_backup_get_version_error, failure.localizedMessage))) + _keyVersionResultError.postValue(LiveEvent(stringProvider.getString(CommonStrings.keys_backup_get_version_error, failure.localizedMessage))) } } @@ -220,7 +220,7 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( ) return } - loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.keys_backup_restore_is_getting_backup_version))) + loadingEvent.postValue(WaitingViewData(stringProvider.getString(CommonStrings.keys_backup_restore_is_getting_backup_version))) viewModelScope.launch(Dispatchers.IO) { try { @@ -245,7 +245,7 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( val keysBackup = session.cryptoService().keysBackupService() val keyVersion = keyVersionResult.value ?: return - loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.loading))) + loadingEvent.postValue(WaitingViewData(stringProvider.getString(CommonStrings.loading))) try { val result = keysBackup.restoreKeyBackupWithPassword( @@ -269,7 +269,7 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( // This is badddddd val version = keyVersion ?: keyVersionResult.value ?: return - loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.loading))) + loadingEvent.postValue(WaitingViewData(stringProvider.getString(CommonStrings.loading))) try { val result = keysBackup.restoreKeysWithRecoveryKey( diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSuccessFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSuccessFragment.kt index 4a1bc49e27..c2c883c6c5 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSuccessFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSuccessFragment.kt @@ -21,10 +21,11 @@ import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.LiveEvent import im.vector.app.databinding.FragmentKeysBackupRestoreSuccessBinding +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings @AndroidEntryPoint class KeysBackupRestoreSuccessFragment : @@ -43,19 +44,19 @@ class KeysBackupRestoreSuccessFragment : if (compareValues(sharedViewModel.importKeyResult?.totalNumberOfKeys, 0) > 0) { sharedViewModel.importKeyResult?.let { val part1 = resources.getQuantityString( - R.plurals.keys_backup_restore_success_description_part1, + CommonPlurals.keys_backup_restore_success_description_part1, it.totalNumberOfKeys, it.totalNumberOfKeys ) val part2 = resources.getQuantityString( - R.plurals.keys_backup_restore_success_description_part2, + CommonPlurals.keys_backup_restore_success_description_part2, it.successfullyNumberOfImportedKeys, it.successfullyNumberOfImportedKeys ) views.successDetailsText.text = String.format("%s\n%s", part1, part2) } // We don't put emoji in string xml as it will crash on old devices - views.successText.text = context?.getString(R.string.keys_backup_restore_success_title, "🎉") + views.successText.text = context?.getString(CommonStrings.keys_backup_restore_success_title, "🎉") } else { - views.successText.text = context?.getString(R.string.keys_backup_restore_success_title_already_up_to_date) + views.successText.text = context?.getString(CommonStrings.keys_backup_restore_success_title_already_up_to_date) views.successDetailsText.isVisible = false } views.keysBackupSetupDoneButton.debouncedClicks { onDone() } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt index 32826d013f..c7086f814a 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt @@ -23,13 +23,13 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.viewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.platform.SimpleFragmentActivity import im.vector.app.core.platform.WaitingViewData import im.vector.app.features.crypto.keysbackup.setup.KeysBackupSetupActivity import im.vector.app.features.crypto.quads.SharedSecureStorageActivity +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME @AndroidEntryPoint @@ -42,7 +42,7 @@ class KeysBackupManageActivity : SimpleFragmentActivity() { } } - override fun getTitleRes() = R.string.encryption_message_recovery + override fun getTitleRes() = CommonStrings.encryption_message_recovery private val viewModel: KeysBackupSettingsViewModel by viewModel() @@ -75,14 +75,14 @@ class KeysBackupManageActivity : SimpleFragmentActivity() { updateWaitingView(null) MaterialAlertDialogBuilder(this) - .setTitle(R.string.unknown_error) - .setMessage(getString(R.string.keys_backup_get_version_error, asyncDelete.error.localizedMessage)) + .setTitle(CommonStrings.unknown_error) + .setMessage(getString(CommonStrings.keys_backup_get_version_error, asyncDelete.error.localizedMessage)) .setCancelable(false) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } is Loading -> { - updateWaitingView(WaitingViewData(getString(R.string.keys_backup_settings_deleting_backup))) + updateWaitingView(WaitingViewData(getString(CommonStrings.keys_backup_settings_deleting_backup))) } else -> { updateWaitingView(null) @@ -107,6 +107,7 @@ class KeysBackupManageActivity : SimpleFragmentActivity() { } } + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() { // When there is no network we could get stuck in infinite loading // because backup state will stay in CheckingBackUpOnHomeserver diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt index c0001501d5..b927b25eb6 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt @@ -23,12 +23,12 @@ import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentKeysBackupSettingsBinding import im.vector.app.features.crypto.keysbackup.restore.KeysBackupRestoreActivity +import im.vector.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint @@ -73,13 +73,13 @@ class KeysBackupSettingsFragment : override fun didSelectDeleteSetupMessageRecovery() { activity?.let { MaterialAlertDialogBuilder(it) - .setTitle(R.string.keys_backup_settings_delete_confirm_title) - .setMessage(R.string.keys_backup_settings_delete_confirm_message) + .setTitle(CommonStrings.keys_backup_settings_delete_confirm_title) + .setMessage(CommonStrings.keys_backup_settings_delete_confirm_message) .setCancelable(false) - .setPositiveButton(R.string.keys_backup_settings_delete_confirm_title) { _, _ -> + .setPositiveButton(CommonStrings.keys_backup_settings_delete_confirm_title) { _, _ -> viewModel.handle(KeyBackupSettingsAction.DeleteKeyBackup) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .setCancelable(true) .show() } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt index b862d406c8..acccf3eee0 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt @@ -29,6 +29,8 @@ import im.vector.app.core.ui.list.ItemStyle import im.vector.app.core.ui.list.genericItem import im.vector.app.features.settings.VectorPreferences import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState @@ -60,7 +62,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( KeysBackupState.Unknown -> { errorWithRetryItem { id("summary") - text(host.stringProvider.getString(R.string.keys_backup_unable_to_get_keys_backup_data)) + text(host.stringProvider.getString(CommonStrings.keys_backup_unable_to_get_keys_backup_data)) listener { host.listener?.loadKeysBackupState() } } @@ -70,17 +72,17 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( KeysBackupState.CheckingBackUpOnHomeserver -> { loadingItem { id("summary") - loadingText(host.stringProvider.getString(R.string.keys_backup_settings_checking_backup_state)) + loadingText(host.stringProvider.getString(CommonStrings.keys_backup_settings_checking_backup_state)) } } KeysBackupState.Disabled -> { genericItem { id("summary") - title(host.stringProvider.getString(R.string.keys_backup_settings_status_not_setup).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.keys_backup_settings_status_not_setup).toEpoxyCharSequence()) style(ItemStyle.BIG_TEXT) if (data.keysBackupVersionTrust()?.usable == false) { - description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup).toEpoxyCharSequence()) + description(host.stringProvider.getString(CommonStrings.keys_backup_settings_untrusted_backup).toEpoxyCharSequence()) } } @@ -91,10 +93,10 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( KeysBackupState.Enabling -> { genericItem { id("summary") - title(host.stringProvider.getString(R.string.keys_backup_settings_status_ko).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.keys_backup_settings_status_ko).toEpoxyCharSequence()) style(ItemStyle.BIG_TEXT) if (data.keysBackupVersionTrust()?.usable == false) { - description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup).toEpoxyCharSequence()) + description(host.stringProvider.getString(CommonStrings.keys_backup_settings_untrusted_backup).toEpoxyCharSequence()) } else { description(keyBackupState.toString().toEpoxyCharSequence()) } @@ -106,12 +108,12 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( KeysBackupState.ReadyToBackUp -> { genericItem { id("summary") - title(host.stringProvider.getString(R.string.keys_backup_settings_status_ok).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.keys_backup_settings_status_ok).toEpoxyCharSequence()) style(ItemStyle.BIG_TEXT) if (data.keysBackupVersionTrust()?.usable == false) { - description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup).toEpoxyCharSequence()) + description(host.stringProvider.getString(CommonStrings.keys_backup_settings_untrusted_backup).toEpoxyCharSequence()) } else { - description(host.stringProvider.getString(R.string.keys_backup_info_keys_all_backup_up).toEpoxyCharSequence()) + description(host.stringProvider.getString(CommonStrings.keys_backup_info_keys_all_backup_up).toEpoxyCharSequence()) } endIconResourceId(R.drawable.unit_test_ok) } @@ -122,18 +124,18 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( KeysBackupState.BackingUp -> { genericItem { id("summary") - title(host.stringProvider.getString(R.string.keys_backup_settings_status_ok).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.keys_backup_settings_status_ok).toEpoxyCharSequence()) style(ItemStyle.BIG_TEXT) hasIndeterminateProcess(true) val remainingKeysToBackup = data.remainingKeysToBackup if (data.keysBackupVersionTrust()?.usable == false) { - description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup).toEpoxyCharSequence()) + description(host.stringProvider.getString(CommonStrings.keys_backup_settings_untrusted_backup).toEpoxyCharSequence()) } else { description( host.stringProvider - .getQuantityString(R.plurals.keys_backup_info_keys_backing_up, remainingKeysToBackup, remainingKeysToBackup) + .getQuantityString(CommonPlurals.keys_backup_info_keys_backing_up, remainingKeysToBackup, remainingKeysToBackup) .toEpoxyCharSequence() ) } @@ -148,13 +150,13 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( // Add infos genericItem { id("version") - title(host.stringProvider.getString(R.string.keys_backup_info_title_version).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.keys_backup_info_title_version).toEpoxyCharSequence()) description(keyVersionResult?.version.orEmpty().toEpoxyCharSequence()) } genericItem { id("algorithm") - title(host.stringProvider.getString(R.string.keys_backup_info_title_algorithm).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.keys_backup_info_title_algorithm).toEpoxyCharSequence()) description(keyVersionResult?.algorithm.orEmpty().toEpoxyCharSequence()) } @@ -168,13 +170,13 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( id("footer") if (isBackupAlreadySetup) { - textButton1(host.stringProvider.getString(R.string.keys_backup_settings_restore_backup_button)) + textButton1(host.stringProvider.getString(CommonStrings.keys_backup_settings_restore_backup_button)) clickOnButton1 { host.listener?.didSelectRestoreMessageRecovery() } - textButton2(host.stringProvider.getString(R.string.keys_backup_settings_delete_backup_button)) + textButton2(host.stringProvider.getString(CommonStrings.keys_backup_settings_delete_backup_button)) clickOnButton2 { host.listener?.didSelectDeleteSetupMessageRecovery() } } else { - textButton1(host.stringProvider.getString(R.string.keys_backup_setup)) + textButton1(host.stringProvider.getString(CommonStrings.keys_backup_setup)) clickOnButton1 { host.listener?.didSelectSetupMessageRecovery() } } } @@ -200,10 +202,10 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( if (userId == session.sessionParams.userId && isSignatureValid && isUserVerified) { genericItem { id(UUID.randomUUID().toString()) - title(host.stringProvider.getString(R.string.keys_backup_info_title_signature).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.keys_backup_info_title_signature).toEpoxyCharSequence()) description( host.stringProvider - .getString(R.string.keys_backup_settings_signature_from_this_user) + .getString(CommonStrings.keys_backup_settings_signature_from_this_user) .toEpoxyCharSequence() ) endIconResourceId(R.drawable.e2e_verified) @@ -217,7 +219,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( .forEach { genericItem { id(UUID.randomUUID().toString()) - title(host.stringProvider.getString(R.string.keys_backup_info_title_signature).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.keys_backup_info_title_signature).toEpoxyCharSequence()) val isDeviceKnown = it.device != null val isDeviceVerified = it.device?.isVerified ?: false @@ -227,7 +229,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( if (!isDeviceKnown) { description( host.stringProvider - .getString(R.string.keys_backup_settings_signature_from_unknown_device, deviceId) + .getString(CommonStrings.keys_backup_settings_signature_from_unknown_device, deviceId) .toEpoxyCharSequence() ) endIconResourceId(R.drawable.e2e_warning) @@ -236,7 +238,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( if (host.session.sessionParams.deviceId == it.deviceId) { description( host.stringProvider - .getString(R.string.keys_backup_settings_valid_signature_from_this_device) + .getString(CommonStrings.keys_backup_settings_valid_signature_from_this_device) .toEpoxyCharSequence() ) endIconResourceId(R.drawable.e2e_verified) @@ -245,7 +247,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( description( host.stringProvider .getString( - R.string.keys_backup_settings_valid_signature_from_verified_device, + CommonStrings.keys_backup_settings_valid_signature_from_verified_device, deviceId ) .toEpoxyCharSequence() @@ -255,7 +257,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( description( host.stringProvider .getString( - R.string.keys_backup_settings_valid_signature_from_unverified_device, + CommonStrings.keys_backup_settings_valid_signature_from_unverified_device, deviceId ) .toEpoxyCharSequence() @@ -270,7 +272,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( description( host.stringProvider .getString( - R.string.keys_backup_settings_invalid_signature_from_verified_device, + CommonStrings.keys_backup_settings_invalid_signature_from_verified_device, deviceId ) .toEpoxyCharSequence() @@ -279,7 +281,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( description( host.stringProvider .getString( - R.string.keys_backup_settings_invalid_signature_from_unverified_device, + CommonStrings.keys_backup_settings_invalid_signature_from_unverified_device, deviceId ) .toEpoxyCharSequence() @@ -293,7 +295,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( is Fail -> { errorWithRetryItem { id("trust") - text(host.stringProvider.getString(R.string.keys_backup_unable_to_get_trust_info)) + text(host.stringProvider.getString(CommonStrings.keys_backup_unable_to_get_trust_info)) listener { host.listener?.loadTrustData() } } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupActivity.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupActivity.kt index 4473d54765..cad07b69cb 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupActivity.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupActivity.kt @@ -24,7 +24,6 @@ import androidx.fragment.app.FragmentManager import androidx.lifecycle.lifecycleScope import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.dialogs.ExportKeysDialog import im.vector.app.core.extensions.observeEvent import im.vector.app.core.extensions.queryExportKeys @@ -33,13 +32,14 @@ import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.platform.SimpleFragmentActivity import im.vector.app.core.utils.toast import im.vector.app.features.crypto.keys.KeysExporter +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import javax.inject.Inject @AndroidEntryPoint class KeysBackupSetupActivity : SimpleFragmentActivity() { - override fun getTitleRes() = R.string.title_activity_keys_backup_setup + override fun getTitleRes() = CommonStrings.title_activity_keys_backup_setup private lateinit var viewModel: KeysBackupSetupSharedViewModel @@ -94,17 +94,21 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() { } KeysBackupSetupSharedViewModel.NAVIGATE_PROMPT_REPLACE -> { MaterialAlertDialogBuilder(this) - .setTitle(R.string.keys_backup_setup_override_backup_prompt_tile) - .setMessage(R.string.keys_backup_setup_override_backup_prompt_description) - .setPositiveButton(R.string.keys_backup_setup_override_replace) { _, _ -> + .setTitle(CommonStrings.keys_backup_setup_override_backup_prompt_tile) + .setMessage(CommonStrings.keys_backup_setup_override_backup_prompt_description) + .setPositiveButton(CommonStrings.keys_backup_setup_override_replace) { _, _ -> viewModel.forceCreateKeyBackup(this) - }.setNegativeButton(R.string.keys_backup_setup_override_stop) { _, _ -> + }.setNegativeButton(CommonStrings.keys_backup_setup_override_stop) { _, _ -> viewModel.stopAndKeepAfterDetectingExistingOnServer() } .show() } KeysBackupSetupSharedViewModel.NAVIGATE_MANUAL_EXPORT -> { - queryExportKeys(session.myUserId, saveStartForActivityResult) + queryExportKeys( + userId = session.myUserId, + applicationName = buildMeta.applicationName, + activityResultLauncher = saveStartForActivityResult, + ) } } } @@ -112,9 +116,9 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() { viewModel.prepareRecoverFailError.observe(this) { error -> if (error != null) { MaterialAlertDialogBuilder(this) - .setTitle(R.string.unknown_error) + .setTitle(CommonStrings.unknown_error) .setMessage(error.localizedMessage) - .setPositiveButton(R.string.ok) { _, _ -> + .setPositiveButton(CommonStrings.ok) { _, _ -> // nop viewModel.prepareRecoverFailError.value = null } @@ -125,9 +129,9 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() { viewModel.creatingBackupError.observe(this) { error -> if (error != null) { MaterialAlertDialogBuilder(this) - .setTitle(R.string.unexpected_error) + .setTitle(CommonStrings.unexpected_error) .setMessage(error.localizedMessage) - .setPositiveButton(R.string.ok) { _, _ -> + .setPositiveButton(CommonStrings.ok) { _, _ -> // nop viewModel.creatingBackupError.value = null } @@ -147,7 +151,7 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() { } }) } else { - toast(getString(R.string.unexpected_error)) + toast(getString(CommonStrings.unexpected_error)) hideWaitingView() } } @@ -157,26 +161,27 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() { lifecycleScope.launch { try { keysExporter.export(passphrase, uri) - toast(getString(R.string.encryption_exported_successfully)) + toast(getString(CommonStrings.encryption_exported_successfully)) setResult(Activity.RESULT_OK, Intent().apply { putExtra(MANUAL_EXPORT, true) }) finish() } catch (failure: Throwable) { - toast(failure.localizedMessage ?: getString(R.string.unexpected_error)) + toast(failure.localizedMessage ?: getString(CommonStrings.unexpected_error)) } hideWaitingView() } } + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() { if (viewModel.shouldPromptOnBack) { if (waitingView?.isVisible == true) { return } MaterialAlertDialogBuilder(this) - .setTitle(R.string.keys_backup_setup_skip_title) - .setMessage(R.string.keys_backup_setup_skip_msg) - .setNegativeButton(R.string.action_cancel, null) - .setPositiveButton(R.string.action_leave) { _, _ -> + .setTitle(CommonStrings.keys_backup_setup_skip_title) + .setMessage(CommonStrings.keys_backup_setup_skip_msg) + .setNegativeButton(CommonStrings.action_cancel, null) + .setPositiveButton(CommonStrings.action_leave) { _, _ -> finish() } .show() diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt index b3543bdc19..a102125b20 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt @@ -21,10 +21,10 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.nulabinc.zxcvbn.Strength -import im.vector.app.R import im.vector.app.core.platform.WaitingViewData import im.vector.app.core.utils.LiveEvent import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.session.Session @@ -104,7 +104,7 @@ class KeysBackupSetupSharedViewModel @Inject constructor( loadingStatus.postValue( WaitingViewData( - context.getString(R.string.keys_backup_setup_step3_generating_key_status), + context.getString(CommonStrings.keys_backup_setup_step3_generating_key_status), progress, total ) @@ -152,7 +152,7 @@ class KeysBackupSetupSharedViewModel @Inject constructor( } private fun createKeysBackup(context: Context, keysBackup: KeysBackupService, forceOverride: Boolean = false) { - loadingStatus.value = WaitingViewData(context.getString(R.string.keys_backup_setup_creating_backup), isIndeterminate = true) + loadingStatus.value = WaitingViewData(context.getString(CommonStrings.keys_backup_setup_creating_backup), isIndeterminate = true) creatingBackupError.value = null diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt index 3a6b11715c..18cf2d84fb 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt @@ -25,11 +25,11 @@ import androidx.lifecycle.viewModelScope import androidx.transition.TransitionManager import com.nulabinc.zxcvbn.Zxcvbn import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.hidePassword import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentKeysBackupSetupStep2Binding import im.vector.app.features.settings.VectorLocaleProvider +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import javax.inject.Inject @@ -143,13 +143,13 @@ class KeysBackupSetupStep2Fragment : private fun doNext() { when { viewModel.passphrase.value.isNullOrEmpty() -> { - viewModel.passphraseError.value = context?.getString(R.string.passphrase_empty_error_message) + viewModel.passphraseError.value = context?.getString(CommonStrings.passphrase_empty_error_message) } viewModel.passphrase.value != viewModel.confirmPassphrase.value -> { - viewModel.confirmPassphraseError.value = context?.getString(R.string.passphrase_passphrase_does_not_match) + viewModel.confirmPassphraseError.value = context?.getString(CommonStrings.passphrase_passphrase_does_not_match) } viewModel.passwordStrength.value?.score ?: 0 < 4 -> { - viewModel.passphraseError.value = context?.getString(R.string.passphrase_passphrase_too_weak) + viewModel.passphraseError.value = context?.getString(CommonStrings.passphrase_passphrase_too_weak) } else -> { viewModel.megolmBackupCreationInfo = null @@ -175,7 +175,7 @@ class KeysBackupSetupStep2Fragment : } else -> { // User has entered a passphrase but want to skip this step. - viewModel.passphraseError.value = context?.getString(R.string.keys_backup_passphrase_not_empty_error_message) + viewModel.passphraseError.value = context?.getString(CommonStrings.keys_backup_passphrase_not_empty_error_message) } } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt index 5dcff20f0f..2d39f71e14 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt @@ -37,6 +37,7 @@ import im.vector.app.core.utils.copyToClipboard import im.vector.app.core.utils.selectTxtFileToWrite import im.vector.app.core.utils.startSharePlainTextIntent import im.vector.app.databinding.FragmentKeysBackupSetupStep3Binding +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -64,8 +65,8 @@ class KeysBackupSetupStep3Fragment : viewModel.passphrase.observe(viewLifecycleOwner) { if (it.isNullOrBlank()) { // Recovery was generated, so show key and options to save - views.keysBackupSetupStep3Label2.text = getString(R.string.keys_backup_setup_step3_text_line2_no_passphrase) - views.keysBackupSetupStep3FinishButton.text = getString(R.string.keys_backup_setup_step3_button_title_no_passphrase) + views.keysBackupSetupStep3Label2.text = getString(CommonStrings.keys_backup_setup_step3_text_line2_no_passphrase) + views.keysBackupSetupStep3FinishButton.text = getString(CommonStrings.keys_backup_setup_step3_button_title_no_passphrase) views.keysBackupSetupStep3RecoveryKeyText.text = viewModel.recoveryKey.value!!.toBase58() .replace(" ", "") @@ -77,8 +78,8 @@ class KeysBackupSetupStep3Fragment : } views.keysBackupSetupStep3RecoveryKeyText.isVisible = true } else { - views.keysBackupSetupStep3Label2.text = getString(R.string.keys_backup_setup_step3_text_line2) - views.keysBackupSetupStep3FinishButton.text = getString(R.string.keys_backup_setup_step3_button_title) + views.keysBackupSetupStep3Label2.text = getString(CommonStrings.keys_backup_setup_step3_text_line2) + views.keysBackupSetupStep3FinishButton.text = getString(CommonStrings.keys_backup_setup_step3_button_title) views.keysBackupSetupStep3RecoveryKeyText.isVisible = false } } @@ -97,7 +98,7 @@ class KeysBackupSetupStep3Fragment : // nothing } else { if (viewModel.passphrase.value.isNullOrBlank() && !viewModel.copyHasBeenMade) { - Toast.makeText(context, R.string.keys_backup_setup_step3_please_make_copy, Toast.LENGTH_LONG).show() + Toast.makeText(context, CommonStrings.keys_backup_setup_step3_please_make_copy, Toast.LENGTH_LONG).show() } else { viewModel.navigateEvent.value = LiveEvent(KeysBackupSetupSharedViewModel.NAVIGATE_FINISH) } @@ -137,7 +138,7 @@ class KeysBackupSetupStep3Fragment : activity = requireActivity(), activityResultLauncher = saveRecoveryActivityResultLauncher, defaultFileName = "recovery-key-$userId-${timestamp}.txt", - chooserHint = getString(R.string.save_recovery_key_chooser_hint) + chooserHint = getString(CommonStrings.save_recovery_key_chooser_hint) ) dialog.dismiss() } @@ -146,9 +147,9 @@ class KeysBackupSetupStep3Fragment : startSharePlainTextIntent( context = requireContext(), activityResultLauncher = null, - chooserTitle = context?.getString(R.string.keys_backup_setup_step3_share_intent_chooser_title), + chooserTitle = context?.getString(CommonStrings.keys_backup_setup_step3_share_intent_chooser_title), text = recoveryKey.toBase58(), - subject = context?.getString(R.string.recovery_key) + subject = context?.getString(CommonStrings.recovery_key) ) viewModel.copyHasBeenMade = true dialog.dismiss() @@ -179,18 +180,18 @@ class KeysBackupSetupStep3Fragment : viewModel.copyHasBeenMade = true activity?.let { MaterialAlertDialogBuilder(it) - .setTitle(R.string.dialog_title_success) - .setMessage(R.string.recovery_key_export_saved) + .setTitle(CommonStrings.dialog_title_success) + .setMessage(CommonStrings.recovery_key_export_saved) } } catch (throwable: Throwable) { activity?.let { MaterialAlertDialogBuilder(it) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(errorFormatter.toHumanReadable(throwable)) } } ?.setCancelable(false) - ?.setPositiveButton(R.string.ok, null) + ?.setPositiveButton(CommonStrings.ok, null) ?.show() } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysrequest/KeyRequestHandler.kt b/vector/src/main/java/im/vector/app/features/crypto/keysrequest/KeyRequestHandler.kt index efe0cf1637..abdb38822b 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysrequest/KeyRequestHandler.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysrequest/KeyRequestHandler.kt @@ -23,6 +23,7 @@ import im.vector.app.core.date.VectorDateFormatter import im.vector.app.features.popup.DefaultVectorAlert import im.vector.app.features.popup.PopupAlertManager import im.vector.app.features.session.coroutineScope +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob @@ -185,45 +186,45 @@ class KeyRequestHandler @Inject constructor( if (moreInfo != null) { val lastSeenIp = if (moreInfo.lastSeenIp.isNullOrBlank()) { - context.getString(R.string.encryption_information_unknown_ip) + context.getString(CommonStrings.encryption_information_unknown_ip) } else { moreInfo.lastSeenIp } val lastSeenTime = dateFormatter.format(moreInfo.lastSeenTs, DateFormatKind.DEFAULT_DATE_AND_TIME) - val lastSeenInfo = context.getString(R.string.devices_details_last_seen_format, lastSeenIp, lastSeenTime) + val lastSeenInfo = context.getString(CommonStrings.devices_details_last_seen_format, lastSeenIp, lastSeenTime) dialogText = if (wasNewDevice) { - context.getString(R.string.you_added_a_new_device_with_info, deviceName, lastSeenInfo) + context.getString(CommonStrings.you_added_a_new_device_with_info, deviceName, lastSeenInfo) } else { - context.getString(R.string.your_unverified_device_requesting_with_info, deviceName, lastSeenInfo) + context.getString(CommonStrings.your_unverified_device_requesting_with_info, deviceName, lastSeenInfo) } } else { dialogText = if (wasNewDevice) { - context.getString(R.string.you_added_a_new_device, deviceName) + context.getString(CommonStrings.you_added_a_new_device, deviceName) } else { - context.getString(R.string.your_unverified_device_requesting, deviceName) + context.getString(CommonStrings.your_unverified_device_requesting, deviceName) } } val alert = DefaultVectorAlert( alertManagerId(userId, deviceId), - context.getString(R.string.key_share_request), + context.getString(CommonStrings.key_share_request), dialogText, R.drawable.key_small ) - alert.colorRes = R.color.key_share_req_accent_color + alert.colorRes = im.vector.lib.ui.styles.R.color.key_share_req_accent_color val mappingKey = keyForMap(userId, deviceId) alert.dismissedAction = Runnable { denyAllRequests(mappingKey) } - alert.addButton(context.getString(R.string.share_without_verifying_short_label), { + alert.addButton(context.getString(CommonStrings.share_without_verifying_short_label), { shareAllSessions(mappingKey) }) - alert.addButton(context.getString(R.string.ignore_request_short_label), { + alert.addButton(context.getString(CommonStrings.ignore_request_short_label), { denyAllRequests(mappingKey) }) diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageActivity.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageActivity.kt index 1960ae81e8..2235b39056 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageActivity.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageActivity.kt @@ -16,6 +16,7 @@ package im.vector.app.features.crypto.quads +import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.content.Intent @@ -29,11 +30,11 @@ import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.viewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.platform.SimpleFragmentActivity import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.features.crypto.recover.SetupMode +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import kotlin.reflect.KClass @@ -70,6 +71,8 @@ class SharedSecureStorageActivity : supportFragmentManager.removeFragmentOnAttachListener(this) } + @Suppress("OVERRIDE_DEPRECATION") + @SuppressLint("MissingSuperCall") override fun onBackPressed() { viewModel.handle(SharedSecureStorageAction.Back) } @@ -93,10 +96,10 @@ class SharedSecureStorageActivity : } is SharedSecureStorageViewEvent.Error -> { MaterialAlertDialogBuilder(this) - .setTitle(getString(R.string.dialog_title_error)) + .setTitle(getString(CommonStrings.dialog_title_error)) .setMessage(it.message) .setCancelable(false) - .setPositiveButton(R.string.ok) { _, _ -> + .setPositiveButton(CommonStrings.ok) { _, _ -> if (it.dismiss) { finish() } diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt index 4ab11a218c..28beffe494 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt @@ -26,12 +26,12 @@ import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.WaitingViewData import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch @@ -108,7 +108,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor( if (integrityResult !is IntegrityResult.Success) { _viewEvents.post( SharedSecureStorageViewEvent.Error( - stringProvider.getString(R.string.enter_secret_storage_invalid), + stringProvider.getString(CommonStrings.enter_secret_storage_invalid), true ) ) @@ -235,7 +235,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor( val keyInfoResult = session.sharedSecretStorageService().getDefaultKey() if (!keyInfoResult.isSuccess()) { _viewEvents.post(SharedSecureStorageViewEvent.HideModalLoading) - _viewEvents.post(SharedSecureStorageViewEvent.Error(stringProvider.getString(R.string.failed_to_access_secure_storage))) + _viewEvents.post(SharedSecureStorageViewEvent.Error(stringProvider.getString(CommonStrings.failed_to_access_secure_storage))) return@launch } val keyInfo = (keyInfoResult as KeyInfoResult.Success).keyInfo @@ -243,15 +243,17 @@ class SharedSecureStorageViewModel @AssistedInject constructor( _viewEvents.post( SharedSecureStorageViewEvent.UpdateLoadingState( WaitingViewData( - message = stringProvider.getString(R.string.keys_backup_restoring_computing_key_waiting_message), + message = stringProvider.getString(CommonStrings.keys_backup_restoring_computing_key_waiting_message), isIndeterminate = true ) ) ) val keySpec = RawBytesKeySpec.fromRecoveryKey(recoveryKey) ?: return@launch Unit.also { - _viewEvents.post(SharedSecureStorageViewEvent.KeyInlineError(stringProvider.getString(R.string.bootstrap_invalid_recovery_key))) + _viewEvents.post(SharedSecureStorageViewEvent.KeyInlineError(stringProvider.getString(CommonStrings.bootstrap_invalid_recovery_key))) _viewEvents.post(SharedSecureStorageViewEvent.HideModalLoading) - setState { copy(checkingSSSSAction = Fail(IllegalArgumentException(stringProvider.getString(R.string.bootstrap_invalid_recovery_key)))) } + setState { + copy(checkingSSSSAction = Fail(IllegalArgumentException(stringProvider.getString(CommonStrings.bootstrap_invalid_recovery_key)))) + } } withContext(Dispatchers.IO) { performRequest(keyInfo, keySpec, decryptedSecretMap) @@ -268,7 +270,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor( }, { setState { copy(checkingSSSSAction = Fail(it)) } _viewEvents.post(SharedSecureStorageViewEvent.HideModalLoading) - _viewEvents.post(SharedSecureStorageViewEvent.KeyInlineError(stringProvider.getString(R.string.keys_backup_passphrase_error_decrypt))) + _viewEvents.post(SharedSecureStorageViewEvent.KeyInlineError(stringProvider.getString(CommonStrings.keys_backup_passphrase_error_decrypt))) }) } } @@ -322,7 +324,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor( _viewEvents.post( SharedSecureStorageViewEvent.UpdateLoadingState( WaitingViewData( - message = stringProvider.getString(R.string.keys_backup_restoring_computing_key_waiting_message), + message = stringProvider.getString(CommonStrings.keys_backup_restoring_computing_key_waiting_message), isIndeterminate = true ) ) @@ -336,7 +338,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor( _viewEvents.post( SharedSecureStorageViewEvent.UpdateLoadingState( WaitingViewData( - message = stringProvider.getString(R.string.keys_backup_restoring_computing_key_waiting_message), + message = stringProvider.getString(CommonStrings.keys_backup_restoring_computing_key_waiting_message), isIndeterminate = false, progress = progress, progressTotal = total @@ -364,7 +366,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor( }, { setState { copy(checkingSSSSAction = Fail(it)) } _viewEvents.post(SharedSecureStorageViewEvent.HideModalLoading) - _viewEvents.post(SharedSecureStorageViewEvent.InlineError(stringProvider.getString(R.string.keys_backup_passphrase_error_decrypt))) + _viewEvents.post(SharedSecureStorageViewEvent.InlineError(stringProvider.getString(CommonStrings.keys_backup_passphrase_error_decrypt))) }) } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageKeyFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageKeyFragment.kt index efb24ebea7..ca07e90b5a 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageKeyFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageKeyFragment.kt @@ -25,12 +25,12 @@ import android.view.inputmethod.EditorInfo import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.activityViewModel import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.startImportTextFromFileIntent import im.vector.app.databinding.FragmentSsssAccessFromKeyBinding import im.vector.lib.core.utils.flow.throttleFirst +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.extensions.tryOrNull @@ -49,7 +49,7 @@ class SharedSecuredStorageKeyFragment : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - views.ssssRestoreWithKeyText.text = getString(R.string.enter_secret_storage_input_key) + views.ssssRestoreWithKeyText.text = getString(CommonStrings.enter_secret_storage_input_key) views.ssssKeyEnterEdittext.editorActionEvents() .throttleFirst(300) diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStoragePassphraseFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStoragePassphraseFragment.kt index 877e4aa164..d373c37d1d 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStoragePassphraseFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStoragePassphraseFragment.kt @@ -25,10 +25,10 @@ import androidx.core.text.toSpannable import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.activityViewModel import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentSsssAccessFromPassphraseBinding import im.vector.lib.core.utils.flow.throttleFirst +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import reactivecircus.flowbinding.android.widget.editorActionEvents @@ -48,10 +48,10 @@ class SharedSecuredStoragePassphraseFragment : super.onViewCreated(view, savedInstanceState) // If has passphrase - val pass = getString(R.string.recovery_passphrase) - val key = getString(R.string.recovery_key) + val pass = getString(CommonStrings.recovery_passphrase) + val key = getString(CommonStrings.recovery_key) views.ssssRestoreWithPassphraseWarningText.text = getString( - R.string.enter_secret_storage_passphrase_or_key, + CommonStrings.enter_secret_storage_passphrase_or_key, pass, key ) diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageResetAllFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageResetAllFragment.kt index d060e3996d..b5ac29f8fb 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageResetAllFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageResetAllFragment.kt @@ -23,11 +23,11 @@ import android.view.ViewGroup import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentSsssResetAllBinding import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheet +import im.vector.lib.strings.CommonPlurals @AndroidEntryPoint class SharedSecuredStorageResetAllFragment : @@ -60,7 +60,7 @@ class SharedSecuredStorageResetAllFragment : views.ssssResetOtherDevices.setTextOrHide( state.activeDeviceCount .takeIf { it > 0 } - ?.let { resources.getQuantityString(R.plurals.secure_backup_reset_devices_you_can_verify, it, it) } + ?.let { resources.getQuantityString(CommonPlurals.secure_backup_reset_devices_you_can_verify, it, it) } ) } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BackupToQuadSMigrationTask.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BackupToQuadSMigrationTask.kt index 94dba48120..34f2f6522b 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BackupToQuadSMigrationTask.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BackupToQuadSMigrationTask.kt @@ -16,10 +16,10 @@ package im.vector.app.features.crypto.recover -import im.vector.app.R import im.vector.app.core.platform.ViewModelTask import im.vector.app.core.platform.WaitingViewData import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME @@ -64,7 +64,7 @@ class BackupToQuadSMigrationTask @Inject constructor( val version = keysBackupService.keysBackupVersion ?: return Result.NoKeyBackupVersion - reportProgress(params, R.string.bootstrap_progress_checking_backup) + reportProgress(params, CommonStrings.bootstrap_progress_checking_backup) val curveKey = (if (params.recoveryKey != null) { extractCurveKeyFromRecoveryKey(params.recoveryKey) @@ -79,7 +79,7 @@ class BackupToQuadSMigrationTask @Inject constructor( params.progressListener?.onProgress( WaitingViewData( stringProvider.getString( - R.string.bootstrap_progress_checking_backup_with_info, + CommonStrings.bootstrap_progress_checking_backup_with_info, "$progress/$total" ) ) @@ -90,7 +90,7 @@ class BackupToQuadSMigrationTask @Inject constructor( } else null) ?: return Result.IllegalParams - reportProgress(params, R.string.bootstrap_progress_compute_curve_key) + reportProgress(params, CommonStrings.bootstrap_progress_compute_curve_key) val recoveryKey = computeRecoveryKey(curveKey) val backupRecoveryKey = BackupUtils.recoveryKeyFromBase58(recoveryKey) val isValid = backupRecoveryKey.let { keysBackupService.isValidRecoveryKeyForCurrentVersion(it) } @@ -100,7 +100,7 @@ class BackupToQuadSMigrationTask @Inject constructor( val info: SsssKeyCreationInfo = when { params.passphrase?.isNotEmpty() == true -> { - reportProgress(params, R.string.bootstrap_progress_generating_ssss) + reportProgress(params, CommonStrings.bootstrap_progress_generating_ssss) quadS.generateKeyWithPassphrase( UUID.randomUUID().toString(), "ssss_key", @@ -111,7 +111,7 @@ class BackupToQuadSMigrationTask @Inject constructor( params.progressListener?.onProgress( WaitingViewData( stringProvider.getString( - R.string.bootstrap_progress_generating_ssss_with_info, + CommonStrings.bootstrap_progress_generating_ssss_with_info, "$progress/$total" ) ) @@ -121,7 +121,7 @@ class BackupToQuadSMigrationTask @Inject constructor( ) } params.recoveryKey != null -> { - reportProgress(params, R.string.bootstrap_progress_generating_ssss_recovery) + reportProgress(params, CommonStrings.bootstrap_progress_generating_ssss_recovery) quadS.generateKey( UUID.randomUUID().toString(), extractCurveKeyFromRecoveryKey(params.recoveryKey)?.let { RawBytesKeySpec(it) }, @@ -136,7 +136,7 @@ class BackupToQuadSMigrationTask @Inject constructor( // Ok, so now we have migrated the old keybackup secret as the quadS key // Now we need to store the keybackup key in SSSS in a compatible way - reportProgress(params, R.string.bootstrap_progress_storing_in_sss) + reportProgress(params, CommonStrings.bootstrap_progress_storing_in_sss) quadS.storeSecret( KEYBACKUP_SECRET_SSSS_NAME, curveKey.toBase64NoPadding(), diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt index 586f60beaf..d8c1b31de6 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt @@ -41,6 +41,7 @@ import im.vector.app.core.extensions.toMvRxBundle import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.databinding.BottomSheetBootstrapBinding import im.vector.app.features.auth.ReAuthActivity +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import kotlin.reflect.KClass @@ -90,9 +91,9 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(event.error) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } BootstrapViewEvents.RecoveryKeySaved -> { @@ -106,7 +107,7 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment reAuthActivityResultLauncher.launch(intent) } @@ -117,10 +118,10 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment + .setTitle(CommonStrings.are_you_sure) + .setMessage(CommonStrings.bootstrap_cancel_text) + .setPositiveButton(CommonStrings._continue, null) + .setNegativeButton(CommonStrings.action_skip) { _, _ -> bottomSheetResult = ResultListener.RESULT_CANCEL dismiss() } @@ -155,48 +156,48 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment { views.bootstrapIcon.isVisible = false - views.bootstrapTitleText.text = getString(R.string.bottom_sheet_setup_secure_backup_title) + views.bootstrapTitleText.text = getString(CommonStrings.bottom_sheet_setup_secure_backup_title) showFragment(BootstrapWaitingFragment::class) } is BootstrapStep.FirstForm -> { views.bootstrapIcon.isVisible = false - views.bootstrapTitleText.text = getString(R.string.bottom_sheet_setup_secure_backup_title) + views.bootstrapTitleText.text = getString(CommonStrings.bottom_sheet_setup_secure_backup_title) showFragment(BootstrapSetupRecoveryKeyFragment::class) } is BootstrapStep.SetupPassphrase -> { views.bootstrapIcon.isVisible = true views.bootstrapIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_security_phrase_24dp)) - views.bootstrapTitleText.text = getString(R.string.set_a_security_phrase_title) + views.bootstrapTitleText.text = getString(CommonStrings.set_a_security_phrase_title) showFragment(BootstrapEnterPassphraseFragment::class) } is BootstrapStep.ConfirmPassphrase -> { views.bootstrapIcon.isVisible = true views.bootstrapIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_security_phrase_24dp)) - views.bootstrapTitleText.text = getString(R.string.set_a_security_phrase_title) + views.bootstrapTitleText.text = getString(CommonStrings.set_a_security_phrase_title) showFragment(BootstrapConfirmPassphraseFragment::class) } is BootstrapStep.AccountReAuth -> { views.bootstrapIcon.isVisible = true views.bootstrapIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_user)) - views.bootstrapTitleText.text = getString(R.string.re_authentication_activity_title) + views.bootstrapTitleText.text = getString(CommonStrings.re_authentication_activity_title) showFragment(BootstrapReAuthFragment::class) } is BootstrapStep.Initializing -> { views.bootstrapIcon.isVisible = true views.bootstrapIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_security_key_24dp)) - views.bootstrapTitleText.text = getString(R.string.bootstrap_loading_title) + views.bootstrapTitleText.text = getString(CommonStrings.bootstrap_loading_title) showFragment(BootstrapWaitingFragment::class) } is BootstrapStep.SaveRecoveryKey -> { views.bootstrapIcon.isVisible = true views.bootstrapIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_security_key_24dp)) - views.bootstrapTitleText.text = getString(R.string.bottom_sheet_save_your_recovery_key_title) + views.bootstrapTitleText.text = getString(CommonStrings.bottom_sheet_save_your_recovery_key_title) showFragment(BootstrapSaveRecoveryKeyFragment::class) } is BootstrapStep.DoneSuccess -> { views.bootstrapIcon.isVisible = true views.bootstrapIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_security_key_24dp)) - views.bootstrapTitleText.text = getString(R.string.bootstrap_finish_title) + views.bootstrapTitleText.text = getString(CommonStrings.bootstrap_finish_title) showFragment(BootstrapConclusionFragment::class) } is BootstrapStep.GetBackupSecretForMigration -> { @@ -209,12 +210,12 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment { views.bootstrapIcon.isVisible = true - views.bootstrapTitleText.text = getString(R.string.bottom_sheet_setup_secure_backup_title) + views.bootstrapTitleText.text = getString(CommonStrings.bottom_sheet_setup_secure_backup_title) showFragment(BootstrapErrorFragment::class) } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapConclusionFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapConclusionFragment.kt index fd1eb821db..c0f58eb80d 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapConclusionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapConclusionFragment.kt @@ -24,11 +24,11 @@ import androidx.core.text.toSpannable import com.airbnb.mvrx.parentFragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.resources.ColorProvider import im.vector.app.core.utils.colorizeMatchingText import im.vector.app.databinding.FragmentBootstrapConclusionBinding +import im.vector.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint @@ -53,13 +53,13 @@ class BootstrapConclusionFragment : if (state.step !is BootstrapStep.DoneSuccess) return@withState views.bootstrapConclusionText.text = getString( - R.string.bootstrap_cross_signing_success, - getString(R.string.recovery_passphrase), - getString(R.string.message_key) + CommonStrings.bootstrap_cross_signing_success, + getString(CommonStrings.recovery_passphrase), + getString(CommonStrings.message_key) ) .toSpannable() - .colorizeMatchingText(getString(R.string.recovery_passphrase), colorProvider.getColorFromAttribute(android.R.attr.textColorLink)) - .colorizeMatchingText(getString(R.string.message_key), colorProvider.getColorFromAttribute(android.R.attr.textColorLink)) + .colorizeMatchingText(getString(CommonStrings.recovery_passphrase), colorProvider.getColorFromAttribute(android.R.attr.textColorLink)) + .colorizeMatchingText(getString(CommonStrings.message_key), colorProvider.getColorFromAttribute(android.R.attr.textColorLink)) views.bootstrapConclusionText.giveAccessibilityFocusOnce() } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapConfirmPassphraseFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapConfirmPassphraseFragment.kt index 3942fc6528..8e55fb38ca 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapConfirmPassphraseFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapConfirmPassphraseFragment.kt @@ -26,11 +26,11 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.parentFragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentBootstrapEnterPassphraseBinding import im.vector.lib.core.utils.flow.throttleFirst +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import reactivecircus.flowbinding.android.widget.editorActionEvents @@ -51,9 +51,9 @@ class BootstrapConfirmPassphraseFragment : views.ssssPassphraseSecurityProgress.isGone = true - views.bootstrapDescriptionText.text = getString(R.string.set_a_security_phrase_again_notice) + views.bootstrapDescriptionText.text = getString(CommonStrings.set_a_security_phrase_again_notice) views.bootstrapDescriptionText.giveAccessibilityFocusOnce() - views.ssssPassphraseEnterEdittext.hint = getString(R.string.set_a_security_phrase_hint) + views.ssssPassphraseEnterEdittext.hint = getString(CommonStrings.set_a_security_phrase_hint) withState(sharedViewModel) { // set initial value (useful when coming back) @@ -95,9 +95,9 @@ class BootstrapConfirmPassphraseFragment : val passphrase = views.ssssPassphraseEnterEdittext.text?.toString() when { passphrase.isNullOrBlank() -> - views.ssssPassphraseEnterTil.error = getString(R.string.passphrase_empty_error_message) + views.ssssPassphraseEnterTil.error = getString(CommonStrings.passphrase_empty_error_message) passphrase != state.passphrase -> - views.ssssPassphraseEnterTil.error = getString(R.string.passphrase_passphrase_does_not_match) + views.ssssPassphraseEnterTil.error = getString(CommonStrings.passphrase_passphrase_does_not_match) else -> { view?.hideKeyboard() sharedViewModel.handle(BootstrapActions.DoInitialize(passphrase)) diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapCrossSigningTask.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapCrossSigningTask.kt index 4190737e7c..bfbd2d55af 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapCrossSigningTask.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapCrossSigningTask.kt @@ -16,10 +16,10 @@ package im.vector.app.features.crypto.recover -import im.vector.app.R import im.vector.app.core.platform.ViewModelTask import im.vector.app.core.platform.WaitingViewData import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.MatrixError @@ -87,7 +87,7 @@ class BootstrapCrossSigningTask @Inject constructor( Timber.d("## BootstrapCrossSigningTask: Cross signing not enabled, so initialize") params.progressListener?.onProgress( WaitingViewData( - stringProvider.getString(R.string.bootstrap_crosssigning_progress_initializing), + stringProvider.getString(CommonStrings.bootstrap_crosssigning_progress_initializing), isIndeterminate = true ) ) @@ -114,7 +114,7 @@ class BootstrapCrossSigningTask @Inject constructor( params.progressListener?.onProgress( WaitingViewData( - stringProvider.getString(R.string.bootstrap_crosssigning_progress_pbkdf2), + stringProvider.getString(CommonStrings.bootstrap_crosssigning_progress_pbkdf2), isIndeterminate = true ) ) @@ -144,7 +144,7 @@ class BootstrapCrossSigningTask @Inject constructor( params.progressListener?.onProgress( WaitingViewData( - stringProvider.getString(R.string.bootstrap_crosssigning_progress_default_key), + stringProvider.getString(CommonStrings.bootstrap_crosssigning_progress_default_key), isIndeterminate = true ) ) @@ -168,7 +168,7 @@ class BootstrapCrossSigningTask @Inject constructor( try { params.progressListener?.onProgress( WaitingViewData( - stringProvider.getString(R.string.bootstrap_crosssigning_progress_save_msk), + stringProvider.getString(CommonStrings.bootstrap_crosssigning_progress_save_msk), isIndeterminate = true ) ) @@ -180,7 +180,7 @@ class BootstrapCrossSigningTask @Inject constructor( ) params.progressListener?.onProgress( WaitingViewData( - stringProvider.getString(R.string.bootstrap_crosssigning_progress_save_usk), + stringProvider.getString(CommonStrings.bootstrap_crosssigning_progress_save_usk), isIndeterminate = true ) ) @@ -192,7 +192,7 @@ class BootstrapCrossSigningTask @Inject constructor( ) params.progressListener?.onProgress( WaitingViewData( - stringProvider.getString(R.string.bootstrap_crosssigning_progress_save_ssk), isIndeterminate = true + stringProvider.getString(CommonStrings.bootstrap_crosssigning_progress_save_ssk), isIndeterminate = true ) ) Timber.d("## BootstrapCrossSigningTask: Creating 4S - Storing SSK...") @@ -209,7 +209,7 @@ class BootstrapCrossSigningTask @Inject constructor( params.progressListener?.onProgress( WaitingViewData( - stringProvider.getString(R.string.bootstrap_crosssigning_progress_key_backup), + stringProvider.getString(CommonStrings.bootstrap_crosssigning_progress_key_backup), isIndeterminate = true ) ) diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapEnterPassphraseFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapEnterPassphraseFragment.kt index 262abd306d..8a3511021e 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapEnterPassphraseFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapEnterPassphraseFragment.kt @@ -25,11 +25,11 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.parentFragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentBootstrapEnterPassphraseBinding import im.vector.app.features.settings.VectorLocaleProvider import im.vector.lib.core.utils.flow.throttleFirst +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import reactivecircus.flowbinding.android.widget.editorActionEvents @@ -51,8 +51,8 @@ class BootstrapEnterPassphraseFragment : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - views.bootstrapDescriptionText.text = getString(R.string.set_a_security_phrase_notice) - views.ssssPassphraseEnterEdittext.hint = getString(R.string.set_a_security_phrase_hint) + views.bootstrapDescriptionText.text = getString(CommonStrings.set_a_security_phrase_notice) + views.ssssPassphraseEnterEdittext.hint = getString(CommonStrings.set_a_security_phrase_hint) withState(sharedViewModel) { // set initial value (useful when coming back) @@ -93,9 +93,9 @@ class BootstrapEnterPassphraseFragment : val score = state.passphraseStrength.invoke()?.score val passphrase = views.ssssPassphraseEnterEdittext.text?.toString() if (passphrase.isNullOrBlank()) { - views.ssssPassphraseEnterTil.error = getString(R.string.passphrase_empty_error_message) + views.ssssPassphraseEnterTil.error = getString(CommonStrings.passphrase_empty_error_message) } else if (score != 4) { - views.ssssPassphraseEnterTil.error = getString(R.string.passphrase_passphrase_too_weak) + views.ssssPassphraseEnterTil.error = getString(CommonStrings.passphrase_passphrase_too_weak) } else { sharedViewModel.handle(BootstrapActions.GoToConfirmPassphrase(passphrase)) } diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapErrorFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapErrorFragment.kt index 26b29d449a..425859921f 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapErrorFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapErrorFragment.kt @@ -21,11 +21,11 @@ import android.view.ViewGroup import com.airbnb.mvrx.parentFragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentBootstrapErrorBinding +import im.vector.lib.strings.CommonStrings @AndroidEntryPoint class BootstrapErrorFragment : @@ -44,7 +44,7 @@ class BootstrapErrorFragment : } else -> { // Should not happen, show a generic error - views.bootstrapDescriptionText.setTextOrHide(getString(R.string.unknown_error)) + views.bootstrapDescriptionText.setTextOrHide(getString(CommonStrings.unknown_error)) } } views.bootstrapRetryButton.onClick { diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapMigrateBackupFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapMigrateBackupFragment.kt index 8df5ce7ad3..7fe3a372e9 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapMigrateBackupFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapMigrateBackupFragment.kt @@ -31,7 +31,6 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.parentFragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseFragment @@ -40,6 +39,7 @@ import im.vector.app.core.utils.colorizeMatchingText import im.vector.app.core.utils.startImportTextFromFileIntent import im.vector.app.databinding.FragmentBootstrapMigrateBackupBinding import im.vector.lib.core.utils.flow.throttleFirst +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.extensions.tryOrNull @@ -97,10 +97,10 @@ class BootstrapMigrateBackupFragment : val secret = views.bootstrapMigrateEditText.text?.toString() if (secret.isNullOrEmpty()) { - val errRes = if (isEnteringKey) R.string.recovery_key_empty_error_message else R.string.passphrase_empty_error_message + val errRes = if (isEnteringKey) CommonStrings.recovery_key_empty_error_message else CommonStrings.passphrase_empty_error_message views.bootstrapRecoveryKeyEnterTil.error = getString(errRes) } else if (isEnteringKey && !isValidRecoveryKey(secret)) { - views.bootstrapRecoveryKeyEnterTil.error = getString(R.string.bootstrap_invalid_recovery_key) + views.bootstrapRecoveryKeyEnterTil.error = getString(CommonStrings.bootstrap_invalid_recovery_key) } else { view?.hideKeyboard() if (isEnteringKey) { @@ -119,8 +119,8 @@ class BootstrapMigrateBackupFragment : if (isEnteringKey) { views.bootstrapMigrateEditText.inputType = TYPE_CLASS_TEXT or TYPE_TEXT_VARIATION_VISIBLE_PASSWORD or TYPE_TEXT_FLAG_MULTI_LINE - val recKey = getString(R.string.bootstrap_migration_backup_recovery_key) - views.bootstrapDescriptionText.text = getString(R.string.enter_account_password, recKey) + val recKey = getString(CommonStrings.bootstrap_migration_backup_recovery_key) + views.bootstrapDescriptionText.text = getString(CommonStrings.enter_account_password, recKey) views.bootstrapMigrateEditText.hint = recKey @@ -128,14 +128,14 @@ class BootstrapMigrateBackupFragment : views.bootstrapMigrateForgotPassphrase.isVisible = false views.bootstrapMigrateUseFile.isVisible = true } else { - views.bootstrapDescriptionText.text = getString(R.string.bootstrap_migration_enter_backup_password) + views.bootstrapDescriptionText.text = getString(CommonStrings.bootstrap_migration_enter_backup_password) - views.bootstrapMigrateEditText.hint = getString(R.string.passphrase_enter_passphrase) + views.bootstrapMigrateEditText.hint = getString(CommonStrings.passphrase_enter_passphrase) views.bootstrapMigrateForgotPassphrase.isVisible = true - val recKey = getString(R.string.bootstrap_migration_use_recovery_key) - views.bootstrapMigrateForgotPassphrase.text = getString(R.string.bootstrap_migration_with_passphrase_helper_with_link, recKey) + val recKey = getString(CommonStrings.bootstrap_migration_use_recovery_key) + views.bootstrapMigrateForgotPassphrase.text = getString(CommonStrings.bootstrap_migration_with_passphrase_helper_with_link, recKey) .toSpannable() .colorizeMatchingText(recKey, colorProvider.getColorFromAttribute(android.R.attr.textColorLink)) diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSaveRecoveryKeyFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSaveRecoveryKeyFragment.kt index 88db55a291..40af7155ba 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSaveRecoveryKeyFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSaveRecoveryKeyFragment.kt @@ -28,13 +28,13 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.parentFragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.safeOpenOutputStream import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.startSharePlainTextIntent import im.vector.app.core.utils.toast import im.vector.app.databinding.FragmentBootstrapSaveKeyBinding +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -69,9 +69,9 @@ class BootstrapSaveRecoveryKeyFragment : try { sharedViewModel.handle(BootstrapActions.SaveReqQueryStarted) - saveStartForActivityResult.launch(Intent.createChooser(intent, getString(R.string.keys_backup_setup_step3_please_make_copy))) + saveStartForActivityResult.launch(Intent.createChooser(intent, getString(CommonStrings.keys_backup_setup_step3_please_make_copy))) } catch (activityNotFoundException: ActivityNotFoundException) { - requireActivity().toast(R.string.error_no_external_application_found) + requireActivity().toast(CommonStrings.error_no_external_application_found) sharedViewModel.handle(BootstrapActions.SaveReqFailed) } } @@ -105,9 +105,9 @@ class BootstrapSaveRecoveryKeyFragment : startSharePlainTextIntent( requireContext(), copyStartForActivityResult, - context?.getString(R.string.keys_backup_setup_step3_share_intent_chooser_title), + context?.getString(CommonStrings.keys_backup_setup_step3_share_intent_chooser_title), recoveryKey, - context?.getString(R.string.recovery_key) + context?.getString(CommonStrings.recovery_key) ) } diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSetupRecoveryKeyFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSetupRecoveryKeyFragment.kt index a28a7c8f56..7f1959a243 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSetupRecoveryKeyFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSetupRecoveryKeyFragment.kt @@ -24,10 +24,10 @@ import androidx.core.view.isVisible import com.airbnb.mvrx.parentFragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentBootstrapSetupRecoveryBinding import im.vector.app.features.raw.wellknown.SecureBackupMethod +import im.vector.lib.strings.CommonStrings @AndroidEntryPoint class BootstrapSetupRecoveryKeyFragment : @@ -82,9 +82,9 @@ class BootstrapSetupRecoveryKeyFragment : private fun renderSetupHeader(needsReset: Boolean) = with(views) { bootstrapSetupSecureText.text = if (needsReset) { - getString(R.string.reset_secure_backup_title) + getString(CommonStrings.reset_secure_backup_title) } else { - getString(R.string.bottom_sheet_setup_secure_backup_subtitle) + getString(CommonStrings.bottom_sheet_setup_secure_backup_subtitle) } bootstrapSetupWarningTextView.isVisible = needsReset } diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt index c9c2c5ce9a..b020421224 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt @@ -25,7 +25,6 @@ import com.nulabinc.zxcvbn.Zxcvbn import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.error.ErrorFormatter @@ -37,6 +36,7 @@ import im.vector.app.features.raw.wellknown.SecureBackupMethod import im.vector.app.features.raw.wellknown.getElementWellknown import im.vector.app.features.raw.wellknown.isSecureBackupRequired import im.vector.app.features.raw.wellknown.secureBackupMethod +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.matrix.android.sdk.api.auth.UIABaseAuth @@ -216,7 +216,7 @@ class BootstrapSharedViewModel @AssistedInject constructor( } else { setState { copy( - passphraseConfirmMatch = Fail(Throwable(stringProvider.getString(R.string.passphrase_passphrase_does_not_match))) + passphraseConfirmMatch = Fail(Throwable(stringProvider.getString(CommonStrings.passphrase_passphrase_does_not_match))) ) } } @@ -277,7 +277,7 @@ class BootstrapSharedViewModel @AssistedInject constructor( BootstrapActions.ReAuthCancelled -> { pendingAuthHandler.reAuthCancelled() setState { - copy(step = BootstrapStep.AccountReAuth(stringProvider.getString(R.string.authentication_error))) + copy(step = BootstrapStep.AccountReAuth(stringProvider.getString(CommonStrings.authentication_error))) } } BootstrapActions.Retry -> { @@ -464,7 +464,7 @@ class BootstrapSharedViewModel @AssistedInject constructor( // it's a bad password / auth setState { copy( - step = BootstrapStep.AccountReAuth(stringProvider.getString(R.string.auth_invalid_login_param)) + step = BootstrapStep.AccountReAuth(stringProvider.getString(CommonStrings.auth_invalid_login_param)) ) } } @@ -474,7 +474,7 @@ class BootstrapSharedViewModel @AssistedInject constructor( bootstrapResult.failure.httpCode == 401) { // Ignore this error } else { - _viewEvents.post(BootstrapViewEvents.ModalError(bootstrapResult.error ?: stringProvider.getString(R.string.matrix_error))) + _viewEvents.post(BootstrapViewEvents.ModalError(bootstrapResult.error ?: stringProvider.getString(CommonStrings.matrix_error))) // Not sure setState { copy( @@ -594,11 +594,11 @@ class BootstrapSharedViewModel @AssistedInject constructor( private fun BackupToQuadSMigrationTask.Result.Failure.toHumanReadable(): String { return when (this) { - is BackupToQuadSMigrationTask.Result.InvalidRecoverySecret -> stringProvider.getString(R.string.keys_backup_passphrase_error_decrypt) + is BackupToQuadSMigrationTask.Result.InvalidRecoverySecret -> stringProvider.getString(CommonStrings.keys_backup_passphrase_error_decrypt) is BackupToQuadSMigrationTask.Result.ErrorFailure -> errorFormatter.toHumanReadable(throwable) // is BackupToQuadSMigrationTask.Result.NoKeyBackupVersion, // is BackupToQuadSMigrationTask.Result.IllegalParams, - else -> stringProvider.getString(R.string.unexpected_error) + else -> stringProvider.getString(CommonStrings.unexpected_error) } } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/KeepItSafeDialog.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/KeepItSafeDialog.kt index 6b9d725aac..2fc7f05d4d 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/KeepItSafeDialog.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/KeepItSafeDialog.kt @@ -23,6 +23,7 @@ import androidx.core.content.ContextCompat import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.databinding.DialogRecoveryKeySavedInfoBinding +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.image import me.gujun.android.span.span @@ -36,24 +37,24 @@ class KeepItSafeDialog { span { image(ContextCompat.getDrawable(activity, R.drawable.ic_check_on)!!) +" " - +activity.getString(R.string.bootstrap_crosssigning_print_it) + +activity.getString(CommonStrings.bootstrap_crosssigning_print_it) +"\n\n" image(ContextCompat.getDrawable(activity, R.drawable.ic_check_on)!!) +" " - +activity.getString(R.string.bootstrap_crosssigning_save_usb) + +activity.getString(CommonStrings.bootstrap_crosssigning_save_usb) +"\n\n" image(ContextCompat.getDrawable(activity, R.drawable.ic_check_on)!!) +" " - +activity.getString(R.string.bootstrap_crosssigning_save_cloud) + +activity.getString(CommonStrings.bootstrap_crosssigning_save_cloud) +"\n\n" } } MaterialAlertDialogBuilder(activity) // .setIcon(android.R.drawable.ic_dialog_alert) -// .setTitle(R.string.devices_delete_dialog_title) +// .setTitle(CommonStrings.devices_delete_dialog_title) .setView(dialogLayout) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .setOnKeyListener(DialogInterface.OnKeyListener { dialog, keyCode, event -> if (event.action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { dialog.cancel() diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt index 363966d68a..d49e1147db 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt @@ -28,6 +28,7 @@ import im.vector.app.features.popup.VerificationVectorAlert import im.vector.app.features.session.coroutineScope import im.vector.lib.core.utils.compat.getParcelableCompat import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel @@ -99,8 +100,8 @@ class IncomingVerificationRequestHandler @Inject constructor( // val name = user.getBestName() // val alert = VerificationVectorAlert( // uid, -// context.getString(R.string.sas_incoming_request_notif_title), -// context.getString(R.string.sas_incoming_request_notif_content, name), +// context.getString(CommonStrings.sas_incoming_request_notif_title), +// context.getString(CommonStrings.sas_incoming_request_notif_content, name), // R.drawable.ic_shield_black, // shouldBeDisplayedIn = { activity -> // if (activity is VectorBaseActivity<*>) { @@ -124,13 +125,13 @@ class IncomingVerificationRequestHandler @Inject constructor( // tx.cancel() // } // addButton( -// context.getString(R.string.action_ignore), +// context.getString(CommonStrings.action_ignore), // LaunchCoroutineRunnable(coroutineScope) { // tx.cancel() // } // ) // addButton( -// context.getString(R.string.action_open), +// context.getString(CommonStrings.action_open), // { // (weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let { // it.navigator.performDeviceVerification(it, tx.otherUserId, tx.transactionId) @@ -168,7 +169,7 @@ class IncomingVerificationRequestHandler @Inject constructor( val alert = VerificationVectorAlert( uid = uniqueIdForVerificationRequest(pr), - title = context.getString(R.string.sas_incoming_request_notif_title), + title = context.getString(CommonStrings.sas_incoming_request_notif_title), description = description, iconId = R.drawable.ic_shield_black, priority = PopupAlertManager.INCOMING_VERIFICATION_REQUEST_PRIORITY, @@ -206,7 +207,7 @@ class IncomingVerificationRequestHandler @Inject constructor( pr.transactionId, ) } - colorAttribute = R.attr.vctr_notice_secondary + colorAttribute = im.vector.lib.ui.styles.R.attr.vctr_notice_secondary // 5mn expiration expirationTimestamp = clock.epochMillis() + (5 * 60 * 1000L) } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt index e63c149a26..b3d05133db 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt @@ -41,6 +41,7 @@ import im.vector.app.features.crypto.quads.SharedSecureStorageViewState import im.vector.app.features.crypto.verification.VerificationAction import im.vector.app.features.crypto.verification.VerificationBottomSheetViewEvents import im.vector.app.features.settings.VectorSettingsActivity +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME @@ -142,10 +143,10 @@ class SelfVerificationBottomSheet : VectorBaseBottomSheetDialogFragment { MaterialAlertDialogBuilder(requireContext()) - .setTitle(getString(R.string.dialog_title_error)) + .setTitle(getString(CommonStrings.dialog_title_error)) .setMessage(event.errorMessage) .setCancelable(false) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } VerificationBottomSheetViewEvents.DismissAndOpenDeviceSettings -> { @@ -180,10 +181,10 @@ class SelfVerificationBottomSheet : VectorBaseBottomSheetDialogFragment { // MaterialAlertDialogBuilder(requireContext()) -// .setTitle(getString(R.string.dialog_title_error)) +// .setTitle(getString(CommonStrings.dialog_title_error)) // .setMessage(it.errorMessage) // .setCancelable(false) -// .setPositiveButton(R.string.ok, null) +// .setPositiveButton(CommonStrings.ok, null) // .show() // Unit // } @@ -204,12 +205,12 @@ class SelfVerificationBottomSheet : VectorBaseBottomSheetDialogFragment { // let's add option to start one - val styledText = stringProvider.getString(R.string.verify_new_session_notice) + val styledText = stringProvider.getString(CommonStrings.verify_new_session_notice) bottomSheetVerificationNoticeItem { id("notice") @@ -172,11 +173,11 @@ class SelfVerificationController @Inject constructor( } bottomSheetVerificationActionItem { id("start") - title(host.stringProvider.getString(R.string.start_verification)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - // subTitle(host.stringProvider.getString(R.string.verification_request_start_notice)) + title(host.stringProvider.getString(CommonStrings.start_verification)) + titleColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) + // subTitle(host.stringProvider.getString(CommonStrings.verification_request_start_notice)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + iconColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) listener { host.listener?.onClickOnVerificationStart() } } } @@ -186,7 +187,7 @@ class SelfVerificationController @Inject constructor( } // bottomSheetVerificationWaitingItem { // id("waiting_pr_loading") -// // title(host.stringProvider.getString(R.string.verification_request_waiting_for, state.otherUserMxItem.getBestName())) +// // title(host.stringProvider.getString(CommonStrings.verification_request_waiting_for, state.otherUserMxItem.getBestName())) // } } is Success -> { @@ -197,9 +198,9 @@ class SelfVerificationController @Inject constructor( id("open_other") style(ItemStyle.NORMAL_TEXT) text( - host.stringProvider.getString(R.string.verification_request_was_sent).toEpoxyCharSequence() + host.stringProvider.getString(CommonStrings.verification_request_was_sent).toEpoxyCharSequence() ) - textColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + textColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) } bottomSheetSelfWaitItem { @@ -212,10 +213,10 @@ class SelfVerificationController @Inject constructor( if (state.isThisSessionVerified) { bottomSheetVerificationActionItem { id("not me") - title(host.stringProvider.getString(R.string.verify_new_session_was_not_me)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + title(host.stringProvider.getString(CommonStrings.verify_new_session_was_not_me)) + titleColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + iconColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) listener { host.selfVerificationListener?.wasNotMe() } @@ -256,7 +257,7 @@ class SelfVerificationController @Inject constructor( is Fail -> { bottomSheetVerificationNoticeItem { id("request_fail") - notice(host.stringProvider.getString(R.string.verification_not_found).toEpoxyCharSequence()) + notice(host.stringProvider.getString(CommonStrings.verification_not_found).toEpoxyCharSequence()) } gotIt { listener?.onDone(false) @@ -269,7 +270,7 @@ class SelfVerificationController @Inject constructor( val host = this bottomSheetVerificationNoticeItem { id("notice") - notice(host.stringProvider.getString(R.string.verification_verify_identity).toEpoxyCharSequence()) + notice(host.stringProvider.getString(CommonStrings.verification_verify_identity).toEpoxyCharSequence()) } bottomSheetDividerItem { id("notice_div") @@ -278,11 +279,11 @@ class SelfVerificationController @Inject constructor( if (state.hasAnyOtherSession.invoke() == true) { bottomSheetVerificationActionItem { id("start") - title(host.stringProvider.getString(R.string.verification_verify_with_another_device)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - // subTitle(host.stringProvider.getString(R.string.verification_request_start_notice)) + title(host.stringProvider.getString(CommonStrings.verification_verify_with_another_device)) + titleColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) + // subTitle(host.stringProvider.getString(CommonStrings.verification_request_start_notice)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + iconColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) listener { host.selfVerificationListener?.onClickOnVerificationStart() } } @@ -294,11 +295,11 @@ class SelfVerificationController @Inject constructor( if (state.quadSContainsSecrets) { bottomSheetVerificationActionItem { id("passphrase") - title(host.stringProvider.getString(R.string.verification_cannot_access_other_session)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - subTitle(host.stringProvider.getString(R.string.verification_use_passphrase)) + title(host.stringProvider.getString(CommonStrings.verification_cannot_access_other_session)) + titleColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) + subTitle(host.stringProvider.getString(CommonStrings.verification_use_passphrase)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + iconColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) listener { host.selfVerificationListener?.onClickRecoverFromPassphrase() } } @@ -310,11 +311,11 @@ class SelfVerificationController @Inject constructor( // option to reset all bottomSheetVerificationActionItem { id("reset") - title(host.stringProvider.getString(R.string.bad_passphrase_key_reset_all_action)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - subTitle(host.stringProvider.getString(R.string.secure_backup_reset_all_no_other_devices)) + title(host.stringProvider.getString(CommonStrings.bad_passphrase_key_reset_all_action)) + titleColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) + subTitle(host.stringProvider.getString(CommonStrings.secure_backup_reset_all_no_other_devices)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + iconColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) listener { host.selfVerificationListener?.onClickResetSecurity() } } @@ -325,10 +326,10 @@ class SelfVerificationController @Inject constructor( bottomSheetVerificationActionItem { id("skip") - title(host.stringProvider.getString(R.string.action_skip)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) + title(host.stringProvider.getString(CommonStrings.action_skip)) + titleColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) + iconColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError)) listener { host.selfVerificationListener?.onClickSkip() } } } @@ -342,7 +343,7 @@ class SelfVerificationController @Inject constructor( is Loading -> { bottomSheetVerificationWaitingItem { id("waiting") - title(host.stringProvider.getString(R.string.verification_request_waiting_for_recovery)) + title(host.stringProvider.getString(CommonStrings.verification_request_waiting_for_recovery)) } } is Success -> { @@ -355,7 +356,7 @@ class SelfVerificationController @Inject constructor( id("notice_4s_failed'") notice( host.stringProvider.getString( - R.string.error_failed_to_import_keys + CommonStrings.error_failed_to_import_keys ) .toEpoxyCharSequence() ) @@ -377,7 +378,7 @@ class SelfVerificationController @Inject constructor( // Loading => We are starting a transaction bottomSheetVerificationWaitingItem { id("waiting") - title(host.stringProvider.getString(R.string.please_wait)) + title(host.stringProvider.getString(CommonStrings.please_wait)) } } is Success -> { diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationFragment.kt index 8badddba8b..cce2290bfe 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationFragment.kt @@ -29,7 +29,6 @@ import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.parentFragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.giveAccessibilityFocus @@ -42,6 +41,7 @@ import im.vector.app.core.utils.registerForPermissionsResult import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding import im.vector.app.features.crypto.verification.VerificationAction import im.vector.app.features.qrcode.QrCodeScannerActivity +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.crypto.verification.EVerificationState import timber.log.Timber import javax.inject.Inject @@ -142,7 +142,7 @@ class SelfVerificationFragment : VectorBaseFragment { MaterialAlertDialogBuilder(requireContext()) - .setTitle(getString(R.string.dialog_title_error)) + .setTitle(getString(CommonStrings.dialog_title_error)) .setMessage(event.errorMessage) .setCancelable(false) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } VerificationBottomSheetViewEvents.ResetAll, @@ -110,15 +111,18 @@ class UserVerificationBottomSheet : VectorBaseBottomSheetDialogFragment { MaterialAlertDialogBuilder(requireContext()) - .setTitle(getString(R.string.dialog_title_confirmation)) + .setTitle(getString(CommonStrings.dialog_title_confirmation)) .setMessage( - getString(R.string.verify_cancel_other, event.otherUserId, event.deviceId ?: "*") + getString(CommonStrings.verify_cancel_other, event.otherUserId, event.deviceId ?: "*") .toSpannable() - .colorizeMatchingText(event.otherUserId, ThemeUtils.getColor(requireContext(), R.attr.vctr_notice_text_color)) + .colorizeMatchingText( + event.otherUserId, + ThemeUtils.getColor(requireContext(), im.vector.lib.ui.styles.R.attr.vctr_notice_text_color) + ) ) .setCancelable(false) - .setPositiveButton(R.string._resume, null) - .setNegativeButton(R.string.action_cancel) { _, _ -> + .setPositiveButton(CommonStrings._resume, null) + .setNegativeButton(CommonStrings.action_cancel) { _, _ -> viewModel.handle(VerificationAction.CancelPendingVerification) } .show() @@ -142,7 +146,7 @@ class UserVerificationBottomSheet : VectorBaseBottomSheetDialogFragment avatarRenderer.render(state.otherUserMxItem, views.otherUserAvatarImageView) - views.otherUserNameText.text = getString(R.string.verification_verify_user, state.otherUserMxItem.getBestName()) + views.otherUserNameText.text = getString(CommonStrings.verification_verify_user, state.otherUserMxItem.getBestName()) views.otherUserShield.render( if (state.otherUserIsTrusted) RoomEncryptionTrustLevel.Trusted else RoomEncryptionTrustLevel.Default diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationController.kt index 16af43713e..1b9ae3792e 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationController.kt @@ -33,6 +33,7 @@ import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationW import im.vector.app.features.displayname.getBestName import im.vector.app.features.html.EventHtmlRenderer import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.crypto.verification.CancelCode import org.matrix.android.sdk.api.session.crypto.verification.EVerificationState import javax.inject.Inject @@ -87,9 +88,9 @@ class UserVerificationController @Inject constructor( when (state.pendingRequest) { Uninitialized -> { // let's add option to start one - val styledText = stringProvider.getString(R.string.verification_request_notice, state.otherUserId) + val styledText = stringProvider.getString(CommonStrings.verification_request_notice, state.otherUserId) .toSpannable() - .colorizeMatchingText(state.otherUserId, colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color)) + .colorizeMatchingText(state.otherUserId, colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_notice_text_color)) bottomSheetVerificationNoticeItem { id("notice") @@ -101,18 +102,18 @@ class UserVerificationController @Inject constructor( } bottomSheetVerificationActionItem { id("start") - title(host.stringProvider.getString(R.string.start_verification)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - subTitle(host.stringProvider.getString(R.string.verification_request_start_notice)) + title(host.stringProvider.getString(CommonStrings.start_verification)) + titleColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) + subTitle(host.stringProvider.getString(CommonStrings.verification_request_start_notice)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + iconColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) listener { host.listener?.onClickOnVerificationStart() } } } is Loading -> { bottomSheetVerificationWaitingItem { id("waiting") - title(host.stringProvider.getString(R.string.verification_request_waiting_for, state.otherUserMxItem.getBestName())) + title(host.stringProvider.getString(CommonStrings.verification_request_waiting_for, state.otherUserMxItem.getBestName())) } } is Success -> { @@ -121,7 +122,7 @@ class UserVerificationController @Inject constructor( EVerificationState.WaitingForReady -> { bottomSheetVerificationWaitingItem { id("waiting") - title(host.stringProvider.getString(R.string.verification_request_waiting_for, state.otherUserMxItem.getBestName())) + title(host.stringProvider.getString(CommonStrings.verification_request_waiting_for, state.otherUserMxItem.getBestName())) } } EVerificationState.Requested -> { @@ -161,10 +162,10 @@ class UserVerificationController @Inject constructor( } // private fun renderStartTransactionOptions(request: PendingVerificationRequest) { -// val scanCodeInstructions = stringProvider.getString(R.string.verification_scan_notice) +// val scanCodeInstructions = stringProvider.getString(CommonStrings.verification_scan_notice) // val host = this -// val scanOtherCodeTitle = stringProvider.getString(R.string.verification_scan_their_code) -// val compareEmojiSubtitle = stringProvider.getString(R.string.verification_scan_emoji_subtitle) +// val scanOtherCodeTitle = stringProvider.getString(CommonStrings.verification_scan_their_code) +// val compareEmojiSubtitle = stringProvider.getString(CommonStrings.verification_scan_emoji_subtitle) // // bottomSheetVerificationNoticeItem { // id("notice") @@ -186,9 +187,9 @@ class UserVerificationController @Inject constructor( // bottomSheetVerificationActionItem { // id("openCamera") // title(scanOtherCodeTitle) -// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// titleColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) // iconRes(R.drawable.ic_camera) -// iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// iconColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) // listener { host.listener?.openCamera() } // } // @@ -198,20 +199,20 @@ class UserVerificationController @Inject constructor( // // bottomSheetVerificationActionItem { // id("openEmoji") -// title(host.stringProvider.getString(R.string.verification_scan_emoji_title)) -// titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// title(host.stringProvider.getString(CommonStrings.verification_scan_emoji_title)) +// titleColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) // subTitle(compareEmojiSubtitle) // iconRes(R.drawable.ic_arrow_right) -// iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// iconColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) // listener { host.listener?.doVerifyBySas() } // } // } else if (request.isSasSupported) { // bottomSheetVerificationActionItem { // id("openEmoji") -// title(host.stringProvider.getString(R.string.verification_no_scan_emoji_title)) -// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// title(host.stringProvider.getString(CommonStrings.verification_no_scan_emoji_title)) +// titleColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) // iconRes(R.drawable.ic_arrow_right) -// iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// iconColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) // listener { host.listener?.doVerifyBySas() } // } // } else { @@ -227,7 +228,7 @@ class UserVerificationController @Inject constructor( // Loading => We are starting a transaction bottomSheetVerificationWaitingItem { id("waiting") - title(host.stringProvider.getString(R.string.please_wait)) + title(host.stringProvider.getString(CommonStrings.please_wait)) } } is Success -> { @@ -261,10 +262,10 @@ class UserVerificationController @Inject constructor( bottomSheetVerificationActionItem { id("done") - title(host.stringProvider.getString(R.string.done)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + title(host.stringProvider.getString(CommonStrings.done)) + titleColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + iconColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) listener { host.listener?.onDone(true) } } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationFragment.kt index 7aac6dcb58..d3b763ce72 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationFragment.kt @@ -29,7 +29,6 @@ import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.parentFragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.giveAccessibilityFocus @@ -42,6 +41,7 @@ import im.vector.app.core.utils.registerForPermissionsResult import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding import im.vector.app.features.crypto.verification.VerificationAction import im.vector.app.features.qrcode.QrCodeScannerActivity +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.crypto.verification.EVerificationState import timber.log.Timber import javax.inject.Inject @@ -122,7 +122,7 @@ class UserVerificationFragment : VectorBaseFragment { bottomSheetVerificationNoticeItem { id("notice") - notice(host.stringProvider.getString(R.string.verification_conclusion_not_secure).toEpoxyCharSequence()) + notice(host.stringProvider.getString(CommonStrings.verification_conclusion_not_secure).toEpoxyCharSequence()) } bottomSheetVerificationBigImageItem { @@ -200,13 +201,13 @@ fun BaseEpoxyVerificationController.renderCancel(cancelCode: CancelCode) { bottomSheetVerificationNoticeItem { id("warning_notice") - notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verification_conclusion_compromised)).toEpoxyCharSequence()) + notice(host.eventHtmlRenderer.render(host.stringProvider.getString(CommonStrings.verification_conclusion_compromised)).toEpoxyCharSequence()) } } else -> { bottomSheetVerificationNoticeItem { id("notice_cancelled") - notice(host.stringProvider.getString(R.string.verify_cancelled_notice).toEpoxyCharSequence()) + notice(host.stringProvider.getString(CommonStrings.verify_cancelled_notice).toEpoxyCharSequence()) } } } @@ -216,7 +217,7 @@ fun BaseEpoxyVerificationController.buildEmojiItem(emoji: List { MaterialAlertDialogBuilder(this) .setMessage(it.message) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() Unit } @@ -150,6 +152,8 @@ class RoomDevToolActivity : } } + @SuppressLint("MissingSuperCall") + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() { viewModel.handle(RoomDevToolAction.OnBackPressed) } @@ -206,21 +210,21 @@ class RoomDevToolActivity : getString(getTitleRes()) } RoomDevToolViewState.Mode.StateEventList -> { - getString(R.string.dev_tools_state_event) + getString(CommonStrings.dev_tools_state_event) } RoomDevToolViewState.Mode.StateEventDetail -> { state.selectedEvent?.type } RoomDevToolViewState.Mode.EditEventContent -> { - getString(R.string.dev_tools_edit_content) + getString(CommonStrings.dev_tools_edit_content) } RoomDevToolViewState.Mode.StateEventListByType -> { state.currentStateType ?: "" } is RoomDevToolViewState.Mode.SendEventForm -> { getString( - if (state.displayMode.isState) R.string.dev_tools_send_custom_state_event - else R.string.dev_tools_send_custom_event + if (state.displayMode.isState) CommonStrings.dev_tools_send_custom_state_event + else CommonStrings.dev_tools_send_custom_event ) } } diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolRootController.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolRootController.kt index 9bde4b676a..78ee42dd96 100644 --- a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolRootController.kt +++ b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolRootController.kt @@ -17,9 +17,9 @@ package im.vector.app.features.devtools import com.airbnb.epoxy.EpoxyController -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericButtonItem +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class RoomDevToolRootController @Inject constructor( @@ -36,21 +36,21 @@ class RoomDevToolRootController @Inject constructor( val host = this genericButtonItem { id("explore") - text(host.stringProvider.getString(R.string.dev_tools_explore_room_state)) + text(host.stringProvider.getString(CommonStrings.dev_tools_explore_room_state)) buttonClickAction { host.interactionListener?.processAction(RoomDevToolAction.ExploreRoomState) } } genericButtonItem { id("send") - text(host.stringProvider.getString(R.string.dev_tools_send_custom_event)) + text(host.stringProvider.getString(CommonStrings.dev_tools_send_custom_event)) buttonClickAction { host.interactionListener?.processAction(RoomDevToolAction.SendCustomEvent(false)) } } genericButtonItem { id("send_state") - text(host.stringProvider.getString(R.string.dev_tools_send_state_event)) + text(host.stringProvider.getString(CommonStrings.dev_tools_send_state_event)) buttonClickAction { host.interactionListener?.processAction(RoomDevToolAction.SendCustomEvent(true)) } diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormController.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormController.kt index 573ec0c085..26a252c6b7 100644 --- a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormController.kt +++ b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormController.kt @@ -17,12 +17,12 @@ package im.vector.app.features.devtools import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.form.formEditTextItem import im.vector.app.features.form.formMultiLineEditTextItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class RoomDevToolSendFormController @Inject constructor( @@ -43,7 +43,7 @@ class RoomDevToolSendFormController @Inject constructor( id("event_type") enabled(true) value(data.sendEventDraft?.type) - hint(host.stringProvider.getString(R.string.dev_tools_form_hint_type)) + hint(host.stringProvider.getString(CommonStrings.dev_tools_form_hint_type)) onTextChange { text -> host.interactionListener?.processAction(RoomDevToolAction.CustomEventTypeChange(text)) } @@ -54,7 +54,7 @@ class RoomDevToolSendFormController @Inject constructor( id("state_key") enabled(true) value(data.sendEventDraft?.stateKey) - hint(host.stringProvider.getString(R.string.dev_tools_form_hint_state_key)) + hint(host.stringProvider.getString(CommonStrings.dev_tools_form_hint_state_key)) onTextChange { text -> host.interactionListener?.processAction(RoomDevToolAction.CustomEventStateKeyChange(text)) } @@ -65,7 +65,7 @@ class RoomDevToolSendFormController @Inject constructor( id("event_content") enabled(true) value(data.sendEventDraft?.content) - hint(host.stringProvider.getString(R.string.dev_tools_form_hint_event_content)) + hint(host.stringProvider.getString(CommonStrings.dev_tools_form_hint_event_content)) onTextChange { text -> host.interactionListener?.processAction(RoomDevToolAction.CustomEventContentChange(text)) } diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolViewModel.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolViewModel.kt index d6aef43f72..0b559251e4 100644 --- a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolViewModel.kt @@ -24,12 +24,12 @@ import com.squareup.moshi.Types import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import org.json.JSONObject import org.matrix.android.sdk.api.query.QueryStringValue @@ -168,19 +168,19 @@ class RoomDevToolViewModel @AssistedInject constructor( viewModelScope.launch { try { val room = session.getRoom(initialState.roomId) - ?: throw IllegalArgumentException(stringProvider.getString(R.string.room_error_not_found)) + ?: throw IllegalArgumentException(stringProvider.getString(CommonStrings.room_error_not_found)) val adapter = MatrixJsonParser.getMoshi() .adapter(Types.newParameterizedType(Map::class.java, String::class.java, Any::class.java)) val json = adapter.fromJson(state.editedContent ?: "") - ?: throw IllegalArgumentException(stringProvider.getString(R.string.dev_tools_error_no_content)) + ?: throw IllegalArgumentException(stringProvider.getString(CommonStrings.dev_tools_error_no_content)) room.stateService().sendStateEvent( state.selectedEvent?.type.orEmpty(), state.selectedEvent?.stateKey.orEmpty(), json ) - _viewEvents.post(DevToolsViewEvents.ShowSnackMessage(stringProvider.getString(R.string.dev_tools_success_state_event))) + _viewEvents.post(DevToolsViewEvents.ShowSnackMessage(stringProvider.getString(CommonStrings.dev_tools_success_state_event))) setState { copy( modalLoading = Success(Unit), @@ -201,15 +201,15 @@ class RoomDevToolViewModel @AssistedInject constructor( viewModelScope.launch { try { val room = session.getRoom(initialState.roomId) - ?: throw IllegalArgumentException(stringProvider.getString(R.string.room_error_not_found)) + ?: throw IllegalArgumentException(stringProvider.getString(CommonStrings.room_error_not_found)) val adapter = MatrixJsonParser.getMoshi() .adapter(Types.newParameterizedType(Map::class.java, String::class.java, Any::class.java)) val json = adapter.fromJson(state.sendEventDraft?.content ?: "") - ?: throw IllegalArgumentException(stringProvider.getString(R.string.dev_tools_error_no_content)) + ?: throw IllegalArgumentException(stringProvider.getString(CommonStrings.dev_tools_error_no_content)) val eventType = state.sendEventDraft?.type - ?: throw IllegalArgumentException(stringProvider.getString(R.string.dev_tools_error_no_message_type)) + ?: throw IllegalArgumentException(stringProvider.getString(CommonStrings.dev_tools_error_no_message_type)) if (isState) { room.stateService().sendStateEvent( @@ -221,14 +221,14 @@ class RoomDevToolViewModel @AssistedInject constructor( // can we try to do some validation?? // val validParse = MoshiProvider.providesMoshi().adapter(MessageContent::class.java).fromJson(it.sendEventDraft.content ?: "") json.toModel(catchError = false) - ?: throw IllegalArgumentException(stringProvider.getString(R.string.dev_tools_error_malformed_event)) + ?: throw IllegalArgumentException(stringProvider.getString(CommonStrings.dev_tools_error_malformed_event)) room.sendService().sendEvent( eventType, json ) } - _viewEvents.post(DevToolsViewEvents.ShowSnackMessage(stringProvider.getString(R.string.dev_tools_success_event))) + _viewEvents.post(DevToolsViewEvents.ShowSnackMessage(stringProvider.getString(CommonStrings.dev_tools_success_event))) setState { copy( modalLoading = Success(Unit), diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt index 831091883a..b3ba1f7f49 100644 --- a/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt +++ b/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt @@ -17,12 +17,13 @@ package im.vector.app.features.devtools import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span import org.json.JSONObject import javax.inject.Inject @@ -43,14 +44,14 @@ class RoomStateListController @Inject constructor( if (stateEventsGroups.isEmpty()) { noResultItem { id("no state events") - text(host.stringProvider.getString(R.string.no_result_placeholder)) + text(host.stringProvider.getString(CommonStrings.no_result_placeholder)) } } else { stateEventsGroups.forEach { entry -> genericItem { id(entry.key) title(entry.key.toEpoxyCharSequence()) - description(host.stringProvider.getQuantityString(R.plurals.entries, entry.value.size, entry.value.size).toEpoxyCharSequence()) + description(host.stringProvider.getQuantityString(CommonPlurals.entries, entry.value.size, entry.value.size).toEpoxyCharSequence()) itemClickAction { host.interactionListener?.processAction(RoomDevToolAction.ShowStateEventType(entry.key)) } @@ -63,7 +64,7 @@ class RoomStateListController @Inject constructor( if (stateEvents.isEmpty()) { noResultItem { id("no state events") - text(host.stringProvider.getString(R.string.no_result_placeholder)) + text(host.stringProvider.getString(CommonStrings.no_result_placeholder)) } } else { stateEvents.forEach { stateEvent -> @@ -79,13 +80,13 @@ class RoomStateListController @Inject constructor( title(span { +"Type: " span { - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) text = "\"${stateEvent.type}\"" textStyle = "normal" } +"\nState Key: " span { - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) text = stateEvent.stateKey.let { "\"$it\"" } textStyle = "normal" } diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt index cb0e1d3e91..7c8da7b4a3 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt @@ -22,7 +22,6 @@ import com.airbnb.mvrx.Incomplete import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized -import im.vector.app.R import im.vector.app.core.epoxy.attributes.ButtonStyle import im.vector.app.core.epoxy.attributes.ButtonType import im.vector.app.core.epoxy.attributes.IconMode @@ -32,6 +31,7 @@ import im.vector.app.core.extensions.getFormattedValue import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.features.form.formAdvancedToggleItem +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.session.identity.SharedState import org.matrix.android.sdk.api.session.identity.ThreePid @@ -78,30 +78,30 @@ class DiscoverySettingsController @Inject constructor( val host = this settingsSectionTitleItem { id("idConsentTitle") - titleResId(R.string.settings_discovery_consent_title) + titleResId(CommonStrings.settings_discovery_consent_title) } if (data.userConsent) { settingsInfoItem { id("idConsentInfo") - helperTextResId(R.string.settings_discovery_consent_notice_on) + helperTextResId(CommonStrings.settings_discovery_consent_notice_on) } settingsButtonItem { id("idConsentButton") colorProvider(host.colorProvider) - buttonTitleId(R.string.settings_discovery_consent_action_revoke) + buttonTitleId(CommonStrings.settings_discovery_consent_action_revoke) buttonStyle(ButtonStyle.DESTRUCTIVE) buttonClickListener { host.listener?.onTapUpdateUserConsent(false) } } } else { settingsInfoItem { id("idConsentInfo") - helperTextResId(R.string.settings_discovery_consent_notice_off_2) + helperTextResId(CommonStrings.settings_discovery_consent_notice_off_2) } settingsButtonItem { id("idConsentButton") colorProvider(host.colorProvider) - buttonTitleId(R.string.settings_discovery_consent_action_give_consent) + buttonTitleId(CommonStrings.settings_discovery_consent_action_give_consent) buttonClickListener { host.listener?.onTapUpdateUserConsent(true) } } } @@ -109,12 +109,12 @@ class DiscoverySettingsController @Inject constructor( private fun buildIdentityServerSection(data: DiscoverySettingsState) { val identityServer = data.identityServer() - val identityServerUrl = identityServer?.serverUrl ?: stringProvider.getString(R.string.none) + val identityServerUrl = identityServer?.serverUrl ?: stringProvider.getString(CommonStrings.none) val host = this settingsSectionTitleItem { id("idServerTitle") - titleResId(R.string.identity_server) + titleResId(CommonStrings.identity_server) } settingsItem { @@ -127,8 +127,8 @@ class DiscoverySettingsController @Inject constructor( formAdvancedToggleItem { id("policy-urls") val titleRes = if (data.isIdentityPolicyUrlsExpanded) { - R.string.settings_discovery_hide_identity_server_policy_title - } else R.string.settings_discovery_show_identity_server_policy_title + CommonStrings.settings_discovery_hide_identity_server_policy_title + } else CommonStrings.settings_discovery_show_identity_server_policy_title title(host.stringProvider.getString(titleRes)) expanded(data.isIdentityPolicyUrlsExpanded) listener { host.listener?.onPolicyUrlsExpandedStateToggled(!data.isIdentityPolicyUrlsExpanded) } @@ -137,7 +137,7 @@ class DiscoverySettingsController @Inject constructor( if (policies.isEmpty()) { settingsInfoItem { id("emptyPolicy") - helperText(host.stringProvider.getString(R.string.settings_discovery_no_policy_provided)) + helperText(host.stringProvider.getString(CommonStrings.settings_discovery_no_policy_provided)) } } else { policies.forEach { policy -> @@ -155,14 +155,14 @@ class DiscoverySettingsController @Inject constructor( if (identityServer != null && data.termsNotSigned) { settingsInfoItem { id("idServerFooter") - helperText(host.stringProvider.getString(R.string.settings_agree_to_terms, identityServerUrl)) + helperText(host.stringProvider.getString(CommonStrings.settings_agree_to_terms, identityServerUrl)) showCompoundDrawable(true) itemClickListener { host.listener?.openIdentityServerTerms() } } settingsButtonItem { id("seeTerms") colorProvider(host.colorProvider) - buttonTitle(host.stringProvider.getString(R.string.open_terms_of, identityServerUrl)) + buttonTitle(host.stringProvider.getString(CommonStrings.open_terms_of, identityServerUrl)) buttonClickListener { host.listener?.openIdentityServerTerms() } } } else { @@ -170,9 +170,9 @@ class DiscoverySettingsController @Inject constructor( id("idServerFooter") showCompoundDrawable(false) if (identityServer != null) { - helperText(host.stringProvider.getString(R.string.settings_discovery_identity_server_info, identityServerUrl)) + helperText(host.stringProvider.getString(CommonStrings.settings_discovery_identity_server_info, identityServerUrl)) } else { - helperTextResId(R.string.settings_discovery_identity_server_info_none) + helperTextResId(CommonStrings.settings_discovery_identity_server_info_none) } } } @@ -181,9 +181,9 @@ class DiscoverySettingsController @Inject constructor( id("change") colorProvider(host.colorProvider) if (identityServer == null) { - buttonTitleId(R.string.add_identity_server) + buttonTitleId(CommonStrings.add_identity_server) } else { - buttonTitleId(R.string.change_identity_server) + buttonTitleId(CommonStrings.change_identity_server) } buttonClickListener { host.listener?.onTapChangeIdentityServer() } } @@ -191,12 +191,12 @@ class DiscoverySettingsController @Inject constructor( if (identityServer != null) { settingsInfoItem { id("removeInfo") - helperTextResId(R.string.settings_discovery_disconnect_identity_server_info) + helperTextResId(CommonStrings.settings_discovery_disconnect_identity_server_info) } settingsButtonItem { id("remove") colorProvider(host.colorProvider) - buttonTitleId(R.string.disconnect_identity_server) + buttonTitleId(CommonStrings.disconnect_identity_server) buttonStyle(ButtonStyle.DESTRUCTIVE) buttonClickListener { host.listener?.onTapDisconnectIdentityServer() } } @@ -207,7 +207,7 @@ class DiscoverySettingsController @Inject constructor( val host = this settingsSectionTitleItem { id("emails") - titleResId(R.string.settings_discovery_emails_title) + titleResId(CommonStrings.settings_discovery_emails_title) } when (emails) { Uninitialized, @@ -226,7 +226,7 @@ class DiscoverySettingsController @Inject constructor( if (emails().isEmpty()) { settingsInfoItem { id("emailsEmpty") - helperText(host.stringProvider.getString(R.string.settings_discovery_no_mails)) + helperText(host.stringProvider.getString(CommonStrings.settings_discovery_no_mails)) } } else { emails().forEach { buildEmail(it) } @@ -247,14 +247,14 @@ class DiscoverySettingsController @Inject constructor( is Loading -> settingsInformationItem { id("info${pidInfo.threePid.value}") - message(host.stringProvider.getString(R.string.settings_discovery_confirm_mail, pidInfo.threePid.value)) - textColor(host.colorProvider.getColor(R.color.vector_info_color)) + message(host.stringProvider.getString(CommonStrings.settings_discovery_confirm_mail, pidInfo.threePid.value)) + textColor(host.colorProvider.getColor(im.vector.lib.ui.styles.R.color.vector_info_color)) } is Fail -> settingsInformationItem { id("info${pidInfo.threePid.value}") - message(host.stringProvider.getString(R.string.settings_discovery_confirm_mail_not_clicked, pidInfo.threePid.value)) - textColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) + message(host.stringProvider.getString(CommonStrings.settings_discovery_confirm_mail_not_clicked, pidInfo.threePid.value)) + textColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError)) } is Success -> Unit /* Cannot happen */ } @@ -275,7 +275,7 @@ class DiscoverySettingsController @Inject constructor( val host = this settingsSectionTitleItem { id("msisdn") - titleResId(R.string.settings_discovery_msisdn_title) + titleResId(CommonStrings.settings_discovery_msisdn_title) } when (msisdns) { @@ -295,7 +295,7 @@ class DiscoverySettingsController @Inject constructor( if (msisdns().isEmpty()) { settingsInfoItem { id("no_msisdn") - helperText(host.stringProvider.getString(R.string.settings_discovery_no_msisdn)) + helperText(host.stringProvider.getString(CommonStrings.settings_discovery_no_msisdn)) } } else { msisdns().forEach { buildMsisdn(it) } @@ -319,7 +319,7 @@ class DiscoverySettingsController @Inject constructor( // Ref: https://github.com/matrix-org/sydent/issues/292 if (error is Failure.ServerError && error.httpCode == HttpsURLConnection.HTTP_INTERNAL_ERROR /* 500 */) { - stringProvider.getString(R.string.settings_text_message_sent_wrong_code) + stringProvider.getString(CommonStrings.settings_text_message_sent_wrong_code) } else { errorFormatter.toHumanReadable(error) } @@ -328,7 +328,7 @@ class DiscoverySettingsController @Inject constructor( } settingsEditTextItem { id("msisdnVerification${pidInfo.threePid.value}") - descriptionText(host.stringProvider.getString(R.string.settings_text_message_sent, phoneNumber)) + descriptionText(host.stringProvider.getString(CommonStrings.settings_text_message_sent, phoneNumber)) errorText(errorText) inProgress(pidInfo.finalRequest is Loading) interactionListener(object : SettingsEditTextItem.Listener { @@ -362,7 +362,7 @@ class DiscoverySettingsController @Inject constructor( is Fail -> { buttonType(ButtonType.NORMAL) buttonStyle(ButtonStyle.DESTRUCTIVE) - buttonTitle(host.stringProvider.getString(R.string.global_retry)) + buttonTitle(host.stringProvider.getString(CommonStrings.global_retry)) iconMode(IconMode.ERROR) buttonClickListener { host.listener?.onTapRetryToRetrieveBindings() } } @@ -399,7 +399,7 @@ class DiscoverySettingsController @Inject constructor( settingsInformationItem { id("info${pidInfo.threePid.value}") message((pidInfo.isShared as? Fail)?.error?.message ?: "") - textColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) + textColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError)) } } diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt index 8c801bdf89..40fe193c01 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt @@ -26,7 +26,6 @@ import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.observeEvent @@ -39,6 +38,7 @@ import im.vector.app.databinding.FragmentGenericRecyclerBinding import im.vector.app.features.discovery.change.SetIdentityServerFragment import im.vector.app.features.navigation.SettingsActivityPayload import im.vector.app.features.settings.VectorSettingsActivity +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.identity.SharedState import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.api.session.terms.TermsService @@ -99,7 +99,7 @@ class DiscoverySettingsFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.settings_discovery_category) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.settings_discovery_category) // If some 3pids are pending, we can try to check if they have been verified here viewModel.handle(DiscoverySettingsAction.Refresh) @@ -153,10 +153,10 @@ class DiscoverySettingsFragment : if (hasBoundIds) { // we should prompt MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.change_identity_server) - .setMessage(getString(R.string.settings_discovery_disconnect_with_bound_pid, state.identityServer(), state.identityServer())) - .setPositiveButton(R.string._continue) { _, _ -> navigateToChangeIdentityServerFragment() } - .setNegativeButton(R.string.action_cancel, null) + .setTitle(CommonStrings.change_identity_server) + .setMessage(getString(CommonStrings.settings_discovery_disconnect_with_bound_pid, state.identityServer(), state.identityServer())) + .setPositiveButton(CommonStrings._continue) { _, _ -> navigateToChangeIdentityServerFragment() } + .setNegativeButton(CommonStrings.action_cancel, null) .show() Unit } else { @@ -172,16 +172,16 @@ class DiscoverySettingsFragment : val serverUrl = state.identityServer()?.serverUrl.orEmpty() val message = if (hasBoundIds) { - getString(R.string.settings_discovery_disconnect_with_bound_pid, serverUrl, serverUrl) + getString(CommonStrings.settings_discovery_disconnect_with_bound_pid, serverUrl, serverUrl) } else { - getString(R.string.disconnect_identity_server_dialog_content, serverUrl) + getString(CommonStrings.disconnect_identity_server_dialog_content, serverUrl) } MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.disconnect_identity_server) + .setTitle(CommonStrings.disconnect_identity_server) .setMessage(message) - .setPositiveButton(R.string.action_disconnect) { _, _ -> viewModel.handle(DiscoverySettingsAction.DisconnectIdentityServer) } - .setNegativeButton(R.string.action_cancel, null) + .setPositiveButton(CommonStrings.action_disconnect) { _, _ -> viewModel.handle(DiscoverySettingsAction.DisconnectIdentityServer) } + .setNegativeButton(CommonStrings.action_cancel, null) .show() } } diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt index 2a975beb58..409b9477f2 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt @@ -24,11 +24,11 @@ import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @@ -393,7 +393,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor( } } viewModelScope.launch { - runCatching { session.fetchIdentityServerWithTerms(stringProvider.getString(R.string.resources_language)) }.fold( + runCatching { session.fetchIdentityServerWithTerms(stringProvider.getString(CommonStrings.resources_language)) }.fold( onSuccess = { setState { copy(identityServer = Success(it)) } }, onFailure = { _viewEvents.post(DiscoverySettingsViewEvents.Failure(it)) } ) @@ -401,6 +401,6 @@ class DiscoverySettingsViewModel @AssistedInject constructor( } private suspend fun fetchIdentityServerWithTerms(): ServerAndPolicies? { - return session.fetchIdentityServerWithTerms(stringProvider.getString(R.string.resources_language)) + return session.fetchIdentityServerWithTerms(stringProvider.getString(CommonStrings.resources_language)) } } diff --git a/vector/src/main/java/im/vector/app/features/discovery/SettingsButtonItem.kt b/vector/src/main/java/im/vector/app/features/discovery/SettingsButtonItem.kt index da432c43b1..6abb7c766f 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/SettingsButtonItem.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/SettingsButtonItem.kt @@ -57,10 +57,10 @@ abstract class SettingsButtonItem : VectorEpoxyModel( when (buttonStyle) { ButtonStyle.POSITIVE -> { - holder.button.setTextColor(colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + holder.button.setTextColor(colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) } ButtonStyle.DESTRUCTIVE -> { - holder.button.setTextColor(colorProvider.getColorFromAttribute(R.attr.colorError)) + holder.button.setTextColor(colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError)) } } diff --git a/vector/src/main/java/im/vector/app/features/discovery/SettingsTextButtonSingleLineItem.kt b/vector/src/main/java/im/vector/app/features/discovery/SettingsTextButtonSingleLineItem.kt index 9810ae2400..969bf168ea 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/SettingsTextButtonSingleLineItem.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/SettingsTextButtonSingleLineItem.kt @@ -116,10 +116,10 @@ abstract class SettingsTextButtonSingleLineItem : VectorEpoxyModel { - holder.mainButton.setTextColor(colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + holder.mainButton.setTextColor(colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) } ButtonStyle.DESTRUCTIVE -> { - holder.mainButton.setTextColor(colorProvider.getColorFromAttribute(R.attr.colorError)) + holder.mainButton.setTextColor(colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError)) } } holder.mainButton.onClick(buttonClickListener) @@ -140,14 +140,14 @@ abstract class SettingsTextButtonSingleLineItem : VectorEpoxyModel { - val errorColor = colorProvider.getColor(R.color.notification_accent_color) + val errorColor = colorProvider.getColor(im.vector.lib.ui.styles.R.color.notification_accent_color) ContextCompat.getDrawable(holder.view.context, R.drawable.ic_notification_privacy_warning)?.apply { ThemeUtils.tintDrawableWithColor(this, errorColor) holder.textView.setCompoundDrawablesWithIntrinsicBounds(this, null, null, null) } } IconMode.ERROR -> { - val errorColor = colorProvider.getColorFromAttribute(R.attr.colorError) + val errorColor = colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError) ContextCompat.getDrawable(holder.view.context, R.drawable.ic_notification_privacy_warning)?.apply { ThemeUtils.tintDrawableWithColor(this, errorColor) holder.textView.setCompoundDrawablesWithIntrinsicBounds(this, null, null, null) diff --git a/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerFragment.kt b/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerFragment.kt index f8499219aa..e6790c24c8 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerFragment.kt @@ -29,7 +29,6 @@ import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.toReducedUrl import im.vector.app.core.platform.VectorBaseFragment @@ -37,6 +36,7 @@ import im.vector.app.core.resources.ColorProvider import im.vector.app.core.utils.colorizeMatchingText import im.vector.app.databinding.FragmentSetIdentityServerBinding import im.vector.app.features.discovery.DiscoverySharedViewModel +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.session.terms.TermsService @@ -62,23 +62,24 @@ class SetIdentityServerFragment : // No default views.identityServerSetDefaultNotice.isVisible = false views.identityServerSetDefaultSubmit.isVisible = false - views.identityServerSetDefaultAlternative.setText(R.string.identity_server_set_alternative_notice_no_default) + views.identityServerSetDefaultAlternative.setText(CommonStrings.identity_server_set_alternative_notice_no_default) } else { views.identityServerSetDefaultNotice.text = getString( - R.string.identity_server_set_default_notice, + CommonStrings.identity_server_set_default_notice, state.homeServerUrl.toReducedUrl(), state.defaultIdentityServerUrl.toReducedUrl() ) .toSpannable() .colorizeMatchingText( state.defaultIdentityServerUrl.toReducedUrl(), - colorProvider.getColorFromAttribute(R.attr.vctr_content_tertiary) + colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_tertiary) ) views.identityServerSetDefaultNotice.isVisible = true views.identityServerSetDefaultSubmit.isVisible = true - views.identityServerSetDefaultSubmit.text = getString(R.string.identity_server_set_default_submit, state.defaultIdentityServerUrl.toReducedUrl()) - views.identityServerSetDefaultAlternative.setText(R.string.identity_server_set_alternative_notice) + views.identityServerSetDefaultSubmit.text = + getString(CommonStrings.identity_server_set_default_submit, state.defaultIdentityServerUrl.toReducedUrl()) + views.identityServerSetDefaultAlternative.setText(CommonStrings.identity_server_set_alternative_notice) } } @@ -118,12 +119,12 @@ class SetIdentityServerFragment : is SetIdentityServerViewEvents.OtherFailure -> showFailure(it.failure) is SetIdentityServerViewEvents.NoTerms -> { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.settings_discovery_no_terms_title) - .setMessage(R.string.settings_discovery_no_terms) - .setPositiveButton(R.string._continue) { _, _ -> + .setTitle(CommonStrings.settings_discovery_no_terms_title) + .setMessage(CommonStrings.settings_discovery_no_terms) + .setPositiveButton(CommonStrings._continue) { _, _ -> processIdentityServerChange() } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() Unit } @@ -146,9 +147,9 @@ class SetIdentityServerFragment : if (failure.forDefault) { // Display the error in a dialog MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(message) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } else { // Display the error inlined @@ -158,7 +159,7 @@ class SetIdentityServerFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.identity_server) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.identity_server) } private val termsActivityResultLauncher = registerStartForActivityResult { diff --git a/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerViewModel.kt b/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerViewModel.kt index b91feb0b3c..675b2650ab 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerViewModel.kt @@ -21,13 +21,13 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import dagger.hilt.EntryPoints -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.SingletonEntryPoint import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.ensureProtocol +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.session.Session @@ -61,7 +61,7 @@ class SetIdentityServerViewModel @AssistedInject constructor( var currentWantedUrl: String? = null private set - private val userLanguage = stringProvider.getString(R.string.resources_language) + private val userLanguage = stringProvider.getString(CommonStrings.resources_language) override fun handle(action: SetIdentityServerAction) { when (action) { @@ -80,7 +80,7 @@ class SetIdentityServerViewModel @AssistedInject constructor( private fun doChangeIdentityServerUrl(url: String, isDefault: Boolean) { if (url.isEmpty()) { - _viewEvents.post(SetIdentityServerViewEvents.Failure(R.string.settings_discovery_please_enter_server, isDefault)) + _viewEvents.post(SetIdentityServerViewEvents.Failure(CommonStrings.settings_discovery_please_enter_server, isDefault)) return } val baseUrl = url.ensureProtocol().also { currentWantedUrl = it } @@ -96,9 +96,9 @@ class SetIdentityServerViewModel @AssistedInject constructor( } catch (failure: Throwable) { when { failure is IdentityServiceError.OutdatedIdentityServer -> - _viewEvents.post(SetIdentityServerViewEvents.Failure(R.string.identity_server_error_outdated_identity_server, isDefault)) + _viewEvents.post(SetIdentityServerViewEvents.Failure(CommonStrings.identity_server_error_outdated_identity_server, isDefault)) failure is Failure.NetworkConnection && failure.ioException is UnknownHostException -> - _viewEvents.post(SetIdentityServerViewEvents.Failure(R.string.settings_discovery_bad_identity_server, isDefault)) + _viewEvents.post(SetIdentityServerViewEvents.Failure(CommonStrings.settings_discovery_bad_identity_server, isDefault)) else -> _viewEvents.post(SetIdentityServerViewEvents.OtherFailure(failure)) } diff --git a/vector/src/main/java/im/vector/app/features/form/FormAdvancedToggleItem.kt b/vector/src/main/java/im/vector/app/features/form/FormAdvancedToggleItem.kt index 6f2aa2086b..48659688b8 100644 --- a/vector/src/main/java/im/vector/app/features/form/FormAdvancedToggleItem.kt +++ b/vector/src/main/java/im/vector/app/features/form/FormAdvancedToggleItem.kt @@ -37,7 +37,7 @@ abstract class FormAdvancedToggleItem : VectorEpoxyModel(R.layout.item_space) { @@ -51,12 +52,14 @@ abstract class HomeSpaceSummaryItem : VectorEpoxyModel(R.layout.item_new_space) { @@ -47,14 +48,17 @@ abstract class NewHomeSpaceSummaryItem : VectorEpoxyModel { - contentDescription = stringProvider.getString(R.string.avatar_of_space, matrixItem.getBestName()) + contentDescription = stringProvider.getString(CommonStrings.avatar_of_space, matrixItem.getBestName()) } is MatrixItem.RoomAliasItem, is MatrixItem.RoomItem -> { - contentDescription = stringProvider.getString(R.string.avatar_of_room, matrixItem.getBestName()) + contentDescription = stringProvider.getString(CommonStrings.avatar_of_room, matrixItem.getBestName()) } is MatrixItem.UserItem -> { - contentDescription = stringProvider.getString(R.string.avatar_of_user, matrixItem.getBestName()) + contentDescription = stringProvider.getString(CommonStrings.avatar_of_user, matrixItem.getBestName()) } is MatrixItem.EveryoneInRoomItem, is MatrixItem.EventItem -> { 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 428e62724b..93fbbf2237 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 @@ -85,6 +85,7 @@ import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.usercode.UserCodeActivity import im.vector.app.features.workers.signout.ServerBackupStatusViewModel import im.vector.lib.core.utils.compat.getParcelableExtraCompat +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -355,10 +356,10 @@ class HomeActivity : private fun handleNotifyUserForThreadsMigration() { MaterialAlertDialogBuilder(this) - .setTitle(R.string.threads_notice_migration_title) - .setMessage(R.string.threads_notice_migration_message) + .setTitle(CommonStrings.threads_notice_migration_title) + .setMessage(CommonStrings.threads_notice_migration_message) .setCancelable(true) - .setPositiveButton(R.string.sas_got_it) { _, _ -> } + .setPositiveButton(CommonStrings.sas_got_it) { _, _ -> } .show() } @@ -389,9 +390,9 @@ class HomeActivity : val isMatrixToLink = deepLink.startsWith(PermalinkService.MATRIX_TO_URL_BASE) || deepLink.startsWith(MATRIX_TO_CUSTOM_SCHEME_URL_BASE) MaterialAlertDialogBuilder(this@HomeActivity) - .setTitle(R.string.dialog_title_error) - .setMessage(if (isMatrixToLink) R.string.permalink_malformed else R.string.universal_link_malformed) - .setPositiveButton(R.string.ok, null) + .setTitle(CommonStrings.dialog_title_error) + .setMessage(if (isMatrixToLink) CommonStrings.permalink_malformed else CommonStrings.universal_link_malformed) + .setPositiveButton(CommonStrings.ok, null) .show() } } @@ -439,8 +440,8 @@ class HomeActivity : promptSecurityEvent( uid = PopupAlertManager.UPGRADE_SECURITY_UID, userItem = events.userItem, - titleRes = R.string.upgrade_security, - descRes = R.string.security_prompt_text, + titleRes = CommonStrings.upgrade_security, + descRes = CommonStrings.security_prompt_text, ) { it.navigator.upgradeSessionSecurity(it, true) } @@ -451,8 +452,8 @@ class HomeActivity : promptSecurityEvent( uid = PopupAlertManager.VERIFY_SESSION_UID, userItem = event.userItem, - titleRes = R.string.crosssigning_verify_this_session, - descRes = R.string.confirm_your_identity, + titleRes = CommonStrings.crosssigning_verify_this_session, + descRes = CommonStrings.confirm_your_identity, ) { // check first if it's not an outdated request? activeSessionHolder.getSafeActiveSession()?.let { session -> @@ -470,14 +471,14 @@ class HomeActivity : private fun handleOnNewSession(event: HomeActivityViewEvents.CurrentSessionNotVerified) { // We need to ask val titleRes = if (event.afterMigration) { - R.string.crosssigning_verify_after_update + CommonStrings.crosssigning_verify_after_update } else { - R.string.crosssigning_verify_this_session + CommonStrings.crosssigning_verify_this_session } val descRes = if (event.afterMigration) { - R.string.confirm_your_identity_after_update + CommonStrings.confirm_your_identity_after_update } else { - R.string.confirm_your_identity + CommonStrings.confirm_your_identity } promptSecurityEvent( uid = PopupAlertManager.VERIFY_SESSION_UID, @@ -494,8 +495,8 @@ class HomeActivity : promptSecurityEvent( uid = PopupAlertManager.UPGRADE_SECURITY_UID, userItem = event.userItem, - titleRes = R.string.crosssigning_cannot_verify_this_session, - descRes = R.string.crosssigning_cannot_verify_this_session_desc, + titleRes = CommonStrings.crosssigning_cannot_verify_this_session, + descRes = CommonStrings.crosssigning_cannot_verify_this_session_desc, ) { it.navigator.open4SSetup(it, SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET) } @@ -505,14 +506,14 @@ class HomeActivity : popupAlertManager.postVectorAlert( DefaultVectorAlert( uid = PopupAlertManager.ENABLE_PUSH_UID, - title = getString(R.string.alert_push_are_disabled_title), - description = getString(R.string.alert_push_are_disabled_description), + title = getString(CommonStrings.alert_push_are_disabled_title), + description = getString(CommonStrings.alert_push_are_disabled_description), iconId = R.drawable.ic_room_actions_notifications_mutes, shouldBeDisplayedIn = { it is HomeActivity } ).apply { - colorInt = ThemeUtils.getColor(this@HomeActivity, R.attr.vctr_notice_secondary) + colorInt = ThemeUtils.getColor(this@HomeActivity, im.vector.lib.ui.styles.R.attr.vctr_notice_secondary) contentAction = Runnable { (weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let { // action(it) @@ -523,10 +524,10 @@ class HomeActivity : dismissedAction = Runnable { homeActivityViewModel.handle(HomeActivityViewActions.PushPromptHasBeenReviewed) } - addButton(getString(R.string.action_dismiss), { + addButton(getString(CommonStrings.action_dismiss), { homeActivityViewModel.handle(HomeActivityViewActions.PushPromptHasBeenReviewed) }, true) - addButton(getString(R.string.settings), { + addButton(getString(CommonStrings.settings), { (weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let { // action(it) homeActivityViewModel.handle(HomeActivityViewActions.PushPromptHasBeenReviewed) @@ -552,7 +553,7 @@ class HomeActivity : iconId = R.drawable.ic_shield_warning ).apply { viewBinder = VerificationVectorAlert.ViewBinder(userItem, avatarRenderer) - colorInt = ThemeUtils.getColor(this@HomeActivity, R.attr.colorPrimary) + colorInt = ThemeUtils.getColor(this@HomeActivity, com.google.android.material.R.attr.colorPrimary) contentAction = Runnable { (weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let { action(it) @@ -563,9 +564,9 @@ class HomeActivity : ) } - override fun onNewIntent(intent: Intent?) { + override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) - val parcelableExtra = intent?.getParcelableExtraCompat(Mavericks.KEY_ARG) + val parcelableExtra = intent.getParcelableExtraCompat(Mavericks.KEY_ARG) if (parcelableExtra?.clearNotification == true) { notificationDrawerManager.clearAllEvents() } @@ -592,10 +593,10 @@ class HomeActivity : vectorUncaughtExceptionHandler.clearAppCrashStatus() MaterialAlertDialogBuilder(this) - .setMessage(R.string.send_bug_report_app_crashed) + .setMessage(CommonStrings.send_bug_report_app_crashed) .setCancelable(false) - .setPositiveButton(R.string.yes) { _, _ -> bugReporter.openBugReportScreen(this) } - .setNegativeButton(R.string.no) { _, _ -> bugReporter.deleteCrashFile() } + .setPositiveButton(CommonStrings.yes) { _, _ -> bugReporter.openBugReportScreen(this) } + .setNegativeButton(CommonStrings.no) { _, _ -> bugReporter.deleteCrashFile() } .show() } @@ -678,18 +679,19 @@ class HomeActivity : private fun launchInviteFriends() { activeSessionHolder.getSafeActiveSession()?.permalinkService()?.createPermalink(sharedActionViewModel.session.myUserId)?.let { permalink -> analyticsTracker.screen(MobileScreen(screenName = MobileScreen.ScreenName.InviteFriends)) - val text = getString(R.string.invite_friends_text, permalink) + val text = getString(CommonStrings.invite_friends_text, permalink) startSharePlainTextIntent( context = this, activityResultLauncher = null, - chooserTitle = getString(R.string.invite_friends), + chooserTitle = getString(CommonStrings.invite_friends), text = text, - extraTitle = getString(R.string.invite_friends_rich_title) + extraTitle = getString(CommonStrings.invite_friends_rich_title) ) } } + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() { if (views.drawerLayout.isDrawerOpen(GravityCompat.START)) { views.drawerLayout.closeDrawer(GravityCompat.START) diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt index d310f574dd..b0a3ebf6dc 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt @@ -58,6 +58,7 @@ import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.workers.signout.BannerState import im.vector.app.features.workers.signout.ServerBackupStatusAction import im.vector.app.features.workers.signout.ServerBackupStatusViewModel +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject @@ -227,12 +228,12 @@ class HomeDetailFragment : alertManager.postVectorAlert( VerificationVectorAlert( uid = uid, - title = getString(R.string.new_session), - description = getString(R.string.verify_this_session, newest.displayName ?: newest.deviceId ?: ""), + title = getString(CommonStrings.new_session), + description = getString(CommonStrings.verify_this_session, newest.displayName ?: newest.deviceId ?: ""), iconId = R.drawable.ic_shield_warning ).apply { viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer) - colorInt = colorProvider.getColorFromAttribute(R.attr.colorPrimary) + colorInt = colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary) contentAction = Runnable { (weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let { vectorBaseActivity -> vectorBaseActivity.navigator @@ -256,12 +257,12 @@ class HomeDetailFragment : alertManager.postVectorAlert( VerificationVectorAlert( uid = uid, - title = getString(R.string.review_unverified_sessions_title), - description = getString(R.string.review_unverified_sessions_description), + title = getString(CommonStrings.review_unverified_sessions_title), + description = getString(CommonStrings.review_unverified_sessions_description), iconId = R.drawable.ic_shield_warning ).apply { viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer) - colorInt = colorProvider.getColorFromAttribute(R.attr.colorPrimary) + colorInt = colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary) contentAction = Runnable { (weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let { activity -> // mark as ignored to avoid showing it again @@ -435,11 +436,11 @@ class HomeDetailFragment : isVisible = count > 0 number = count maxCharacterCount = 3 - badgeTextColor = ThemeUtils.getColor(requireContext(), R.attr.colorOnPrimary) + badgeTextColor = ThemeUtils.getColor(requireContext(), com.google.android.material.R.attr.colorOnPrimary) backgroundColor = if (highlight) { - ThemeUtils.getColor(requireContext(), R.attr.colorError) + ThemeUtils.getColor(requireContext(), com.google.android.material.R.attr.colorError) } else { - ThemeUtils.getColor(requireContext(), R.attr.vctr_unread_background) + ThemeUtils.getColor(requireContext(), im.vector.lib.ui.styles.R.attr.vctr_unread_background) } } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt index dcf4d87894..c8f6eccbff 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt @@ -20,7 +20,7 @@ import androidx.annotation.StringRes import com.airbnb.mvrx.Async import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.Uninitialized -import im.vector.app.R +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.sync.SyncRequestState import org.matrix.android.sdk.api.session.sync.SyncState @@ -49,5 +49,5 @@ data class HomeDetailViewState( sealed class HomeTab(@StringRes val titleRes: Int) { data class RoomList(val displayMode: RoomListDisplayMode) : HomeTab(displayMode.titleRes) - object DialPad : HomeTab(R.string.call_dial_pad_title) + object DialPad : HomeTab(CommonStrings.call_dial_pad_title) } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDrawerFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDrawerFragment.kt index 22d9709229..3b0287f95f 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDrawerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDrawerFragment.kt @@ -38,6 +38,7 @@ import im.vector.app.features.settings.VectorSettingsActivity import im.vector.app.features.spaces.SpaceListFragment import im.vector.app.features.usercode.UserCodeActivity import im.vector.app.features.workers.signout.SignOutUiWorker +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject @@ -105,14 +106,14 @@ class HomeDrawerFragment : views.homeDrawerInviteFriendButton.debouncedClicks { permalinkFactory.createPermalinkOfCurrentUser()?.let { permalink -> analyticsTracker.screen(MobileScreen(screenName = MobileScreen.ScreenName.InviteFriends)) - val text = getString(R.string.invite_friends_text, permalink) + val text = getString(CommonStrings.invite_friends_text, permalink) startSharePlainTextIntent( context = requireContext(), activityResultLauncher = null, - chooserTitle = getString(R.string.invite_friends), + chooserTitle = getString(CommonStrings.invite_friends), text = text, - extraTitle = getString(R.string.invite_friends_rich_title) + extraTitle = getString(CommonStrings.invite_friends_rich_title) ) } } diff --git a/vector/src/main/java/im/vector/app/features/home/InitSyncStepFormatter.kt b/vector/src/main/java/im/vector/app/features/home/InitSyncStepFormatter.kt index f4626477c7..73f7998483 100644 --- a/vector/src/main/java/im/vector/app/features/home/InitSyncStepFormatter.kt +++ b/vector/src/main/java/im/vector/app/features/home/InitSyncStepFormatter.kt @@ -16,8 +16,8 @@ package im.vector.app.features.home -import im.vector.app.R import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.sync.InitialSyncStep import javax.inject.Inject @@ -27,15 +27,15 @@ class InitSyncStepFormatter @Inject constructor( fun format(initialSyncStep: InitialSyncStep): String { return stringProvider.getString( when (initialSyncStep) { - InitialSyncStep.ServerComputing -> R.string.initial_sync_start_server_computing - InitialSyncStep.Downloading -> R.string.initial_sync_start_downloading - InitialSyncStep.ImportingAccount -> R.string.initial_sync_start_importing_account - InitialSyncStep.ImportingAccountCrypto -> R.string.initial_sync_start_importing_account_crypto - InitialSyncStep.ImportingAccountRoom -> R.string.initial_sync_start_importing_account_rooms - InitialSyncStep.ImportingAccountData -> R.string.initial_sync_start_importing_account_data - InitialSyncStep.ImportingAccountJoinedRooms -> R.string.initial_sync_start_importing_account_joined_rooms - InitialSyncStep.ImportingAccountInvitedRooms -> R.string.initial_sync_start_importing_account_invited_rooms - InitialSyncStep.ImportingAccountLeftRooms -> R.string.initial_sync_start_importing_account_left_rooms + InitialSyncStep.ServerComputing -> CommonStrings.initial_sync_start_server_computing + InitialSyncStep.Downloading -> CommonStrings.initial_sync_start_downloading + InitialSyncStep.ImportingAccount -> CommonStrings.initial_sync_start_importing_account + InitialSyncStep.ImportingAccountCrypto -> CommonStrings.initial_sync_start_importing_account_crypto + InitialSyncStep.ImportingAccountRoom -> CommonStrings.initial_sync_start_importing_account_rooms + InitialSyncStep.ImportingAccountData -> CommonStrings.initial_sync_start_importing_account_data + InitialSyncStep.ImportingAccountJoinedRooms -> CommonStrings.initial_sync_start_importing_account_joined_rooms + InitialSyncStep.ImportingAccountInvitedRooms -> CommonStrings.initial_sync_start_importing_account_invited_rooms + InitialSyncStep.ImportingAccountLeftRooms -> CommonStrings.initial_sync_start_importing_account_left_rooms } ) } diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt index 0bb833e770..07a45c6a9e 100644 --- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt @@ -62,6 +62,7 @@ import im.vector.app.features.spaces.SpaceListBottomSheet import im.vector.app.features.workers.signout.BannerState import im.vector.app.features.workers.signout.ServerBackupStatusAction import im.vector.app.features.workers.signout.ServerBackupStatusViewModel +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo @@ -252,12 +253,12 @@ class NewHomeDetailFragment : alertManager.postVectorAlert( VerificationVectorAlert( uid = uid, - title = getString(R.string.new_session), - description = getString(R.string.verify_this_session, newest.displayName ?: newest.deviceId ?: ""), + title = getString(CommonStrings.new_session), + description = getString(CommonStrings.verify_this_session, newest.displayName ?: newest.deviceId ?: ""), iconId = R.drawable.ic_shield_warning ).apply { viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer) - colorInt = colorProvider.getColorFromAttribute(R.attr.colorPrimary) + colorInt = colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary) contentAction = Runnable { (weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let { vectorBaseActivity -> vectorBaseActivity.navigator @@ -281,8 +282,8 @@ class NewHomeDetailFragment : alertManager.postVectorAlert( VerificationVectorAlert( uid = uid, - title = getString(R.string.review_unverified_sessions_title), - description = getString(R.string.review_unverified_sessions_description), + title = getString(CommonStrings.review_unverified_sessions_title), + description = getString(CommonStrings.review_unverified_sessions_description), iconId = R.drawable.ic_shield_warning, shouldBeDisplayedIn = { activity -> // do not show when there is an ongoing verification flow @@ -293,7 +294,7 @@ class NewHomeDetailFragment : } ).apply { viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer) - colorInt = colorProvider.getColorFromAttribute(R.attr.colorPrimary) + colorInt = colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary) contentAction = Runnable { (weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let { activity -> // mark as ignored to avoid showing it again @@ -313,7 +314,7 @@ class NewHomeDetailFragment : } private fun onSpaceChange(spaceSummary: RoomSummary?) { - views.collapsingToolbar.title = (spaceSummary?.displayName ?: getString(R.string.all_chats)) + views.collapsingToolbar.title = (spaceSummary?.displayName ?: getString(CommonStrings.all_chats)) } private fun setupKeysBackupBanner() { diff --git a/vector/src/main/java/im/vector/app/features/home/NotificationPermissionManager.kt b/vector/src/main/java/im/vector/app/features/home/NotificationPermissionManager.kt index 4f585becca..2e820cf84e 100644 --- a/vector/src/main/java/im/vector/app/features/home/NotificationPermissionManager.kt +++ b/vector/src/main/java/im/vector/app/features/home/NotificationPermissionManager.kt @@ -23,9 +23,9 @@ import android.os.Build import androidx.activity.result.ActivityResultLauncher import androidx.annotation.RequiresApi import androidx.core.content.ContextCompat -import im.vector.app.R import im.vector.app.core.utils.checkPermissions import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.util.BuildVersionSdkIntProvider import javax.inject.Inject @@ -54,7 +54,7 @@ class NotificationPermissionManager @Inject constructor( listOf(Manifest.permission.POST_NOTIFICATIONS), activity, activityResultLauncher = requestPermissionLauncher, - if (showRationale) R.string.permissions_rationale_msg_notification else 0 + if (showRationale) CommonStrings.permissions_rationale_msg_notification else 0 ) } diff --git a/vector/src/main/java/im/vector/app/features/home/RoomListDisplayMode.kt b/vector/src/main/java/im/vector/app/features/home/RoomListDisplayMode.kt index f0c707135f..5f3ae34841 100644 --- a/vector/src/main/java/im/vector/app/features/home/RoomListDisplayMode.kt +++ b/vector/src/main/java/im/vector/app/features/home/RoomListDisplayMode.kt @@ -17,11 +17,11 @@ package im.vector.app.features.home import androidx.annotation.StringRes -import im.vector.app.R +import im.vector.lib.strings.CommonStrings enum class RoomListDisplayMode(@StringRes val titleRes: Int) { - NOTIFICATIONS(R.string.bottom_action_notification), - PEOPLE(R.string.bottom_action_people_x), - ROOMS(R.string.bottom_action_rooms), + NOTIFICATIONS(CommonStrings.bottom_action_notification), + PEOPLE(CommonStrings.bottom_action_people_x), + ROOMS(CommonStrings.bottom_action_rooms), FILTERED(/* Not used */ 0) } diff --git a/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt b/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt index d83c65ad5e..ecf4f27980 100644 --- a/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt +++ b/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt @@ -25,7 +25,6 @@ import androidx.core.content.edit import androidx.core.content.getSystemService import androidx.core.content.pm.ShortcutInfoCompat import androidx.core.content.pm.ShortcutManagerCompat -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.DefaultPreferences import im.vector.app.core.dispatchers.CoroutineDispatchers @@ -34,6 +33,7 @@ import im.vector.app.features.MainActivity import im.vector.app.features.home.room.detail.RoomDetailActivity import im.vector.app.features.pin.PinCodeStore import im.vector.app.features.pin.PinCodeStoreListener +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.flow.flowOn @@ -131,7 +131,7 @@ class ShortcutsHandler @Inject constructor( ShortcutManagerCompat.disableShortcuts( context, deadShortcutIds, - stringProvider.getString(R.string.shortcut_disabled_reason_room_left) + stringProvider.getString(CommonStrings.shortcut_disabled_reason_room_left) ) } } @@ -178,7 +178,7 @@ class ShortcutsHandler @Inject constructor( ShortcutManagerCompat.disableShortcuts( context, shortcutIdsToDisable, - stringProvider.getString(R.string.shortcut_disabled_reason_sign_out) + stringProvider.getString(CommonStrings.shortcut_disabled_reason_sign_out) ) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/JoinReplacementRoomBottomSheet.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/JoinReplacementRoomBottomSheet.kt index ed8135371a..06c63cf33f 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/JoinReplacementRoomBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/JoinReplacementRoomBottomSheet.kt @@ -26,12 +26,12 @@ import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.parentFragmentViewModel import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.platform.ButtonStateView import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.databinding.BottomSheetTombstoneJoinBinding +import im.vector.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint @@ -64,7 +64,7 @@ class JoinReplacementRoomBottomSheet : Uninitialized, is Loading -> { views.roomUpgradeButton.render(ButtonStateView.State.Loading) - views.descriptionText.setText(R.string.it_may_take_some_time) + views.descriptionText.setText(CommonStrings.it_may_take_some_time) } is Success -> { views.roomUpgradeButton.render(ButtonStateView.State.Loaded) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailActivity.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailActivity.kt index 2ed3bf8614..96447e11af 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailActivity.kt @@ -181,11 +181,11 @@ class RoomDetailActivity : .forEach { it.scrollToTop() } } + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() { if (views.drawerLayout.isDrawerOpen(GravityCompat.START)) { views.drawerLayout.closeDrawer(GravityCompat.START) } else { - @Suppress("DEPRECATION") super.onBackPressed() } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomMessageTouchHelperCallback.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomMessageTouchHelperCallback.kt index 9efea7c33d..4da7208345 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomMessageTouchHelperCallback.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomMessageTouchHelperCallback.kt @@ -32,7 +32,6 @@ import androidx.recyclerview.widget.RecyclerView import com.airbnb.epoxy.EpoxyModel import com.airbnb.epoxy.EpoxyTouchHelperCallback import com.airbnb.epoxy.EpoxyViewHolder -import im.vector.app.R import im.vector.app.features.themes.ThemeUtils import im.vector.lib.core.utils.timer.Clock import timber.log.Timber @@ -66,7 +65,7 @@ class RoomMessageTouchHelperCallback( init { DrawableCompat.setTint( imageDrawable, - ThemeUtils.getColor(context, R.attr.vctr_content_primary) + ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_content_primary) ) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/StartCallActionsHandler.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/StartCallActionsHandler.kt index 8d2d086275..87eb63c3d4 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/StartCallActionsHandler.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/StartCallActionsHandler.kt @@ -20,12 +20,12 @@ import androidx.activity.result.ActivityResultLauncher import androidx.fragment.app.Fragment import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder -import im.vector.app.R import im.vector.app.core.utils.PERMISSIONS_FOR_AUDIO_IP_CALL import im.vector.app.core.utils.PERMISSIONS_FOR_VIDEO_IP_CALL import im.vector.app.core.utils.checkPermissions import im.vector.app.features.call.webrtc.WebRtcCallManager import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings class StartCallActionsHandler( private val roomId: String, @@ -58,10 +58,10 @@ class StartCallActionsHandler( val pendingInvite = roomSummary.invitedMembersCount ?: 0 > 0 if (pendingInvite) { // wait for other to join - showDialogWithMessage(fragment.getString(R.string.cannot_call_yourself_with_invite)) + showDialogWithMessage(fragment.getString(CommonStrings.cannot_call_yourself_with_invite)) } else { // You cannot place a call with yourself. - showDialogWithMessage(fragment.getString(R.string.cannot_call_yourself)) + showDialogWithMessage(fragment.getString(CommonStrings.cannot_call_yourself)) } } 2 -> { @@ -72,9 +72,9 @@ class StartCallActionsHandler( showDialogWithMessage( fragment.getString( if (state.isDm()) { - R.string.no_permissions_to_start_webrtc_call_in_direct_room + CommonStrings.no_permissions_to_start_webrtc_call_in_direct_room } else { - R.string.no_permissions_to_start_webrtc_call + CommonStrings.no_permissions_to_start_webrtc_call } ) ) @@ -90,9 +90,9 @@ class StartCallActionsHandler( showDialogWithMessage( fragment.getString( if (state.isDm()) { - R.string.no_permissions_to_start_conf_call_in_direct_room + CommonStrings.no_permissions_to_start_conf_call_in_direct_room } else { - R.string.no_permissions_to_start_conf_call + CommonStrings.no_permissions_to_start_conf_call } ) ) @@ -101,13 +101,13 @@ class StartCallActionsHandler( // A conference is already in progress, return } else { MaterialAlertDialogBuilder(fragment.requireContext()) - .setTitle(if (isVideoCall) R.string.video_meeting else R.string.audio_meeting) - .setMessage(R.string.audio_video_meeting_description) - .setPositiveButton(fragment.getString(R.string.create)) { _, _ -> + .setTitle(if (isVideoCall) CommonStrings.video_meeting else CommonStrings.audio_meeting) + .setMessage(CommonStrings.audio_video_meeting_description) + .setPositiveButton(fragment.getString(CommonStrings.create)) { _, _ -> // create the widget, then navigate to it.. timelineViewModel.handle(RoomDetailAction.AddJitsiWidget(isVideoCall)) } - .setNegativeButton(fragment.getString(R.string.action_cancel), null) + .setNegativeButton(fragment.getString(CommonStrings.action_cancel), null) .show() } } @@ -118,11 +118,11 @@ class StartCallActionsHandler( private fun safeStartCall(isVideoCall: Boolean) { if (vectorPreferences.preventAccidentalCall()) { MaterialAlertDialogBuilder(fragment.requireActivity()) - .setMessage(if (isVideoCall) R.string.start_video_call_prompt_msg else R.string.start_voice_call_prompt_msg) - .setPositiveButton(if (isVideoCall) R.string.start_video_call else R.string.start_voice_call) { _, _ -> + .setMessage(if (isVideoCall) CommonStrings.start_video_call_prompt_msg else CommonStrings.start_voice_call_prompt_msg) + .setPositiveButton(if (isVideoCall) CommonStrings.start_video_call else CommonStrings.start_voice_call) { _, _ -> safeStartCall2(isVideoCall) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } else { safeStartCall2(isVideoCall) @@ -137,7 +137,7 @@ class StartCallActionsHandler( PERMISSIONS_FOR_VIDEO_IP_CALL, fragment.requireActivity(), startCallActivityResultLauncher, - R.string.permissions_rationale_msg_camera_and_audio + CommonStrings.permissions_rationale_msg_camera_and_audio )) { timelineViewModel.pendingAction = null timelineViewModel.handle(startCallAction) @@ -147,7 +147,7 @@ class StartCallActionsHandler( PERMISSIONS_FOR_AUDIO_IP_CALL, fragment.requireActivity(), startCallActivityResultLauncher, - R.string.permissions_rationale_msg_record_audio + CommonStrings.permissions_rationale_msg_record_audio )) { timelineViewModel.pendingAction = null timelineViewModel.handle(startCallAction) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index 43dfbf8bd4..173454b720 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -186,6 +186,7 @@ import im.vector.app.features.widgets.WidgetArgs import im.vector.app.features.widgets.WidgetKind import im.vector.app.features.widgets.permissions.RoomWidgetPermissionBottomSheet import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -596,10 +597,10 @@ class TimelineFragment : return object : FailedMessagesWarningView.Callback { override fun onDeleteAllClicked() { MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.event_status_delete_all_failed_dialog_title) - .setMessage(getString(R.string.event_status_delete_all_failed_dialog_message)) - .setNegativeButton(R.string.no, null) - .setPositiveButton(R.string.yes) { _, _ -> + .setTitle(CommonStrings.event_status_delete_all_failed_dialog_title) + .setMessage(getString(CommonStrings.event_status_delete_all_failed_dialog_message)) + .setNegativeButton(CommonStrings.no, null) + .setPositiveButton(CommonStrings.yes) { _, _ -> timelineViewModel.handle(RoomDetailAction.RemoveAllFailedMessages) } .show() @@ -678,13 +679,13 @@ class TimelineFragment : val v: View = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_no_sticker_pack, null) builder .setView(v) - .setPositiveButton(R.string.yes) { _, _ -> + .setPositiveButton(CommonStrings.yes) { _, _ -> // Open integration manager, to the sticker installation page openIntegrationManager( screen = WidgetType.StickerPicker.preferred ) } - .setNegativeButton(R.string.no, null) + .setNegativeButton(CommonStrings.no, null) .show() } @@ -841,14 +842,14 @@ class TimelineFragment : val actionView = matrixAppsMenuItem.actionView actionView ?.findViewById(R.id.action_view_icon_image) - ?.setColorFilter(ThemeUtils.getColor(requireContext(), R.attr.vctr_content_secondary)) + ?.setColorFilter(ThemeUtils.getColor(requireContext(), im.vector.lib.ui.styles.R.attr.vctr_content_secondary)) actionView?.findViewById(R.id.cart_badge)?.isVisible = false matrixAppsMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER) } else { val actionView = matrixAppsMenuItem.actionView actionView ?.findViewById(R.id.action_view_icon_image) - ?.setColorFilter(colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + ?.setColorFilter(colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) actionView?.findViewById(R.id.cart_badge)?.setTextOrHide("$widgetsCount") @Suppress("AlwaysShowAction") matrixAppsMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) @@ -897,7 +898,7 @@ class TimelineFragment : getRootThreadEventId()?.let { val permalink = permalinkFactory.createPermalink(timelineArgs.roomId, it) copyToClipboard(requireContext(), permalink, false) - showSnackWithMessage(getString(R.string.copied_to_clipboard)) + showSnackWithMessage(getString(CommonStrings.copied_to_clipboard)) } true } @@ -919,6 +920,7 @@ class TimelineFragment : /** * Update menu thread notification badge appropriately. */ + @SuppressLint("SetTextI18n") private fun updateMenuThreadNotificationBadge(menu: Menu, state: RoomDetailViewState) { val menuThreadList = menu.findItem(R.id.menu_timeline_thread_list).actionView val badgeFrameLayout = menuThreadList?.findViewById(R.id.threadNotificationBadgeFrameLayout) ?: return @@ -929,9 +931,12 @@ class TimelineFragment : if (unreadThreadMessages > 0) { badgeFrameLayout.isVisible = true - badgeTextView.text = unreadThreadMessages.toString() + badgeTextView.text = "$unreadThreadMessages" val badgeDrawable = DrawableCompat.wrap(badgeFrameLayout.background) - val color = ContextCompat.getColor(requireContext(), if (userIsMentioned) R.color.palette_vermilion else R.color.palette_gray_200) + val color = ContextCompat.getColor( + requireContext(), + if (userIsMentioned) im.vector.lib.ui.styles.R.color.palette_vermilion else im.vector.lib.ui.styles.R.color.palette_gray_200 + ) DrawableCompat.setTint(badgeDrawable, color) badgeFrameLayout.background = badgeDrawable } else { @@ -964,12 +969,12 @@ class TimelineFragment : private fun displayDisabledIntegrationDialog() { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.disabled_integration_dialog_title) - .setMessage(R.string.disabled_integration_dialog_content) - .setPositiveButton(R.string.settings) { _, _ -> + .setTitle(CommonStrings.disabled_integration_dialog_title) + .setMessage(CommonStrings.disabled_integration_dialog_content) + .setPositiveButton(CommonStrings.settings) { _, _ -> navigator.openSettings(requireActivity(), VectorSettingsActivity.EXTRA_DIRECT_ACCESS_GENERAL) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } @@ -1029,7 +1034,7 @@ class TimelineFragment : } } else { if (deniedPermanently) { - activity?.onPermissionDeniedDialog(R.string.denied_permission_generic) + activity?.onPermissionDeniedDialog(CommonStrings.denied_permission_generic) } cleanUpAfterPermissionNotGranted() } @@ -1206,7 +1211,7 @@ class TimelineFragment : views.roomNotFoundText.text = when (asyncRoomSummary.error) { is RoomNotFound -> { getString( - R.string.timeline_error_room_not_found, + CommonStrings.timeline_error_room_not_found, if (vectorPreferences.developerMode()) { "\nDeveloper info: $timelineArgs" } else { @@ -1233,7 +1238,7 @@ class TimelineFragment : views.includeRoomToolbar.roomToolbarContentView.isVisible = false views.includeThreadToolbar.roomToolbarThreadConstraintLayout.isVisible = false setupToolbar(views.roomToolbar) - .setTitle(R.string.room_member_open_or_create_dm) + .setTitle(CommonStrings.room_member_open_or_create_dm) .allowBack(useCross = true) } isThreadTimeLine() -> { @@ -1245,7 +1250,7 @@ class TimelineFragment : views.includeThreadToolbar.roomToolbarThreadShieldImageView.render(it.roomEncryptionTrustLevel) views.includeThreadToolbar.roomToolbarThreadSubtitleTextView.text = it.displayName } - views.includeThreadToolbar.roomToolbarThreadTitleTextView.text = resources.getText(R.string.thread_timeline_title) + views.includeThreadToolbar.roomToolbarThreadTitleTextView.text = resources.getText(CommonStrings.thread_timeline_title) } else -> { views.includeRoomToolbar.roomToolbarContentView.isVisible = true @@ -1268,15 +1273,15 @@ class TimelineFragment : private fun displayE2eError(withHeldCode: WithHeldCode?) { val msgId = when (withHeldCode) { - WithHeldCode.BLACKLISTED -> R.string.crypto_error_withheld_blacklisted - WithHeldCode.UNVERIFIED -> R.string.crypto_error_withheld_unverified + WithHeldCode.BLACKLISTED -> CommonStrings.crypto_error_withheld_blacklisted + WithHeldCode.UNVERIFIED -> CommonStrings.crypto_error_withheld_unverified WithHeldCode.UNAUTHORISED, - WithHeldCode.UNAVAILABLE -> R.string.crypto_error_withheld_generic - else -> R.string.notice_crypto_unable_to_decrypt_friendly_desc + WithHeldCode.UNAVAILABLE -> CommonStrings.crypto_error_withheld_generic + else -> CommonStrings.notice_crypto_unable_to_decrypt_friendly_desc } MaterialAlertDialogBuilder(requireActivity()) .setMessage(msgId) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } @@ -1286,13 +1291,13 @@ class TimelineFragment : val views = DialogReportContentBinding.bind(layout) MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.report_content_custom_title) + .setTitle(CommonStrings.report_content_custom_title) .setView(layout) - .setPositiveButton(R.string.report_content_custom_submit) { _, _ -> + .setPositiveButton(CommonStrings.report_content_custom_submit) { _, _ -> val reason = views.dialogReportContentInput.text.toString() timelineViewModel.handle(RoomDetailAction.ReportContent(action.eventId, action.senderId, reason)) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } @@ -1302,8 +1307,8 @@ class TimelineFragment : activity = requireActivity(), askForReason = action.askForReason, confirmationRes = action.dialogDescriptionRes, - positiveRes = R.string.action_remove, - reasonHintRes = R.string.delete_event_dialog_reason_hint, + positiveRes = CommonStrings.action_remove, + reasonHintRes = CommonStrings.delete_event_dialog_reason_hint, titleRes = action.dialogTitleRes ) { reason -> timelineViewModel.handle(RoomDetailAction.RedactAction(action.eventId, reason)) @@ -1312,13 +1317,13 @@ class TimelineFragment : private fun displayRoomDetailActionFailure(result: RoomDetailViewEvents.ActionFailure) { @StringRes val titleResId = when (result.action) { - RoomDetailAction.VoiceBroadcastAction.Recording.Start -> R.string.error_voice_broadcast_unauthorized_title - else -> R.string.dialog_title_error + RoomDetailAction.VoiceBroadcastAction.Recording.Start -> CommonStrings.error_voice_broadcast_unauthorized_title + else -> CommonStrings.dialog_title_error } MaterialAlertDialogBuilder(requireActivity()) .setTitle(titleResId) .setMessage(errorFormatter.toHumanReadable(result.throwable)) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } @@ -1327,41 +1332,53 @@ class TimelineFragment : is RoomDetailAction.ReportContent -> { when { data.spam -> { - MaterialAlertDialogBuilder(requireActivity(), R.style.ThemeOverlay_Vector_MaterialAlertDialog_NegativeDestructive) - .setTitle(R.string.content_reported_as_spam_title) - .setMessage(R.string.content_reported_as_spam_content) - .setPositiveButton(R.string.ok, null) - .setNegativeButton(R.string.block_user) { _, _ -> + MaterialAlertDialogBuilder( + requireActivity(), + im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_NegativeDestructive + ) + .setTitle(CommonStrings.content_reported_as_spam_title) + .setMessage(CommonStrings.content_reported_as_spam_content) + .setPositiveButton(CommonStrings.ok, null) + .setNegativeButton(CommonStrings.block_user) { _, _ -> timelineViewModel.handle(RoomDetailAction.IgnoreUser(data.senderId)) } .show() } data.inappropriate -> { - MaterialAlertDialogBuilder(requireActivity(), R.style.ThemeOverlay_Vector_MaterialAlertDialog_NegativeDestructive) - .setTitle(R.string.content_reported_as_inappropriate_title) - .setMessage(R.string.content_reported_as_inappropriate_content) - .setPositiveButton(R.string.ok, null) - .setNegativeButton(R.string.block_user) { _, _ -> + MaterialAlertDialogBuilder( + requireActivity(), + im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_NegativeDestructive + ) + .setTitle(CommonStrings.content_reported_as_inappropriate_title) + .setMessage(CommonStrings.content_reported_as_inappropriate_content) + .setPositiveButton(CommonStrings.ok, null) + .setNegativeButton(CommonStrings.block_user) { _, _ -> timelineViewModel.handle(RoomDetailAction.IgnoreUser(data.senderId)) } .show() } data.user -> { - MaterialAlertDialogBuilder(requireActivity(), R.style.ThemeOverlay_Vector_MaterialAlertDialog_NegativeDestructive) - .setTitle(R.string.user_reported_as_inappropriate_title) - .setMessage(R.string.user_reported_as_inappropriate_content) - .setPositiveButton(R.string.ok, null) - .setNegativeButton(R.string.block_user) { _, _ -> + MaterialAlertDialogBuilder( + requireActivity(), + im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_NegativeDestructive + ) + .setTitle(CommonStrings.user_reported_as_inappropriate_title) + .setMessage(CommonStrings.user_reported_as_inappropriate_content) + .setPositiveButton(CommonStrings.ok, null) + .setNegativeButton(CommonStrings.block_user) { _, _ -> timelineViewModel.handle(RoomDetailAction.IgnoreUser(data.senderId)) } .show() } else -> { - MaterialAlertDialogBuilder(requireActivity(), R.style.ThemeOverlay_Vector_MaterialAlertDialog_NegativeDestructive) - .setTitle(R.string.content_reported_title) - .setMessage(R.string.content_reported_content) - .setPositiveButton(R.string.ok, null) - .setNegativeButton(R.string.block_user) { _, _ -> + MaterialAlertDialogBuilder( + requireActivity(), + im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_NegativeDestructive + ) + .setTitle(CommonStrings.content_reported_title) + .setMessage(CommonStrings.content_reported_content) + .setPositiveButton(CommonStrings.ok, null) + .setNegativeButton(CommonStrings.block_user) { _, _ -> timelineViewModel.handle(RoomDetailAction.IgnoreUser(data.senderId)) } .show() @@ -1409,7 +1426,7 @@ class TimelineFragment : return false } return if (eventId == null) { - showSnackWithMessage(getString(R.string.navigate_to_room_when_already_in_the_room)) + showSnackWithMessage(getString(CommonStrings.navigate_to_room_when_already_in_the_room)) true } else { // Highlight and scroll to this event @@ -1418,7 +1435,7 @@ class TimelineFragment : } } else { return if (rootThreadEventId == getRootThreadEventId() && eventId == null) { - showSnackWithMessage(getString(R.string.navigate_to_thread_when_already_in_the_thread)) + showSnackWithMessage(getString(CommonStrings.navigate_to_thread_when_already_in_the_thread)) true } else if (rootThreadEventId == getRootThreadEventId() && eventId != null) { // we are in the same thread @@ -1458,25 +1475,25 @@ class TimelineFragment : } private fun displayUrlConfirmationDialog(seenUrl: String, actualUrl: String, continueTo: String = actualUrl) { - MaterialAlertDialogBuilder(requireActivity(), R.style.ThemeOverlay_Vector_MaterialAlertDialog_NegativeDestructive) - .setTitle(R.string.external_link_confirmation_title) + MaterialAlertDialogBuilder(requireActivity(), im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_NegativeDestructive) + .setTitle(CommonStrings.external_link_confirmation_title) .setMessage( - getString(R.string.external_link_confirmation_message, seenUrl, actualUrl) + getString(CommonStrings.external_link_confirmation_message, seenUrl, actualUrl) .toSpannable() - .colorizeMatchingText(actualUrl, colorProvider.getColorFromAttribute(R.attr.vctr_content_tertiary)) - .colorizeMatchingText(seenUrl, colorProvider.getColorFromAttribute(R.attr.vctr_content_tertiary)) + .colorizeMatchingText(actualUrl, colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_tertiary)) + .colorizeMatchingText(seenUrl, colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_tertiary)) ) - .setPositiveButton(R.string._continue) { _, _ -> + .setPositiveButton(CommonStrings._continue) { _, _ -> openUrlInExternalBrowser(requireContext(), continueTo) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } override fun onUrlLongClicked(url: String): Boolean { - if (url != getString(R.string.edited_suffix) && url.isValidUrl()) { + if (url != getString(CommonStrings.edited_suffix) && url.isValidUrl()) { // Copy the url to the clipboard - copyToClipboard(requireContext(), url, true, R.string.link_copied_to_clipboard) + copyToClipboard(requireContext(), url, true, CommonStrings.link_copied_to_clipboard) } return true } @@ -1575,10 +1592,10 @@ class TimelineFragment : timelineViewModel.handle(RoomDetailAction.CancelSend(action.event, true)) } else { MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.dialog_title_confirmation) - .setMessage(getString(R.string.event_status_cancel_sending_dialog_message)) - .setNegativeButton(R.string.no, null) - .setPositiveButton(R.string.yes) { _, _ -> + .setTitle(CommonStrings.dialog_title_confirmation) + .setMessage(getString(CommonStrings.event_status_cancel_sending_dialog_message)) + .setNegativeButton(CommonStrings.no, null) + .setPositiveButton(CommonStrings.yes) { _, _ -> timelineViewModel.handle(RoomDetailAction.CancelSend(action.event, false)) } .show() @@ -1717,7 +1734,7 @@ class TimelineFragment : } } else { if (deniedPermanently) { - activity?.onPermissionDeniedDialog(R.string.denied_permission_generic) + activity?.onPermissionDeniedDialog(CommonStrings.denied_permission_generic) } cleanUpAfterPermissionNotGranted() } @@ -1769,7 +1786,7 @@ class TimelineFragment : is EventSharedAction.Copy -> { // I need info about the current selected message :/ copyToClipboard(requireContext(), action.content, false) - showSnackWithMessage(getString(R.string.copied_to_clipboard)) + showSnackWithMessage(getString(CommonStrings.copied_to_clipboard)) } is EventSharedAction.Redact -> { promptConfirmationToRedactEvent(action) @@ -1807,7 +1824,7 @@ class TimelineFragment : } else if (withState(messageComposerViewModel) { it.isVoiceMessageIdle }) { messageComposerViewModel.handle(MessageComposerAction.EnterEditMode(action.eventId)) } else { - requireActivity().toast(R.string.error_voice_message_cannot_reply_or_edit) + requireActivity().toast(CommonStrings.error_voice_message_cannot_reply_or_edit) } } is EventSharedAction.Quote -> { @@ -1817,27 +1834,27 @@ class TimelineFragment : if (withState(messageComposerViewModel) { it.isVoiceMessageIdle }) { messageComposerViewModel.handle(MessageComposerAction.EnterReplyMode(action.eventId)) } else { - requireActivity().toast(R.string.error_voice_message_cannot_reply_or_edit) + requireActivity().toast(CommonStrings.error_voice_message_cannot_reply_or_edit) } } is EventSharedAction.ReplyInThread -> { if (withState(messageComposerViewModel) { it.isVoiceMessageIdle }) { onReplyInThreadClicked(action) } else { - requireActivity().toast(R.string.error_voice_message_cannot_reply_or_edit) + requireActivity().toast(CommonStrings.error_voice_message_cannot_reply_or_edit) } } is EventSharedAction.ViewInRoom -> { if (withState(messageComposerViewModel) { it.isVoiceMessageIdle }) { handleViewInRoomAction() } else { - requireActivity().toast(R.string.error_voice_message_cannot_reply_or_edit) + requireActivity().toast(CommonStrings.error_voice_message_cannot_reply_or_edit) } } is EventSharedAction.CopyPermalink -> { val permalink = permalinkFactory.createPermalink(timelineArgs.roomId, action.eventId) copyToClipboard(requireContext(), permalink, false) - showSnackWithMessage(getString(R.string.copied_to_clipboard)) + showSnackWithMessage(getString(CommonStrings.copied_to_clipboard)) } is EventSharedAction.Resend -> { timelineViewModel.handle(RoomDetailAction.ResendMessage(action.eventId)) @@ -1902,22 +1919,22 @@ class TimelineFragment : } private fun askConfirmationToEndPoll(eventId: String) { - MaterialAlertDialogBuilder(requireContext(), R.style.ThemeOverlay_Vector_MaterialAlertDialog) - .setTitle(R.string.end_poll_confirmation_title) - .setMessage(R.string.end_poll_confirmation_description) - .setNegativeButton(R.string.action_cancel, null) - .setPositiveButton(R.string.end_poll_confirmation_approve_button) { _, _ -> + MaterialAlertDialogBuilder(requireContext(), im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog) + .setTitle(CommonStrings.end_poll_confirmation_title) + .setMessage(CommonStrings.end_poll_confirmation_description) + .setNegativeButton(CommonStrings.action_cancel, null) + .setPositiveButton(CommonStrings.end_poll_confirmation_approve_button) { _, _ -> timelineViewModel.handle(RoomDetailAction.EndPoll(eventId)) } .show() } private fun askConfirmationToIgnoreUser(senderId: String) { - MaterialAlertDialogBuilder(requireContext(), R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) - .setTitle(R.string.room_participants_action_ignore_title) - .setMessage(R.string.room_participants_action_ignore_prompt_msg) - .setNegativeButton(R.string.action_cancel, null) - .setPositiveButton(R.string.room_participants_action_ignore) { _, _ -> + MaterialAlertDialogBuilder(requireContext(), im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) + .setTitle(CommonStrings.room_participants_action_ignore_title) + .setMessage(CommonStrings.room_participants_action_ignore_prompt_msg) + .setNegativeButton(CommonStrings.action_cancel, null) + .setPositiveButton(CommonStrings.room_participants_action_ignore) { _, _ -> timelineViewModel.handle(RoomDetailAction.IgnoreUser(senderId)) } .show() @@ -1930,7 +1947,7 @@ class TimelineFragment : private fun showDialogWithMessage(message: String) { MaterialAlertDialogBuilder(requireContext()) .setMessage(message) - .setPositiveButton(getString(R.string.ok), null) + .setPositiveButton(getString(CommonStrings.ok), null) .show() } @@ -1973,11 +1990,11 @@ class TimelineFragment : private fun displayThreadsBetaOptInDialog() { activity?.let { MaterialAlertDialogBuilder(it) - .setTitle(R.string.threads_beta_enable_notice_title) + .setTitle(CommonStrings.threads_beta_enable_notice_title) .setMessage(threadsManager.getBetaEnableThreadsMessage()) .setCancelable(true) - .setNegativeButton(R.string.action_not_now) { _, _ -> } - .setPositiveButton(R.string.action_try_it_out) { _, _ -> + .setNegativeButton(CommonStrings.action_not_now) { _, _ -> } + .setPositiveButton(CommonStrings.action_try_it_out) { _, _ -> threadsManager.enableThreadsAndRestart(it) } .show() @@ -2043,10 +2060,10 @@ class TimelineFragment : .show( activity = requireActivity(), askForReason = false, - confirmationRes = R.string.stop_voice_broadcast_content, - positiveRes = R.string.action_stop, + confirmationRes = CommonStrings.stop_voice_broadcast_content, + positiveRes = CommonStrings.action_stop, reasonHintRes = 0, - titleRes = R.string.stop_voice_broadcast_dialog_title + titleRes = CommonStrings.stop_voice_broadcast_dialog_title ) { timelineViewModel.handle(RoomDetailAction.VoiceBroadcastAction.Recording.StopConfirmed) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt index 15b5b139de..69db780873 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt @@ -72,6 +72,7 @@ import im.vector.app.features.settings.VectorDataStore import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.voicebroadcast.VoiceBroadcastHelper import im.vector.lib.core.utils.flow.chunk +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.combine @@ -684,7 +685,7 @@ class TimelineViewModel @AssistedInject constructor( val widget = jitsiService.createJitsiWidget(initialState.roomId, action.withVideo) _viewEvents.post(RoomDetailViewEvents.JoinJitsiConference(widget, action.withVideo)) } catch (failure: Throwable) { - _viewEvents.post(RoomDetailViewEvents.ShowMessage(stringProvider.getString(R.string.failed_to_add_widget))) + _viewEvents.post(RoomDetailViewEvents.ShowMessage(stringProvider.getString(CommonStrings.failed_to_add_widget))) } finally { _viewEvents.post(RoomDetailViewEvents.HideWaitingView) } @@ -713,7 +714,7 @@ class TimelineViewModel @AssistedInject constructor( ) } } catch (failure: Throwable) { - _viewEvents.post(RoomDetailViewEvents.ShowMessage(stringProvider.getString(R.string.failed_to_remove_widget))) + _viewEvents.post(RoomDetailViewEvents.ShowMessage(stringProvider.getString(CommonStrings.failed_to_remove_widget))) } finally { if (isJitsiWidget) { setState { copy(jitsiState = jitsiState.copy(deleteWidgetInProgress = false)) } @@ -1244,7 +1245,7 @@ class TimelineViewModel @AssistedInject constructor( // Check if this request is still active and handled by me room.getTimelineEvent(action.eventId)?.let { session.cryptoService().reRequestRoomKeyForEvent(it.root) - _viewEvents.post(RoomDetailViewEvents.ShowMessage(stringProvider.getString(R.string.e2e_re_request_encryption_key_dialog_content))) + _viewEvents.post(RoomDetailViewEvents.ShowMessage(stringProvider.getString(CommonStrings.e2e_re_request_encryption_key_dialog_content))) } } } @@ -1329,7 +1330,7 @@ class TimelineViewModel @AssistedInject constructor( when (creationState) { LocalRoomCreationState.NOT_CREATED -> Unit LocalRoomCreationState.CREATING -> - _viewEvents.post(RoomDetailViewEvents.ShowWaitingView(stringProvider.getString(R.string.creating_direct_room))) + _viewEvents.post(RoomDetailViewEvents.ShowWaitingView(stringProvider.getString(CommonStrings.creating_direct_room))) LocalRoomCreationState.FAILURE -> { _viewEvents.post(RoomDetailViewEvents.HideWaitingView) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt index 53770aada9..007902e6db 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt @@ -94,6 +94,7 @@ import im.vector.app.features.poll.PollMode import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.share.SharedData import im.vector.app.features.voice.VoiceFailure +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filterIsInstance @@ -321,7 +322,7 @@ class MessageComposerFragment : VectorBaseFragment(), A private fun setupComposer() { val composerEditText = composer.editText - composerEditText.setHint(R.string.room_message_placeholder) + composerEditText.setHint(CommonStrings.room_message_placeholder) (composer as? RichTextComposerLayout)?.let { initAutoCompleter(it.richTextEditText) @@ -455,7 +456,7 @@ class MessageComposerFragment : VectorBaseFragment(), A fatalError("Should not happen as we're generating a File based share Intent", vectorPreferences.failFast()) }) if (!isHandled) { - Toast.makeText(requireContext(), R.string.error_handling_incoming_share, Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), CommonStrings.error_handling_incoming_share, Toast.LENGTH_SHORT).show() } return isHandled } @@ -514,16 +515,16 @@ class MessageComposerFragment : VectorBaseFragment(), A private fun createEmojiPopup(): EmojiPopup { return EmojiPopup( rootView = views.root, - keyboardAnimationStyle = R.style.emoji_fade_animation_style, + keyboardAnimationStyle = com.vanniktech.emoji.R.style.emoji_fade_animation_style, onEmojiPopupShownListener = { composer.emojiButton?.apply { - contentDescription = getString(R.string.a11y_close_emoji_picker) + contentDescription = getString(CommonStrings.a11y_close_emoji_picker) setImageResource(R.drawable.ic_keyboard) } }, onEmojiPopupDismissListener = lifecycleAwareDismissAction { composer.emojiButton?.apply { - contentDescription = getString(R.string.a11y_open_emoji_picker) + contentDescription = getString(CommonStrings.a11y_open_emoji_picker) setImageResource(R.drawable.ic_insert_emoji) } }, @@ -556,8 +557,8 @@ class MessageComposerFragment : VectorBaseFragment(), A private fun displayErrorVoiceBroadcastInProgress() { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.error_voice_message_broadcast_in_progress) - .setMessage(getString(R.string.error_voice_message_broadcast_in_progress_message)) + .setTitle(CommonStrings.error_voice_message_broadcast_in_progress) + .setMessage(getString(CommonStrings.error_voice_message_broadcast_in_progress_message)) .setPositiveButton(android.R.string.ok, null) .show() } @@ -578,12 +579,12 @@ class MessageComposerFragment : VectorBaseFragment(), A private fun promptUnignoreUser(command: ParsedCommand.UnignoreUser) { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.room_participants_action_unignore_title) - .setMessage(getString(R.string.settings_unignore_user, command.userId)) - .setPositiveButton(R.string.unignore) { _, _ -> + .setTitle(CommonStrings.room_participants_action_unignore_title) + .setMessage(getString(CommonStrings.settings_unignore_user, command.userId)) + .setPositiveButton(CommonStrings.unignore) { _, _ -> messageComposerViewModel.handle(MessageComposerAction.SlashCommandConfirmed(command)) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } @@ -593,10 +594,10 @@ class MessageComposerFragment : VectorBaseFragment(), A showLoading(null) } is MessageComposerViewEvents.SlashCommandError -> { - displayCommandError(getString(R.string.command_problem_with_parameters, sendMessageResult.command.command)) + displayCommandError(getString(CommonStrings.command_problem_with_parameters, sendMessageResult.command.command)) } is MessageComposerViewEvents.SlashCommandUnknown -> { - displayCommandError(getString(R.string.unrecognized_command, sendMessageResult.command)) + displayCommandError(getString(CommonStrings.unrecognized_command, sendMessageResult.command)) } is MessageComposerViewEvents.SlashCommandResultOk -> { handleSlashCommandResultOk(sendMessageResult.parsedCommand) @@ -606,10 +607,10 @@ class MessageComposerFragment : VectorBaseFragment(), A displayCommandError(errorFormatter.toHumanReadable(sendMessageResult.throwable)) } is MessageComposerViewEvents.SlashCommandNotImplemented -> { - displayCommandError(getString(R.string.not_implemented)) + displayCommandError(getString(CommonStrings.not_implemented)) } is MessageComposerViewEvents.SlashCommandNotSupportedInThreads -> { - displayCommandError(getString(R.string.command_not_supported_in_threads, sendMessageResult.command.command)) + displayCommandError(getString(CommonStrings.command_not_supported_in_threads, sendMessageResult.command.command)) } } @@ -624,7 +625,7 @@ class MessageComposerFragment : VectorBaseFragment(), A navigator.openDevTools(requireContext(), roomId) } is ParsedCommand.SetMarkdown -> { - showSnackWithMessage(getString(if (parsedCommand.enable) R.string.markdown_has_been_enabled else R.string.markdown_has_been_disabled)) + showSnackWithMessage(getString(if (parsedCommand.enable) CommonStrings.markdown_has_been_enabled else CommonStrings.markdown_has_been_disabled)) } else -> Unit } @@ -632,9 +633,9 @@ class MessageComposerFragment : VectorBaseFragment(), A private fun displayCommandError(message: String) { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.command_error) + .setTitle(CommonStrings.command_error) .setMessage(message) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } @@ -694,7 +695,7 @@ class MessageComposerFragment : VectorBaseFragment(), A } } else { if (deniedPermanently) { - activity?.onPermissionDeniedDialog(R.string.denied_permission_generic) + activity?.onPermissionDeniedDialog(CommonStrings.denied_permission_generic) } cleanUpAfterPermissionNotGranted() } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt index 648c88b4d2..1969fcfeae 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt @@ -23,7 +23,6 @@ import com.airbnb.mvrx.withState import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.extensions.getVectorLastMessageContent @@ -52,6 +51,7 @@ import im.vector.app.features.voicebroadcast.model.asVoiceBroadcastEvent import im.vector.app.features.voicebroadcast.usecase.GetVoiceBroadcastStateEventLiveUseCase import im.vector.app.features.voicebroadcast.voiceBroadcastId import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flatMapLatest @@ -409,7 +409,7 @@ class MessageComposerViewModel @AssistedInject constructor( popDraft(room) } is ParsedCommand.SendSpoiler -> { - val text = "[${stringProvider.getString(R.string.spoiler)}](${parsedCommand.message})" + val text = "[${stringProvider.getString(CommonStrings.spoiler)}](${parsedCommand.message})" val formattedText = "${parsedCommand.message}" if (state.rootThreadEventId != null) { room.relationService().replyInThread( @@ -475,7 +475,7 @@ class MessageComposerViewModel @AssistedInject constructor( _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand)) _viewEvents.post( MessageComposerViewEvents - .ShowMessage(stringProvider.getString(R.string.command_description_discard_session_not_handled)) + .ShowMessage(stringProvider.getString(CommonStrings.command_description_discard_session_not_handled)) ) } } @@ -706,8 +706,8 @@ class MessageComposerViewModel @AssistedInject constructor( if (sendChatEffect.message.isBlank()) { val defaultMessage = stringProvider.getString( when (sendChatEffect.chatEffect) { - ChatEffect.CONFETTI -> R.string.default_message_emote_confetti - ChatEffect.SNOWFALL -> R.string.default_message_emote_snow + ChatEffect.CONFETTI -> CommonStrings.default_message_emote_confetti + ChatEffect.SNOWFALL -> CommonStrings.default_message_emote_snow } ) room.sendService().sendTextMessage(defaultMessage, MessageType.MSGTYPE_EMOTE) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/PlainTextComposerLayout.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/PlainTextComposerLayout.kt index 4570ec6056..bf7376b3da 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/PlainTextComposerLayout.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/PlainTextComposerLayout.kt @@ -40,6 +40,7 @@ import im.vector.app.features.home.room.detail.timeline.image.buildImageContentR import im.vector.app.features.html.EventHtmlRenderer import im.vector.app.features.html.PillsPostProcessor import im.vector.app.features.media.ImageContentRenderer +import im.vector.lib.strings.CommonStrings import org.commonmark.parser.Parser import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent @@ -151,10 +152,10 @@ class PlainTextComposerLayout @JvmOverloads constructor( views.sendButton.apply { if (mode is MessageComposerMode.Edit) { - contentDescription = resources.getString(R.string.action_save) + contentDescription = resources.getString(CommonStrings.action_save) setImageResource(R.drawable.ic_composer_rich_text_save) } else { - contentDescription = resources.getString(R.string.action_send) + contentDescription = resources.getString(CommonStrings.action_send) setImageResource(R.drawable.ic_rich_composer_send) } } @@ -182,8 +183,8 @@ class PlainTextComposerLayout @JvmOverloads constructor( val nonFormattedBody = when (messageContent) { is MessageAudioContent -> getAudioContentBodyText(messageContent) is MessagePollContent -> messageContent.getBestPollCreationInfo()?.question?.getBestQuestion() - is MessageBeaconInfoContent -> resources.getString(R.string.live_location_description) - is MessageEndPollContent -> resources.getString(R.string.message_reply_to_ended_poll_preview) + is MessageBeaconInfoContent -> resources.getString(CommonStrings.live_location_description) + is MessageEndPollContent -> resources.getString(CommonStrings.message_reply_to_ended_poll_preview) else -> messageContent?.body.orEmpty() } var formattedBody: CharSequence? = null @@ -235,9 +236,9 @@ class PlainTextComposerLayout @JvmOverloads constructor( private fun getAudioContentBodyText(messageContent: MessageAudioContent): String { val formattedDuration = DateUtils.formatElapsedTime(((messageContent.audioInfo?.duration ?: 0) / 1000).toLong()) return if (messageContent.voiceMessageIndicator != null) { - resources.getString(R.string.voice_message_reply_content, formattedDuration) + resources.getString(CommonStrings.voice_message_reply_content, formattedDuration) } else { - resources.getString(R.string.audio_message_reply_content, messageContent.body, formattedDuration) + resources.getString(CommonStrings.audio_message_reply_content, messageContent.body, formattedDuration) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt index a0d28be365..31b95800ce 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt @@ -52,6 +52,7 @@ import im.vector.app.databinding.ComposerRichTextLayoutBinding import im.vector.app.databinding.ViewRichTextMenuButtonBinding import im.vector.app.features.home.room.detail.composer.images.UriContentListener import im.vector.app.features.home.room.detail.composer.mentions.PillDisplayHandler +import im.vector.lib.strings.CommonStrings import io.element.android.wysiwyg.EditorEditText import io.element.android.wysiwyg.display.MentionDisplayHandler import io.element.android.wysiwyg.display.TextDisplay @@ -118,12 +119,13 @@ internal class RichTextComposerLayout @JvmOverloads constructor( private val borderShapeDrawable: MaterialShapeDrawable by lazy { MaterialShapeDrawable().apply { val typedData = TypedValue() - val lineColor = context.theme.obtainStyledAttributes(typedData.data, intArrayOf(R.attr.vctr_content_quaternary)) + val lineColor = context.theme.obtainStyledAttributes(typedData.data, intArrayOf(im.vector.lib.ui.styles.R.attr.vctr_content_quaternary)) .getColor(0, 0) strokeColor = ColorStateList.valueOf(lineColor) + @Suppress("DEPRECATION") strokeWidth = 1 * resources.displayMetrics.scaledDensity fillColor = ColorStateList.valueOf(Color.TRANSPARENT) - val cornerSize = resources.getDimensionPixelSize(R.dimen.rich_text_composer_corner_radius_single_line) + val cornerSize = resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.rich_text_composer_corner_radius_single_line) setCornerSize(cornerSize.toFloat()) } } @@ -162,10 +164,10 @@ internal class RichTextComposerLayout @JvmOverloads constructor( // Calculate a new shape for the border according to the position in screen val isSingleLine = editText.lineCount == 1 val cornerSize = if (!isSingleLine || hasRelatedMessage) { - resources.getDimensionPixelSize(R.dimen.rich_text_composer_corner_radius_expanded).toFloat() + resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.rich_text_composer_corner_radius_expanded).toFloat() } else { - val multilineCornerSize = resources.getDimensionPixelSize(R.dimen.rich_text_composer_corner_radius_expanded) - val singleLineCornerSize = resources.getDimensionPixelSize(R.dimen.rich_text_composer_corner_radius_single_line) + val multilineCornerSize = resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.rich_text_composer_corner_radius_expanded) + val singleLineCornerSize = resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.rich_text_composer_corner_radius_single_line) val diff = singleLineCornerSize - multilineCornerSize multilineCornerSize + diff * (1 - percentage) } @@ -259,40 +261,40 @@ internal class RichTextComposerLayout @JvmOverloads constructor( } private fun setupRichTextMenu() { - addRichTextMenuItem(R.drawable.ic_composer_bold, R.string.rich_text_editor_format_bold, ComposerAction.BOLD) { + addRichTextMenuItem(R.drawable.ic_composer_bold, CommonStrings.rich_text_editor_format_bold, ComposerAction.BOLD) { views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Bold) } - addRichTextMenuItem(R.drawable.ic_composer_italic, R.string.rich_text_editor_format_italic, ComposerAction.ITALIC) { + addRichTextMenuItem(R.drawable.ic_composer_italic, CommonStrings.rich_text_editor_format_italic, ComposerAction.ITALIC) { views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Italic) } - addRichTextMenuItem(R.drawable.ic_composer_underlined, R.string.rich_text_editor_format_underline, ComposerAction.UNDERLINE) { + addRichTextMenuItem(R.drawable.ic_composer_underlined, CommonStrings.rich_text_editor_format_underline, ComposerAction.UNDERLINE) { views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Underline) } - addRichTextMenuItem(R.drawable.ic_composer_strikethrough, R.string.rich_text_editor_format_strikethrough, ComposerAction.STRIKE_THROUGH) { + addRichTextMenuItem(R.drawable.ic_composer_strikethrough, CommonStrings.rich_text_editor_format_strikethrough, ComposerAction.STRIKE_THROUGH) { views.richTextComposerEditText.toggleInlineFormat(InlineFormat.StrikeThrough) } - addRichTextMenuItem(R.drawable.ic_composer_bullet_list, R.string.rich_text_editor_bullet_list, ComposerAction.UNORDERED_LIST) { + addRichTextMenuItem(R.drawable.ic_composer_bullet_list, CommonStrings.rich_text_editor_bullet_list, ComposerAction.UNORDERED_LIST) { views.richTextComposerEditText.toggleList(ordered = false) } - addRichTextMenuItem(R.drawable.ic_composer_numbered_list, R.string.rich_text_editor_numbered_list, ComposerAction.ORDERED_LIST) { + addRichTextMenuItem(R.drawable.ic_composer_numbered_list, CommonStrings.rich_text_editor_numbered_list, ComposerAction.ORDERED_LIST) { views.richTextComposerEditText.toggleList(ordered = true) } - addRichTextMenuItem(R.drawable.ic_composer_indent, R.string.rich_text_editor_indent, ComposerAction.INDENT) { + addRichTextMenuItem(R.drawable.ic_composer_indent, CommonStrings.rich_text_editor_indent, ComposerAction.INDENT) { views.richTextComposerEditText.indent() } - addRichTextMenuItem(R.drawable.ic_composer_unindent, R.string.rich_text_editor_unindent, ComposerAction.UNINDENT) { + addRichTextMenuItem(R.drawable.ic_composer_unindent, CommonStrings.rich_text_editor_unindent, ComposerAction.UNINDENT) { views.richTextComposerEditText.unindent() } - addRichTextMenuItem(R.drawable.ic_composer_quote, R.string.rich_text_editor_quote, ComposerAction.QUOTE) { + addRichTextMenuItem(R.drawable.ic_composer_quote, CommonStrings.rich_text_editor_quote, ComposerAction.QUOTE) { views.richTextComposerEditText.toggleQuote() } - addRichTextMenuItem(R.drawable.ic_composer_inline_code, R.string.rich_text_editor_inline_code, ComposerAction.INLINE_CODE) { + addRichTextMenuItem(R.drawable.ic_composer_inline_code, CommonStrings.rich_text_editor_inline_code, ComposerAction.INLINE_CODE) { views.richTextComposerEditText.toggleInlineFormat(InlineFormat.InlineCode) } - addRichTextMenuItem(R.drawable.ic_composer_code_block, R.string.rich_text_editor_code_block, ComposerAction.CODE_BLOCK) { + addRichTextMenuItem(R.drawable.ic_composer_code_block, CommonStrings.rich_text_editor_code_block, ComposerAction.CODE_BLOCK) { views.richTextComposerEditText.toggleCodeBlock() } - addRichTextMenuItem(R.drawable.ic_composer_link, R.string.rich_text_editor_link, ComposerAction.LINK) { + addRichTextMenuItem(R.drawable.ic_composer_link, CommonStrings.rich_text_editor_link, ComposerAction.LINK) { views.richTextComposerEditText.getLinkAction()?.let { when (it) { LinkAction.InsertLink -> callback?.onSetLink(isTextSupported = true, initialLink = null) @@ -438,9 +440,9 @@ internal class RichTextComposerLayout @JvmOverloads constructor( private fun updateTextFieldBorder(isFullScreen: Boolean) { val isMultiline = editText.editableText.lines().count() > 1 || isFullScreen || hasRelatedMessage val cornerSize = if (isMultiline) { - resources.getDimensionPixelSize(R.dimen.rich_text_composer_corner_radius_expanded) + resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.rich_text_composer_corner_radius_expanded) } else { - resources.getDimensionPixelSize(R.dimen.rich_text_composer_corner_radius_single_line) + resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.rich_text_composer_corner_radius_single_line) }.toFloat() borderShapeDrawable.setCornerSize(cornerSize) } @@ -493,27 +495,27 @@ internal class RichTextComposerLayout @JvmOverloads constructor( views.sendButton.apply { if (mode is MessageComposerMode.Edit) { - contentDescription = resources.getString(R.string.action_save) + contentDescription = resources.getString(CommonStrings.action_save) setImageResource(R.drawable.ic_composer_rich_text_save) } else { - contentDescription = resources.getString(R.string.action_send) + contentDescription = resources.getString(CommonStrings.action_send) setImageResource(R.drawable.ic_rich_composer_send) } } when (mode) { is MessageComposerMode.Edit -> { - views.composerModeTitleView.setText(R.string.editing) + views.composerModeTitleView.setText(CommonStrings.editing) views.composerModeIconView.setImageResource(R.drawable.ic_composer_rich_text_editor_edit) } is MessageComposerMode.Quote -> { - views.composerModeTitleView.setText(R.string.quoting) + views.composerModeTitleView.setText(CommonStrings.quoting) views.composerModeIconView.setImageResource(R.drawable.ic_quote) } is MessageComposerMode.Reply -> { val senderInfo = mode.event.senderInfo val userName = senderInfo.displayName ?: senderInfo.disambiguatedDisplayName - views.composerModeTitleView.text = resources.getString(R.string.replying_to, userName) + views.composerModeTitleView.text = resources.getString(CommonStrings.replying_to, userName) views.composerModeIconView.setImageResource(R.drawable.ic_reply) } else -> Unit diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/link/SetLinkFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/link/SetLinkFragment.kt index 008a8017ee..465d758abf 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/link/SetLinkFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/link/SetLinkFragment.kt @@ -29,9 +29,9 @@ import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.VectorBaseDialogFragment import im.vector.app.databinding.FragmentSetLinkBinding +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.parcelize.Parcelize @@ -101,9 +101,9 @@ class SetLinkFragment : override fun invalidate() = withState(viewModel) { viewState -> views.toolbar.title = getString( if (viewState.initialLink != null) { - R.string.set_link_edit + CommonStrings.set_link_edit } else { - R.string.set_link_create + CommonStrings.set_link_create } ) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/DraggableStateProcessor.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/DraggableStateProcessor.kt index 1ff937add5..354585dba5 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/DraggableStateProcessor.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/DraggableStateProcessor.kt @@ -18,7 +18,6 @@ package im.vector.app.features.home.room.detail.composer.voice import android.content.res.Resources import android.view.MotionEvent -import im.vector.app.R import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.home.room.detail.composer.voice.VoiceMessageRecorderView.DraggingState import kotlin.math.absoluteValue @@ -30,7 +29,7 @@ class DraggableStateProcessor( private val distanceToLock = dimensionConverter.dpToPx(48).toFloat() private val distanceToCancel = dimensionConverter.dpToPx(120).toFloat() - private val rtlXMultiplier = resources.getInteger(R.integer.rtl_x_multiplier) + private val rtlXMultiplier = resources.getInteger(im.vector.lib.ui.styles.R.integer.rtl_x_multiplier) private var firstX: Float = 0f private var firstY: Float = 0f diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageRecorderView.kt index 76656457b9..78b4c2cd19 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageRecorderView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageRecorderView.kt @@ -28,6 +28,7 @@ import im.vector.app.databinding.ViewVoiceMessageRecorderBinding import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker import im.vector.lib.core.utils.timer.Clock import im.vector.lib.core.utils.timer.CountUpTimer +import im.vector.lib.strings.CommonStrings import javax.inject.Inject import kotlin.math.floor @@ -138,7 +139,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor( } is RecordingUiState.Recording -> { startRecordingTicker(startFromLocked = false, startAt = recordingState.recordingStartTimestamp) - voiceMessageViews.renderToast(context.getString(R.string.voice_message_release_to_send_toast)) + voiceMessageViews.renderToast(context.getString(CommonStrings.voice_message_release_to_send_toast)) voiceMessageViews.showRecordingViews() dragState = DraggingState.Ready } @@ -208,7 +209,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor( } else if (timeDiffToRecordingLimit in 10_000..10_999) { post { val secondsRemaining = floor(timeDiffToRecordingLimit / 1000f).toInt() - voiceMessageViews.renderToast(context.getString(R.string.voice_message_n_seconds_warning_toast, secondsRemaining)) + voiceMessageViews.renderToast(context.getString(CommonStrings.voice_message_n_seconds_warning_toast, secondsRemaining)) vibrate(context) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageViews.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageViews.kt index ca31c53bb3..066b3f9f2b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageViews.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageViews.kt @@ -38,6 +38,7 @@ import im.vector.app.features.home.room.detail.composer.voice.VoiceMessageRecord import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.voice.AudioWaveformView +import im.vector.lib.strings.CommonStrings class VoiceMessageViews( private val resources: Resources, @@ -47,7 +48,7 @@ class VoiceMessageViews( private val distanceToLock = dimensionConverter.dpToPx(48).toFloat() private val distanceToCancel = dimensionConverter.dpToPx(120).toFloat() - private val rtlXMultiplier = resources.getInteger(R.integer.rtl_x_multiplier) + private val rtlXMultiplier = resources.getInteger(im.vector.lib.ui.styles.R.integer.rtl_x_multiplier) fun start(actions: Actions) { views.voiceMessageSendButton.setOnClickListener { @@ -119,7 +120,7 @@ class VoiceMessageViews( } fun renderLocking(distanceY: Float) { - views.voiceMessageLockImage.setAttributeTintedImageResource(R.drawable.ic_voice_message_locked, R.attr.colorPrimary) + views.voiceMessageLockImage.setAttributeTintedImageResource(R.drawable.ic_voice_message_locked, com.google.android.material.R.attr.colorPrimary) val translationAmount = -distanceY.coerceIn(0F, distanceToLock) views.voiceMessageMicButton.translationY = translationAmount views.voiceMessageLockArrow.translationY = translationAmount @@ -149,7 +150,7 @@ class VoiceMessageViews( fun showRecordingViews() { views.voiceMessageBackgroundView.isVisible = true views.voiceMessageMicButton.setImageResource(R.drawable.ic_composer_rich_mic_pressed) - views.voiceMessageMicButton.setAttributeTintedBackground(R.drawable.circle_with_halo, R.attr.colorPrimary) + views.voiceMessageMicButton.setAttributeTintedBackground(R.drawable.circle_with_halo, com.google.android.material.R.attr.colorPrimary) views.voiceMessageMicButton.updateLayoutParams { setMargins(0, 0, 0, 0) } @@ -297,7 +298,7 @@ class VoiceMessageViews( views.voicePlaybackControlButton.isVisible = false views.voiceMessageSendButton.isVisible = true views.voicePlaybackWaveform.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES - renderToast(resources.getString(R.string.voice_message_tap_to_stop_toast)) + renderToast(resources.getString(CommonStrings.voice_message_tap_to_stop_toast)) } fun initViews() { @@ -309,17 +310,17 @@ class VoiceMessageViews( fun renderPlaying(state: AudioMessagePlaybackTracker.Listener.State.Playing) { views.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_pause) - views.voicePlaybackControlButton.contentDescription = resources.getString(R.string.a11y_pause_voice_message) + views.voicePlaybackControlButton.contentDescription = resources.getString(CommonStrings.a11y_pause_voice_message) val formattedTimerText = DateUtils.formatElapsedTime((state.playbackTime / 1000).toLong()) views.voicePlaybackTime.text = formattedTimerText - val waveformColorIdle = ThemeUtils.getColor(views.voicePlaybackWaveform.context, R.attr.vctr_content_quaternary) - val waveformColorPlayed = ThemeUtils.getColor(views.voicePlaybackWaveform.context, R.attr.vctr_content_secondary) + val waveformColorIdle = ThemeUtils.getColor(views.voicePlaybackWaveform.context, im.vector.lib.ui.styles.R.attr.vctr_content_quaternary) + val waveformColorPlayed = ThemeUtils.getColor(views.voicePlaybackWaveform.context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary) views.voicePlaybackWaveform.updateColors(state.percentage, waveformColorPlayed, waveformColorIdle) } fun renderIdle() { views.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play) - views.voicePlaybackControlButton.contentDescription = resources.getString(R.string.a11y_play_voice_message) + views.voicePlaybackControlButton.contentDescription = resources.getString(CommonStrings.a11y_play_voice_message) views.voicePlaybackWaveform.summarize() } @@ -351,7 +352,7 @@ class VoiceMessageViews( fun renderRecordingWaveform(amplitudeList: List) { views.voicePlaybackWaveform.doOnLayout { waveFormView -> - val waveformColor = ThemeUtils.getColor(waveFormView.context, R.attr.vctr_content_quaternary) + val waveformColor = ThemeUtils.getColor(waveFormView.context, im.vector.lib.ui.styles.R.attr.vctr_content_quaternary) amplitudeList.forEach { (waveFormView as AudioWaveformView).add(AudioWaveformView.FFT(it.toFloat(), waveformColor)) } @@ -360,7 +361,7 @@ class VoiceMessageViews( fun renderVisibilityChanged(parentChanged: Boolean, visibility: Int) { if (parentChanged && visibility == ConstraintLayout.VISIBLE) { - views.voiceMessageMicButton.contentDescription = resources.getString(R.string.a11y_start_voice_message) + views.voiceMessageMicButton.contentDescription = resources.getString(CommonStrings.a11y_start_voice_message) } else { views.voiceMessageMicButton.contentDescription = "" } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceRecorderFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceRecorderFragment.kt index e5f93368b1..29c960a71d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceRecorderFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceRecorderFragment.kt @@ -24,7 +24,6 @@ import androidx.core.view.isVisible import com.airbnb.mvrx.parentFragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.hardware.vibrate import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.PERMISSIONS_FOR_VOICE_MESSAGE @@ -41,6 +40,7 @@ import im.vector.app.features.home.room.detail.composer.SendMode import im.vector.app.features.home.room.detail.composer.boolean import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint @@ -56,7 +56,7 @@ class VoiceRecorderFragment : VectorBaseFragment() if (allGranted) { // In this case, let the user start again the gesture } else if (deniedPermanently) { - vectorBaseActivity.onPermissionDeniedSnackbar(R.string.denied_permission_voice_message) + vectorBaseActivity.onPermissionDeniedSnackbar(CommonStrings.denied_permission_voice_message) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt index 713ca80089..5878e283b5 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt @@ -40,6 +40,7 @@ import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentSearchBinding import im.vector.app.features.analytics.plan.ViewRoom import im.vector.app.features.home.room.threads.arguments.ThreadTimelineArgs +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.getRootThreadEventId @@ -99,7 +100,7 @@ class SearchFragment : } is Success -> { views.stateView.state = StateView.State.Empty( - title = getString(R.string.search_no_results), + title = getString(CommonStrings.search_no_results), image = ContextCompat.getDrawable(requireContext(), R.drawable.ic_search_no_results) ) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt index 71c0427c97..075963aeab 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt @@ -23,7 +23,6 @@ import android.text.style.StyleSpan import com.airbnb.epoxy.EpoxyModel import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.epoxy.VisibilityState -import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter import im.vector.app.core.epoxy.loadingItem @@ -35,6 +34,7 @@ import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.format.DisplayableEventFormatter import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event @@ -83,12 +83,12 @@ class SearchResultController @Inject constructor( // All returned results by the server has been filtered out and there is no more result noResultItem { id("noResult") - text(host.stringProvider.getString(R.string.no_result_placeholder)) + text(host.stringProvider.getString(CommonStrings.no_result_placeholder)) } } else { noResultItem { id("noMoreResult") - text(host.stringProvider.getString(R.string.no_more_results)) + text(host.stringProvider.getString(CommonStrings.no_more_results)) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt index 60cbf1311a..91eda36dc0 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt @@ -16,6 +16,7 @@ package im.vector.app.features.home.room.detail.search +import android.annotation.SuppressLint import android.widget.ImageView import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout @@ -48,6 +49,7 @@ abstract class SearchResultItem : VectorEpoxyModel(R.la @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var threadSummaryListener: ClickListener? = null + @SuppressLint("SetTextI18n") override fun bind(holder: Holder) { super.bind(holder) @@ -61,7 +63,7 @@ abstract class SearchResultItem : VectorEpoxyModel(R.la threadDetails?.let { if (it.isRootThread) { showThreadSummary(holder) - holder.threadSummaryCounterTextView.text = it.numberOfThreads.toString() + holder.threadSummaryCounterTextView.text = "${it.numberOfThreads}" holder.threadSummaryInfoTextView.text = threadSummaryFormatted.orEmpty() val userId = it.threadSummarySenderInfo?.userId ?: return@let val displayName = it.threadSummarySenderInfo?.displayName diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/MessageColorProvider.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/MessageColorProvider.kt index 8b03185293..f9e056f146 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/MessageColorProvider.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/MessageColorProvider.kt @@ -17,7 +17,6 @@ package im.vector.app.features.home.room.detail.timeline import androidx.annotation.ColorInt -import im.vector.app.R import im.vector.app.core.resources.ColorProvider import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider import im.vector.app.features.settings.VectorPreferences @@ -42,17 +41,17 @@ class MessageColorProvider @Inject constructor( when (sendState) { // SendStates, in the classical order they will occur SendState.UNKNOWN, - SendState.UNSENT -> colorProvider.getColorFromAttribute(R.attr.vctr_sending_message_text_color) - SendState.ENCRYPTING -> colorProvider.getColorFromAttribute(R.attr.vctr_encrypting_message_text_color) - SendState.SENDING -> colorProvider.getColorFromAttribute(R.attr.vctr_sending_message_text_color) + SendState.UNSENT -> colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_sending_message_text_color) + SendState.ENCRYPTING -> colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_encrypting_message_text_color) + SendState.SENDING -> colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_sending_message_text_color) SendState.SENT, - SendState.SYNCED -> colorProvider.getColorFromAttribute(R.attr.vctr_message_text_color) + SendState.SYNCED -> colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_message_text_color) SendState.UNDELIVERED, - SendState.FAILED_UNKNOWN_DEVICES -> colorProvider.getColorFromAttribute(R.attr.vctr_unsent_message_text_color) + SendState.FAILED_UNKNOWN_DEVICES -> colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_unsent_message_text_color) } } else { // When not in developer mode, we use only one color - colorProvider.getColorFromAttribute(R.attr.vctr_message_text_color) + colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_message_text_color) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/EventSharedAction.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/EventSharedAction.kt index 7b9bdd6bc4..0645ffc591 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/EventSharedAction.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/EventSharedAction.kt @@ -21,6 +21,7 @@ import androidx.annotation.StringRes import im.vector.app.R import im.vector.app.core.platform.VectorSharedAction import im.vector.app.features.home.room.detail.timeline.item.MessageInformationData +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent @@ -37,79 +38,79 @@ sealed class EventSharedAction( EventSharedAction(0, 0) data class AddReaction(val eventId: String) : - EventSharedAction(R.string.message_add_reaction, R.drawable.ic_add_reaction) + EventSharedAction(CommonStrings.message_add_reaction, R.drawable.ic_add_reaction) data class Copy(val content: String) : - EventSharedAction(R.string.action_copy, R.drawable.ic_copy) + EventSharedAction(CommonStrings.action_copy, R.drawable.ic_copy) data class Edit(val eventId: String, val eventType: String) : - EventSharedAction(R.string.edit, R.drawable.ic_edit) + EventSharedAction(CommonStrings.edit, R.drawable.ic_edit) data class Quote(val eventId: String) : - EventSharedAction(R.string.action_quote, R.drawable.ic_quote) + EventSharedAction(CommonStrings.action_quote, R.drawable.ic_quote) data class Reply(val eventId: String) : - EventSharedAction(R.string.reply, R.drawable.ic_reply) + EventSharedAction(CommonStrings.reply, R.drawable.ic_reply) data class ReplyInThread(val eventId: String, val startsThread: Boolean) : - EventSharedAction(R.string.reply_in_thread, R.drawable.ic_reply_in_thread) + EventSharedAction(CommonStrings.reply_in_thread, R.drawable.ic_reply_in_thread) object ViewInRoom : - EventSharedAction(R.string.view_in_room, R.drawable.ic_threads_view_in_room_24) + EventSharedAction(CommonStrings.view_in_room, R.drawable.ic_threads_view_in_room_24) data class Share(val eventId: String, val messageContent: MessageContent) : - EventSharedAction(R.string.action_share, R.drawable.ic_share) + EventSharedAction(CommonStrings.action_share, R.drawable.ic_share) data class Save(val eventId: String, val messageContent: MessageWithAttachmentContent) : - EventSharedAction(R.string.action_save, R.drawable.ic_material_save) + EventSharedAction(CommonStrings.action_save, R.drawable.ic_material_save) data class Resend(val eventId: String) : - EventSharedAction(R.string.global_retry, R.drawable.ic_refresh_cw) + EventSharedAction(CommonStrings.global_retry, R.drawable.ic_refresh_cw) data class Remove(val eventId: String) : - EventSharedAction(R.string.action_remove, R.drawable.ic_trash, true) + EventSharedAction(CommonStrings.action_remove, R.drawable.ic_trash, true) data class Redact(val eventId: String, val askForReason: Boolean, val dialogTitleRes: Int, val dialogDescriptionRes: Int) : - EventSharedAction(R.string.message_action_item_redact, R.drawable.ic_delete, true) + EventSharedAction(CommonStrings.message_action_item_redact, R.drawable.ic_delete, true) data class Cancel(val event: TimelineEvent, val force: Boolean) : - EventSharedAction(R.string.action_cancel, R.drawable.ic_close_round) + EventSharedAction(CommonStrings.action_cancel, R.drawable.ic_close_round) data class ViewSource(val content: String) : - EventSharedAction(R.string.view_source, R.drawable.ic_view_source) + EventSharedAction(CommonStrings.view_source, R.drawable.ic_view_source) data class ViewDecryptedSource(val content: String) : - EventSharedAction(R.string.view_decrypted_source, R.drawable.ic_view_source) + EventSharedAction(CommonStrings.view_decrypted_source, R.drawable.ic_view_source) data class CopyPermalink(val eventId: String) : - EventSharedAction(R.string.permalink, R.drawable.ic_permalink) + EventSharedAction(CommonStrings.permalink, R.drawable.ic_permalink) data class ReportContent(val eventId: String, val senderId: String?) : - EventSharedAction(R.string.report_content, R.drawable.ic_flag) + EventSharedAction(CommonStrings.report_content, R.drawable.ic_flag) data class ReportContentSpam(val eventId: String, val senderId: String?) : - EventSharedAction(R.string.report_content_spam, R.drawable.ic_report_spam) + EventSharedAction(CommonStrings.report_content_spam, R.drawable.ic_report_spam) data class ReportContentInappropriate(val eventId: String, val senderId: String?) : - EventSharedAction(R.string.report_content_inappropriate, R.drawable.ic_report_inappropriate) + EventSharedAction(CommonStrings.report_content_inappropriate, R.drawable.ic_report_inappropriate) data class ReportContentCustom(val eventId: String, val senderId: String?) : - EventSharedAction(R.string.report_content_custom, R.drawable.ic_report_custom) + EventSharedAction(CommonStrings.report_content_custom, R.drawable.ic_report_custom) data class IgnoreUser(val senderId: String?) : - EventSharedAction(R.string.message_ignore_user, R.drawable.ic_alert_triangle, true) + EventSharedAction(CommonStrings.message_ignore_user, R.drawable.ic_alert_triangle, true) data class ReportUser(val eventId: String, val senderId: String?) : - EventSharedAction(R.string.message_report_user, R.drawable.ic_flag, true) + EventSharedAction(CommonStrings.message_report_user, R.drawable.ic_flag, true) data class QuickReact(val eventId: String, val clickedOn: String, val add: Boolean) : EventSharedAction(0, 0) data class ViewReactions(val messageInformationData: MessageInformationData) : - EventSharedAction(R.string.message_view_reaction, R.drawable.ic_view_reactions) + EventSharedAction(CommonStrings.message_view_reaction, R.drawable.ic_view_reactions) data class ViewEditHistory(val messageInformationData: MessageInformationData) : - EventSharedAction(R.string.message_view_edit_history, R.drawable.ic_view_edit_history) + EventSharedAction(CommonStrings.message_view_edit_history, R.drawable.ic_view_edit_history) // An url in the event preview has been clicked data class OnUrlClicked(val url: String, val title: String) : @@ -120,11 +121,11 @@ sealed class EventSharedAction( EventSharedAction(0, 0) data class ReRequestKey(val eventId: String) : - EventSharedAction(R.string.e2e_re_request_encryption_key, R.drawable.key_small) + EventSharedAction(CommonStrings.e2e_re_request_encryption_key, R.drawable.key_small) object UseKeyBackup : - EventSharedAction(R.string.e2e_use_keybackup, R.drawable.shield) + EventSharedAction(CommonStrings.e2e_use_keybackup, R.drawable.shield) data class EndPoll(val eventId: String) : - EventSharedAction(R.string.poll_end_action, R.drawable.ic_check_on) + EventSharedAction(CommonStrings.poll_end_action, R.drawable.ic_check_on) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt index 7ab8862886..99122151fc 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt @@ -45,6 +45,7 @@ import im.vector.app.features.location.toLocationData import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.settings.VectorPreferences import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.session.events.model.isLocationMessage @@ -103,7 +104,7 @@ class MessageActionsEpoxyController @Inject constructor( // Get more details about the error val errorMessage = state.timelineEvent()?.root?.sendStateError() ?.let { errorFormatter.toHumanReadable(Failure.ServerError(it, 0)) } - ?: stringProvider.getString(R.string.unable_to_send_message) + ?: stringProvider.getString(CommonStrings.unable_to_send_message) bottomSheetSendStateItem { id("send_state") showProgress(false) @@ -114,14 +115,14 @@ class MessageActionsEpoxyController @Inject constructor( bottomSheetSendStateItem { id("send_state") showProgress(true) - text(host.stringProvider.getString(R.string.event_status_sending_message)) + text(host.stringProvider.getString(CommonStrings.event_status_sending_message)) } } else if (sendState == SendState.SENT) { bottomSheetSendStateItem { id("send_state") showProgress(false) drawableStart(R.drawable.ic_message_sent) - text(host.stringProvider.getString(R.string.event_status_sent_message)) + text(host.stringProvider.getString(CommonStrings.event_status_sent_message)) } } @@ -130,7 +131,7 @@ class MessageActionsEpoxyController @Inject constructor( bottomSheetSendStateItem { id("e2e_clear") showProgress(false) - text(host.stringProvider.getString(R.string.unencrypted)) + text(host.stringProvider.getString(CommonStrings.unencrypted)) drawableStart(R.drawable.ic_shield_warning_small) } } @@ -139,7 +140,7 @@ class MessageActionsEpoxyController @Inject constructor( bottomSheetSendStateItem { id("e2e_unverified") showProgress(false) - text(host.stringProvider.getString(R.string.encrypted_unverified)) + text(host.stringProvider.getString(CommonStrings.encrypted_unverified)) drawableStart(R.drawable.ic_shield_warning_small) } } @@ -147,7 +148,7 @@ class MessageActionsEpoxyController @Inject constructor( bottomSheetSendStateItem { id("e2e_unsafe") showProgress(false) - text(host.stringProvider.getString(R.string.key_authenticity_not_guaranteed)) + text(host.stringProvider.getString(CommonStrings.key_authenticity_not_guaranteed)) drawableStart(R.drawable.ic_shield_gray) } } @@ -155,7 +156,7 @@ class MessageActionsEpoxyController @Inject constructor( bottomSheetSendStateItem { id("e2e_deleted") showProgress(false) - text(host.stringProvider.getString(R.string.encrypted_by_deleted)) + text(host.stringProvider.getString(CommonStrings.encrypted_by_deleted)) drawableStart(R.drawable.ic_shield_warning_small) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt index aa8229d1bd..c95a46f2b4 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt @@ -20,7 +20,6 @@ import dagger.Lazy import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.error.ErrorFormatter @@ -36,6 +35,7 @@ import im.vector.app.features.html.VectorHtmlCompressor import im.vector.app.features.powerlevel.PowerLevelsFlowFactory import im.vector.app.features.reactions.data.EmojiDataSource import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.launchIn @@ -197,7 +197,7 @@ class MessageActionsViewModel @AssistedInject constructor( eventHtmlRenderer.get().render(html, pillsPostProcessor) } else if (messageContent is MessageVerificationRequestContent) { - stringProvider.getString(R.string.verification_request) + stringProvider.getString(CommonStrings.verification_request) } else { messageContent?.body } @@ -218,10 +218,10 @@ class MessageActionsViewModel @AssistedInject constructor( } in EventType.POLL_START.values -> { (timelineEvent.getVectorLastMessageContent() as? MessagePollContent)?.getBestPollCreationInfo()?.question?.getBestQuestion() - ?: stringProvider.getString(R.string.message_reply_to_poll_preview) + ?: stringProvider.getString(CommonStrings.message_reply_to_poll_preview) } in EventType.POLL_END.values -> { - stringProvider.getString(R.string.message_reply_to_ended_poll_preview) + stringProvider.getString(CommonStrings.message_reply_to_ended_poll_preview) } else -> null } @@ -242,15 +242,15 @@ class MessageActionsViewModel @AssistedInject constructor( .let { reason -> if (reason == null) { if (timelineEvent.root.isRedactedBySameUser()) { - stringProvider.getString(R.string.event_redacted_by_user_reason) + stringProvider.getString(CommonStrings.event_redacted_by_user_reason) } else { - stringProvider.getString(R.string.event_redacted_by_admin_reason) + stringProvider.getString(CommonStrings.event_redacted_by_admin_reason) } } else { if (timelineEvent.root.isRedactedBySameUser()) { - stringProvider.getString(R.string.event_redacted_by_user_reason_with_reason, reason) + stringProvider.getString(CommonStrings.event_redacted_by_user_reason_with_reason, reason) } else { - stringProvider.getString(R.string.event_redacted_by_admin_reason_with_reason, reason) + stringProvider.getString(CommonStrings.event_redacted_by_admin_reason_with_reason, reason) } } } @@ -282,7 +282,7 @@ class MessageActionsViewModel @AssistedInject constructor( add(EventSharedAction.ViewSource(timelineEvent.root.toContentStringWithIndent())) if (timelineEvent.isEncrypted() && timelineEvent.root.mxDecryptionResult != null) { val decryptedContent = timelineEvent.root.toClearContentStringWithIndent() - ?: stringProvider.getString(R.string.encryption_information_decryption_error) + ?: stringProvider.getString(CommonStrings.encryption_information_decryption_error) add(EventSharedAction.ViewDecryptedSource(decryptedContent)) } } @@ -388,8 +388,8 @@ class MessageActionsViewModel @AssistedInject constructor( EventSharedAction.Redact( eventId, askForReason = informationData.senderId != session.myUserId, - dialogTitleRes = R.string.delete_poll_dialog_title, - dialogDescriptionRes = R.string.delete_poll_dialog_content + dialogTitleRes = CommonStrings.delete_poll_dialog_title, + dialogDescriptionRes = CommonStrings.delete_poll_dialog_content ) ) } else { @@ -397,8 +397,8 @@ class MessageActionsViewModel @AssistedInject constructor( EventSharedAction.Redact( eventId, askForReason = informationData.senderId != session.myUserId, - dialogTitleRes = R.string.delete_event_dialog_title, - dialogDescriptionRes = R.string.delete_event_dialog_content + dialogTitleRes = CommonStrings.delete_event_dialog_title, + dialogDescriptionRes = CommonStrings.delete_event_dialog_content ) ) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryBottomSheet.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryBottomSheet.kt index d01a607d17..56387b8046 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryBottomSheet.kt @@ -29,6 +29,7 @@ import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.databinding.BottomSheetGenericListWithTitleBinding import im.vector.app.features.home.room.detail.timeline.action.TimelineEventFragmentArgs import im.vector.app.features.home.room.detail.timeline.item.MessageInformationData +import im.vector.lib.strings.CommonStrings import javax.inject.Inject /** @@ -53,7 +54,7 @@ class ViewEditHistoryBottomSheet : dividerDrawable = R.drawable.divider_horizontal_on_secondary, hasFixedSize = false ) - views.bottomSheetTitle.text = context?.getString(R.string.message_edits) + views.bottomSheetTitle.text = context?.getString(CommonStrings.message_edits) } override fun onDestroyView() { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt index 6c18c78615..a07e3d1465 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt @@ -21,7 +21,6 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized -import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter import im.vector.app.core.resources.ColorProvider @@ -33,6 +32,7 @@ import im.vector.app.core.ui.list.genericLoaderItem import im.vector.app.features.html.EventHtmlRenderer import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span import name.fraser.neil.plaintext.diff_match_patch import org.matrix.android.sdk.api.session.events.model.Event @@ -66,7 +66,7 @@ class ViewEditHistoryEpoxyController @Inject constructor( is Fail -> { genericFooterItem { id("failure") - text(host.stringProvider.getString(R.string.unknown_error).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.unknown_error).toEpoxyCharSequence()) } } is Success -> { @@ -80,7 +80,7 @@ class ViewEditHistoryEpoxyController @Inject constructor( if (sourceEvents.isEmpty()) { genericItem { id("footer") - title(host.stringProvider.getString(R.string.no_message_edits_found).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.no_message_edits_found).toEpoxyCharSequence()) } } else { var lastDate: Calendar? = null @@ -117,14 +117,14 @@ class ViewEditHistoryEpoxyController @Inject constructor( diff_match_patch.Operation.DELETE -> { span { text = it.text.replace("\n", " ") - textColor = colorProvider.getColorFromAttribute(R.attr.colorError) + textColor = colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError) textDecorationLine = "line-through" } } diff_match_patch.Operation.INSERT -> { span { text = it.text - textColor = colorProvider.getColor(R.color.palette_element_green) + textColor = colorProvider.getColor(im.vector.lib.ui.styles.R.color.palette_element_green) } } else -> { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/DefaultItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/DefaultItemFactory.kt index d704003627..0dacef11b7 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/DefaultItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/DefaultItemFactory.kt @@ -16,7 +16,6 @@ package im.vector.app.features.home.room.detail.timeline.factory -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.TimelineEventController @@ -25,6 +24,7 @@ import im.vector.app.features.home.room.detail.timeline.helper.MessageInformatio import im.vector.app.features.home.room.detail.timeline.item.DefaultItem import im.vector.app.features.home.room.detail.timeline.item.DefaultItem_ import im.vector.app.features.home.room.detail.timeline.item.MessageInformationData +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class DefaultItemFactory @Inject constructor( @@ -57,9 +57,9 @@ class DefaultItemFactory @Inject constructor( fun create(params: TimelineItemFactoryParams, throwable: Throwable? = null): DefaultItem { val event = params.event val text = if (throwable == null) { - stringProvider.getString(R.string.rendering_event_error_type_of_event_not_handled, event.root.getClearType()) + stringProvider.getString(CommonStrings.rendering_event_error_type_of_event_not_handled, event.root.getClearType()) } else { - stringProvider.getString(R.string.rendering_event_error_exception, event.root.eventId) + stringProvider.getString(CommonStrings.rendering_event_error_exception, event.root.eventId) } val informationData = informationDataFactory.create(params) return create(text, informationData, params.isHighlighted, params.callback) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt index 4bc68c10aa..42611a0dab 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt @@ -28,6 +28,7 @@ import im.vector.app.features.home.room.detail.timeline.item.MessageTextItem_ import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod import im.vector.app.features.settings.VectorPreferences import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.image import me.gujun.android.span.span import org.matrix.android.sdk.api.session.crypto.MXCryptoError @@ -58,22 +59,22 @@ class EncryptedItemFactory @Inject constructor( val spannableStr = if (vectorPreferences.developerMode()) { val errorDescription = if (cryptoError == MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID) { - stringProvider.getString(R.string.notice_crypto_error_unknown_inbound_session_id) + stringProvider.getString(CommonStrings.notice_crypto_error_unknown_inbound_session_id) } else { // TODO i18n cryptoError?.name } - val message = stringProvider.getString(R.string.encrypted_message).takeIf { cryptoError == null } - ?: stringProvider.getString(R.string.notice_crypto_unable_to_decrypt, errorDescription) + val message = stringProvider.getString(CommonStrings.encrypted_message).takeIf { cryptoError == null } + ?: stringProvider.getString(CommonStrings.notice_crypto_unable_to_decrypt, errorDescription) span(message) { textStyle = "italic" - textColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + textColor = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) } } else { - val colorFromAttribute = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + val colorFromAttribute = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) if (cryptoError == null) { - span(stringProvider.getString(R.string.encrypted_message)) { + span(stringProvider.getString(CommonStrings.encrypted_message)) { textStyle = "italic" textColor = colorFromAttribute } @@ -85,7 +86,7 @@ class EncryptedItemFactory @Inject constructor( image(it, "baseline") +" " } - span(stringProvider.getString(R.string.notice_crypto_unable_to_decrypt_final)) { + span(stringProvider.getString(CommonStrings.notice_crypto_unable_to_decrypt_final)) { textStyle = "italic" textColor = colorFromAttribute } @@ -97,7 +98,7 @@ class EncryptedItemFactory @Inject constructor( image(it, "baseline") +" " } - span(stringProvider.getString(R.string.notice_crypto_unable_to_decrypt_friendly)) { + span(stringProvider.getString(CommonStrings.notice_crypto_unable_to_decrypt_friendly)) { textStyle = "italic" textColor = colorFromAttribute } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt index 9d757a5f2e..e7f9aa4aab 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt @@ -16,7 +16,6 @@ package im.vector.app.features.home.room.detail.timeline.factory -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.room.detail.timeline.MessageColorProvider import im.vector.app.features.home.room.detail.timeline.helper.AvatarSizeProvider @@ -24,6 +23,7 @@ import im.vector.app.features.home.room.detail.timeline.helper.MessageInformatio import im.vector.app.features.home.room.detail.timeline.helper.MessageItemAttributesFactory import im.vector.app.features.home.room.detail.timeline.item.StatusTileTimelineItem import im.vector.app.features.home.room.detail.timeline.item.StatusTileTimelineItem_ +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.Session @@ -63,24 +63,24 @@ class EncryptionItemFactory @Inject constructor( val isWaitingUser = roomSummary?.isEncrypted.orFalse() && roomSummary?.joinedMembersCount == 1 && roomSummary.invitedMembersCount == 0 when { RoomLocalEcho.isLocalEchoId(event.root.roomId.orEmpty()) -> Triple( - R.string.encryption_enabled, - R.string.direct_room_encryption_enabled_tile_description_future, + CommonStrings.encryption_enabled, + CommonStrings.direct_room_encryption_enabled_tile_description_future, StatusTileTimelineItem.ShieldUIState.BLACK ) isWaitingUser -> Triple( - R.string.direct_room_encryption_enabled_waiting_users, - R.string.direct_room_encryption_enabled_waiting_users_tile_description, + CommonStrings.direct_room_encryption_enabled_waiting_users, + CommonStrings.direct_room_encryption_enabled_waiting_users_tile_description, StatusTileTimelineItem.ShieldUIState.WAITING ) else -> Triple( - R.string.encryption_enabled, - R.string.direct_room_encryption_enabled_tile_description, + CommonStrings.encryption_enabled, + CommonStrings.direct_room_encryption_enabled_tile_description, StatusTileTimelineItem.ShieldUIState.BLACK ) } } else -> { - Triple(R.string.encryption_enabled, R.string.encryption_enabled_tile_description, StatusTileTimelineItem.ShieldUIState.BLACK) + Triple(CommonStrings.encryption_enabled, CommonStrings.encryption_enabled_tile_description, StatusTileTimelineItem.ShieldUIState.BLACK) } } @@ -88,8 +88,8 @@ class EncryptionItemFactory @Inject constructor( description = stringProvider.getString(resDescription) shield = resShield } else { - title = stringProvider.getString(R.string.encryption_misconfigured) - description = stringProvider.getString(R.string.encryption_unknown_algorithm_tile_description) + title = stringProvider.getString(CommonStrings.encryption_misconfigured) + description = stringProvider.getString(CommonStrings.encryption_unknown_algorithm_tile_description) shield = StatusTileTimelineItem.ShieldUIState.ERROR } return StatusTileTimelineItem_() diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt index b9457b9dc1..5fa7418be4 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt @@ -16,7 +16,6 @@ package im.vector.app.features.home.room.detail.timeline.factory -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.extensions.prevOrNull import im.vector.app.features.home.AvatarRenderer @@ -31,6 +30,7 @@ import im.vector.app.features.home.room.detail.timeline.item.MergedRoomCreationI import im.vector.app.features.home.room.detail.timeline.item.MergedSimilarEventsItem import im.vector.app.features.home.room.detail.timeline.item.MergedSimilarEventsItem_ import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod +import im.vector.lib.strings.CommonPlurals import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.query.QueryStringValue @@ -250,9 +250,9 @@ class MergedHeaderItemFactory @Inject constructor( private fun getSummaryTitleResId(event: Event): Int? { val type = event.getClearType() return when { - type == EventType.STATE_ROOM_MEMBER -> R.plurals.membership_changes - type == EventType.STATE_ROOM_SERVER_ACL -> R.plurals.notice_room_server_acl_changes - event.isRedacted() -> R.plurals.room_removed_messages + type == EventType.STATE_ROOM_MEMBER -> CommonPlurals.membership_changes + type == EventType.STATE_ROOM_SERVER_ACL -> CommonPlurals.notice_room_server_acl_changes + event.isRedacted() -> CommonPlurals.room_removed_messages else -> null } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt index 94189a7a53..3ec962768b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -83,6 +83,7 @@ import im.vector.app.features.voicebroadcast.isVoiceBroadcast import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span import org.matrix.android.sdk.api.MatrixUrls.isMxcUrl import org.matrix.android.sdk.api.session.Session @@ -179,7 +180,7 @@ class MessageItemFactory @Inject constructor( val messageContent = event.getVectorLastMessageContent() if (messageContent == null) { - val malformedText = stringProvider.getString(R.string.malformed_message) + val malformedText = stringProvider.getString(CommonStrings.malformed_message) return defaultItemFactory.create(malformedText, informationData, highlight, callback) } if (messageContent.relatesTo?.type == RelationType.REPLACE || @@ -292,7 +293,7 @@ class MessageItemFactory @Inject constructor( val pollContent = latestContent?.toModel() return if (pollContent == null) { - val title = stringProvider.getString(R.string.message_reply_to_ended_poll_preview).toEpoxyCharSequence() + val title = stringProvider.getString(CommonStrings.message_reply_to_ended_poll_preview).toEpoxyCharSequence() PollItem_() .attributes(attributes) .eventId(informationData.eventId) @@ -681,9 +682,9 @@ class MessageItemFactory @Inject constructor( ): Spannable { val spannable = SpannableStringBuilder() spannable.append(linkifiedBody) - val editedSuffix = stringProvider.getString(R.string.edited_suffix) + val editedSuffix = stringProvider.getString(CommonStrings.edited_suffix) spannable.append(" ").append(editedSuffix) - val color = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + val color = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) val editStart = spannable.lastIndexOf(editedSuffix) val editEnd = editStart + editedSuffix.length spannable.setSpan( @@ -729,7 +730,7 @@ class MessageItemFactory @Inject constructor( val htmlBody = messageContent.getHtmlBody() val formattedBody = span { text = htmlBody - textColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + textColor = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) textStyle = "italic" } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/PollItemViewStateFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/PollItemViewStateFactory.kt index b630a514e4..21a19e599e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/PollItemViewStateFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/PollItemViewStateFactory.kt @@ -16,10 +16,11 @@ package im.vector.app.features.home.room.detail.timeline.factory -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.room.detail.timeline.item.PollResponseData import im.vector.app.features.poll.PollItemViewState +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent import org.matrix.android.sdk.api.session.room.model.message.PollCreationInfo @@ -61,7 +62,7 @@ class PollItemViewStateFactory @Inject constructor( private fun createSendingPollViewState(question: String, pollCreationInfo: PollCreationInfo?): PollItemViewState { return PollItemViewState( question = question, - votesStatus = stringProvider.getString(R.string.poll_no_votes_cast), + votesStatus = stringProvider.getString(CommonStrings.poll_no_votes_cast), canVote = false, optionViewStates = pollOptionViewStateFactory.createPollSendingOptions(pollCreationInfo), ) @@ -74,9 +75,9 @@ class PollItemViewStateFactory @Inject constructor( totalVotes: Int, ): PollItemViewState { val totalVotesText = if (pollResponseData?.hasEncryptedRelatedEvents.orFalse()) { - stringProvider.getString(R.string.unable_to_decrypt_some_events_in_poll) + stringProvider.getString(CommonStrings.unable_to_decrypt_some_events_in_poll) } else { - stringProvider.getQuantityString(R.plurals.poll_total_vote_count_after_ended, totalVotes, totalVotes) + stringProvider.getQuantityString(CommonPlurals.poll_total_vote_count_after_ended, totalVotes, totalVotes) } return PollItemViewState( question = question, @@ -93,7 +94,7 @@ class PollItemViewStateFactory @Inject constructor( ): PollItemViewState { return PollItemViewState( question = question, - votesStatus = stringProvider.getString(R.string.poll_undisclosed_not_ended), + votesStatus = stringProvider.getString(CommonStrings.poll_undisclosed_not_ended), canVote = true, optionViewStates = pollOptionViewStateFactory.createPollUndisclosedOptions(pollCreationInfo, pollResponseData), ) @@ -106,9 +107,9 @@ class PollItemViewStateFactory @Inject constructor( totalVotes: Int ): PollItemViewState { val totalVotesText = if (pollResponseData?.hasEncryptedRelatedEvents.orFalse()) { - stringProvider.getString(R.string.unable_to_decrypt_some_events_in_poll) + stringProvider.getString(CommonStrings.unable_to_decrypt_some_events_in_poll) } else { - stringProvider.getQuantityString(R.plurals.poll_total_vote_count_before_ended_and_voted, totalVotes, totalVotes) + stringProvider.getQuantityString(CommonPlurals.poll_total_vote_count_before_ended_and_voted, totalVotes, totalVotes) } return PollItemViewState( question = question, @@ -124,9 +125,9 @@ class PollItemViewStateFactory @Inject constructor( totalVotes: Int ): PollItemViewState { val totalVotesText = if (totalVotes == 0) { - stringProvider.getString(R.string.poll_no_votes_cast) + stringProvider.getString(CommonStrings.poll_no_votes_cast) } else { - stringProvider.getQuantityString(R.plurals.poll_total_vote_count_before_ended_and_not_voted, totalVotes, totalVotes) + stringProvider.getQuantityString(CommonPlurals.poll_total_vote_count_before_ended_and_not_voted, totalVotes, totalVotes) } return PollItemViewState( question = question, diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt index 33851c808a..10463ee225 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt @@ -16,12 +16,12 @@ package im.vector.app.features.home.room.detail.timeline.factory -import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyModel import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.UserPreferencesProvider import im.vector.app.features.home.room.detail.timeline.item.RoomCreateItem_ import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.events.model.toModel @@ -41,9 +41,9 @@ class RoomCreateItemFactory @Inject constructor( val predecessorId = createRoomContent.predecessor?.roomId ?: return defaultRendering(params) val roomLink = session.permalinkService().createRoomPermalink(predecessorId) ?: return null val text = span { - +stringProvider.getString(R.string.room_tombstone_continuation_description) + +stringProvider.getString(CommonStrings.room_tombstone_continuation_description) +"\n" - span(stringProvider.getString(R.string.room_tombstone_predecessor_link)) { + span(stringProvider.getString(CommonStrings.room_tombstone_predecessor_link)) { textDecorationLine = "underline" onClick = { params.callback?.onRoomCreateLinkClicked(roomLink) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/VerificationItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/VerificationItemFactory.kt index 9a40cb6730..9dc0d6ddc8 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/VerificationItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/VerificationItemFactory.kt @@ -15,7 +15,6 @@ */ package im.vector.app.features.home.room.detail.timeline.factory -import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyModel import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.UserPreferencesProvider @@ -25,6 +24,7 @@ import im.vector.app.features.home.room.detail.timeline.helper.MessageInformatio import im.vector.app.features.home.room.detail.timeline.helper.MessageItemAttributesFactory import im.vector.app.features.home.room.detail.timeline.item.StatusTileTimelineItem import im.vector.app.features.home.room.detail.timeline.item.StatusTileTimelineItem_ +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.crypto.verification.CancelCode import org.matrix.android.sdk.api.session.crypto.verification.VerificationState @@ -92,7 +92,7 @@ class VerificationItemFactory @Inject constructor( return StatusTileTimelineItem_() .attributes( StatusTileTimelineItem.Attributes( - title = stringProvider.getString(R.string.verification_conclusion_warning), + title = stringProvider.getString(CommonStrings.verification_conclusion_warning), description = "${informationData.memberName} (${informationData.senderId})", shieldUIState = StatusTileTimelineItem.ShieldUIState.RED, informationData = informationData, @@ -126,7 +126,7 @@ class VerificationItemFactory @Inject constructor( return StatusTileTimelineItem_() .attributes( StatusTileTimelineItem.Attributes( - title = stringProvider.getString(R.string.sas_verified), + title = stringProvider.getString(CommonStrings.sas_verified), description = "${informationData.memberName} (${informationData.senderId})", shieldUIState = StatusTileTimelineItem.ShieldUIState.GREEN, informationData = informationData, diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt index eaa0bbb51a..932fb93cb8 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt @@ -29,6 +29,7 @@ import im.vector.app.features.voicebroadcast.VoiceBroadcastConstants import im.vector.app.features.voicebroadcast.isLive import im.vector.app.features.voicebroadcast.isVoiceBroadcast import im.vector.app.features.voicebroadcast.model.asVoiceBroadcastEvent +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.image import me.gujun.android.span.span import org.commonmark.node.Document @@ -62,7 +63,7 @@ class DisplayableEventFormatter @Inject constructor( if (timelineEvent.root.isEncrypted() && timelineEvent.root.mxDecryptionResult == null) { - return stringProvider.getString(R.string.encrypted_message) + return stringProvider.getString(CommonStrings.encrypted_message) } val senderName = timelineEvent.senderInfo.disambiguatedDisplayName @@ -82,32 +83,32 @@ class DisplayableEventFormatter @Inject constructor( } } MessageType.MSGTYPE_VERIFICATION_REQUEST -> { - simpleFormat(senderName, stringProvider.getString(R.string.verification_request), appendAuthor) + simpleFormat(senderName, stringProvider.getString(CommonStrings.verification_request), appendAuthor) } MessageType.MSGTYPE_IMAGE -> { - simpleFormat(senderName, stringProvider.getString(R.string.sent_an_image), appendAuthor) + simpleFormat(senderName, stringProvider.getString(CommonStrings.sent_an_image), appendAuthor) } MessageType.MSGTYPE_AUDIO -> { when { (messageContent as? MessageAudioContent)?.voiceMessageIndicator == null -> { - simpleFormat(senderName, stringProvider.getString(R.string.sent_an_audio_file), appendAuthor) + simpleFormat(senderName, stringProvider.getString(CommonStrings.sent_an_audio_file), appendAuthor) } timelineEvent.root.asMessageAudioEvent().isVoiceBroadcast() -> { - simpleFormat(senderName, stringProvider.getString(R.string.started_a_voice_broadcast), appendAuthor) + simpleFormat(senderName, stringProvider.getString(CommonStrings.started_a_voice_broadcast), appendAuthor) } else -> { - simpleFormat(senderName, stringProvider.getString(R.string.sent_a_voice_message), appendAuthor) + simpleFormat(senderName, stringProvider.getString(CommonStrings.sent_a_voice_message), appendAuthor) } } } MessageType.MSGTYPE_VIDEO -> { - simpleFormat(senderName, stringProvider.getString(R.string.sent_a_video), appendAuthor) + simpleFormat(senderName, stringProvider.getString(CommonStrings.sent_a_video), appendAuthor) } MessageType.MSGTYPE_FILE -> { - simpleFormat(senderName, stringProvider.getString(R.string.sent_a_file), appendAuthor) + simpleFormat(senderName, stringProvider.getString(CommonStrings.sent_a_file), appendAuthor) } MessageType.MSGTYPE_LOCATION -> { - simpleFormat(senderName, stringProvider.getString(R.string.sent_location), appendAuthor) + simpleFormat(senderName, stringProvider.getString(CommonStrings.sent_location), appendAuthor) } else -> { simpleFormat(senderName, messageContent.body, appendAuthor) @@ -116,18 +117,18 @@ class DisplayableEventFormatter @Inject constructor( } ?: span { } } EventType.STICKER -> { - simpleFormat(senderName, stringProvider.getString(R.string.send_a_sticker), appendAuthor) + simpleFormat(senderName, stringProvider.getString(CommonStrings.send_a_sticker), appendAuthor) } EventType.REACTION -> { timelineEvent.root.getClearContent().toModel()?.relatesTo?.let { - val emojiSpanned = emojiSpanify.spanify(stringProvider.getString(R.string.sent_a_reaction, it.key)) + val emojiSpanned = emojiSpanify.spanify(stringProvider.getString(CommonStrings.sent_a_reaction, it.key)) simpleFormat(senderName, emojiSpanned, appendAuthor) } ?: span { } } EventType.KEY_VERIFICATION_CANCEL, EventType.KEY_VERIFICATION_DONE -> { // cancel and done can appear in timeline, so should have representation - simpleFormat(senderName, stringProvider.getString(R.string.sent_verification_conclusion), appendAuthor) + simpleFormat(senderName, stringProvider.getString(CommonStrings.sent_verification_conclusion), appendAuthor) } EventType.KEY_VERIFICATION_START, EventType.KEY_VERIFICATION_ACCEPT, @@ -139,16 +140,16 @@ class DisplayableEventFormatter @Inject constructor( } in EventType.POLL_START.values -> { (timelineEvent.getVectorLastMessageContent() as? MessagePollContent)?.getBestPollCreationInfo()?.question?.getBestQuestion() - ?: stringProvider.getString(R.string.sent_a_poll) + ?: stringProvider.getString(CommonStrings.sent_a_poll) } in EventType.POLL_RESPONSE.values -> { - stringProvider.getString(R.string.poll_response_room_list_preview) + stringProvider.getString(CommonStrings.poll_response_room_list_preview) } in EventType.POLL_END.values -> { - stringProvider.getString(R.string.poll_end_room_list_preview) + stringProvider.getString(CommonStrings.poll_end_room_list_preview) } in EventType.STATE_ROOM_BEACON_INFO.values -> { - simpleFormat(senderName, stringProvider.getString(R.string.sent_live_location), appendAuthor) + simpleFormat(senderName, stringProvider.getString(CommonStrings.sent_live_location), appendAuthor) } VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO -> { formatVoiceBroadcastEvent(timelineEvent.root, isDm, senderName) @@ -185,7 +186,7 @@ class DisplayableEventFormatter @Inject constructor( // The event is encrypted if (event.isEncrypted() && event.mxDecryptionResult == null) { - return stringProvider.getString(R.string.encrypted_message) + return stringProvider.getString(CommonStrings.encrypted_message) } return when (event.getClearType()) { @@ -203,26 +204,26 @@ class DisplayableEventFormatter @Inject constructor( } } MessageType.MSGTYPE_VERIFICATION_REQUEST -> { - stringProvider.getString(R.string.verification_request) + stringProvider.getString(CommonStrings.verification_request) } MessageType.MSGTYPE_IMAGE -> { - stringProvider.getString(R.string.sent_an_image) + stringProvider.getString(CommonStrings.sent_an_image) } MessageType.MSGTYPE_AUDIO -> { if ((messageContent as? MessageAudioContent)?.voiceMessageIndicator != null) { - stringProvider.getString(R.string.sent_a_voice_message) + stringProvider.getString(CommonStrings.sent_a_voice_message) } else { - stringProvider.getString(R.string.sent_an_audio_file) + stringProvider.getString(CommonStrings.sent_an_audio_file) } } MessageType.MSGTYPE_VIDEO -> { - stringProvider.getString(R.string.sent_a_video) + stringProvider.getString(CommonStrings.sent_a_video) } MessageType.MSGTYPE_FILE -> { - stringProvider.getString(R.string.sent_a_file) + stringProvider.getString(CommonStrings.sent_a_file) } MessageType.MSGTYPE_LOCATION -> { - stringProvider.getString(R.string.sent_location) + stringProvider.getString(CommonStrings.sent_location) } else -> { messageContent.body @@ -231,25 +232,25 @@ class DisplayableEventFormatter @Inject constructor( } ?: span { } } EventType.STICKER -> { - stringProvider.getString(R.string.send_a_sticker) + stringProvider.getString(CommonStrings.send_a_sticker) } EventType.REACTION -> { event.getClearContent().toModel()?.relatesTo?.let { - emojiSpanify.spanify(stringProvider.getString(R.string.sent_a_reaction, it.key)) + emojiSpanify.spanify(stringProvider.getString(CommonStrings.sent_a_reaction, it.key)) } ?: span { } } in EventType.POLL_START.values -> { event.getClearContent().toModel(catchError = true)?.pollCreationInfo?.question?.question - ?: stringProvider.getString(R.string.sent_a_poll) + ?: stringProvider.getString(CommonStrings.sent_a_poll) } in EventType.POLL_RESPONSE.values -> { - stringProvider.getString(R.string.poll_response_room_list_preview) + stringProvider.getString(CommonStrings.poll_response_room_list_preview) } in EventType.POLL_END.values -> { - stringProvider.getString(R.string.poll_end_room_list_preview) + stringProvider.getString(CommonStrings.poll_end_room_list_preview) } in EventType.STATE_ROOM_BEACON_INFO.values -> { - stringProvider.getString(R.string.sent_live_location) + stringProvider.getString(CommonStrings.sent_live_location) } else -> { span { @@ -262,7 +263,7 @@ class DisplayableEventFormatter @Inject constructor( return if (appendAuthor) { span { text = senderName - textColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_primary) + textColor = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary) } .append(": ") .append(body) @@ -274,12 +275,12 @@ class DisplayableEventFormatter @Inject constructor( private fun formatVoiceBroadcastEvent(event: Event, isDm: Boolean, senderName: String): CharSequence { return if (event.asVoiceBroadcastEvent()?.isLive == true) { span { - drawableProvider.getDrawable(R.drawable.ic_voice_broadcast, colorProvider.getColor(R.color.palette_vermilion))?.let { + drawableProvider.getDrawable(R.drawable.ic_voice_broadcast, colorProvider.getColor(im.vector.lib.ui.styles.R.color.palette_vermilion))?.let { image(it) +" " } - span(stringProvider.getString(R.string.voice_broadcast_live_broadcast)) { - textColor = colorProvider.getColor(R.color.palette_vermilion) + span(stringProvider.getString(CommonStrings.voice_broadcast_live_broadcast)) { + textColor = colorProvider.getColor(im.vector.lib.ui.styles.R.color.palette_vermilion) } } } else { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/EventDetailsFormatter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/EventDetailsFormatter.kt index 1d3f016951..d99c055451 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/EventDetailsFormatter.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/EventDetailsFormatter.kt @@ -17,8 +17,8 @@ package im.vector.app.features.home.room.detail.timeline.format import android.content.Context -import im.vector.app.R import im.vector.app.core.utils.TextUtils +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.isAudioMessage import org.matrix.android.sdk.api.session.events.model.isFileMessage @@ -60,9 +60,9 @@ class EventDetailsFormatter @Inject constructor( } } - private fun formatPollMessage() = context.getString(R.string.message_reply_to_poll_preview) + private fun formatPollMessage() = context.getString(CommonStrings.message_reply_to_poll_preview) - private fun formatPollEndMessage() = context.getString(R.string.message_reply_to_ended_poll_preview) + private fun formatPollEndMessage() = context.getString(CommonStrings.message_reply_to_ended_poll_preview) /** * Example: "1024 x 720 - 670 kB". diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/NoticeEventFormatter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/NoticeEventFormatter.kt index 62945195c8..6d8abc7e71 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/NoticeEventFormatter.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/NoticeEventFormatter.kt @@ -17,13 +17,14 @@ package im.vector.app.features.home.room.detail.timeline.format import im.vector.app.ActiveSessionDataSource -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.roomprofile.permissions.RoleFormatter import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.voicebroadcast.VoiceBroadcastConstants import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState import im.vector.app.features.voicebroadcast.model.asVoiceBroadcastEvent +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.extensions.appendNl import org.matrix.android.sdk.api.extensions.orFalse @@ -136,7 +137,7 @@ class NoticeEventFormatter @Inject constructor( val fromStr = roleFormatter.format(from) val toStr = roleFormatter.format(to) val displayName = event.roomId?.let { roomService?.getRoomMember(userId, it)?.displayName } ?: userId - val diff = sp.getString(R.string.notice_power_level_diff, displayName, fromStr, toStr) + val diff = sp.getString(CommonStrings.notice_power_level_diff, displayName, fromStr, toStr) diffs.add(diff) } } @@ -145,9 +146,9 @@ class NoticeEventFormatter @Inject constructor( } val diffStr = diffs.joinToString(separator = ", ") return if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_power_level_changed_by_you, diffStr) + sp.getString(CommonStrings.notice_power_level_changed_by_you, diffStr) } else { - sp.getString(R.string.notice_power_level_changed, disambiguatedDisplayName, diffStr) + sp.getString(CommonStrings.notice_power_level_changed, disambiguatedDisplayName, diffStr) } } @@ -159,25 +160,25 @@ class NoticeEventFormatter @Inject constructor( if (previousWidgetContent?.isActive().orFalse()) { // Widget has been modified if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_widget_modified_by_you, widgetName) + sp.getString(CommonStrings.notice_widget_modified_by_you, widgetName) } else { - sp.getString(R.string.notice_widget_modified, disambiguatedDisplayName, widgetName) + sp.getString(CommonStrings.notice_widget_modified, disambiguatedDisplayName, widgetName) } } else { // Widget has been added if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_widget_added_by_you, widgetName) + sp.getString(CommonStrings.notice_widget_added_by_you, widgetName) } else { - sp.getString(R.string.notice_widget_added, disambiguatedDisplayName, widgetName) + sp.getString(CommonStrings.notice_widget_added, disambiguatedDisplayName, widgetName) } } } else { // Widget has been removed val widgetName = previousWidgetContent?.getHumanName() if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_widget_removed_by_you, widgetName) + sp.getString(CommonStrings.notice_widget_removed_by_you, widgetName) } else { - sp.getString(R.string.notice_widget_removed, disambiguatedDisplayName, widgetName) + sp.getString(CommonStrings.notice_widget_removed, disambiguatedDisplayName, widgetName) } } } @@ -214,9 +215,9 @@ class NoticeEventFormatter @Inject constructor( ?.takeIf { it.creator.isNullOrBlank().not() } ?.let { if (event.isSentByCurrentUser()) { - sp.getString(if (isDm) R.string.notice_direct_room_created_by_you else R.string.notice_room_created_by_you) + sp.getString(if (isDm) CommonStrings.notice_direct_room_created_by_you else CommonStrings.notice_room_created_by_you) } else { - sp.getString(if (isDm) R.string.notice_direct_room_created else R.string.notice_room_created, it.creator) + sp.getString(if (isDm) CommonStrings.notice_direct_room_created else CommonStrings.notice_room_created, it.creator) } } } @@ -225,24 +226,24 @@ class NoticeEventFormatter @Inject constructor( val content = event.content.toModel() ?: return null return if (content.name.isNullOrBlank()) { if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_name_removed_by_you) + sp.getString(CommonStrings.notice_room_name_removed_by_you) } else { - sp.getString(R.string.notice_room_name_removed, senderName) + sp.getString(CommonStrings.notice_room_name_removed, senderName) } } else { if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_name_changed_by_you, content.name) + sp.getString(CommonStrings.notice_room_name_changed_by_you, content.name) } else { - sp.getString(R.string.notice_room_name_changed, senderName, content.name) + sp.getString(CommonStrings.notice_room_name_changed, senderName, content.name) } } } private fun formatRoomTombstoneEvent(event: Event, senderName: String?, isDm: Boolean): CharSequence? { return if (event.isSentByCurrentUser()) { - sp.getString(if (isDm) R.string.notice_direct_room_update_by_you else R.string.notice_room_update_by_you) + sp.getString(if (isDm) CommonStrings.notice_direct_room_update_by_you else CommonStrings.notice_room_update_by_you) } else { - sp.getString(if (isDm) R.string.notice_direct_room_update else R.string.notice_room_update, senderName) + sp.getString(if (isDm) CommonStrings.notice_direct_room_update else CommonStrings.notice_room_update, senderName) } } @@ -250,15 +251,15 @@ class NoticeEventFormatter @Inject constructor( val content = event.content.toModel() ?: return null return if (content.topic.isNullOrEmpty()) { if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_topic_removed_by_you) + sp.getString(CommonStrings.notice_room_topic_removed_by_you) } else { - sp.getString(R.string.notice_room_topic_removed, senderName) + sp.getString(CommonStrings.notice_room_topic_removed, senderName) } } else { if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_topic_changed_by_you, content.topic) + sp.getString(CommonStrings.notice_room_topic_changed_by_you, content.topic) } else { - sp.getString(R.string.notice_room_topic_changed, senderName, content.topic) + sp.getString(CommonStrings.notice_room_topic_changed, senderName, content.topic) } } } @@ -267,15 +268,15 @@ class NoticeEventFormatter @Inject constructor( val content = event.content.toModel() ?: return null return if (content.avatarUrl.isNullOrEmpty()) { if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_avatar_removed_by_you) + sp.getString(CommonStrings.notice_room_avatar_removed_by_you) } else { - sp.getString(R.string.notice_room_avatar_removed, senderName) + sp.getString(CommonStrings.notice_room_avatar_removed, senderName) } } else { if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_avatar_changed_by_you) + sp.getString(CommonStrings.notice_room_avatar_changed_by_you) } else { - sp.getString(R.string.notice_room_avatar_changed, senderName) + sp.getString(CommonStrings.notice_room_avatar_changed, senderName) } } } @@ -286,12 +287,12 @@ class NoticeEventFormatter @Inject constructor( val historyVisibilitySuffix = roomHistoryVisibilityFormatter.getNoticeSuffix(historyVisibility) return if (event.isSentByCurrentUser()) { sp.getString( - if (isDm) R.string.notice_made_future_direct_room_visibility_by_you else R.string.notice_made_future_room_visibility_by_you, + if (isDm) CommonStrings.notice_made_future_direct_room_visibility_by_you else CommonStrings.notice_made_future_room_visibility_by_you, historyVisibilitySuffix ) } else { sp.getString( - if (isDm) R.string.notice_made_future_direct_room_visibility else R.string.notice_made_future_room_visibility, + if (isDm) CommonStrings.notice_made_future_direct_room_visibility else CommonStrings.notice_made_future_room_visibility, senderName, historyVisibilitySuffix ) } @@ -307,15 +308,15 @@ class NoticeEventFormatter @Inject constructor( if (event.isSentByCurrentUser()) { sp.getString( if (isDm) { - R.string.notice_direct_room_third_party_revoked_invite_by_you + CommonStrings.notice_direct_room_third_party_revoked_invite_by_you } else { - R.string.notice_room_third_party_revoked_invite_by_you + CommonStrings.notice_room_third_party_revoked_invite_by_you }, prevContent.displayName ) } else { sp.getString( - if (isDm) R.string.notice_direct_room_third_party_revoked_invite else R.string.notice_room_third_party_revoked_invite, + if (isDm) CommonStrings.notice_direct_room_third_party_revoked_invite else CommonStrings.notice_room_third_party_revoked_invite, senderName, prevContent.displayName ) } @@ -324,12 +325,12 @@ class NoticeEventFormatter @Inject constructor( // Invitation case if (event.isSentByCurrentUser()) { sp.getString( - if (isDm) R.string.notice_direct_room_third_party_invite_by_you else R.string.notice_room_third_party_invite_by_you, + if (isDm) CommonStrings.notice_direct_room_third_party_invite_by_you else CommonStrings.notice_room_third_party_invite_by_you, content.displayName ) } else { sp.getString( - if (isDm) R.string.notice_direct_room_third_party_invite else R.string.notice_room_third_party_invite, + if (isDm) CommonStrings.notice_direct_room_third_party_invite else CommonStrings.notice_room_third_party_invite, senderName, content.displayName ) } @@ -345,41 +346,41 @@ class NoticeEventFormatter @Inject constructor( val isVideoCall = content.isVideo() return if (isVideoCall) { if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_placed_video_call_by_you) + sp.getString(CommonStrings.notice_placed_video_call_by_you) } else { - sp.getString(R.string.notice_placed_video_call, senderName) + sp.getString(CommonStrings.notice_placed_video_call, senderName) } } else { if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_placed_voice_call_by_you) + sp.getString(CommonStrings.notice_placed_voice_call_by_you) } else { - sp.getString(R.string.notice_placed_voice_call, senderName) + sp.getString(CommonStrings.notice_placed_voice_call, senderName) } } } EventType.CALL_ANSWER -> if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_answered_call_by_you) + sp.getString(CommonStrings.notice_answered_call_by_you) } else { - sp.getString(R.string.notice_answered_call, senderName) + sp.getString(CommonStrings.notice_answered_call, senderName) } EventType.CALL_HANGUP -> if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_ended_call_by_you) + sp.getString(CommonStrings.notice_ended_call_by_you) } else { - sp.getString(R.string.notice_ended_call, senderName) + sp.getString(CommonStrings.notice_ended_call, senderName) } EventType.CALL_CANDIDATES -> if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_call_candidates_by_you) + sp.getString(CommonStrings.notice_call_candidates_by_you) } else { - sp.getString(R.string.notice_call_candidates, senderName) + sp.getString(CommonStrings.notice_call_candidates, senderName) } EventType.CALL_REJECT -> if (event.isSentByCurrentUser()) { - sp.getString(R.string.call_tile_you_declined_this_call) + sp.getString(CommonStrings.call_tile_you_declined_this_call) } else { - sp.getString(R.string.call_tile_other_declined, senderName) + sp.getString(CommonStrings.call_tile_other_declined, senderName) } else -> null } @@ -407,21 +408,21 @@ class NoticeEventFormatter @Inject constructor( return when { addedAliases.isNotEmpty() && removedAliases.isNotEmpty() -> if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_aliases_added_and_removed_by_you, addedAliases.joinToString(), removedAliases.joinToString()) + sp.getString(CommonStrings.notice_room_aliases_added_and_removed_by_you, addedAliases.joinToString(), removedAliases.joinToString()) } else { - sp.getString(R.string.notice_room_aliases_added_and_removed, senderName, addedAliases.joinToString(), removedAliases.joinToString()) + sp.getString(CommonStrings.notice_room_aliases_added_and_removed, senderName, addedAliases.joinToString(), removedAliases.joinToString()) } addedAliases.isNotEmpty() -> if (event.isSentByCurrentUser()) { - sp.getQuantityString(R.plurals.notice_room_aliases_added_by_you, addedAliases.size, addedAliases.joinToString()) + sp.getQuantityString(CommonPlurals.notice_room_aliases_added_by_you, addedAliases.size, addedAliases.joinToString()) } else { - sp.getQuantityString(R.plurals.notice_room_aliases_added, addedAliases.size, senderName, addedAliases.joinToString()) + sp.getQuantityString(CommonPlurals.notice_room_aliases_added, addedAliases.size, senderName, addedAliases.joinToString()) } removedAliases.isNotEmpty() -> if (event.isSentByCurrentUser()) { - sp.getQuantityString(R.plurals.notice_room_aliases_removed_by_you, removedAliases.size, removedAliases.joinToString()) + sp.getQuantityString(CommonPlurals.notice_room_aliases_removed_by_you, removedAliases.size, removedAliases.joinToString()) } else { - sp.getQuantityString(R.plurals.notice_room_aliases_removed, removedAliases.size, senderName, removedAliases.joinToString()) + sp.getQuantityString(CommonPlurals.notice_room_aliases_removed, removedAliases.size, senderName, removedAliases.joinToString()) } else -> { Timber.w("Alias event without any change...") @@ -439,21 +440,21 @@ class NoticeEventFormatter @Inject constructor( append( if (prevEventContent == null) { if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_server_acl_set_title_by_you) + sp.getString(CommonStrings.notice_room_server_acl_set_title_by_you) } else { - sp.getString(R.string.notice_room_server_acl_set_title, senderName) + sp.getString(CommonStrings.notice_room_server_acl_set_title, senderName) } } else { if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_server_acl_updated_title_by_you) + sp.getString(CommonStrings.notice_room_server_acl_updated_title_by_you) } else { - sp.getString(R.string.notice_room_server_acl_updated_title, senderName) + sp.getString(CommonStrings.notice_room_server_acl_updated_title, senderName) } } ) if (eventContent.allowList.isEmpty()) { // Special case for stuck room - appendNl(sp.getString(R.string.notice_room_server_acl_allow_is_empty)) + appendNl(sp.getString(CommonStrings.notice_room_server_acl_allow_is_empty)) } else if (vectorPreferences.developerMode()) { // Details, only in developer mode appendAclDetails(eventContent, prevEventContent) @@ -463,12 +464,12 @@ class NoticeEventFormatter @Inject constructor( private fun StringBuilder.appendAclDetails(eventContent: RoomServerAclContent, prevEventContent: RoomServerAclContent?) { if (prevEventContent == null) { - eventContent.allowList.forEach { appendNl(sp.getString(R.string.notice_room_server_acl_set_allowed, it)) } - eventContent.denyList.forEach { appendNl(sp.getString(R.string.notice_room_server_acl_set_banned, it)) } + eventContent.allowList.forEach { appendNl(sp.getString(CommonStrings.notice_room_server_acl_set_allowed, it)) } + eventContent.denyList.forEach { appendNl(sp.getString(CommonStrings.notice_room_server_acl_set_banned, it)) } if (eventContent.allowIpLiterals) { - appendNl(sp.getString(R.string.notice_room_server_acl_set_ip_literals_allowed)) + appendNl(sp.getString(CommonStrings.notice_room_server_acl_set_ip_literals_allowed)) } else { - appendNl(sp.getString(R.string.notice_room_server_acl_set_ip_literals_not_allowed)) + appendNl(sp.getString(CommonStrings.notice_room_server_acl_set_ip_literals_not_allowed)) } } else { // Display only diff @@ -476,31 +477,31 @@ class NoticeEventFormatter @Inject constructor( // New allowed servers (eventContent.allowList - prevEventContent.allowList) .also { hasChanged = hasChanged || it.isNotEmpty() } - .forEach { appendNl(sp.getString(R.string.notice_room_server_acl_updated_allowed, it)) } + .forEach { appendNl(sp.getString(CommonStrings.notice_room_server_acl_updated_allowed, it)) } // Removed allowed servers (prevEventContent.allowList - eventContent.allowList) .also { hasChanged = hasChanged || it.isNotEmpty() } - .forEach { appendNl(sp.getString(R.string.notice_room_server_acl_updated_was_allowed, it)) } + .forEach { appendNl(sp.getString(CommonStrings.notice_room_server_acl_updated_was_allowed, it)) } // New denied servers (eventContent.denyList - prevEventContent.denyList) .also { hasChanged = hasChanged || it.isNotEmpty() } - .forEach { appendNl(sp.getString(R.string.notice_room_server_acl_updated_banned, it)) } + .forEach { appendNl(sp.getString(CommonStrings.notice_room_server_acl_updated_banned, it)) } // Removed denied servers (prevEventContent.denyList - eventContent.denyList) .also { hasChanged = hasChanged || it.isNotEmpty() } - .forEach { appendNl(sp.getString(R.string.notice_room_server_acl_updated_was_banned, it)) } + .forEach { appendNl(sp.getString(CommonStrings.notice_room_server_acl_updated_was_banned, it)) } if (prevEventContent.allowIpLiterals != eventContent.allowIpLiterals) { hasChanged = true if (eventContent.allowIpLiterals) { - appendNl(sp.getString(R.string.notice_room_server_acl_updated_ip_literals_allowed)) + appendNl(sp.getString(CommonStrings.notice_room_server_acl_updated_ip_literals_allowed)) } else { - appendNl(sp.getString(R.string.notice_room_server_acl_updated_ip_literals_not_allowed)) + appendNl(sp.getString(CommonStrings.notice_room_server_acl_updated_ip_literals_not_allowed)) } } if (!hasChanged) { - appendNl(sp.getString(R.string.notice_room_server_acl_updated_no_change)) + appendNl(sp.getString(CommonStrings.notice_room_server_acl_updated_no_change)) } } } @@ -519,57 +520,57 @@ class NoticeEventFormatter @Inject constructor( added.isEmpty() && removed.isEmpty() && canonicalAlias == prevCanonicalAlias -> { // No difference between the two events say something as we can't simply hide the event from here if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_canonical_alias_no_change_by_you) + sp.getString(CommonStrings.notice_room_canonical_alias_no_change_by_you) } else { - sp.getString(R.string.notice_room_canonical_alias_no_change, senderName) + sp.getString(CommonStrings.notice_room_canonical_alias_no_change, senderName) } } added.isEmpty() && removed.isEmpty() -> { // Canonical has changed if (canonicalAlias != null) { if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_canonical_alias_set_by_you, canonicalAlias) + sp.getString(CommonStrings.notice_room_canonical_alias_set_by_you, canonicalAlias) } else { - sp.getString(R.string.notice_room_canonical_alias_set, senderName, canonicalAlias) + sp.getString(CommonStrings.notice_room_canonical_alias_set, senderName, canonicalAlias) } } else { if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_canonical_alias_unset_by_you) + sp.getString(CommonStrings.notice_room_canonical_alias_unset_by_you) } else { - sp.getString(R.string.notice_room_canonical_alias_unset, senderName) + sp.getString(CommonStrings.notice_room_canonical_alias_unset, senderName) } } } added.isEmpty() && canonicalAlias == prevCanonicalAlias -> { // Some alternative has been removed if (event.isSentByCurrentUser()) { - sp.getQuantityString(R.plurals.notice_room_canonical_alias_alternative_removed_by_you, removed.size, removed.joinToString()) + sp.getQuantityString(CommonPlurals.notice_room_canonical_alias_alternative_removed_by_you, removed.size, removed.joinToString()) } else { - sp.getQuantityString(R.plurals.notice_room_canonical_alias_alternative_removed, removed.size, senderName, removed.joinToString()) + sp.getQuantityString(CommonPlurals.notice_room_canonical_alias_alternative_removed, removed.size, senderName, removed.joinToString()) } } removed.isEmpty() && canonicalAlias == prevCanonicalAlias -> { // Some alternative has been added if (event.isSentByCurrentUser()) { - sp.getQuantityString(R.plurals.notice_room_canonical_alias_alternative_added_by_you, added.size, added.joinToString()) + sp.getQuantityString(CommonPlurals.notice_room_canonical_alias_alternative_added_by_you, added.size, added.joinToString()) } else { - sp.getQuantityString(R.plurals.notice_room_canonical_alias_alternative_added, added.size, senderName, added.joinToString()) + sp.getQuantityString(CommonPlurals.notice_room_canonical_alias_alternative_added, added.size, senderName, added.joinToString()) } } canonicalAlias == prevCanonicalAlias -> { // Alternative added and removed if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_canonical_alias_alternative_changed_by_you) + sp.getString(CommonStrings.notice_room_canonical_alias_alternative_changed_by_you) } else { - sp.getString(R.string.notice_room_canonical_alias_alternative_changed, senderName) + sp.getString(CommonStrings.notice_room_canonical_alias_alternative_changed, senderName) } } else -> { // Main and removed, or main and added, or main and added and removed if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_canonical_alias_main_and_alternative_changed_by_you) + sp.getString(CommonStrings.notice_room_canonical_alias_main_and_alternative_changed_by_you) } else { - sp.getString(R.string.notice_room_canonical_alias_main_and_alternative_changed, senderName) + sp.getString(CommonStrings.notice_room_canonical_alias_main_and_alternative_changed, senderName) } } } @@ -581,22 +582,26 @@ class NoticeEventFormatter @Inject constructor( GuestAccess.CanJoin -> if (event.isSentByCurrentUser()) { sp.getString( - if (isDm) R.string.notice_direct_room_guest_access_can_join_by_you else R.string.notice_room_guest_access_can_join_by_you + if (isDm) CommonStrings.notice_direct_room_guest_access_can_join_by_you else CommonStrings.notice_room_guest_access_can_join_by_you ) } else { sp.getString( - if (isDm) R.string.notice_direct_room_guest_access_can_join else R.string.notice_room_guest_access_can_join, + if (isDm) CommonStrings.notice_direct_room_guest_access_can_join else CommonStrings.notice_room_guest_access_can_join, senderName ) } GuestAccess.Forbidden -> if (event.isSentByCurrentUser()) { sp.getString( - if (isDm) R.string.notice_direct_room_guest_access_forbidden_by_you else R.string.notice_room_guest_access_forbidden_by_you + if (isDm) { + CommonStrings.notice_direct_room_guest_access_forbidden_by_you + } else { + CommonStrings.notice_room_guest_access_forbidden_by_you + } ) } else { sp.getString( - if (isDm) R.string.notice_direct_room_guest_access_forbidden else R.string.notice_room_guest_access_forbidden, + if (isDm) CommonStrings.notice_direct_room_guest_access_forbidden else CommonStrings.notice_room_guest_access_forbidden, senderName ) } @@ -612,15 +617,15 @@ class NoticeEventFormatter @Inject constructor( return when (content.algorithm) { MXCRYPTO_ALGORITHM_MEGOLM -> if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_end_to_end_ok_by_you) + sp.getString(CommonStrings.notice_end_to_end_ok_by_you) } else { - sp.getString(R.string.notice_end_to_end_ok, senderName) + sp.getString(CommonStrings.notice_end_to_end_ok, senderName) } else -> if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_end_to_end_unknown_algorithm_by_you, content.algorithm) + sp.getString(CommonStrings.notice_end_to_end_unknown_algorithm_by_you, content.algorithm) } else { - sp.getString(R.string.notice_end_to_end_unknown_algorithm, senderName, content.algorithm) + sp.getString(CommonStrings.notice_end_to_end_unknown_algorithm, senderName, content.algorithm) } } } @@ -632,21 +637,21 @@ class NoticeEventFormatter @Inject constructor( val displayNameText = when { prevEventContent?.displayName.isNullOrEmpty() -> if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_display_name_set_by_you, eventContent?.displayName) + sp.getString(CommonStrings.notice_display_name_set_by_you, eventContent?.displayName) } else { - sp.getString(R.string.notice_display_name_set, event.senderId, eventContent?.displayName) + sp.getString(CommonStrings.notice_display_name_set, event.senderId, eventContent?.displayName) } eventContent?.displayName.isNullOrEmpty() -> if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_display_name_removed_by_you, prevEventContent?.displayName) + sp.getString(CommonStrings.notice_display_name_removed_by_you, prevEventContent?.displayName) } else { - sp.getString(R.string.notice_display_name_removed, event.senderId, prevEventContent?.displayName) + sp.getString(CommonStrings.notice_display_name_removed, event.senderId, prevEventContent?.displayName) } else -> if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_display_name_changed_from_by_you, prevEventContent?.displayName, eventContent?.displayName) + sp.getString(CommonStrings.notice_display_name_changed_from_by_you, prevEventContent?.displayName, eventContent?.displayName) } else { - sp.getString(R.string.notice_display_name_changed_to, prevEventContent?.displayName, eventContent?.displayName) + sp.getString(CommonStrings.notice_display_name_changed_to, prevEventContent?.displayName, eventContent?.displayName) } } displayText.append(displayNameText) @@ -655,12 +660,12 @@ class NoticeEventFormatter @Inject constructor( if (eventContent?.avatarUrl != prevEventContent?.avatarUrl) { val displayAvatarText = if (displayText.isNotEmpty()) { displayText.append(" ") - sp.getString(R.string.notice_avatar_changed_too) + sp.getString(CommonStrings.notice_avatar_changed_too) } else { if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_avatar_url_changed_by_you) + sp.getString(CommonStrings.notice_avatar_url_changed_by_you) } else { - sp.getString(R.string.notice_avatar_url_changed, senderName) + sp.getString(CommonStrings.notice_avatar_url_changed, senderName) } } displayText.append(displayAvatarText) @@ -668,9 +673,9 @@ class NoticeEventFormatter @Inject constructor( if (displayText.isEmpty()) { displayText.append( if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_member_no_changes_by_you) + sp.getString(CommonStrings.notice_member_no_changes_by_you) } else { - sp.getString(R.string.notice_member_no_changes, senderName) + sp.getString(CommonStrings.notice_member_no_changes, senderName) } ) } @@ -694,39 +699,44 @@ class NoticeEventFormatter @Inject constructor( val threePidDisplayName = eventContent.thirdPartyInvite?.displayName ?: "" eventContent.safeReason?.let { reason -> if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_third_party_registered_invite_with_reason_by_you, threePidDisplayName, reason) + sp.getString(CommonStrings.notice_room_third_party_registered_invite_with_reason_by_you, threePidDisplayName, reason) } else { - sp.getString(R.string.notice_room_third_party_registered_invite_with_reason, userWhoHasAccepted, threePidDisplayName, reason) + sp.getString( + CommonStrings.notice_room_third_party_registered_invite_with_reason, + userWhoHasAccepted, + threePidDisplayName, + reason + ) } } ?: if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_room_third_party_registered_invite_by_you, threePidDisplayName) + sp.getString(CommonStrings.notice_room_third_party_registered_invite_by_you, threePidDisplayName) } else { - sp.getString(R.string.notice_room_third_party_registered_invite, userWhoHasAccepted, threePidDisplayName) + sp.getString(CommonStrings.notice_room_third_party_registered_invite, userWhoHasAccepted, threePidDisplayName) } } event.stateKey == currentUserId -> eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_invite_you_with_reason, senderDisplayName, reason) - } ?: sp.getString(R.string.notice_room_invite_you, senderDisplayName) + sp.getString(CommonStrings.notice_room_invite_you_with_reason, senderDisplayName, reason) + } ?: sp.getString(CommonStrings.notice_room_invite_you, senderDisplayName) event.stateKey.isNullOrEmpty() -> if (event.isSentByCurrentUser()) { eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_invite_no_invitee_with_reason_by_you, reason) - } ?: sp.getString(R.string.notice_room_invite_no_invitee_by_you) + sp.getString(CommonStrings.notice_room_invite_no_invitee_with_reason_by_you, reason) + } ?: sp.getString(CommonStrings.notice_room_invite_no_invitee_by_you) } else { eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_invite_no_invitee_with_reason, senderDisplayName, reason) - } ?: sp.getString(R.string.notice_room_invite_no_invitee, senderDisplayName) + sp.getString(CommonStrings.notice_room_invite_no_invitee_with_reason, senderDisplayName, reason) + } ?: sp.getString(CommonStrings.notice_room_invite_no_invitee, senderDisplayName) } else -> if (event.isSentByCurrentUser()) { eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_invite_with_reason_by_you, targetDisplayName, reason) - } ?: sp.getString(R.string.notice_room_invite_by_you, targetDisplayName) + sp.getString(CommonStrings.notice_room_invite_with_reason_by_you, targetDisplayName, reason) + } ?: sp.getString(CommonStrings.notice_room_invite_by_you, targetDisplayName) } else { eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_invite_with_reason, senderDisplayName, targetDisplayName, reason) - } ?: sp.getString(R.string.notice_room_invite, senderDisplayName, targetDisplayName) + sp.getString(CommonStrings.notice_room_invite_with_reason, senderDisplayName, targetDisplayName, reason) + } ?: sp.getString(CommonStrings.notice_room_invite, senderDisplayName, targetDisplayName) } } } @@ -734,21 +744,21 @@ class NoticeEventFormatter @Inject constructor( eventContent.safeReason?.let { reason -> if (event.isSentByCurrentUser()) { sp.getString( - if (isDm) R.string.notice_direct_room_join_with_reason_by_you else R.string.notice_room_join_with_reason_by_you, + if (isDm) CommonStrings.notice_direct_room_join_with_reason_by_you else CommonStrings.notice_room_join_with_reason_by_you, reason ) } else { sp.getString( - if (isDm) R.string.notice_direct_room_join_with_reason else R.string.notice_room_join_with_reason, + if (isDm) CommonStrings.notice_direct_room_join_with_reason else CommonStrings.notice_room_join_with_reason, senderDisplayName, reason ) } } ?: run { if (event.isSentByCurrentUser()) { - sp.getString(if (isDm) R.string.notice_direct_room_join_by_you else R.string.notice_room_join_by_you) + sp.getString(if (isDm) CommonStrings.notice_direct_room_join_by_you else CommonStrings.notice_room_join_by_you) } else { sp.getString( - if (isDm) R.string.notice_direct_room_join else R.string.notice_room_join, + if (isDm) CommonStrings.notice_direct_room_join else CommonStrings.notice_room_join, senderDisplayName ) } @@ -760,36 +770,36 @@ class NoticeEventFormatter @Inject constructor( Membership.INVITE -> if (event.isSentByCurrentUser()) { eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_reject_with_reason_by_you, reason) - } ?: sp.getString(R.string.notice_room_reject_by_you) + sp.getString(CommonStrings.notice_room_reject_with_reason_by_you, reason) + } ?: sp.getString(CommonStrings.notice_room_reject_by_you) } else { eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_reject_with_reason, senderDisplayName, reason) - } ?: sp.getString(R.string.notice_room_reject, senderDisplayName) + sp.getString(CommonStrings.notice_room_reject_with_reason, senderDisplayName, reason) + } ?: sp.getString(CommonStrings.notice_room_reject, senderDisplayName) } else -> eventContent.safeReason?.let { reason -> if (event.isSentByCurrentUser()) { sp.getString( if (isDm) { - R.string.notice_direct_room_leave_with_reason_by_you + CommonStrings.notice_direct_room_leave_with_reason_by_you } else { - R.string.notice_room_leave_with_reason_by_you + CommonStrings.notice_room_leave_with_reason_by_you }, reason ) } else { sp.getString( - if (isDm) R.string.notice_direct_room_leave_with_reason else R.string.notice_room_leave_with_reason, + if (isDm) CommonStrings.notice_direct_room_leave_with_reason else CommonStrings.notice_room_leave_with_reason, senderDisplayName, reason ) } } ?: run { if (event.isSentByCurrentUser()) { - sp.getString(if (isDm) R.string.notice_direct_room_leave_by_you else R.string.notice_room_leave_by_you) + sp.getString(if (isDm) CommonStrings.notice_direct_room_leave_by_you else CommonStrings.notice_room_leave_by_you) } else { sp.getString( - if (isDm) R.string.notice_direct_room_leave else R.string.notice_room_leave, + if (isDm) CommonStrings.notice_direct_room_leave else CommonStrings.notice_room_leave, senderDisplayName ) } @@ -800,33 +810,33 @@ class NoticeEventFormatter @Inject constructor( Membership.INVITE -> if (event.isSentByCurrentUser()) { eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_withdraw_with_reason_by_you, targetDisplayName, reason) - } ?: sp.getString(R.string.notice_room_withdraw_by_you, targetDisplayName) + sp.getString(CommonStrings.notice_room_withdraw_with_reason_by_you, targetDisplayName, reason) + } ?: sp.getString(CommonStrings.notice_room_withdraw_by_you, targetDisplayName) } else { eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_withdraw_with_reason, senderDisplayName, targetDisplayName, reason) - } ?: sp.getString(R.string.notice_room_withdraw, senderDisplayName, targetDisplayName) + sp.getString(CommonStrings.notice_room_withdraw_with_reason, senderDisplayName, targetDisplayName, reason) + } ?: sp.getString(CommonStrings.notice_room_withdraw, senderDisplayName, targetDisplayName) } Membership.LEAVE, Membership.JOIN -> if (event.isSentByCurrentUser()) { eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_remove_with_reason_by_you, targetDisplayName, reason) - } ?: sp.getString(R.string.notice_room_remove_by_you, targetDisplayName) + sp.getString(CommonStrings.notice_room_remove_with_reason_by_you, targetDisplayName, reason) + } ?: sp.getString(CommonStrings.notice_room_remove_by_you, targetDisplayName) } else { eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_remove_with_reason, senderDisplayName, targetDisplayName, reason) - } ?: sp.getString(R.string.notice_room_remove, senderDisplayName, targetDisplayName) + sp.getString(CommonStrings.notice_room_remove_with_reason, senderDisplayName, targetDisplayName, reason) + } ?: sp.getString(CommonStrings.notice_room_remove, senderDisplayName, targetDisplayName) } Membership.BAN -> if (event.isSentByCurrentUser()) { eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_unban_with_reason_by_you, targetDisplayName, reason) - } ?: sp.getString(R.string.notice_room_unban_by_you, targetDisplayName) + sp.getString(CommonStrings.notice_room_unban_with_reason_by_you, targetDisplayName, reason) + } ?: sp.getString(CommonStrings.notice_room_unban_by_you, targetDisplayName) } else { eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_unban_with_reason, senderDisplayName, targetDisplayName, reason) - } ?: sp.getString(R.string.notice_room_unban, senderDisplayName, targetDisplayName) + sp.getString(CommonStrings.notice_room_unban_with_reason, senderDisplayName, targetDisplayName, reason) + } ?: sp.getString(CommonStrings.notice_room_unban, senderDisplayName, targetDisplayName) } else -> null } @@ -834,22 +844,22 @@ class NoticeEventFormatter @Inject constructor( Membership.BAN -> if (event.isSentByCurrentUser()) { eventContent.safeReason?.let { - sp.getString(R.string.notice_room_ban_with_reason_by_you, targetDisplayName, it) - } ?: sp.getString(R.string.notice_room_ban_by_you, targetDisplayName) + sp.getString(CommonStrings.notice_room_ban_with_reason_by_you, targetDisplayName, it) + } ?: sp.getString(CommonStrings.notice_room_ban_by_you, targetDisplayName) } else { eventContent.safeReason?.let { - sp.getString(R.string.notice_room_ban_with_reason, senderDisplayName, targetDisplayName, it) - } ?: sp.getString(R.string.notice_room_ban, senderDisplayName, targetDisplayName) + sp.getString(CommonStrings.notice_room_ban_with_reason, senderDisplayName, targetDisplayName, it) + } ?: sp.getString(CommonStrings.notice_room_ban, senderDisplayName, targetDisplayName) } Membership.KNOCK -> if (event.isSentByCurrentUser()) { eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_remove_with_reason_by_you, targetDisplayName, reason) - } ?: sp.getString(R.string.notice_room_remove_by_you, targetDisplayName) + sp.getString(CommonStrings.notice_room_remove_with_reason_by_you, targetDisplayName, reason) + } ?: sp.getString(CommonStrings.notice_room_remove_by_you, targetDisplayName) } else { eventContent.safeReason?.let { reason -> - sp.getString(R.string.notice_room_remove_with_reason, senderDisplayName, targetDisplayName, reason) - } ?: sp.getString(R.string.notice_room_remove, senderDisplayName, targetDisplayName) + sp.getString(CommonStrings.notice_room_remove_with_reason, senderDisplayName, targetDisplayName, reason) + } ?: sp.getString(CommonStrings.notice_room_remove, senderDisplayName, targetDisplayName) } else -> null } @@ -860,18 +870,18 @@ class NoticeEventFormatter @Inject constructor( return when (content.joinRules) { RoomJoinRules.INVITE -> if (event.isSentByCurrentUser()) { - sp.getString(if (isDm) R.string.direct_room_join_rules_invite_by_you else R.string.room_join_rules_invite_by_you) + sp.getString(if (isDm) CommonStrings.direct_room_join_rules_invite_by_you else CommonStrings.room_join_rules_invite_by_you) } else { sp.getString( - if (isDm) R.string.direct_room_join_rules_invite else R.string.room_join_rules_invite, + if (isDm) CommonStrings.direct_room_join_rules_invite else CommonStrings.room_join_rules_invite, senderName ) } RoomJoinRules.PUBLIC -> if (event.isSentByCurrentUser()) { - sp.getString(R.string.room_join_rules_public_by_you) + sp.getString(CommonStrings.room_join_rules_public_by_you) } else { - sp.getString(R.string.room_join_rules_public, senderName) + sp.getString(CommonStrings.room_join_rules_public, senderName) } else -> null } @@ -887,15 +897,15 @@ class NoticeEventFormatter @Inject constructor( .let { reason -> if (reason == null) { if (event.isRedactedBySameUser()) { - sp.getString(R.string.event_redacted_by_user_reason) + sp.getString(CommonStrings.event_redacted_by_user_reason) } else { - sp.getString(R.string.event_redacted_by_admin_reason) + sp.getString(CommonStrings.event_redacted_by_admin_reason) } } else { if (event.isRedactedBySameUser()) { - sp.getString(R.string.event_redacted_by_user_reason_with_reason, reason) + sp.getString(CommonStrings.event_redacted_by_user_reason_with_reason, reason) } else { - sp.getString(R.string.event_redacted_by_admin_reason_with_reason, reason) + sp.getString(CommonStrings.event_redacted_by_admin_reason_with_reason, reason) } } } @@ -904,9 +914,9 @@ class NoticeEventFormatter @Inject constructor( private fun formatVoiceBroadcastEvent(event: Event, senderName: String?): CharSequence { return if (event.asVoiceBroadcastEvent()?.content?.voiceBroadcastState == VoiceBroadcastState.STOPPED) { if (event.isSentByCurrentUser()) { - sp.getString(R.string.notice_voice_broadcast_ended_by_you) + sp.getString(CommonStrings.notice_voice_broadcast_ended_by_you) } else { - sp.getString(R.string.notice_voice_broadcast_ended, senderName) + sp.getString(CommonStrings.notice_voice_broadcast_ended, senderName) } } else { formatDebug(event) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/RoomHistoryVisibilityFormatter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/RoomHistoryVisibilityFormatter.kt index 76b303775a..c79831b91b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/RoomHistoryVisibilityFormatter.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/RoomHistoryVisibilityFormatter.kt @@ -16,8 +16,8 @@ package im.vector.app.features.home.room.detail.timeline.format -import im.vector.app.R import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility import javax.inject.Inject @@ -27,10 +27,10 @@ class RoomHistoryVisibilityFormatter @Inject constructor( fun getNoticeSuffix(roomHistoryVisibility: RoomHistoryVisibility): String { return stringProvider.getString( when (roomHistoryVisibility) { - RoomHistoryVisibility.WORLD_READABLE -> R.string.notice_room_visibility_world_readable - RoomHistoryVisibility.SHARED -> R.string.notice_room_visibility_shared - RoomHistoryVisibility.INVITED -> R.string.notice_room_visibility_invited - RoomHistoryVisibility.JOINED -> R.string.notice_room_visibility_joined + RoomHistoryVisibility.WORLD_READABLE -> CommonStrings.notice_room_visibility_world_readable + RoomHistoryVisibility.SHARED -> CommonStrings.notice_room_visibility_shared + RoomHistoryVisibility.INVITED -> CommonStrings.notice_room_visibility_invited + RoomHistoryVisibility.JOINED -> CommonStrings.notice_room_visibility_joined } ) } @@ -38,10 +38,10 @@ class RoomHistoryVisibilityFormatter @Inject constructor( fun getSetting(roomHistoryVisibility: RoomHistoryVisibility): String { return stringProvider.getString( when (roomHistoryVisibility) { - RoomHistoryVisibility.WORLD_READABLE -> R.string.room_settings_read_history_entry_anyone - RoomHistoryVisibility.SHARED -> R.string.room_settings_read_history_entry_members_only_option_time_shared - RoomHistoryVisibility.INVITED -> R.string.room_settings_read_history_entry_members_only_invited - RoomHistoryVisibility.JOINED -> R.string.room_settings_read_history_entry_members_only_joined + RoomHistoryVisibility.WORLD_READABLE -> CommonStrings.room_settings_read_history_entry_anyone + RoomHistoryVisibility.SHARED -> CommonStrings.room_settings_read_history_entry_members_only_option_time_shared + RoomHistoryVisibility.INVITED -> CommonStrings.room_settings_read_history_entry_members_only_invited + RoomHistoryVisibility.JOINED -> CommonStrings.room_settings_read_history_entry_members_only_joined } ) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt index cda4af89ce..e7f8636123 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt @@ -28,6 +28,7 @@ import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.utils.TextUtils import im.vector.app.features.home.room.detail.timeline.MessageColorProvider +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker import org.matrix.android.sdk.api.session.room.send.SendState import javax.inject.Inject @@ -100,7 +101,7 @@ private class ContentMediaProgressUpdater( progressBar.isVisible = true progressBar.isIndeterminate = true progressBar.progress = 0 - progressTextView.text = progressLayout.context.getString(R.string.send_file_step_idle) + progressTextView.text = progressLayout.context.getString(CommonStrings.send_file_step_idle) progressTextView.setTextColor(messageColorProvider.getMessageTextColor(SendState.UNSENT)) } else { progressLayout.isVisible = false @@ -108,19 +109,19 @@ private class ContentMediaProgressUpdater( } private fun handleEncryptingThumbnail() { - doHandleEncrypting(R.string.send_file_step_encrypting_thumbnail, 0, 0) + doHandleEncrypting(CommonStrings.send_file_step_encrypting_thumbnail, 0, 0) } private fun handleProgressThumbnail(state: ContentUploadStateTracker.State.UploadingThumbnail) { - doHandleProgress(R.string.send_file_step_sending_thumbnail, state.current, state.total) + doHandleProgress(CommonStrings.send_file_step_sending_thumbnail, state.current, state.total) } private fun handleEncrypting(state: ContentUploadStateTracker.State.Encrypting) { - doHandleEncrypting(R.string.send_file_step_encrypting_file, state.current, state.total) + doHandleEncrypting(CommonStrings.send_file_step_encrypting_file, state.current, state.total) } private fun handleProgress(state: ContentUploadStateTracker.State.Uploading) { - doHandleProgress(R.string.send_file_step_sending_file, state.current, state.total) + doHandleProgress(CommonStrings.send_file_step_sending_file, state.current, state.total) } private fun handleCompressingImage() { @@ -128,7 +129,7 @@ private class ContentMediaProgressUpdater( progressBar.isVisible = true progressBar.isIndeterminate = true progressTextView.isVisible = true - progressTextView.text = progressLayout.context.getString(R.string.send_file_step_compressing_image) + progressTextView.text = progressLayout.context.getString(CommonStrings.send_file_step_compressing_image) progressTextView.setTextColor(messageColorProvider.getMessageTextColor(SendState.SENDING)) } @@ -141,7 +142,7 @@ private class ContentMediaProgressUpdater( progressBar.progress = state.percent.toInt() progressTextView.isVisible = true // False positive is here... - progressTextView.text = progressLayout.context.getString(R.string.send_file_step_compressing_video, state.percent.toInt()) + progressTextView.text = progressLayout.context.getString(CommonStrings.send_file_step_compressing_video, state.percent.toInt()) progressTextView.setTextColor(messageColorProvider.getMessageTextColor(SendState.SENDING)) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MatrixItemColorProvider.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MatrixItemColorProvider.kt index e23e003768..819d31752e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MatrixItemColorProvider.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MatrixItemColorProvider.kt @@ -20,8 +20,8 @@ import android.graphics.Color import androidx.annotation.ColorInt import androidx.annotation.ColorRes import androidx.annotation.VisibleForTesting -import im.vector.app.R import im.vector.app.core.resources.ColorProvider +import im.vector.lib.ui.styles.R import org.matrix.android.sdk.api.util.MatrixItem import timber.log.Timber import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageItemAttributesFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageItemAttributesFactory.kt index ad7482d9a5..ff22cb3484 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageItemAttributesFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageItemAttributesFactory.kt @@ -16,7 +16,6 @@ package im.vector.app.features.home.room.detail.timeline.helper import im.vector.app.EmojiCompatFontProvider -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.UserPreferencesProvider import im.vector.app.features.home.AvatarRenderer @@ -26,6 +25,7 @@ import im.vector.app.features.home.room.detail.timeline.format.DisplayableEventF import im.vector.app.features.home.room.detail.timeline.item.AbsMessageItem import im.vector.app.features.home.room.detail.timeline.item.MessageInformationData import im.vector.app.features.home.room.detail.timeline.item.ReactionsSummaryEvents +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.threads.ThreadDetails import javax.inject.Inject @@ -66,7 +66,7 @@ class MessageItemAttributesFactory @Inject constructor( threadCallback = callback, readReceiptsCallback = callback, emojiTypeFace = emojiCompatFontProvider.typeface, - decryptionErrorMessage = stringProvider.getString(R.string.encrypted_message), + decryptionErrorMessage = stringProvider.getString(CommonStrings.encrypted_message), threadSummaryFormatted = displayableEventFormatter.formatThreadSummary(threadDetails?.threadSummaryLatestEvent).toString(), threadDetails = threadDetails, reactionsSummaryEvents = reactionsSummaryEvents, diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt index 107873b776..5fc0f58aa1 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt @@ -19,7 +19,6 @@ package im.vector.app.features.home.room.detail.timeline.helper import android.content.res.Resources import androidx.recyclerview.widget.RecyclerView import dagger.hilt.android.scopes.ActivityScoped -import im.vector.app.R import im.vector.app.features.settings.VectorPreferences import javax.inject.Inject import kotlin.math.roundToInt @@ -51,7 +50,7 @@ class TimelineMediaSizeProvider @Inject constructor( maxImageHeight = (height * 0.7f).roundToInt() } return if (vectorPreferences.useMessageBubblesLayout()) { - val bubbleMaxImageWidth = maxImageWidth.coerceAtMost(resources.getDimensionPixelSize(R.dimen.chat_bubble_fixed_size)) + val bubbleMaxImageWidth = maxImageWidth.coerceAtMost(resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.chat_bubble_fixed_size)) Pair(bubbleMaxImageWidth, maxImageHeight) } else { Pair(maxImageWidth, maxImageHeight) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt index ab383f04ff..c6e8d27a22 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt @@ -40,6 +40,8 @@ import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.app.features.home.room.detail.timeline.view.TimelineMessageLayoutRenderer import im.vector.app.features.reactions.widget.ReactionButton import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.send.SendState private const val MAX_REACTIONS_TO_SHOW = 8 @@ -110,13 +112,13 @@ abstract class AbsBaseMessageItem(@LayoutRes layo if (reactions.count() > MAX_REACTIONS_TO_SHOW) { val showReactionsTextView = createReactionTextView(holder) if (reactionsSummary.showAll) { - showReactionsTextView.setText(R.string.message_reaction_show_less) + showReactionsTextView.setText(CommonStrings.message_reaction_show_less) showReactionsTextView.onClick { baseAttributes.reactionsSummaryEvents?.onShowLessClicked?.invoke() } } else { val moreCount = reactions.count() - MAX_REACTIONS_TO_SHOW - showReactionsTextView.text = holder.view.resources.getQuantityString(R.plurals.message_reaction_show_more, moreCount, moreCount) + showReactionsTextView.text = holder.view.resources.getQuantityString(CommonPlurals.message_reaction_show_more, moreCount, moreCount) showReactionsTextView.onClick { baseAttributes.reactionsSummaryEvents?.onShowMoreClicked?.invoke() } @@ -135,11 +137,11 @@ abstract class AbsBaseMessageItem(@LayoutRes layo } private fun createReactionTextView(holder: H): TextView { - return TextView(ContextThemeWrapper(holder.view.context, R.style.TimelineReactionView)).apply { + return TextView(ContextThemeWrapper(holder.view.context, im.vector.lib.ui.styles.R.style.TimelineReactionView)).apply { background = getDrawable(context, R.drawable.reaction_rounded_rect_shape_off) - TextViewCompat.setTextAppearance(this, R.style.TextAppearance_Vector_Micro) + TextViewCompat.setTextAppearance(this, im.vector.lib.ui.styles.R.style.TextAppearance_Vector_Micro) setTypeface(typeface, Typeface.BOLD) - setTextColor(ThemeUtils.getColor(context, R.attr.vctr_content_secondary)) + setTextColor(ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary)) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageItem.kt index 869b7d17e2..1ea7705efa 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageItem.kt @@ -16,6 +16,7 @@ package im.vector.app.features.home.room.detail.timeline.item +import android.annotation.SuppressLint import android.graphics.Typeface import android.view.View import android.widget.ImageView @@ -69,6 +70,7 @@ abstract class AbsMessageItem( } } + @SuppressLint("SetTextI18n") override fun bind(holder: H) { super.bind(holder) if (attributes.informationData.messageLayout.showAvatar) { @@ -112,7 +114,7 @@ abstract class AbsMessageItem( holder.threadSummaryConstraintLayout.onClick(_threadClickListener) attributes.threadDetails?.let { threadDetails -> holder.threadSummaryConstraintLayout.isVisible = threadDetails.isRootThread - holder.threadSummaryCounterTextView.text = threadDetails.numberOfThreads.toString() + holder.threadSummaryCounterTextView.text = "${threadDetails.numberOfThreads}" holder.threadSummaryInfoTextView.text = attributes.threadSummaryFormatted ?: attributes.decryptionErrorMessage val userId = threadDetails.threadSummarySenderInfo?.userId ?: return@let diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageLocationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageLocationItem.kt index c3294d0301..5eef70d32e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageLocationItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageLocationItem.kt @@ -86,7 +86,7 @@ abstract class AbsMessageLocationItem( override fun onLoadFailed( e: GlideException?, model: Any?, - target: Target?, + target: Target, isFirstResource: Boolean ): Boolean { holder.staticMapPinImageView.setImageDrawable(null) @@ -98,10 +98,10 @@ abstract class AbsMessageLocationItem( } override fun onResourceReady( - resource: Drawable?, - model: Any?, + resource: Drawable, + model: Any, target: Target?, - dataSource: DataSource?, + dataSource: DataSource, isFirstResource: Boolean ): Boolean { locationPinProvider?.create(pinMatrixItem) { pinDrawable -> diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageVoiceBroadcastItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageVoiceBroadcastItem.kt index 21d1abbdf2..40deb848a1 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageVoiceBroadcastItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageVoiceBroadcastItem.kt @@ -75,14 +75,14 @@ abstract class AbsMessageVoiceBroadcastItem(@LayoutRes layoutId: Int) : BaseEventItem(layoutId) { @@ -35,10 +36,10 @@ abstract class BasedMergedItem(@LayoutRes layoutId: } if (attributes.isCollapsed) { holder.separatorView.visibility = View.GONE - holder.expandView.setText(R.string.merged_events_expand) + holder.expandView.setText(CommonStrings.merged_events_expand) } else { holder.separatorView.visibility = View.VISIBLE - holder.expandView.setText(R.string.merged_events_collapse) + holder.expandView.setText(CommonStrings.merged_events_collapse) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/CallTileTimelineItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/CallTileTimelineItem.kt index 86aada82ac..047a98eb3d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/CallTileTimelineItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/CallTileTimelineItem.kt @@ -37,6 +37,7 @@ import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.RoomDetailAction import im.vector.app.features.home.room.detail.timeline.MessageColorProvider import im.vector.app.features.home.room.detail.timeline.TimelineEventController +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.util.MatrixItem @EpoxyModelClass @@ -73,20 +74,20 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem { - val endCallStatus = holder.resources.getString(R.string.call_tile_video_call_has_ended, attributes.formattedDuration) + val endCallStatus = holder.resources.getString(CommonStrings.call_tile_video_call_has_ended, attributes.formattedDuration) holder.statusView.setStatus(endCallStatus) } CallKind.AUDIO -> { - val endCallStatus = holder.resources.getString(R.string.call_tile_voice_call_has_ended, attributes.formattedDuration) + val endCallStatus = holder.resources.getString(CommonStrings.call_tile_voice_call_has_ended, attributes.formattedDuration) holder.statusView.setStatus(endCallStatus) } CallKind.CONFERENCE -> { - holder.statusView.setStatus(R.string.call_tile_ended) + holder.statusView.setStatus(CommonStrings.call_tile_ended) } } } private fun renderRejectedStatus(holder: Holder) { holder.acceptRejectViewGroup.isVisible = true - holder.acceptView.setText(R.string.call_tile_call_back) - holder.acceptView.setLeftDrawable(attributes.callKind.icon, R.attr.colorOnPrimary) + holder.acceptView.setText(CommonStrings.call_tile_call_back) + holder.acceptView.setLeftDrawable(attributes.callKind.icon, com.google.android.material.R.attr.colorOnPrimary) holder.acceptView.onClick { val callbackAction = RoomDetailAction.StartCall(attributes.callKind == CallKind.VIDEO) attributes.callback?.onTimelineItemAction(callbackAction) @@ -123,15 +124,15 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem { holder.rejectView.isVisible = true - holder.rejectView.setText(R.string.action_leave) - holder.rejectView.setLeftDrawable(R.drawable.ic_call_hangup, R.attr.colorOnPrimary) + holder.rejectView.setText(CommonStrings.action_leave) + holder.rejectView.setLeftDrawable(R.drawable.ic_call_hangup, com.google.android.material.R.attr.colorOnPrimary) holder.rejectView.onClick { attributes.callback?.onTimelineItemAction(RoomDetailAction.LeaveJitsiCall) } } attributes.isStillActive -> { holder.rejectView.isVisible = true - holder.rejectView.setText(R.string.call_notification_hangup) - holder.rejectView.setLeftDrawable(R.drawable.ic_call_hangup, R.attr.colorOnPrimary) + holder.rejectView.setText(CommonStrings.call_notification_hangup) + holder.rejectView.setLeftDrawable(R.drawable.ic_call_hangup, com.google.android.material.R.attr.colorOnPrimary) holder.rejectView.onClick { attributes.callback?.onTimelineItemAction(RoomDetailAction.EndCall) } @@ -161,9 +162,9 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem { holder.acceptRejectViewGroup.isVisible = true @@ -186,18 +187,18 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem { @@ -207,16 +208,16 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem { - holder.statusView.setStatus(R.string.call_tile_video_active) + holder.statusView.setStatus(CommonStrings.call_tile_video_active) } attributes.informationData.sentByMe -> { - holder.statusView.setStatus(R.string.call_ringing) + holder.statusView.setStatus(CommonStrings.call_ringing) } attributes.callKind.isVoiceCall -> { - holder.statusView.setStatus(R.string.call_tile_voice_incoming) + holder.statusView.setStatus(CommonStrings.call_tile_voice_incoming) } else -> { - holder.statusView.setStatus(R.string.call_tile_video_incoming) + holder.statusView.setStatus(CommonStrings.call_tile_video_incoming) } } } @@ -268,9 +269,9 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem Triple( - R.string.encryption_enabled, - R.string.direct_room_encryption_enabled_tile_description_future, + CommonStrings.encryption_enabled, + CommonStrings.direct_room_encryption_enabled_tile_description_future, R.drawable.ic_shield_black ) isWaitingUser -> Triple( - R.string.direct_room_encryption_enabled_waiting_users, - R.string.direct_room_encryption_enabled_waiting_users_tile_description, + CommonStrings.direct_room_encryption_enabled_waiting_users, + CommonStrings.direct_room_encryption_enabled_waiting_users_tile_description, R.drawable.ic_room_profile_member_list ) else -> Triple( - R.string.encryption_enabled, - R.string.direct_room_encryption_enabled_tile_description, + CommonStrings.encryption_enabled, + CommonStrings.direct_room_encryption_enabled_tile_description, R.drawable.ic_shield_black ) } } else -> { - Triple(R.string.encryption_enabled, R.string.encryption_enabled_tile_description, R.drawable.ic_shield_black) + Triple(CommonStrings.encryption_enabled, CommonStrings.encryption_enabled_tile_description, R.drawable.ic_shield_black) } } @@ -164,8 +165,8 @@ abstract class MergedRoomCreationItem : BasedMergedItem { if (attributes.isLocalRoom) { - resources.getString(R.string.send_your_first_msg_to_invite, roomSummary?.displayName.orEmpty()) + resources.getString(CommonStrings.send_your_first_msg_to_invite, roomSummary?.displayName.orEmpty()) } else { - resources.getString(R.string.this_is_the_beginning_of_dm, roomSummary?.displayName.orEmpty()) + resources.getString(CommonStrings.this_is_the_beginning_of_dm, roomSummary?.displayName.orEmpty()) } } roomDisplayName.isNullOrBlank() || roomSummary?.name.isNullOrBlank() -> { - holder.view.resources.getString(R.string.this_is_the_beginning_of_room_no_name) + holder.view.resources.getString(CommonStrings.this_is_the_beginning_of_room_no_name) } else -> { - holder.view.resources.getString(R.string.this_is_the_beginning_of_room, roomDisplayName) + holder.view.resources.getString(CommonStrings.this_is_the_beginning_of_room, roomDisplayName) } } holder.roomDescriptionText.text = description if (isDirectRoom && attributes.isLocalRoom) { - TextViewCompat.setTextAppearance(holder.roomDescriptionText, R.style.TextAppearance_Vector_Subtitle) - holder.roomDescriptionText.setTextColor(ThemeUtils.getColor(holder.roomDescriptionText.context, R.attr.vctr_content_primary)) + TextViewCompat.setTextAppearance(holder.roomDescriptionText, im.vector.lib.ui.styles.R.style.TextAppearance_Vector_Subtitle) + holder.roomDescriptionText.setTextColor( + ThemeUtils.getColor(holder.roomDescriptionText.context, im.vector.lib.ui.styles.R.attr.vctr_content_primary) + ) } } @@ -245,8 +248,8 @@ abstract class MergedRoomCreationItem : BasedMergedItem() { @@ -87,7 +88,7 @@ abstract class MessageAudioItem : AbsMessageItem() { if (attributes.informationData.sendState.hasFailed()) { holder.audioPlaybackControlButton.setImageResource(R.drawable.ic_cross) holder.audioPlaybackControlButton.contentDescription = - holder.view.context.getString(R.string.error_audio_message_unable_to_play, filename) + holder.view.context.getString(CommonStrings.error_audio_message_unable_to_play, filename) holder.progressLayout.isVisible = false } else { contentUploadStateTrackerBinder.bind(attributes.informationData.eventId, izLocalFile, holder.progressLayout) @@ -98,7 +99,7 @@ abstract class MessageAudioItem : AbsMessageItem() { val backgroundTint = if (attributes.informationData.messageLayout is TimelineMessageLayout.Bubble) { Color.TRANSPARENT } else { - ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_quinary) + ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_quinary) } holder.mainLayout.backgroundTintList = ColorStateList.valueOf(backgroundTint) } @@ -112,10 +113,10 @@ abstract class MessageAudioItem : AbsMessageItem() { holder.filenameView.onClick(attributes.itemClickListener) holder.audioPlaybackDuration.text = formattedDuration holder.fileSize.text = holder.rootLayout.context.getString( - R.string.audio_message_file_size, formattedFileSize + CommonStrings.audio_message_file_size, formattedFileSize ) holder.mainLayout.contentDescription = holder.rootLayout.context.getString( - R.string.a11y_audio_message_item, filename, durationContentDescription, formattedFileSize + CommonStrings.a11y_audio_message_item, filename, durationContentDescription, formattedFileSize ) } @@ -154,7 +155,7 @@ abstract class MessageAudioItem : AbsMessageItem() { private fun renderIdleState(holder: Holder) { holder.audioPlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play) holder.audioPlaybackControlButton.contentDescription = - holder.view.context.getString(R.string.a11y_play_audio_message, filename) + holder.view.context.getString(CommonStrings.a11y_play_audio_message, filename) holder.audioPlaybackTime.text = formatPlaybackTime(duration) holder.audioSeekBar.progress = 0 } @@ -162,7 +163,7 @@ abstract class MessageAudioItem : AbsMessageItem() { private fun renderPlayingState(holder: Holder, state: AudioMessagePlaybackTracker.Listener.State.Playing) { holder.audioPlaybackControlButton.setImageResource(R.drawable.ic_play_pause_pause) holder.audioPlaybackControlButton.contentDescription = - holder.view.context.getString(R.string.a11y_pause_audio_message, filename) + holder.view.context.getString(CommonStrings.a11y_pause_audio_message, filename) if (!isUserSeeking) { holder.audioPlaybackTime.text = formatPlaybackTime(state.playbackTime) @@ -173,7 +174,7 @@ abstract class MessageAudioItem : AbsMessageItem() { private fun renderPausedState(holder: Holder, state: AudioMessagePlaybackTracker.Listener.State.Paused) { holder.audioPlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play) holder.audioPlaybackControlButton.contentDescription = - holder.view.context.getString(R.string.a11y_play_audio_message, filename) + holder.view.context.getString(CommonStrings.a11y_play_audio_message, filename) holder.audioPlaybackTime.text = formatPlaybackTime(state.playbackTime) holder.audioSeekBar.progress = (state.percentage * 100).toInt() } @@ -183,7 +184,7 @@ abstract class MessageAudioItem : AbsMessageItem() { private fun getPlaybackTimeContentDescription(context: Context, time: Int): String { val formattedPlaybackTime = formatPlaybackTime(time) val (minutes, seconds) = formattedPlaybackTime.split(":").map { it.toIntOrNull() ?: 0 } - return context.getString(R.string.a11y_audio_playback_duration, minutes, seconds) + return context.getString(CommonStrings.a11y_audio_playback_duration, minutes, seconds) } override fun unbind(holder: Holder) { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt index bf16c8959e..7b657da2df 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt @@ -87,7 +87,7 @@ abstract class MessageFileItem : AbsMessageItem() { val backgroundTint = if (attributes.informationData.messageLayout is TimelineMessageLayout.Bubble) { Color.TRANSPARENT } else { - ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_quinary) + ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_quinary) } holder.mainLayout.backgroundTintList = ColorStateList.valueOf(backgroundTint) holder.filenameView.onClick(attributes.itemClickListener) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceBroadcastListeningItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceBroadcastListeningItem.kt index b9d70b51cb..916700e488 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceBroadcastListeningItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceBroadcastListeningItem.kt @@ -34,6 +34,7 @@ import im.vector.app.features.voicebroadcast.listening.VoiceBroadcastPlayer import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState import im.vector.app.features.voicebroadcast.views.VoiceBroadcastBufferingView import im.vector.app.features.voicebroadcast.views.VoiceBroadcastMetadataView +import im.vector.lib.strings.CommonStrings @EpoxyModelClass abstract class MessageVoiceBroadcastListeningItem : AbsMessageVoiceBroadcastItem() { @@ -121,13 +122,13 @@ abstract class MessageVoiceBroadcastListeningItem : AbsMessageVoiceBroadcastItem VoiceBroadcastPlayer.State.Playing, VoiceBroadcastPlayer.State.Buffering -> { playPauseButton.setImageResource(R.drawable.ic_play_pause_pause) - playPauseButton.contentDescription = view.resources.getString(R.string.a11y_pause_voice_broadcast) + playPauseButton.contentDescription = view.resources.getString(CommonStrings.a11y_pause_voice_broadcast) } is VoiceBroadcastPlayer.State.Error, VoiceBroadcastPlayer.State.Idle, VoiceBroadcastPlayer.State.Paused -> { playPauseButton.setImageResource(R.drawable.ic_play_pause_play) - playPauseButton.contentDescription = view.resources.getString(R.string.a11y_play_voice_broadcast) + playPauseButton.contentDescription = view.resources.getString(CommonStrings.a11y_play_voice_broadcast) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceBroadcastRecordingItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceBroadcastRecordingItem.kt index abf14c0867..e8612b1ca1 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceBroadcastRecordingItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceBroadcastRecordingItem.kt @@ -28,6 +28,7 @@ import im.vector.app.features.home.room.detail.RoomDetailAction.VoiceBroadcastAc import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState import im.vector.app.features.voicebroadcast.recording.VoiceBroadcastRecorder import im.vector.app.features.voicebroadcast.views.VoiceBroadcastMetadataView +import im.vector.lib.strings.CommonStrings import org.threeten.bp.Duration @EpoxyModelClass @@ -75,7 +76,7 @@ abstract class MessageVoiceBroadcastRecordingItem : AbsMessageVoiceBroadcastItem holder.view.context, Duration.ofSeconds(remainingTime.coerceAtLeast(0L)) ) - holder.remainingTimeMetadata.value = holder.view.resources.getString(R.string.voice_broadcast_recording_time_left, formattedDuration) + holder.remainingTimeMetadata.value = holder.view.resources.getString(CommonStrings.voice_broadcast_recording_time_left, formattedDuration) holder.remainingTimeMetadata.isVisible = true } else { holder.remainingTimeMetadata.isVisible = false @@ -107,10 +108,10 @@ abstract class MessageVoiceBroadcastRecordingItem : AbsMessageVoiceBroadcastItem recordButton.isEnabled = true renderErrorState(holder, false) - val drawableColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + val drawableColor = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) val drawable = drawableProvider.getDrawable(R.drawable.ic_play_pause_pause, drawableColor) recordButton.setImageDrawable(drawable) - recordButton.contentDescription = holder.view.resources.getString(R.string.a11y_pause_voice_broadcast_record) + recordButton.contentDescription = holder.view.resources.getString(CommonStrings.a11y_pause_voice_broadcast_record) recordButton.onClick { callback?.onTimelineItemAction(VoiceBroadcastAction.Recording.Pause) } stopRecordButton.onClick { callback?.onTimelineItemAction(VoiceBroadcastAction.Recording.Stop) } } @@ -121,7 +122,7 @@ abstract class MessageVoiceBroadcastRecordingItem : AbsMessageVoiceBroadcastItem renderErrorState(holder, false) recordButton.setImageResource(R.drawable.ic_recording_dot) - recordButton.contentDescription = holder.view.resources.getString(R.string.a11y_resume_voice_broadcast_record) + recordButton.contentDescription = holder.view.resources.getString(CommonStrings.a11y_resume_voice_broadcast_record) recordButton.onClick { callback?.onTimelineItemAction(VoiceBroadcastAction.Recording.Resume) } stopRecordButton.onClick { callback?.onTimelineItemAction(VoiceBroadcastAction.Recording.Stop) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt index a8e215b4a9..35afa547f5 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt @@ -36,6 +36,7 @@ import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStat import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.voice.AudioWaveformView +import im.vector.lib.strings.CommonStrings @EpoxyModelClass abstract class MessageVoiceItem : AbsMessageItem() { @@ -79,7 +80,7 @@ abstract class MessageVoiceItem : AbsMessageItem() { contentUploadStateTrackerBinder.bind(attributes.informationData.eventId, izLocalFile, holder.progressLayout) } else { holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_cross) - holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.error_voice_message_unable_to_play) + holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(CommonStrings.error_voice_message_unable_to_play) holder.progressLayout.isVisible = false } @@ -90,7 +91,7 @@ abstract class MessageVoiceItem : AbsMessageItem() { val backgroundTint = if (attributes.informationData.messageLayout is TimelineMessageLayout.Bubble) { Color.TRANSPARENT } else { - ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_quinary) + ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_quinary) } holder.voicePlaybackLayout.backgroundTintList = ColorStateList.valueOf(backgroundTint) } @@ -99,8 +100,8 @@ abstract class MessageVoiceItem : AbsMessageItem() { holder.voicePlaybackWaveform.setOnLongClickListener(attributes.itemLongClickListener) holder.voicePlaybackControlButton.setOnClickListener { playbackControlButtonClickListener?.invoke(it) } - val waveformColorIdle = ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_quaternary) - val waveformColorPlayed = ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary) + val waveformColorIdle = ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_quaternary) + val waveformColorPlayed = ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary) holder.voicePlaybackWaveform.clear() waveform.forEach { amplitude -> @@ -137,21 +138,21 @@ abstract class MessageVoiceItem : AbsMessageItem() { private fun renderIdleState(holder: Holder, idleColor: Int, playedColor: Int) { holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play) - holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.a11y_play_voice_message) + holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(CommonStrings.a11y_play_voice_message) holder.voicePlaybackTime.text = formatPlaybackTime(duration) holder.voicePlaybackWaveform.updateColors(0f, playedColor, idleColor) } private fun renderPlayingState(holder: Holder, state: AudioMessagePlaybackTracker.Listener.State.Playing, idleColor: Int, playedColor: Int) { holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_pause) - holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.a11y_pause_voice_message) + holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(CommonStrings.a11y_pause_voice_message) holder.voicePlaybackTime.text = formatPlaybackTime(state.playbackTime) holder.voicePlaybackWaveform.updateColors(state.percentage, playedColor, idleColor) } private fun renderPausedState(holder: Holder, state: AudioMessagePlaybackTracker.Listener.State.Paused, idleColor: Int, playedColor: Int) { holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play) - holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.a11y_play_voice_message) + holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(CommonStrings.a11y_play_voice_message) holder.voicePlaybackTime.text = formatPlaybackTime(state.playbackTime) holder.voicePlaybackWaveform.updateColors(state.percentage, playedColor, idleColor) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/PollOptionView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/PollOptionView.kt index e8d636e20b..0edfe77af2 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/PollOptionView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/PollOptionView.kt @@ -26,6 +26,7 @@ import im.vector.app.R import im.vector.app.core.extensions.setAttributeTintedImageResource import im.vector.app.databinding.ItemPollOptionBinding import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonPlurals class PollOptionView @JvmOverloads constructor( context: Context, @@ -64,8 +65,8 @@ class PollOptionView @JvmOverloads constructor( val drawableStart = if (state.isWinner) R.drawable.ic_poll_winner else 0 views.optionVoteCountTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(drawableStart, 0, 0, 0) views.optionVoteCountTextView.setTextColor( - if (state.isWinner) ThemeUtils.getColor(context, R.attr.colorPrimary) - else ThemeUtils.getColor(context, R.attr.vctr_content_secondary) + if (state.isWinner) ThemeUtils.getColor(context, com.google.android.material.R.attr.colorPrimary) + else ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary) ) showVotes(state.voteCount, state.votePercentage) renderVoteSelection(state.isWinner) @@ -95,7 +96,7 @@ class PollOptionView @JvmOverloads constructor( private fun showVotes(voteCount: Int, votePercentage: Double) { views.optionVoteCountTextView.apply { isVisible = true - text = resources.getQuantityString(R.plurals.poll_option_vote_count, voteCount, voteCount) + text = resources.getQuantityString(CommonPlurals.poll_option_vote_count, voteCount, voteCount) } views.optionVoteProgress.apply { val progressValue = (votePercentage * 100).toInt() @@ -114,11 +115,11 @@ class PollOptionView @JvmOverloads constructor( private fun renderVoteSelection(isSelected: Boolean) { if (isSelected) { - views.optionBorderImageView.setAttributeTintedImageResource(R.drawable.bg_poll_option, R.attr.colorPrimary) + views.optionBorderImageView.setAttributeTintedImageResource(R.drawable.bg_poll_option, com.google.android.material.R.attr.colorPrimary) views.optionVoteProgress.progressDrawable = AppCompatResources.getDrawable(context, R.drawable.poll_option_progressbar_checked) views.optionCheckImageView.setImageResource(R.drawable.poll_option_checked) } else { - views.optionBorderImageView.setAttributeTintedImageResource(R.drawable.bg_poll_option, R.attr.vctr_content_quinary) + views.optionBorderImageView.setAttributeTintedImageResource(R.drawable.bg_poll_option, im.vector.lib.ui.styles.R.attr.vctr_content_quinary) views.optionVoteProgress.progressDrawable = AppCompatResources.getDrawable(context, R.drawable.poll_option_progressbar_unchecked) views.optionCheckImageView.setImageResource(R.drawable.poll_option_unchecked) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/VerificationRequestItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/VerificationRequestItem.kt index 47b9a1afa9..86d11ba319 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/VerificationRequestItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/VerificationRequestItem.kt @@ -36,6 +36,7 @@ import im.vector.app.features.home.room.detail.RoomDetailAction import im.vector.app.features.home.room.detail.timeline.MessageColorProvider import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.crypto.verification.VerificationService import org.matrix.android.sdk.api.session.crypto.verification.VerificationState @@ -65,9 +66,9 @@ abstract class VerificationRequestItem : AbsBaseMessageItem { holder.buttonBar.isVisible = false holder.statusTextView.text = holder.view.context - .getString(R.string.verification_request_other_cancelled, attributes.informationData.memberName) + .getString(CommonStrings.verification_request_other_cancelled, attributes.informationData.memberName) holder.statusTextView.isVisible = true } VerificationState.CANCELED_BY_ME -> { holder.buttonBar.isVisible = false - holder.statusTextView.text = holder.view.context.getString(R.string.verification_request_you_cancelled) + holder.statusTextView.text = holder.view.context.getString(CommonStrings.verification_request_you_cancelled) holder.statusTextView.isVisible = true } VerificationState.WAITING -> { holder.buttonBar.isVisible = false - holder.statusTextView.text = holder.view.context.getString(R.string.verification_request_waiting) + holder.statusTextView.text = holder.view.context.getString(CommonStrings.verification_request_waiting) holder.statusTextView.isVisible = true } VerificationState.DONE -> { holder.buttonBar.isVisible = false holder.statusTextView.text = if (attributes.informationData.sentByMe) { - holder.view.context.getString(R.string.verification_request_other_accepted, attributes.otherUserName) + holder.view.context.getString(CommonStrings.verification_request_other_accepted, attributes.otherUserName) } else { - holder.view.context.getString(R.string.verification_request_you_accepted) + holder.view.context.getString(CommonStrings.verification_request_you_accepted) } holder.statusTextView.isVisible = true } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsBottomSheet.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsBottomSheet.kt index 6c6a722f02..ba31307777 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsBottomSheet.kt @@ -32,6 +32,7 @@ import im.vector.app.features.home.room.detail.timeline.action.EventSharedAction import im.vector.app.features.home.room.detail.timeline.action.MessageSharedActionViewModel import im.vector.app.features.home.room.detail.timeline.action.TimelineEventFragmentArgs import im.vector.app.features.home.room.detail.timeline.item.MessageInformationData +import im.vector.lib.strings.CommonStrings import javax.inject.Inject /** @@ -60,7 +61,7 @@ class ViewReactionsBottomSheet : hasFixedSize = false, dividerDrawable = R.drawable.divider_horizontal_on_secondary ) - views.bottomSheetTitle.text = context?.getString(R.string.reactions) + views.bottomSheetTitle.text = context?.getString(CommonStrings.reactions) epoxyController.listener = this } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsEpoxyController.kt index 7f619d3838..271ed6ebab 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsEpoxyController.kt @@ -22,11 +22,11 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import im.vector.app.EmojiSpanify -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.core.ui.list.genericLoaderItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import javax.inject.Inject /** @@ -52,7 +52,7 @@ class ViewReactionsEpoxyController @Inject constructor( is Fail -> { genericFooterItem { id("failure") - text(host.stringProvider.getString(R.string.unknown_error).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.unknown_error).toEpoxyCharSequence()) } } is Success -> { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/readreceipts/DisplayReadReceiptsBottomSheet.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/readreceipts/DisplayReadReceiptsBottomSheet.kt index f3658cdf1d..c09b5de1ee 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/readreceipts/DisplayReadReceiptsBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/readreceipts/DisplayReadReceiptsBottomSheet.kt @@ -23,7 +23,6 @@ import android.view.View import android.view.ViewGroup import com.airbnb.mvrx.args import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment @@ -31,6 +30,7 @@ import im.vector.app.databinding.BottomSheetGenericListWithTitleBinding import im.vector.app.features.home.room.detail.timeline.action.EventSharedAction import im.vector.app.features.home.room.detail.timeline.action.MessageSharedActionViewModel import im.vector.app.features.home.room.detail.timeline.item.ReadReceiptData +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import javax.inject.Inject @@ -61,7 +61,7 @@ class DisplayReadReceiptsBottomSheet : super.onViewCreated(view, savedInstanceState) sharedActionViewModel = activityViewModelProvider.get(MessageSharedActionViewModel::class.java) views.bottomSheetRecyclerView.configureWith(epoxyController, hasFixedSize = false) - views.bottomSheetTitle.text = getString(R.string.seen_by) + views.bottomSheetTitle.text = getString(CommonStrings.seen_by) epoxyController.listener = this epoxyController.setData(displayReadReceiptArgs.readReceipts) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/EventTextRenderer.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/EventTextRenderer.kt index 79e8690c91..c895eba45c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/EventTextRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/EventTextRenderer.kt @@ -24,11 +24,11 @@ import android.util.Patterns import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.glide.GlideApp import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.html.PillImageSpan +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.getRoomSummary import org.matrix.android.sdk.api.session.getUserOrDefault @@ -99,7 +99,7 @@ class EventTextRenderer @AssistedInject constructor( private fun addPermalinksSpans(text: Spannable) { for (match in Patterns.WEB_URL.toRegex().findAll(text)) { val url = text.substring(match.range) - val supportedHosts = context.resources.getStringArray(R.array.permalink_supported_hosts) + val supportedHosts = context.resources.getStringArray(im.vector.app.config.R.array.permalink_supported_hosts) val isPermalinkSupported = sessionHolder.getSafeActiveSession()?.permalinkService()?.isPermalinkSupported(supportedHosts, url).orFalse() val matrixItem = if (isPermalinkSupported) { when (val permalinkData = PermalinkParser.parse(url)) { @@ -136,7 +136,7 @@ class EventTextRenderer @AssistedInject constructor( val room: RoomSummary? = sessionHolder.getSafeActiveSession()?.getRoomSummary(roomIdOrAlias) when { isRoomAlias -> MatrixItem.RoomAliasItem(roomIdOrAlias, room?.displayName, room?.avatarUrl) - room == null -> MatrixItem.RoomItem(roomIdOrAlias, context.getString(R.string.pill_message_unknown_room_or_space)) + room == null -> MatrixItem.RoomItem(roomIdOrAlias, context.getString(CommonStrings.pill_message_unknown_room_or_space)) room.roomType == RoomType.SPACE -> MatrixItem.SpaceItem(roomIdOrAlias, room.displayName, room.avatarUrl) else -> MatrixItem.RoomItem(roomIdOrAlias, room.displayName, room.avatarUrl) } @@ -146,25 +146,25 @@ class EventTextRenderer @AssistedInject constructor( val event = session?.eventService()?.getEventFromCache(roomId, eventId!!) val user = event?.senderId?.let { session.roomService().getRoomMember(it, roomId) } val text = user?.let { - context.getString(R.string.pill_message_from_user, user.displayName) - } ?: context.getString(R.string.pill_message_from_unknown_user) + context.getString(CommonStrings.pill_message_from_user, user.displayName) + } ?: context.getString(CommonStrings.pill_message_from_unknown_user) MatrixItem.RoomItem(roomIdOrAlias, text, user?.avatarUrl, user?.displayName) } else { val room: RoomSummary? = sessionHolder.getSafeActiveSession()?.getRoomSummary(roomIdOrAlias) when { isRoomAlias -> MatrixItem.RoomAliasItem( roomIdOrAlias, - context.getString(R.string.pill_message_in_room, room?.displayName ?: roomIdOrAlias), + context.getString(CommonStrings.pill_message_in_room, room?.displayName ?: roomIdOrAlias), room?.avatarUrl, room?.displayName ) room != null -> MatrixItem.RoomItem( roomIdOrAlias, - context.getString(R.string.pill_message_in_room, room.displayName), + context.getString(CommonStrings.pill_message_in_room, room.displayName), room.avatarUrl, room.displayName ) - else -> MatrixItem.RoomItem(roomIdOrAlias, context.getString(R.string.pill_message_in_unknown_room)) + else -> MatrixItem.RoomItem(roomIdOrAlias, context.getString(CommonStrings.pill_message_in_unknown_room)) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/ProcessBodyOfReplyToEventUseCase.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/ProcessBodyOfReplyToEventUseCase.kt index d6e97e0ef9..58cfe9b254 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/ProcessBodyOfReplyToEventUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/ProcessBodyOfReplyToEventUseCase.kt @@ -16,9 +16,9 @@ package im.vector.app.features.home.room.detail.timeline.render -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.getPollQuestion import org.matrix.android.sdk.api.session.events.model.getRelationContent @@ -59,46 +59,46 @@ class ProcessBodyOfReplyToEventUseCase @Inject constructor( matrixFormattedBody.replaceRange( afterBreakingLineIndex, endOfBlockQuoteIndex, - stringProvider.getString(R.string.message_reply_to_sender_sent_file) + stringProvider.getString(CommonStrings.message_reply_to_sender_sent_file) ) } repliedToEvent.isVoiceMessage() -> { matrixFormattedBody.replaceRange( afterBreakingLineIndex, endOfBlockQuoteIndex, - stringProvider.getString(R.string.message_reply_to_sender_sent_voice_message) + stringProvider.getString(CommonStrings.message_reply_to_sender_sent_voice_message) ) } repliedToEvent.isAudioMessage() -> { matrixFormattedBody.replaceRange( afterBreakingLineIndex, endOfBlockQuoteIndex, - stringProvider.getString(R.string.message_reply_to_sender_sent_audio_file) + stringProvider.getString(CommonStrings.message_reply_to_sender_sent_audio_file) ) } repliedToEvent.isImageMessage() -> { matrixFormattedBody.replaceRange( afterBreakingLineIndex, endOfBlockQuoteIndex, - stringProvider.getString(R.string.message_reply_to_sender_sent_image) + stringProvider.getString(CommonStrings.message_reply_to_sender_sent_image) ) } repliedToEvent.isVideoMessage() -> { matrixFormattedBody.replaceRange( afterBreakingLineIndex, endOfBlockQuoteIndex, - stringProvider.getString(R.string.message_reply_to_sender_sent_video) + stringProvider.getString(CommonStrings.message_reply_to_sender_sent_video) ) } repliedToEvent.isSticker() -> { matrixFormattedBody.replaceRange( afterBreakingLineIndex, endOfBlockQuoteIndex, - stringProvider.getString(R.string.message_reply_to_sender_sent_sticker) + stringProvider.getString(CommonStrings.message_reply_to_sender_sent_sticker) ) } repliedToEvent.isPollEnd() -> { - val fallbackText = stringProvider.getString(R.string.message_reply_to_sender_ended_poll) + val fallbackText = stringProvider.getString(CommonStrings.message_reply_to_sender_ended_poll) val repliedText = getPollQuestionFromPollEnd(repliedToEvent) matrixFormattedBody.replaceRange( afterBreakingLineIndex, @@ -107,7 +107,7 @@ class ProcessBodyOfReplyToEventUseCase @Inject constructor( ) } repliedToEvent.isPollStart() -> { - val fallbackText = stringProvider.getString(R.string.message_reply_to_sender_created_poll) + val fallbackText = stringProvider.getString(CommonStrings.message_reply_to_sender_created_poll) val repliedText = repliedToEvent.getPollQuestion() matrixFormattedBody.replaceRange( afterBreakingLineIndex, @@ -119,7 +119,7 @@ class ProcessBodyOfReplyToEventUseCase @Inject constructor( matrixFormattedBody.replaceRange( afterBreakingLineIndex, endOfBlockQuoteIndex, - stringProvider.getString(R.string.live_location_description) + stringProvider.getString(CommonStrings.live_location_description) ) } else -> matrixFormattedBody @@ -130,7 +130,7 @@ class ProcessBodyOfReplyToEventUseCase @Inject constructor( return withTranslatedContent.replace( IN_REPLY_TO, - stringProvider.getString(R.string.message_reply_to_prefix) + stringProvider.getString(CommonStrings.message_reply_to_prefix) ) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt index 6e34aeeca2..ca46520a45 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt @@ -17,7 +17,6 @@ package im.vector.app.features.home.room.detail.timeline.style import android.content.res.Resources -import im.vector.app.R import im.vector.app.core.extensions.getVectorLastMessageContent import im.vector.app.core.extensions.localDateTime import im.vector.app.core.resources.LocaleProvider @@ -79,7 +78,7 @@ class TimelineMessageLayoutFactory @Inject constructor( } private val cornerRadius: Float by lazy { - resources.getDimensionPixelSize(R.dimen.chat_bubble_corner_radius).toFloat() + resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.chat_bubble_corner_radius).toFloat() } private val isRTL: Boolean by lazy { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt index 0e2429d45a..1c1a42cb47 100755 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt @@ -49,7 +49,7 @@ class PreviewUrlView @JvmOverloads constructor( init { setupView() - radius = resources.getDimensionPixelSize(R.dimen.preview_url_view_corner_radius).toFloat() + radius = resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.preview_url_view_corner_radius).toFloat() cardElevation = 0f } @@ -86,7 +86,7 @@ class PreviewUrlView @JvmOverloads constructor( override fun renderMessageLayout(messageLayout: TimelineMessageLayout) { when (messageLayout) { is TimelineMessageLayout.Default -> { - val backgroundColor = ThemeUtils.getColor(context, R.attr.vctr_system) + val backgroundColor = ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_system) setCardBackgroundColor(backgroundColor) val guidelineBegin = DimensionConverter(resources).dpToPx(8) views.urlPreviewStartGuideline.setGuidelineBegin(guidelineBegin) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/view/MessageBubbleView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/view/MessageBubbleView.kt index 6ac787b719..2c07cf3f50 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/view/MessageBubbleView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/view/MessageBubbleView.kt @@ -59,8 +59,8 @@ class MessageBubbleView @JvmOverloads constructor( init { inflate(context, R.layout.view_message_bubble, this) - context.withStyledAttributes(attrs, R.styleable.MessageBubble) { - isIncoming = getBoolean(R.styleable.MessageBubble_incoming_style, false) + context.withStyledAttributes(attrs, im.vector.lib.ui.styles.R.styleable.MessageBubble) { + isIncoming = getBoolean(im.vector.lib.ui.styles.R.styleable.MessageBubble_incoming_style, false) } } @@ -89,7 +89,8 @@ class MessageBubbleView @JvmOverloads constructor( outlineProvider = ViewOutlineProvider.BACKGROUND clipToOutline = true background = RippleDrawable( - ContextCompat.getColorStateList(context, R.color.mtrl_btn_ripple_color) ?: ColorStateList.valueOf(Color.TRANSPARENT), + ContextCompat.getColorStateList(context, com.google.android.material.R.color.mtrl_btn_ripple_color) + ?: ColorStateList.valueOf(Color.TRANSPARENT), bubbleDrawable, rippleMaskDrawable ) @@ -114,7 +115,12 @@ class MessageBubbleView @JvmOverloads constructor( this.fillColor = if (isPseudoBubble) { ColorStateList.valueOf(Color.TRANSPARENT) } else { - val backgroundColorAttr = if (isIncoming) R.attr.vctr_message_bubble_inbound else R.attr.vctr_message_bubble_outbound + val backgroundColorAttr = + if (isIncoming) { + im.vector.lib.ui.styles.R.attr.vctr_message_bubble_inbound + } else { + im.vector.lib.ui.styles.R.attr.vctr_message_bubble_outbound + } val backgroundColor = ThemeUtils.getColor(context, backgroundColorAttr) ColorStateList.valueOf(backgroundColor) } @@ -127,7 +133,7 @@ class MessageBubbleView @JvmOverloads constructor( clone(views.bubbleView) clear(R.id.viewStubContainer, ConstraintSet.END) if (timestampInsideMessage) { - connect(R.id.viewStubContainer, ConstraintSet.END, R.id.parent, ConstraintSet.END, 0) + connect(R.id.viewStubContainer, ConstraintSet.END, com.google.android.material.R.id.parent, ConstraintSet.END, 0) } else { connect(R.id.viewStubContainer, ConstraintSet.END, R.id.messageTimeView, ConstraintSet.START, 0) } @@ -137,12 +143,12 @@ class MessageBubbleView @JvmOverloads constructor( private fun TimelineMessageLayout.Bubble.toggleMessageOverlay() = apply { if (addMessageOverlay) { - val timeColor = ContextCompat.getColor(context, R.color.palette_white) + val timeColor = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.palette_white) views.messageTimeView.setTextColor(timeColor) views.messageOverlayView.isVisible = true (views.messageOverlayView.background as? GradientDrawable)?.cornerRadii = cornersRadius.toFloatArray() } else { - val timeColor = ThemeUtils.getColor(context, R.attr.vctr_content_tertiary) + val timeColor = ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_content_tertiary) views.messageTimeView.setTextColor(timeColor) views.messageOverlayView.isVisible = false } @@ -159,17 +165,17 @@ class MessageBubbleView @JvmOverloads constructor( private fun TimelineMessageLayout.Bubble.setMargins() = apply { if (isIncoming) { views.messageEndGuideline.updateLayoutParams { - marginEnd = resources.getDimensionPixelSize(R.dimen.chat_bubble_margin_end) + marginEnd = resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.chat_bubble_margin_end) } views.messageStartGuideline.updateLayoutParams { - marginStart = resources.getDimensionPixelSize(R.dimen.chat_bubble_margin_start) + marginStart = resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.chat_bubble_margin_start) } } else { views.messageEndGuideline.updateLayoutParams { - marginEnd = resources.getDimensionPixelSize(R.dimen.chat_bubble_margin_start) + marginEnd = resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.chat_bubble_margin_start) } views.messageStartGuideline.updateLayoutParams { - marginStart = resources.getDimensionPixelSize(R.dimen.chat_bubble_margin_end) + marginStart = resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.chat_bubble_margin_end) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomBottomSheet.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomBottomSheet.kt index 31662abd83..c3738c9c13 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomBottomSheet.kt @@ -28,11 +28,11 @@ import com.airbnb.mvrx.Success import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.databinding.BottomSheetRoomUpgradeBinding +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import javax.inject.Inject @@ -60,14 +60,14 @@ class MigrateRoomBottomSheet : val viewModel: MigrateRoomViewModel by fragmentViewModel() override fun invalidate() = withState(viewModel) { state -> - views.headerText.setText(if (state.isPublic) R.string.upgrade_public_room else R.string.upgrade_private_room) + views.headerText.setText(if (state.isPublic) CommonStrings.upgrade_public_room else CommonStrings.upgrade_private_room) if (state.migrationReason == MigrationReason.MANUAL) { - views.descriptionText.text = getString(R.string.upgrade_room_warning) - views.upgradeFromTo.text = getString(R.string.upgrade_public_room_from_to, state.currentVersion, state.newVersion) + views.descriptionText.text = getString(CommonStrings.upgrade_room_warning) + views.upgradeFromTo.text = getString(CommonStrings.upgrade_public_room_from_to, state.currentVersion, state.newVersion) } else if (state.migrationReason == MigrationReason.FOR_RESTRICTED) { views.descriptionText.setTextOrHide(state.customDescription) - views.upgradeFromTo.text = getString(R.string.upgrade_room_for_restricted_note) + views.upgradeFromTo.text = getString(CommonStrings.upgrade_room_for_restricted_note) } if (state.autoMigrateMembersAndParents) { @@ -94,10 +94,10 @@ class MigrateRoomBottomSheet : val errorText = when (result) { is UpgradeRoomViewModelTask.Result.UnknownRoom -> { // should not happen - getString(R.string.unknown_error) + getString(CommonStrings.unknown_error) } is UpgradeRoomViewModelTask.Result.NotAllowed -> { - getString(R.string.upgrade_room_no_power_to_manage) + getString(CommonStrings.upgrade_room_no_power_to_manage) } is UpgradeRoomViewModelTask.Result.ErrorFailure -> { errorFormatter.toHumanReadable(result.throwable) @@ -106,7 +106,7 @@ class MigrateRoomBottomSheet : } views.inlineError.setTextOrHide(errorText) views.button.isVisible = true - views.button.text = getString(R.string.global_retry) + views.button.text = getString(CommonStrings.global_retry) } is UpgradeRoomViewModelTask.Result.Success -> { setFragmentResult(REQUEST_KEY, Bundle().apply { @@ -118,7 +118,7 @@ class MigrateRoomBottomSheet : } else -> { views.button.isVisible = true - views.button.text = getString(R.string.upgrade) + views.button.text = getString(CommonStrings.upgrade) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsBannerView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsBannerView.kt index b934136dc2..235f8e65b6 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsBannerView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsBannerView.kt @@ -22,6 +22,7 @@ import android.view.View import android.widget.RelativeLayout import im.vector.app.R import im.vector.app.databinding.ViewRoomWidgetsBannerBinding +import im.vector.lib.strings.CommonPlurals import org.matrix.android.sdk.api.session.widgets.model.Widget class RoomWidgetsBannerView @JvmOverloads constructor( @@ -56,7 +57,7 @@ class RoomWidgetsBannerView @JvmOverloads constructor( visibility = View.GONE } else { visibility = View.VISIBLE - views.activeWidgetsLabel.text = context.resources.getQuantityString(R.plurals.active_widgets, widgets.size, widgets.size) + views.activeWidgetsLabel.text = context.resources.getQuantityString(CommonPlurals.active_widgets, widgets.size, widgets.size) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsBottomSheet.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsBottomSheet.kt index 72f9688ad8..e8e8d7fee7 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsBottomSheet.kt @@ -23,7 +23,6 @@ import android.view.ViewGroup import com.airbnb.mvrx.parentFragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment @@ -33,6 +32,7 @@ import im.vector.app.features.home.room.detail.RoomDetailAction import im.vector.app.features.home.room.detail.RoomDetailViewState import im.vector.app.features.home.room.detail.TimelineViewModel import im.vector.app.features.navigation.Navigator +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.widgets.model.Widget import javax.inject.Inject @@ -57,9 +57,9 @@ class RoomWidgetsBottomSheet : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) views.bottomSheetRecyclerView.configureWith(epoxyController, hasFixedSize = false) - views.bottomSheetTitle.text = getString(R.string.active_widgets_title) + views.bottomSheetTitle.text = getString(CommonStrings.active_widgets_title) views.bottomSheetTitle.textSize = 20f - views.bottomSheetTitle.setTextColor(colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + views.bottomSheetTitle.setTextColor(colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) epoxyController.listener = this timelineViewModel.onAsync(RoomDetailViewState::activeRoomWidgets) { epoxyController.setData(it) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsController.kt index ef122509a4..dccd5b00b8 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsController.kt @@ -17,12 +17,12 @@ package im.vector.app.features.home.room.detail.widget import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericButtonItem import im.vector.app.core.ui.list.genericFooterItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.widgets.model.Widget import javax.inject.Inject @@ -42,7 +42,7 @@ class RoomWidgetsController @Inject constructor( if (widgets.isEmpty()) { genericFooterItem { id("empty") - text(host.stringProvider.getString(R.string.room_no_active_widgets).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.room_no_active_widgets).toEpoxyCharSequence()) } } else { widgets.forEach { widget -> @@ -55,8 +55,8 @@ class RoomWidgetsController @Inject constructor( } genericButtonItem { id("addIntegration") - text(host.stringProvider.getString(R.string.room_manage_integrations)) - textColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + text(host.stringProvider.getString(CommonStrings.room_manage_integrations)) + textColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) buttonClickAction { host.listener?.didSelectManageWidgets() } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/filtered/FilteredRoomFooterItem.kt b/vector/src/main/java/im/vector/app/features/home/room/filtered/FilteredRoomFooterItem.kt index 7994240ec0..8a751b27ad 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/filtered/FilteredRoomFooterItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/filtered/FilteredRoomFooterItem.kt @@ -24,6 +24,7 @@ import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel import im.vector.app.core.epoxy.onClick +import im.vector.lib.strings.CommonStrings @EpoxyModelClass abstract class FilteredRoomFooterItem : VectorEpoxyModel(R.layout.item_room_filter_footer) { @@ -44,7 +45,7 @@ abstract class FilteredRoomFooterItem : VectorEpoxyModel(R.la override fun bind(holder: Holder) { super.bind(holder) - val tintColor = ThemeUtils.getColor(holder.rootView.context, R.attr.vctr_content_secondary) + val tintColor = ThemeUtils.getColor(holder.rootView.context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary) val expandedArrowDrawableRes = if (expanded) R.drawable.ic_expand_more else R.drawable.ic_expand_less val expandedArrowDrawable = ContextCompat.getDrawable(holder.rootView.context, expandedArrowDrawableRes)?.also { DrawableCompat.setTint(it, tintColor) } holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State.Count(unreadNotificationCount, showHighlighted)) holder.titleView.text = title - holder.counterView.text = itemCount.takeIf { it > 0 }?.toString().orEmpty() + holder.counterView.text = if (itemCount > 0) "$itemCount" else null holder.counterView.setCompoundDrawablesWithIntrinsicBounds(null, null, expandedArrowDrawable, null) holder.rootView.onClick(listener) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFooterController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFooterController.kt index 269af4afa0..5f853dcace 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFooterController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFooterController.kt @@ -17,13 +17,13 @@ package im.vector.app.features.home.room.list import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.epoxy.helpFooterItem import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.UserPreferencesProvider import im.vector.app.features.home.RoomListDisplayMode import im.vector.app.features.home.room.filtered.FilteredRoomFooterItem import im.vector.app.features.home.room.filtered.filteredRoomFooterItem +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class RoomListFooterController @Inject constructor( @@ -48,7 +48,7 @@ class RoomListFooterController @Inject constructor( if (userPreferencesProvider.shouldShowLongClickOnRoomHelp()) { helpFooterItem { id("long_click_help") - text(host.stringProvider.getString(R.string.help_long_click_on_room_for_more_options)) + text(host.stringProvider.getString(CommonStrings.help_long_click_on_room_for_more_options)) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt index 970b1c34e1..a0ab6a6681 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt @@ -54,6 +54,7 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA import im.vector.app.features.home.room.list.widget.NotifsFabMenuView import im.vector.app.features.matrixto.OriginOfMatrixTo import im.vector.app.features.notifications.NotificationDrawerManager +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -462,19 +463,22 @@ class RoomListFragment : private fun promptLeaveRoom(roomId: String) { val isPublicRoom = roomListViewModel.isPublicRoom(roomId) val message = buildString { - append(getString(R.string.room_participants_leave_prompt_msg)) + append(getString(CommonStrings.room_participants_leave_prompt_msg)) if (!isPublicRoom) { append("\n\n") - append(getString(R.string.room_participants_leave_private_warning)) + append(getString(CommonStrings.room_participants_leave_private_warning)) } } - MaterialAlertDialogBuilder(requireContext(), if (isPublicRoom) 0 else R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) - .setTitle(R.string.room_participants_leave_prompt_title) + MaterialAlertDialogBuilder( + requireContext(), + if (isPublicRoom) 0 else im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive + ) + .setTitle(CommonStrings.room_participants_leave_prompt_title) .setMessage(message) - .setPositiveButton(R.string.action_leave) { _, _ -> + .setPositiveButton(CommonStrings.action_leave) { _, _ -> roomListViewModel.handle(RoomListAction.LeaveRoom(roomId)) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } @@ -489,24 +493,24 @@ class RoomListFragment : val emptyState = when (roomListParams.displayMode) { RoomListDisplayMode.NOTIFICATIONS -> { StateView.State.Empty( - title = getString(R.string.room_list_catchup_empty_title), + title = getString(CommonStrings.room_list_catchup_empty_title), image = ContextCompat.getDrawable(requireContext(), R.drawable.ic_noun_party_popper), - message = getString(R.string.room_list_catchup_empty_body) + message = getString(CommonStrings.room_list_catchup_empty_body) ) } RoomListDisplayMode.PEOPLE -> StateView.State.Empty( - title = getString(R.string.room_list_people_empty_title), + title = getString(CommonStrings.room_list_people_empty_title), image = ContextCompat.getDrawable(requireContext(), R.drawable.empty_state_dm), isBigImage = true, - message = getString(R.string.room_list_people_empty_body) + message = getString(CommonStrings.room_list_people_empty_body) ) RoomListDisplayMode.ROOMS -> StateView.State.Empty( - title = getString(R.string.room_list_rooms_empty_title), + title = getString(CommonStrings.room_list_rooms_empty_title), image = ContextCompat.getDrawable(requireContext(), R.drawable.empty_state_room), isBigImage = true, - message = getString(R.string.room_list_rooms_empty_body) + message = getString(CommonStrings.room_list_rooms_empty_body) ) RoomListDisplayMode.FILTERED -> // Always display the content in this mode, because if the footer diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt index 236cf3fb69..13912aa654 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt @@ -23,12 +23,12 @@ import androidx.lifecycle.asFlow import androidx.lifecycle.liveData import androidx.paging.PagedList import com.airbnb.mvrx.Async -import im.vector.app.R import im.vector.app.SpaceStateHandler import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.RoomListDisplayMode import im.vector.app.features.invite.AutoAcceptInvites import im.vector.app.features.invite.showInvites +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow @@ -115,7 +115,7 @@ class RoomListSectionBuilder( addSection( sections = sections, activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.invitations_header, + nameRes = CommonStrings.invitations_header, notifyOfLocalEcho = true, spaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL, countRoomAsNotif = true @@ -128,7 +128,7 @@ class RoomListSectionBuilder( addSection( sections, activeSpaceAwareQueries, - R.string.bottom_action_favourites, + CommonStrings.bottom_action_favourites, false, RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL ) { @@ -140,7 +140,7 @@ class RoomListSectionBuilder( addSection( sections = sections, activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.bottom_action_rooms, + nameRes = CommonStrings.bottom_action_rooms, notifyOfLocalEcho = false, spaceFilterStrategy = if (onlyOrphansInHome) { RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL @@ -156,7 +156,7 @@ class RoomListSectionBuilder( addSection( sections = sections, activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.low_priority_header, + nameRes = CommonStrings.low_priority_header, notifyOfLocalEcho = false, spaceFilterStrategy = if (onlyOrphansInHome) { RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL @@ -172,7 +172,7 @@ class RoomListSectionBuilder( addSection( sections = sections, activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.system_alerts_header, + nameRes = CommonStrings.system_alerts_header, notifyOfLocalEcho = false, spaceFilterStrategy = if (onlyOrphansInHome) { RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL @@ -224,7 +224,7 @@ class RoomListSectionBuilder( sections.add( RoomsSection( - sectionName = stringProvider.getString(R.string.suggested_header), + sectionName = stringProvider.getString(CommonStrings.suggested_header), liveSuggested = liveSuggestedRooms, notifyOfLocalEcho = false, itemCount = suggestedRoomsFlow.map { suggestions -> suggestions.size } @@ -240,7 +240,7 @@ class RoomListSectionBuilder( addSection( sections = sections, activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.invitations_header, + nameRes = CommonStrings.invitations_header, notifyOfLocalEcho = true, spaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL, countRoomAsNotif = true @@ -253,7 +253,7 @@ class RoomListSectionBuilder( addSection( sections, activeSpaceAwareQueries, - R.string.bottom_action_favourites, + CommonStrings.bottom_action_favourites, false, RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL ) { @@ -265,7 +265,7 @@ class RoomListSectionBuilder( addSection( sections, activeSpaceAwareQueries, - R.string.bottom_action_people_x, + CommonStrings.bottom_action_people_x, false, RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL ) { @@ -277,7 +277,7 @@ class RoomListSectionBuilder( addSection( sections, activeSpaceAwareQueries, - R.string.low_priority_header, + CommonStrings.low_priority_header, false, RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL ) { @@ -295,7 +295,7 @@ class RoomListSectionBuilder( addSection( sections = sections, activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.invitations_header, + nameRes = CommonStrings.invitations_header, notifyOfLocalEcho = true, spaceFilterStrategy = if (onlyOrphansInHome) { RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL @@ -311,7 +311,7 @@ class RoomListSectionBuilder( addSection( sections = sections, activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.bottom_action_rooms, + nameRes = CommonStrings.bottom_action_rooms, notifyOfLocalEcho = false, spaceFilterStrategy = if (onlyOrphansInHome) { RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL @@ -331,7 +331,7 @@ class RoomListSectionBuilder( it.memberships = Membership.activeMemberships() }, { queryParams -> - val name = stringProvider.getString(R.string.bottom_action_rooms) + val name = stringProvider.getString(CommonStrings.bottom_action_rooms) val updatableFilterLivePageResult = session.roomService().getFilteredPagedRoomSummariesLive(queryParams) onUpdatable(updatableFilterLivePageResult) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryCenteredItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryCenteredItem.kt index 764f50456c..1b4f6fd5cb 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryCenteredItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryCenteredItem.kt @@ -112,7 +112,7 @@ abstract class RoomSummaryCenteredItem : VectorEpoxyModel(R.layo private fun renderSelection(holder: Holder, isSelected: Boolean) { if (isSelected) { holder.avatarCheckedImageView.visibility = View.VISIBLE - val backgroundColor = ThemeUtils.getColor(holder.view.context, R.attr.colorPrimary) + val backgroundColor = ThemeUtils.getColor(holder.view.context, com.google.android.material.R.attr.colorPrimary) val backgroundDrawable = TextDrawable.builder().buildRound("", backgroundColor) holder.avatarImageView.setImageDrawable(backgroundDrawable) } else { diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt index 18c8ea3bde..1f91715195 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt @@ -19,7 +19,6 @@ package im.vector.app.features.home.room.list import com.airbnb.mvrx.Async import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading -import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter import im.vector.app.core.epoxy.VectorEpoxyModel @@ -33,6 +32,8 @@ import im.vector.app.features.home.room.typing.TypingHelper import im.vector.app.features.voicebroadcast.isLive import im.vector.app.features.voicebroadcast.model.asVoiceBroadcastEvent import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState import org.matrix.android.sdk.api.session.room.model.Membership @@ -83,12 +84,12 @@ class RoomSummaryItemFactory @Inject constructor( .topic(spaceChildInfo.topic) .errorLabel( error?.let { - stringProvider.getString(R.string.error_failed_to_join_room, errorFormatter.toHumanReadable(it)) + stringProvider.getString(CommonStrings.error_failed_to_join_room, errorFormatter.toHumanReadable(it)) } ) .buttonLabel( - if (error != null) stringProvider.getString(R.string.global_retry) - else stringProvider.getString(R.string.action_join) + if (error != null) stringProvider.getString(CommonStrings.global_retry) + else stringProvider.getString(CommonStrings.action_join) ) .loading(suggestedRoomJoiningStates[spaceChildInfo.childRoomId] is Loading) .memberCount(spaceChildInfo.activeMemberCount ?: 0) @@ -105,7 +106,7 @@ class RoomSummaryItemFactory @Inject constructor( roomSummary.inviterId } else { roomSummary.inviterId?.let { - stringProvider.getString(R.string.invited_by, it) + stringProvider.getString(CommonStrings.invited_by, it) } } @@ -229,8 +230,8 @@ class RoomSummaryItemFactory @Inject constructor( when (val size = directParentNames.size) { 0 -> null 1 -> directParentNames.first() - 2 -> stringProvider.getString(R.string.search_space_two_parents, directParentNames[0], directParentNames[1]) - else -> stringProvider.getQuantityString(R.plurals.search_space_multiple_parents, size - 1, directParentNames[0], size - 1) + 2 -> stringProvider.getString(CommonStrings.search_space_two_parents, directParentNames[0], directParentNames[1]) + else -> stringProvider.getQuantityString(CommonPlurals.search_space_multiple_parents, size - 1, directParentNames[0], size - 1) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/SectionHeaderAdapter.kt b/vector/src/main/java/im/vector/app/features/home/room/list/SectionHeaderAdapter.kt index 6cbc467628..d6dc2c9cd5 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/SectionHeaderAdapter.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/SectionHeaderAdapter.kt @@ -85,7 +85,7 @@ class SectionHeaderAdapter constructor( fun bind(roomsSectionData: RoomsSectionData) { binding.roomCategoryTitleView.text = roomsSectionData.name - val tintColor = ThemeUtils.getColor(binding.root.context, R.attr.vctr_content_secondary) + val tintColor = ThemeUtils.getColor(binding.root.context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary) val collapsableArrowDrawable: Drawable? = if (roomsSectionData.isCollapsable) { val expandedArrowDrawableRes = if (roomsSectionData.isExpanded) R.drawable.ic_expand_more else R.drawable.ic_expand_less ContextCompat.getDrawable(binding.root.context, expandedArrowDrawableRes)?.also { @@ -96,7 +96,7 @@ class SectionHeaderAdapter constructor( } binding.root.isClickable = roomsSectionData.isCollapsable binding.roomCategoryCounterView.setCompoundDrawablesWithIntrinsicBounds(null, null, collapsableArrowDrawable, null) - binding.roomCategoryCounterView.text = roomsSectionData.itemCount.takeIf { it > 0 }?.toString().orEmpty() + binding.roomCategoryCounterView.text = if (roomsSectionData.itemCount > 0) "${roomsSectionData.itemCount}" else null binding.roomCategoryUnreadCounterBadgeView.render( UnreadCounterBadgeView.State.Count(roomsSectionData.notificationCount, roomsSectionData.isHighlighted) ) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/SpaceChildInfoItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/SpaceChildInfoItem.kt index 964a39fb0f..a770779087 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/SpaceChildInfoItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/SpaceChildInfoItem.kt @@ -36,6 +36,7 @@ import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.image import me.gujun.android.span.span import org.matrix.android.sdk.api.util.MatrixItem @@ -67,13 +68,13 @@ abstract class SpaceChildInfoItem : VectorEpoxyModel( it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) itemLongClickListener?.onLongClick(it) ?: false } - holder.titleView.text = matrixItem.displayName ?: holder.rootView.context.getString(R.string.unnamed_room) + holder.titleView.text = matrixItem.displayName ?: holder.rootView.context.getString(CommonStrings.unnamed_room) avatarRenderer.render(matrixItem, holder.avatarImageView) holder.descriptionText.text = span { span { apply { - val tintColor = ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary) + val tintColor = ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary) ContextCompat.getDrawable(holder.view.context, R.drawable.ic_member_small) ?.apply { ThemeUtils.tintDrawableWithColor(this, tintColor) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt index b629ca8bac..ddb6a806c5 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt @@ -27,7 +27,6 @@ import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith @@ -37,6 +36,7 @@ import im.vector.app.features.navigation.Navigator import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsAction import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsViewEvents import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsViewModel +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState import javax.inject.Inject @@ -126,9 +126,9 @@ class RoomListQuickActionsBottomSheet : private fun displayErrorDialog(throwable: Throwable) { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(errorFormatter.toHumanReadable(throwable)) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt index e1837a32de..0f0def124e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt @@ -17,7 +17,6 @@ package im.vector.app.features.home.room.list.actions import androidx.annotation.StringRes import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem import im.vector.app.core.epoxy.bottomsheet.bottomSheetActionItem import im.vector.app.core.epoxy.bottomsheet.bottomSheetRoomPreviewItem @@ -27,6 +26,7 @@ import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roomprofile.notifications.notificationOptions import im.vector.app.features.roomprofile.notifications.notificationStateMapped +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject @@ -82,9 +82,9 @@ class RoomListQuickActionsEpoxyController @Inject constructor( @StringRes private fun titleForNotificationState(notificationState: RoomNotificationState): Int? = when (notificationState) { - RoomNotificationState.ALL_MESSAGES_NOISY -> R.string.room_settings_all_messages - RoomNotificationState.MENTIONS_ONLY -> R.string.room_settings_mention_and_keyword_only - RoomNotificationState.MUTE -> R.string.room_settings_none + RoomNotificationState.ALL_MESSAGES_NOISY -> CommonStrings.room_settings_all_messages + RoomNotificationState.MENTIONS_ONLY -> CommonStrings.room_settings_mention_and_keyword_only + RoomNotificationState.MUTE -> CommonStrings.room_settings_none else -> null } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsSharedAction.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsSharedAction.kt index 8c84aa55e1..b8defad814 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsSharedAction.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsSharedAction.kt @@ -20,6 +20,7 @@ import androidx.annotation.DrawableRes import androidx.annotation.StringRes import im.vector.app.R import im.vector.app.core.platform.VectorSharedAction +import im.vector.lib.strings.CommonStrings sealed class RoomListQuickActionsSharedAction( @StringRes val titleRes: Int, @@ -28,42 +29,42 @@ sealed class RoomListQuickActionsSharedAction( ) : VectorSharedAction { data class NotificationsAllNoisy(val roomId: String) : RoomListQuickActionsSharedAction( - R.string.room_list_quick_actions_notifications_all_noisy, + CommonStrings.room_list_quick_actions_notifications_all_noisy, R.drawable.ic_room_actions_notifications_all_noisy ) data class NotificationsAll(val roomId: String) : RoomListQuickActionsSharedAction( - R.string.room_list_quick_actions_notifications_all, + CommonStrings.room_list_quick_actions_notifications_all, R.drawable.ic_room_actions_notifications_all ) data class NotificationsMentionsOnly(val roomId: String) : RoomListQuickActionsSharedAction( - R.string.room_list_quick_actions_notifications_mentions, + CommonStrings.room_list_quick_actions_notifications_mentions, R.drawable.ic_room_actions_notifications_mentions ) data class NotificationsMute(val roomId: String) : RoomListQuickActionsSharedAction( - R.string.room_list_quick_actions_notifications_mute, + CommonStrings.room_list_quick_actions_notifications_mute, R.drawable.ic_room_actions_notifications_mutes ) data class Settings(val roomId: String) : RoomListQuickActionsSharedAction( - R.string.room_list_quick_actions_settings, + CommonStrings.room_list_quick_actions_settings, R.drawable.ic_room_actions_settings ) data class LowPriority(val roomId: String) : RoomListQuickActionsSharedAction( - R.string.room_list_quick_actions_low_priority_add, + CommonStrings.room_list_quick_actions_low_priority_add, R.drawable.ic_low_priority_24 ) data class Favorite(val roomId: String) : RoomListQuickActionsSharedAction( - R.string.room_list_quick_actions_favorite_add, + CommonStrings.room_list_quick_actions_favorite_add, R.drawable.ic_star_24dp ) data class Leave(val roomId: String, val showIcon: Boolean = true) : RoomListQuickActionsSharedAction( - R.string.room_list_quick_actions_leave, + CommonStrings.room_list_quick_actions_leave, if (showIcon) R.drawable.ic_room_actions_leave else null, true ) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt index 20e1797127..bfd264d8b0 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListFragment.kt @@ -29,7 +29,6 @@ import com.airbnb.epoxy.OnModelBuildFinishedListener import com.airbnb.mvrx.fragmentViewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.epoxy.LayoutManagerStateRestorer import im.vector.app.core.extensions.cleanup import im.vector.app.core.platform.StateView @@ -46,6 +45,7 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA import im.vector.app.features.home.room.list.home.header.HomeRoomFilter import im.vector.app.features.home.room.list.home.header.HomeRoomsHeadersController import im.vector.app.features.home.room.list.home.invites.InvitesActivity +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -197,19 +197,22 @@ class HomeRoomListFragment : private fun promptLeaveRoom(roomId: String) { val isPublicRoom = roomListViewModel.isPublicRoom(roomId) val message = buildString { - append(getString(R.string.room_participants_leave_prompt_msg)) + append(getString(CommonStrings.room_participants_leave_prompt_msg)) if (!isPublicRoom) { append("\n\n") - append(getString(R.string.room_participants_leave_private_warning)) + append(getString(CommonStrings.room_participants_leave_private_warning)) } } - MaterialAlertDialogBuilder(requireContext(), if (isPublicRoom) 0 else R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) - .setTitle(R.string.room_participants_leave_prompt_title) + MaterialAlertDialogBuilder( + requireContext(), + if (isPublicRoom) 0 else im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive + ) + .setTitle(CommonStrings.room_participants_leave_prompt_title) .setMessage(message) - .setPositiveButton(R.string.action_leave) { _, _ -> + .setPositiveButton(CommonStrings.action_leave) { _, _ -> roomListViewModel.handle(HomeRoomListAction.LeaveRoom(roomId)) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListViewModel.kt index 5ce96646c6..558db63062 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListViewModel.kt @@ -35,6 +35,7 @@ import im.vector.app.features.analytics.extensions.toTrackingValue import im.vector.app.features.analytics.plan.UserProperties import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.room.list.home.header.HomeRoomFilter +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged @@ -284,24 +285,24 @@ class HomeRoomListViewModel @AssistedInject constructor( HomeRoomFilter.ALL -> if (selectedSpace != null) { StateView.State.Empty( - title = stringProvider.getString(R.string.home_empty_space_no_rooms_title, selectedSpace.displayName), - message = stringProvider.getString(R.string.home_empty_space_no_rooms_message), + title = stringProvider.getString(CommonStrings.home_empty_space_no_rooms_title, selectedSpace.displayName), + message = stringProvider.getString(CommonStrings.home_empty_space_no_rooms_message), image = drawableProvider.getDrawable(R.drawable.ill_empty_space), isBigImage = true ) } else { val userName = session.getUserOrDefault(session.myUserId).toMatrixItem().getBestName() StateView.State.Empty( - title = stringProvider.getString(R.string.home_empty_no_rooms_title, userName), - message = stringProvider.getString(R.string.home_empty_no_rooms_message), + title = stringProvider.getString(CommonStrings.home_empty_no_rooms_title, userName), + message = stringProvider.getString(CommonStrings.home_empty_no_rooms_message), image = drawableProvider.getDrawable(R.drawable.ill_empty_all_chats), isBigImage = true ) } HomeRoomFilter.UNREADS -> StateView.State.Empty( - title = stringProvider.getString(R.string.home_empty_no_unreads_title), - message = stringProvider.getString(R.string.home_empty_no_unreads_message), + title = stringProvider.getString(CommonStrings.home_empty_no_unreads_title), + message = stringProvider.getString(CommonStrings.home_empty_no_unreads_message), image = drawableProvider.getDrawable(R.drawable.ill_empty_unreads), isBigImage = true, imageScaleType = ImageView.ScaleType.CENTER_INSIDE diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/home/header/HomeRoomFilter.kt b/vector/src/main/java/im/vector/app/features/home/room/list/home/header/HomeRoomFilter.kt index 9bd800a47c..9f4e7f20b1 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/home/header/HomeRoomFilter.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/home/header/HomeRoomFilter.kt @@ -17,11 +17,11 @@ package im.vector.app.features.home.room.list.home.header import androidx.annotation.StringRes -import im.vector.app.R +import im.vector.lib.strings.CommonStrings enum class HomeRoomFilter(@StringRes val titleRes: Int) { - ALL(R.string.room_list_filter_all), - UNREADS(R.string.room_list_filter_unreads), - FAVOURITES(R.string.room_list_filter_favourites), - PEOPlE(R.string.room_list_filter_people), + ALL(CommonStrings.room_list_filter_all), + UNREADS(CommonStrings.room_list_filter_unreads), + FAVOURITES(CommonStrings.room_list_filter_favourites), + PEOPlE(CommonStrings.room_list_filter_people), } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/home/header/HomeRoomsHeadersController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/home/header/HomeRoomsHeadersController.kt index 3cc058985a..fcd61bc9de 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/home/header/HomeRoomsHeadersController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/home/header/HomeRoomsHeadersController.kt @@ -25,7 +25,6 @@ import com.airbnb.epoxy.EpoxyController import com.airbnb.epoxy.EpoxyModel import com.airbnb.epoxy.carousel import com.google.android.material.color.MaterialColors -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.FirstItemUpdatedObserver import im.vector.app.features.analytics.AnalyticsTracker @@ -108,7 +107,7 @@ class HomeRoomsHeadersController @Inject constructor( host.unsubscribeAdapterObserver() host.subscribeAdapterObserver() - val colorSurface = MaterialColors.getColor(view, R.attr.vctr_toolbar_background) + val colorSurface = MaterialColors.getColor(view, im.vector.lib.ui.styles.R.attr.vctr_toolbar_background) view.setBackgroundColor(colorSurface) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/home/invites/InvitesViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/home/invites/InvitesViewModel.kt index 8ef7c2bfef..623613a2ee 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/home/invites/InvitesViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/home/invites/InvitesViewModel.kt @@ -28,6 +28,7 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.DrawableProvider import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.catch @@ -155,9 +156,9 @@ class InvitesViewModel @AssistedInject constructor( .map { if (it.isEmpty()) { InvitesContentState.Empty( - title = stringProvider.getString(R.string.invites_empty_title), + title = stringProvider.getString(CommonStrings.invites_empty_title), image = drawableProvider.getDrawable(R.drawable.ic_invites_empty), - message = stringProvider.getString(R.string.invites_empty_message) + message = stringProvider.getString(CommonStrings.invites_empty_message) ) } else { invitesCount = it.loadedCount diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/home/release/ReleaseNotesFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/home/release/ReleaseNotesFragment.kt index 6b86897dc8..46feb354b5 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/home/release/ReleaseNotesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/home/release/ReleaseNotesFragment.kt @@ -30,6 +30,7 @@ import im.vector.app.R import im.vector.app.core.epoxy.onClick import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.BottomSheetReleaseNotesBinding +import im.vector.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint @@ -92,18 +93,18 @@ class ReleaseNotesFragment : VectorBaseFragment( return ReleaseCarouselData( listOf( ReleaseCarouselData.Item( - R.string.onboarding_new_app_layout_welcome_title, - R.string.onboarding_new_app_layout_welcome_message, + CommonStrings.onboarding_new_app_layout_welcome_title, + CommonStrings.onboarding_new_app_layout_welcome_message, R.drawable.ill_app_layout_onboarding_rooms ), ReleaseCarouselData.Item( - R.string.onboarding_new_app_layout_spaces_title, - R.string.onboarding_new_app_layout_spaces_message, + CommonStrings.onboarding_new_app_layout_spaces_title, + CommonStrings.onboarding_new_app_layout_spaces_message, R.drawable.ill_app_layout_onboarding_spaces ), ReleaseCarouselData.Item( - R.string.onboarding_new_app_layout_feedback_title, - R.string.onboarding_new_app_layout_feedback_message, + CommonStrings.onboarding_new_app_layout_feedback_title, + CommonStrings.onboarding_new_app_layout_feedback_message, R.drawable.ill_app_layout_onboarding_rooms ), ) @@ -122,9 +123,9 @@ class ReleaseNotesFragment : VectorBaseFragment( private fun updateButtonText(selectedIndex: Int) { val isLastItem = selectedIndex == views.releaseNotesCarouselIndicator.tabCount - 1 if (isLastItem) { - views.releaseNotesButtonNext.setText(R.string.onboarding_new_app_layout_button_try) + views.releaseNotesButtonNext.setText(CommonStrings.onboarding_new_app_layout_button_try) } else { - views.releaseNotesButtonNext.setText(R.string.action_next) + views.releaseNotesButtonNext.setText(CommonStrings.action_next) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/widget/NotifsFabMenuView.kt b/vector/src/main/java/im/vector/app/features/home/room/list/widget/NotifsFabMenuView.kt index 1487c30957..f20f661a3e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/widget/NotifsFabMenuView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/widget/NotifsFabMenuView.kt @@ -23,6 +23,7 @@ import androidx.core.view.isVisible import com.google.android.material.floatingactionbutton.FloatingActionButton import im.vector.app.R import im.vector.app.databinding.MotionNotifsFabMenuMergeBinding +import im.vector.lib.strings.CommonStrings class NotifsFabMenuView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, @@ -64,13 +65,13 @@ class NotifsFabMenuView @JvmOverloads constructor( override fun transitionToEnd() { super.transitionToEnd() - views.createRoomButton.contentDescription = context.getString(R.string.a11y_create_menu_close) + views.createRoomButton.contentDescription = context.getString(CommonStrings.a11y_create_menu_close) } override fun transitionToStart() { super.transitionToStart() - views.createRoomButton.contentDescription = context.getString(R.string.a11y_create_menu_open) + views.createRoomButton.contentDescription = context.getString(CommonStrings.a11y_create_menu_open) } fun show() { diff --git a/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsActivity.kt b/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsActivity.kt index 014b9f0504..9507c1288f 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsActivity.kt @@ -21,7 +21,6 @@ import android.content.Intent import android.os.Bundle import androidx.fragment.app.FragmentTransaction import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.addFragmentToBackstack import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.platform.VectorBaseActivity @@ -100,10 +99,10 @@ class ThreadsActivity : VectorBaseActivity() { analyticsTracker.capture(Interaction.Name.MobileThreadListThreadItem.toAnalyticsInteraction()) val commonOption: (FragmentTransaction) -> Unit = { it.setCustomAnimations( - R.anim.animation_slide_in_right, - R.anim.animation_slide_out_left, - R.anim.animation_slide_in_left, - R.anim.animation_slide_out_right + im.vector.lib.ui.styles.R.anim.animation_slide_in_right, + im.vector.lib.ui.styles.R.anim.animation_slide_out_left, + im.vector.lib.ui.styles.R.anim.animation_slide_in_left, + im.vector.lib.ui.styles.R.anim.animation_slide_out_right ) } addFragmentToBackstack( diff --git a/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsManager.kt b/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsManager.kt index ffb42bec1b..30d1e5494b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsManager.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsManager.kt @@ -20,11 +20,11 @@ import android.app.Activity import android.text.Spanned import androidx.annotation.StringRes import androidx.core.text.HtmlCompat -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.MainActivity import im.vector.app.features.MainActivityArgs import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.settings.LightweightSettingsStorage import javax.inject.Inject @@ -51,16 +51,16 @@ class ThreadsManager @Inject constructor( * Generates and return an Html spanned string to be rendered especially in dialogs. */ private fun generateLearnMoreHtmlString(@StringRes messageId: Int): Spanned { - val learnMore = stringProvider.getString(R.string.action_learn_more) - val learnMoreUrl = stringProvider.getString(R.string.threads_learn_more_url) + val learnMore = stringProvider.getString(CommonStrings.action_learn_more) + val learnMoreUrl = stringProvider.getString(im.vector.app.config.R.string.threads_learn_more_url) val href = "$learnMore.

" val message = stringProvider.getString(messageId, href) return HtmlCompat.fromHtml(message, HtmlCompat.FROM_HTML_MODE_LEGACY) } fun getBetaEnableThreadsMessage(): Spanned = - generateLearnMoreHtmlString(R.string.threads_beta_enable_notice_message) + generateLearnMoreHtmlString(CommonStrings.threads_beta_enable_notice_message) fun getLabsEnableThreadsMessage(): Spanned = - generateLearnMoreHtmlString(R.string.threads_labs_enable_notice_message) + generateLearnMoreHtmlString(CommonStrings.threads_labs_enable_notice_message) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/threads/list/model/ThreadListItem.kt b/vector/src/main/java/im/vector/app/features/home/room/threads/list/model/ThreadListItem.kt index 6284a1a067..8345758700 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/threads/list/model/ThreadListItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/threads/list/model/ThreadListItem.kt @@ -34,6 +34,7 @@ import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.threads.ThreadNotificationState import org.matrix.android.sdk.api.util.MatrixItem @@ -60,12 +61,12 @@ abstract class ThreadListItem : VectorEpoxyModel(R.layout holder.titleTextView.text = title holder.dateTextView.text = date if (rootMessageDeleted) { - holder.rootMessageTextView.text = holder.view.context.getString(R.string.event_redacted) - holder.rootMessageTextView.setTextColor(ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary)) - holder.rootMessageTextView.setLeftDrawable(R.drawable.ic_trash_16, R.attr.vctr_content_tertiary) + holder.rootMessageTextView.text = holder.view.context.getString(CommonStrings.event_redacted) + holder.rootMessageTextView.setTextColor(ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary)) + holder.rootMessageTextView.setLeftDrawable(R.drawable.ic_trash_16, im.vector.lib.ui.styles.R.attr.vctr_content_tertiary) holder.rootMessageTextView.compoundDrawablePadding = DimensionConverter(holder.view.context.resources).dpToPx(10) } else { - holder.rootMessageTextView.setTextColor(ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_primary)) + holder.rootMessageTextView.setTextColor(ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_primary)) holder.rootMessageTextView.text = rootMessage holder.rootMessageTextView.clearDrawables() } @@ -83,11 +84,11 @@ abstract class ThreadListItem : VectorEpoxyModel(R.layout when (threadNotificationState) { ThreadNotificationState.NEW_MESSAGE -> { holder.unreadImageView.isVisible = true - holder.unreadImageView.setColorFilter(ContextCompat.getColor(holder.view.context, R.color.palette_gray_200)) + holder.unreadImageView.setColorFilter(ContextCompat.getColor(holder.view.context, im.vector.lib.ui.styles.R.color.palette_gray_200)) } ThreadNotificationState.NEW_HIGHLIGHTED_MESSAGE -> { holder.unreadImageView.isVisible = true - holder.unreadImageView.setColorFilter(ContextCompat.getColor(holder.view.context, R.color.palette_vermilion)) + holder.unreadImageView.setColorFilter(ContextCompat.getColor(holder.view.context, im.vector.lib.ui.styles.R.color.palette_vermilion)) } else -> { holder.unreadImageView.isVisible = false diff --git a/vector/src/main/java/im/vector/app/features/home/room/threads/list/views/ThreadListBottomSheet.kt b/vector/src/main/java/im/vector/app/features/home/room/threads/list/views/ThreadListBottomSheet.kt index 07684a796e..82731666fc 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/threads/list/views/ThreadListBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/threads/list/views/ThreadListBottomSheet.kt @@ -61,11 +61,11 @@ class ThreadListBottomSheet : VectorBaseBottomSheetDialogFragment + it.setMessage(CommonStrings.thread_list_not_available) + it.setPositiveButton(CommonStrings.ok) { _, _ -> requireActivity().finish() } } else { // Other error, can retry // (Can happen on first request or on pagination request) it.setMessage(errorFormatter.toHumanReadable(error)) - it.setPositiveButton(R.string.ok, null) - it.setNegativeButton(R.string.global_retry) { _, _ -> + it.setPositiveButton(CommonStrings.ok, null) + it.setNegativeButton(CommonStrings.global_retry) { _, _ -> threadListViewModel.handle(ThreadListViewActions.TryAgain) } } @@ -180,14 +181,14 @@ class ThreadListFragment : private fun initTextConstants() { views.threadListEmptyNoticeTextView.text = String.format( - resources.getString(R.string.thread_list_empty_notice), - resources.getString(R.string.reply_in_thread) + resources.getString(CommonStrings.thread_list_empty_notice), + resources.getString(CommonStrings.reply_in_thread) ) } private fun initBetaFeedback() { - views.threadsFeedBackConstraintLayout.isVisible = resources.getBoolean(R.bool.feature_threads_beta_feedback_enabled) - views.threadFeedbackDivider.isVisible = resources.getBoolean(R.bool.feature_threads_beta_feedback_enabled) + views.threadsFeedBackConstraintLayout.isVisible = resources.getBoolean(im.vector.app.config.R.bool.feature_threads_beta_feedback_enabled) + views.threadFeedbackDivider.isVisible = resources.getBoolean(im.vector.app.config.R.bool.feature_threads_beta_feedback_enabled) views.threadsFeedBackConstraintLayout.debouncedClicks { bugReporter.openBugReportScreen(requireActivity(), reportType = ReportType.THREADS_BETA_FEEDBACK) } @@ -211,7 +212,7 @@ class ThreadListFragment : val matrixItem = MatrixItem.RoomItem(threadListArgs.roomId, threadListArgs.displayName, threadListArgs.avatarUrl) avatarRenderer.render(matrixItem, views.includeThreadListToolbar.roomToolbarThreadImageView) views.includeThreadListToolbar.roomToolbarThreadShieldImageView.render(threadListArgs.roomEncryptionTrustLevel) - views.includeThreadListToolbar.roomToolbarThreadTitleTextView.text = resources.getText(R.string.thread_list_title) + views.includeThreadListToolbar.roomToolbarThreadTitleTextView.text = resources.getText(CommonStrings.thread_list_title) views.includeThreadListToolbar.roomToolbarThreadSubtitleTextView.text = threadListArgs.displayName } diff --git a/vector/src/main/java/im/vector/app/features/home/room/typing/TypingHelper.kt b/vector/src/main/java/im/vector/app/features/home/room/typing/TypingHelper.kt index 8f5f57b86b..203f876872 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/typing/TypingHelper.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/typing/TypingHelper.kt @@ -16,8 +16,8 @@ package im.vector.app.features.home.room.typing -import im.vector.app.R import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.sender.SenderInfo import javax.inject.Inject @@ -31,16 +31,16 @@ class TypingHelper @Inject constructor(private val stringProvider: StringProvide typingUsers.isEmpty() -> "" typingUsers.size == 1 -> - stringProvider.getString(R.string.room_one_user_is_typing, typingUsers[0].disambiguatedDisplayName) + stringProvider.getString(CommonStrings.room_one_user_is_typing, typingUsers[0].disambiguatedDisplayName) typingUsers.size == 2 -> stringProvider.getString( - R.string.room_two_users_are_typing, + CommonStrings.room_two_users_are_typing, typingUsers[0].disambiguatedDisplayName, typingUsers[1].disambiguatedDisplayName ) else -> stringProvider.getString( - R.string.room_many_users_are_typing, + CommonStrings.room_many_users_are_typing, typingUsers[0].disambiguatedDisplayName, typingUsers[1].disambiguatedDisplayName ) @@ -52,11 +52,11 @@ class TypingHelper @Inject constructor(private val stringProvider: StringProvide typingUsers.isEmpty() -> "" typingUsers.size == 1 -> typingUsers[0].disambiguatedDisplayName typingUsers.size == 2 -> stringProvider.getString( - R.string.room_notification_two_users_are_typing, + CommonStrings.room_notification_two_users_are_typing, typingUsers[0].disambiguatedDisplayName, typingUsers[1].disambiguatedDisplayName ) else -> stringProvider.getString( - R.string.room_notification_more_than_two_users_are_typing, + CommonStrings.room_notification_more_than_two_users_are_typing, typingUsers[0].disambiguatedDisplayName, typingUsers[1].disambiguatedDisplayName ) } diff --git a/vector/src/main/java/im/vector/app/features/homeserver/ServerUrlsRepository.kt b/vector/src/main/java/im/vector/app/features/homeserver/ServerUrlsRepository.kt index 5b1496028d..3ab81b6837 100644 --- a/vector/src/main/java/im/vector/app/features/homeserver/ServerUrlsRepository.kt +++ b/vector/src/main/java/im/vector/app/features/homeserver/ServerUrlsRepository.kt @@ -18,7 +18,6 @@ package im.vector.app.features.homeserver import android.content.SharedPreferences import androidx.core.content.edit -import im.vector.app.R import im.vector.app.core.di.DefaultPreferences import im.vector.app.core.resources.StringProvider import javax.inject.Inject @@ -90,5 +89,5 @@ class ServerUrlsRepository @Inject constructor( /** * Return default homeserver url from resources. */ - private fun getDefaultHomeServerUrl() = stringProvider.getString(R.string.matrix_org_server_url) + private fun getDefaultHomeServerUrl() = stringProvider.getString(im.vector.app.config.R.string.matrix_org_server_url) } diff --git a/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt b/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt index a1130bd251..d6e821437f 100644 --- a/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt +++ b/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt @@ -38,6 +38,7 @@ import im.vector.app.core.glide.GlideRequests import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orTrue import org.matrix.android.sdk.api.session.room.send.MatrixItemSpan import org.matrix.android.sdk.api.util.MatrixItem @@ -124,16 +125,16 @@ class PillImageSpan( // Private methods ***************************************************************************** private fun createChipDrawable(): ChipDrawable { - val textPadding = context.resources.getDimension(R.dimen.pill_text_padding) + val textPadding = context.resources.getDimension(im.vector.lib.ui.styles.R.dimen.pill_text_padding) val icon = when { matrixItem is MatrixItem.RoomAliasItem && matrixItem.avatarUrl.isNullOrEmpty() && - matrixItem.displayName == context.getString(R.string.pill_message_in_room, matrixItem.id) -> { + matrixItem.displayName == context.getString(CommonStrings.pill_message_in_room, matrixItem.id) -> { ContextCompat.getDrawable(context, R.drawable.ic_permalink_round) } matrixItem is MatrixItem.RoomItem && matrixItem.avatarUrl.isNullOrEmpty() && ( - matrixItem.displayName == context.getString(R.string.pill_message_in_unknown_room) || - matrixItem.displayName == context.getString(R.string.pill_message_unknown_room_or_space) || - matrixItem.displayName == context.getString(R.string.pill_message_from_unknown_user) + matrixItem.displayName == context.getString(CommonStrings.pill_message_in_unknown_room) || + matrixItem.displayName == context.getString(CommonStrings.pill_message_unknown_room_or_space) || + matrixItem.displayName == context.getString(CommonStrings.pill_message_from_unknown_user) ) -> { ContextCompat.getDrawable(context, R.drawable.ic_permalink_round) } @@ -153,13 +154,13 @@ class PillImageSpan( text = matrixItem.getBestName() textEndPadding = textPadding textStartPadding = textPadding - setChipMinHeightResource(R.dimen.pill_min_height) - setChipIconSizeResource(R.dimen.pill_avatar_size) + setChipMinHeightResource(im.vector.lib.ui.styles.R.dimen.pill_min_height) + setChipIconSizeResource(im.vector.lib.ui.styles.R.dimen.pill_avatar_size) chipIcon = icon if (matrixItem is MatrixItem.EveryoneInRoomItem) { - chipBackgroundColor = ColorStateList.valueOf(ThemeUtils.getColor(context, R.attr.colorError)) + chipBackgroundColor = ColorStateList.valueOf(ThemeUtils.getColor(context, com.google.android.material.R.attr.colorError)) // setTextColor API does not exist right now for ChipDrawable, use textAppearance - setTextAppearanceResource(R.style.TextAppearance_Vector_Body_OnError) + setTextAppearanceResource(im.vector.lib.ui.styles.R.style.TextAppearance_Vector_Body_OnError) } setBounds(0, 0, intrinsicWidth, intrinsicHeight) } diff --git a/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt b/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt index 92d5b16998..2d9978057f 100644 --- a/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt +++ b/vector/src/main/java/im/vector/app/features/html/PillsPostProcessor.kt @@ -22,7 +22,6 @@ import android.text.Spanned import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.glide.GlideApp import im.vector.app.features.home.AvatarRenderer @@ -107,7 +106,7 @@ class PillsPostProcessor @AssistedInject constructor( PillImageSpan(GlideApp.with(context), avatarRenderer, context, matrixItem) private fun LinkSpan.createPillSpan(): PillImageSpan? { - val supportedHosts = context.resources.getStringArray(R.array.permalink_supported_hosts) + val supportedHosts = context.resources.getStringArray(im.vector.app.config.R.array.permalink_supported_hosts) val isPermalinkSupported = sessionHolder.getSafeActiveSession()?.permalinkService()?.isPermalinkSupported(supportedHosts, url).orFalse() if (isPermalinkSupported) { val matrixItem = when (val permalinkData = PermalinkParser.parse(url)) { diff --git a/vector/src/main/java/im/vector/app/features/html/SpoilerSpan.kt b/vector/src/main/java/im/vector/app/features/html/SpoilerSpan.kt index 4c75cd8cee..b78c0f283d 100644 --- a/vector/src/main/java/im/vector/app/features/html/SpoilerSpan.kt +++ b/vector/src/main/java/im/vector/app/features/html/SpoilerSpan.kt @@ -20,7 +20,6 @@ import android.graphics.Color import android.text.TextPaint import android.text.style.ClickableSpan import android.view.View -import im.vector.app.R import im.vector.app.core.resources.ColorProvider class SpoilerSpan(private val colorProvider: ColorProvider) : ClickableSpan() { @@ -34,11 +33,11 @@ class SpoilerSpan(private val colorProvider: ColorProvider) : ClickableSpan() { override fun updateDrawState(tp: TextPaint) { if (isHidden) { - tp.bgColor = colorProvider.getColorFromAttribute(R.attr.vctr_spoiler_background_color) + tp.bgColor = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_spoiler_background_color) tp.color = Color.TRANSPARENT } else { - tp.bgColor = colorProvider.getColorFromAttribute(R.attr.vctr_markdown_block_background_color) - tp.color = colorProvider.getColorFromAttribute(R.attr.vctr_content_primary) + tp.bgColor = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_markdown_block_background_color) + tp.color = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary) } } } diff --git a/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt b/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt index c000efaef2..d48a2614aa 100644 --- a/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt +++ b/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt @@ -42,6 +42,7 @@ import im.vector.app.features.userdirectory.UserListFragment import im.vector.app.features.userdirectory.UserListFragmentArgs import im.vector.app.features.userdirectory.UserListSharedAction import im.vector.app.features.userdirectory.UserListSharedActionViewModel +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.parcelize.Parcelize @@ -82,7 +83,7 @@ class InviteUsersToRoomActivity : SimpleFragmentActivity() { views.container, UserListFragment::class.java, UserListFragmentArgs( - title = getString(R.string.invite_users_to_room_title), + title = getString(CommonStrings.invite_users_to_room_title), menuResId = R.menu.vector_invite_users_to_room, submitMenuItemId = R.id.action_invite_users_to_room_invite, excludedUserIds = viewModel.getUserIdsOfRoomMembers(), @@ -100,12 +101,12 @@ class InviteUsersToRoomActivity : SimpleFragmentActivity() { viewModel.handle(InviteUsersToRoomAction.InviteSelectedUsers(action.selections)) } else { MaterialAlertDialogBuilder(this) - .setTitle(R.string.dialog_title_confirmation) - .setMessage(getString(R.string.invite_unknown_users_dialog_content, unknownUsers.joinToString("\n • ", " • ") { it.getMxId() })) - .setPositiveButton(R.string.invite_unknown_users_dialog_submit) { _, _ -> + .setTitle(CommonStrings.dialog_title_confirmation) + .setMessage(getString(CommonStrings.invite_unknown_users_dialog_content, unknownUsers.joinToString("\n • ", " • ") { it.getMxId() })) + .setPositiveButton(CommonStrings.invite_unknown_users_dialog_submit) { _, _ -> viewModel.handle(InviteUsersToRoomAction.InviteSelectedUsers(action.selections)) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } } @@ -121,7 +122,7 @@ class InviteUsersToRoomActivity : SimpleFragmentActivity() { if (allGranted) { doOnPostResume { addFragmentToBackstack(views.container, ContactsBookFragment::class.java) } } else if (deniedPermanently) { - onPermissionDeniedSnackbar(R.string.permissions_denied_add_contact) + onPermissionDeniedSnackbar(CommonStrings.permissions_denied_add_contact) } } @@ -134,20 +135,20 @@ class InviteUsersToRoomActivity : SimpleFragmentActivity() { } private fun renderInviteLoading() { - updateWaitingView(WaitingViewData(getString(R.string.inviting_users_to_room))) + updateWaitingView(WaitingViewData(getString(CommonStrings.inviting_users_to_room))) } private fun renderInviteFailure(error: Throwable) { hideWaitingView() val message = if (error is Failure.ServerError && error.httpCode == HttpURLConnection.HTTP_INTERNAL_ERROR /*500*/) { // This error happen if the invited userId does not exist. - getString(R.string.invite_users_to_room_failure) + getString(CommonStrings.invite_users_to_room_failure) } else { errorFormatter.toHumanReadable(error) } MaterialAlertDialogBuilder(this) .setMessage(message) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } diff --git a/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomViewModel.kt b/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomViewModel.kt index 68b0329a86..86971a39ad 100644 --- a/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomViewModel.kt @@ -20,12 +20,13 @@ import com.airbnb.mvrx.MavericksViewModelFactory import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.features.userdirectory.PendingSelection +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.launchIn @@ -68,16 +69,16 @@ class InviteUsersToRoomViewModel @AssistedInject constructor( val successMessage = when (selections.size) { 1 -> stringProvider.getString( - R.string.invitation_sent_to_one_user, + CommonStrings.invitation_sent_to_one_user, selections.first().getBestName() ) 2 -> stringProvider.getString( - R.string.invitations_sent_to_two_users, + CommonStrings.invitations_sent_to_two_users, selections.first().getBestName(), selections.last().getBestName() ) else -> stringProvider.getQuantityString( - R.plurals.invitations_sent_to_one_and_more_users, + CommonPlurals.invitations_sent_to_one_and_more_users, selections.size - 1, selections.first().getBestName(), selections.size - 1 diff --git a/vector/src/main/java/im/vector/app/features/invite/VectorInviteView.kt b/vector/src/main/java/im/vector/app/features/invite/VectorInviteView.kt index 7c5159ce11..491ba4c886 100644 --- a/vector/src/main/java/im/vector/app/features/invite/VectorInviteView.kt +++ b/vector/src/main/java/im/vector/app/features/invite/VectorInviteView.kt @@ -25,6 +25,7 @@ import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R import im.vector.app.databinding.VectorInviteViewBinding import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.util.toMatrixItem @@ -62,13 +63,13 @@ class VectorInviteView @JvmOverloads constructor(context: Context, attrs: Attrib avatarRenderer.render(sender.toMatrixItem(), views.inviteAvatarView) views.inviteIdentifierView.text = sender.userId views.inviteNameView.text = sender.displayName - views.inviteLabelView.text = context.getString(R.string.send_you_invite) + views.inviteLabelView.text = context.getString(CommonStrings.send_you_invite) } else { updateLayoutParams { height = LayoutParams.WRAP_CONTENT } views.inviteAvatarView.visibility = View.GONE views.inviteIdentifierView.visibility = View.GONE views.inviteNameView.visibility = View.GONE - views.inviteLabelView.text = context.getString(R.string.invited_by, sender.userId) + views.inviteLabelView.text = context.getString(CommonStrings.invited_by, sender.userId) } InviteButtonStateBinder.bind(views.inviteAcceptView, views.inviteRejectView, changeMembershipState) } diff --git a/vector/src/main/java/im/vector/app/features/link/LinkHandlerActivity.kt b/vector/src/main/java/im/vector/app/features/link/LinkHandlerActivity.kt index 1ca67e1fb7..f8f4c7dc79 100644 --- a/vector/src/main/java/im/vector/app/features/link/LinkHandlerActivity.kt +++ b/vector/src/main/java/im/vector/app/features/link/LinkHandlerActivity.kt @@ -23,7 +23,6 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.viewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.utils.toast @@ -33,6 +32,7 @@ import im.vector.app.features.home.HomeActivity import im.vector.app.features.login.LoginConfig import im.vector.app.features.permalink.PermalinkHandler import im.vector.app.features.start.StartAppViewModel +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.permalinks.PermalinkService import timber.log.Timber @@ -73,7 +73,7 @@ class LinkHandlerActivity : VectorBaseActivity() { } } - override fun onNewIntent(intent: Intent?) { + override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) handleIntent() } @@ -89,10 +89,10 @@ class LinkHandlerActivity : VectorBaseActivity() { uri.getQueryParameter(LoginConfig.CONFIG_HS_PARAMETER) != null -> handleConfigUrl(uri) uri.toString().startsWith(PermalinkService.MATRIX_TO_URL_BASE) -> handleSupportedHostUrl() uri.toString().startsWith(PermalinkHandler.MATRIX_TO_CUSTOM_SCHEME_URL_BASE) -> handleSupportedHostUrl() - resources.getStringArray(R.array.permalink_supported_hosts).contains(uri.host) -> handleSupportedHostUrl() + resources.getStringArray(im.vector.app.config.R.array.permalink_supported_hosts).contains(uri.host) -> handleSupportedHostUrl() else -> { // Other links are not yet handled, but should not come here (manifest configuration error?) - toast(R.string.universal_link_malformed) + toast(CommonStrings.universal_link_malformed) finish() } } @@ -139,11 +139,11 @@ class LinkHandlerActivity : VectorBaseActivity() { */ private fun displayAlreadyLoginPopup(uri: Uri) { MaterialAlertDialogBuilder(this) - .setTitle(R.string.dialog_title_warning) - .setMessage(R.string.error_user_already_logged_in) + .setTitle(CommonStrings.dialog_title_warning) + .setMessage(CommonStrings.error_user_already_logged_in) .setCancelable(false) - .setPositiveButton(R.string.logout) { _, _ -> safeSignout(uri) } - .setNegativeButton(R.string.action_cancel) { _, _ -> finish() } + .setPositiveButton(CommonStrings.logout) { _, _ -> safeSignout(uri) } + .setNegativeButton(CommonStrings.action_cancel) { _, _ -> finish() } .show() } @@ -168,10 +168,10 @@ class LinkHandlerActivity : VectorBaseActivity() { private fun displayError(failure: Throwable) { MaterialAlertDialogBuilder(this) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(errorFormatter.toHumanReadable(failure)) .setCancelable(false) - .setPositiveButton(R.string.ok) { _, _ -> finish() } + .setPositiveButton(CommonStrings.ok) { _, _ -> finish() } .show() } } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationDialog.kt b/vector/src/main/java/im/vector/app/features/location/LocationDialog.kt index 81ce75e57d..cc99cf3a40 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationDialog.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationDialog.kt @@ -18,13 +18,13 @@ package im.vector.app.features.location import androidx.fragment.app.Fragment import com.google.android.material.dialog.MaterialAlertDialogBuilder -import im.vector.app.R +import im.vector.lib.strings.CommonStrings fun Fragment.showUserLocationNotAvailableErrorDialog(onConfirmListener: () -> Unit) { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.location_not_available_dialog_title) - .setMessage(R.string.location_not_available_dialog_content) - .setPositiveButton(R.string.ok) { _, _ -> + .setTitle(CommonStrings.location_not_available_dialog_title) + .setMessage(CommonStrings.location_not_available_dialog_content) + .setPositiveButton(CommonStrings.ok) { _, _ -> onConfirmListener() } .setCancelable(false) diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt index d39dd42c5f..e0e3b2134a 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt @@ -32,7 +32,6 @@ import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.mapbox.mapboxsdk.maps.MapView import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.PERMISSIONS_FOR_FOREGROUND_LOCATION_SHARING @@ -47,6 +46,7 @@ import im.vector.app.features.location.live.duration.ChooseLiveDurationBottomShe import im.vector.app.features.location.live.tracking.LocationSharingAndroidService import im.vector.app.features.location.option.LocationSharingOption import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import org.matrix.android.sdk.api.util.MatrixItem import java.lang.ref.WeakReference @@ -182,9 +182,9 @@ class LocationSharingFragment : private fun handleLiveLocationSharingNotEnoughPermission() { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.live_location_not_enough_permission_dialog_title) - .setMessage(R.string.live_location_not_enough_permission_dialog_description) - .setPositiveButton(R.string.ok, null) + .setTitle(CommonStrings.live_location_not_enough_permission_dialog_title) + .setMessage(CommonStrings.live_location_not_enough_permission_dialog_description) + .setPositiveButton(CommonStrings.ok, null) .show() } @@ -245,7 +245,7 @@ class LocationSharingFragment : if (allGranted) { startLiveLocationSharing() } else if (deniedPermanently) { - activity?.onPermissionDeniedDialog(R.string.denied_permission_generic) + activity?.onPermissionDeniedDialog(CommonStrings.denied_permission_generic) } } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt index e11bfbf16e..8b763acfc5 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt @@ -19,13 +19,13 @@ package im.vector.app.features.location import android.graphics.drawable.Drawable import androidx.annotation.StringRes import com.airbnb.mvrx.MavericksState -import im.vector.app.R +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orTrue import org.matrix.android.sdk.api.util.MatrixItem enum class LocationSharingMode(@StringRes val titleRes: Int) { - STATIC_SHARING(R.string.location_activity_title_static_sharing), - PREVIEW(R.string.location_activity_title_preview) + STATIC_SHARING(CommonStrings.location_activity_title_static_sharing), + PREVIEW(CommonStrings.location_activity_title_preview) } data class LocationSharingViewState( diff --git a/vector/src/main/java/im/vector/app/features/location/MapLoadingErrorView.kt b/vector/src/main/java/im/vector/app/features/location/MapLoadingErrorView.kt index 8ea4fcac54..883585c2fc 100644 --- a/vector/src/main/java/im/vector/app/features/location/MapLoadingErrorView.kt +++ b/vector/src/main/java/im/vector/app/features/location/MapLoadingErrorView.kt @@ -23,10 +23,10 @@ import android.util.AttributeSet import android.view.LayoutInflater import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.res.use -import im.vector.app.R import im.vector.app.core.glide.GlideApp import im.vector.app.databinding.ViewMapLoadingErrorBinding import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings /** * Custom view to display an error when map fails to load. @@ -43,7 +43,7 @@ class MapLoadingErrorView @JvmOverloads constructor( init { context.obtainStyledAttributes( attrs, - R.styleable.MapLoadingErrorView, + im.vector.lib.ui.styles.R.styleable.MapLoadingErrorView, 0, 0 ).use { @@ -52,9 +52,9 @@ class MapLoadingErrorView @JvmOverloads constructor( } private fun setErrorDescription(typedArray: TypedArray) { - val description = typedArray.getString(R.styleable.MapLoadingErrorView_mapErrorDescription) + val description = typedArray.getString(im.vector.lib.ui.styles.R.styleable.MapLoadingErrorView_mapErrorDescription) if (description.isNullOrEmpty()) { - binding.mapLoadingErrorDescription.setText(R.string.location_share_loading_map_error) + binding.mapLoadingErrorDescription.setText(CommonStrings.location_share_loading_map_error) } else { binding.mapLoadingErrorDescription.text = description } @@ -62,7 +62,7 @@ class MapLoadingErrorView @JvmOverloads constructor( fun render(mapLoadingErrorViewState: MapLoadingErrorViewState) { GlideApp.with(binding.mapLoadingErrorBackground) - .load(ColorDrawable(ThemeUtils.getColor(context, R.attr.vctr_system))) + .load(ColorDrawable(ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_system))) .transform(mapLoadingErrorViewState.backgroundTransformation) .into(binding.mapLoadingErrorBackground) } diff --git a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt index d7e3463a5c..f815867b13 100644 --- a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt +++ b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt @@ -37,6 +37,7 @@ import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions import com.mapbox.mapboxsdk.style.layers.Property import im.vector.app.R import im.vector.app.core.utils.DimensionConverter +import im.vector.lib.strings.CommonStrings import timber.log.Timber private const val USER_PIN_ID = "user-pin-id" @@ -67,7 +68,7 @@ class MapTilerMapView @JvmOverloads constructor( init { context.obtainStyledAttributes( attrs, - R.styleable.MapTilerMapView, + im.vector.lib.ui.styles.R.styleable.MapTilerMapView, 0, 0 ).use { @@ -77,7 +78,7 @@ class MapTilerMapView @JvmOverloads constructor( } private fun setLocateButtonVisibility(typedArray: TypedArray) { - showLocationButton = typedArray.getBoolean(R.styleable.MapTilerMapView_showLocateButton, false) + showLocationButton = typedArray.getBoolean(im.vector.lib.ui.styles.R.styleable.MapTilerMapView_showLocateButton, false) } override fun onDestroy() { @@ -126,11 +127,13 @@ class MapTilerMapView @JvmOverloads constructor( private fun createLocateButton(): ImageView = ImageView(context).apply { setImageDrawable(ContextCompat.getDrawable(context, R.drawable.btn_locate)) - contentDescription = context.getString(R.string.a11y_location_share_locate_button) + contentDescription = context.getString(CommonStrings.a11y_location_share_locate_button) layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) updateLayoutParams { - val marginHorizontal = context.resources.getDimensionPixelOffset(R.dimen.location_sharing_locate_button_margin_horizontal) - val marginVertical = context.resources.getDimensionPixelOffset(R.dimen.location_sharing_locate_button_margin_vertical) + val marginHorizontal = + context.resources.getDimensionPixelOffset(im.vector.lib.ui.styles.R.dimen.location_sharing_locate_button_margin_horizontal) + val marginVertical = + context.resources.getDimensionPixelOffset(im.vector.lib.ui.styles.R.dimen.location_sharing_locate_button_margin_vertical) setMargins(marginHorizontal, marginVertical, marginHorizontal, marginVertical) } updateLayoutParams { @@ -141,7 +144,7 @@ class MapTilerMapView @JvmOverloads constructor( private fun adjustCompassButton(map: MapboxMap) { locateButton.post { val marginTop = locateButton.height + locateButton.marginTop + locateButton.marginBottom - val marginRight = context.resources.getDimensionPixelOffset(R.dimen.location_sharing_compass_button_margin_horizontal) + val marginRight = context.resources.getDimensionPixelOffset(im.vector.lib.ui.styles.R.dimen.location_sharing_compass_button_margin_horizontal) map.uiSettings.setCompassMargins(0, marginTop, marginRight, 0) } } diff --git a/vector/src/main/java/im/vector/app/features/location/live/LiveLocationEndedBannerView.kt b/vector/src/main/java/im/vector/app/features/location/live/LiveLocationEndedBannerView.kt index 29037a710a..effe01b923 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/LiveLocationEndedBannerView.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/LiveLocationEndedBannerView.kt @@ -23,7 +23,6 @@ import android.view.LayoutInflater import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.res.use import androidx.core.view.updateLayoutParams -import im.vector.app.R import im.vector.app.databinding.ViewLiveLocationEndedBannerBinding private const val BACKGROUND_ALPHA = 0.75f @@ -42,7 +41,7 @@ class LiveLocationEndedBannerView @JvmOverloads constructor( init { context.obtainStyledAttributes( attrs, - R.styleable.LiveLocationEndedBannerView, + im.vector.lib.ui.styles.R.styleable.LiveLocationEndedBannerView, 0, 0 ).use { @@ -52,12 +51,12 @@ class LiveLocationEndedBannerView @JvmOverloads constructor( } private fun setBackgroundAlpha(typedArray: TypedArray) { - val withAlpha = typedArray.getBoolean(R.styleable.LiveLocationEndedBannerView_locLiveEndedBkgWithAlpha, false) + val withAlpha = typedArray.getBoolean(im.vector.lib.ui.styles.R.styleable.LiveLocationEndedBannerView_locLiveEndedBkgWithAlpha, false) binding.liveLocationEndedBannerBackground.alpha = if (withAlpha) BACKGROUND_ALPHA else 1f } private fun setIconMarginStart(typedArray: TypedArray) { - val margin = typedArray.getDimensionPixelOffset(R.styleable.LiveLocationEndedBannerView_locLiveEndedIconMarginStart, 0) + val margin = typedArray.getDimensionPixelOffset(im.vector.lib.ui.styles.R.styleable.LiveLocationEndedBannerView_locLiveEndedIconMarginStart, 0) binding.liveLocationEndedBannerIcon.updateLayoutParams { marginStart = margin } diff --git a/vector/src/main/java/im/vector/app/features/location/live/LiveLocationRunningBannerView.kt b/vector/src/main/java/im/vector/app/features/location/live/LiveLocationRunningBannerView.kt index 0872250abb..abab8e839a 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/LiveLocationRunningBannerView.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/LiveLocationRunningBannerView.kt @@ -33,6 +33,7 @@ import im.vector.app.core.glide.GlideApp import im.vector.app.core.utils.TextUtils import im.vector.app.databinding.ViewLiveLocationRunningBannerBinding import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings import org.threeten.bp.Duration private const val REMAINING_TIME_COUNTER_INTERVAL_IN_MS = 1000L @@ -77,7 +78,7 @@ class LiveLocationRunningBannerView @JvmOverloads constructor( private fun renderEmitter(viewState: LiveLocationMessageBannerViewState.Emitter) { stopButton.isVisible = true - title.text = context.getString(R.string.location_share_live_enabled) + title.text = context.getString(CommonStrings.location_share_live_enabled) countDownTimer?.cancel() viewState.remainingTimeInMillis @@ -87,14 +88,14 @@ class LiveLocationRunningBannerView @JvmOverloads constructor( override fun onTick(millisUntilFinished: Long) { val duration = Duration.ofMillis(millisUntilFinished.coerceAtLeast(0L)) subTitle.text = context.getString( - R.string.location_share_live_remaining_time, + CommonStrings.location_share_live_remaining_time, TextUtils.formatDurationWithUnits(context, duration) ) } override fun onFinish() { subTitle.text = context.getString( - R.string.location_share_live_remaining_time, + CommonStrings.location_share_live_remaining_time, TextUtils.formatDurationWithUnits(context, Duration.ofMillis(0L)) ) } @@ -125,8 +126,8 @@ class LiveLocationRunningBannerView @JvmOverloads constructor( private fun renderWatcher(viewState: LiveLocationMessageBannerViewState.Watcher) { stopButton.isVisible = false - title.text = context.getString(R.string.location_share_live_view) - subTitle.text = context.getString(R.string.location_share_live_until, viewState.formattedLocalTimeOfEndOfLive) + title.text = context.getString(CommonStrings.location_share_live_view) + subTitle.text = context.getString(CommonStrings.location_share_live_until, viewState.formattedLocalTimeOfEndOfLive) } override fun onDetachedFromWindow() { diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationBottomSheetController.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationBottomSheetController.kt index 80f845c3b2..631613d97b 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationBottomSheetController.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationBottomSheetController.kt @@ -17,7 +17,6 @@ package im.vector.app.features.location.live.map import com.airbnb.epoxy.EpoxyController -import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter import im.vector.app.core.resources.DateProvider @@ -25,6 +24,7 @@ import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.toTimestamp import im.vector.app.features.home.AvatarRenderer import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class LiveLocationBottomSheetController @Inject constructor( @@ -80,6 +80,6 @@ class LiveLocationBottomSheetController @Inject constructor( private fun getFormattedLocalTimeEndOfLive(endOfLiveDateTimestampMillis: Long?): String { val endOfLiveDateTime = DateProvider.toLocalDateTime(endOfLiveDateTimestampMillis) val formattedDateTime = endOfLiveDateTime.toTimestamp().let { vectorDateFormatter.format(it, DateFormatKind.MESSAGE_SIMPLE) } - return stringProvider.getString(R.string.location_share_live_until, formattedDateTime) + return stringProvider.getString(CommonStrings.location_share_live_until, formattedDateTime) } } diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewActivity.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewActivity.kt index b6304c0b5a..4722fdb924 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewActivity.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewActivity.kt @@ -20,12 +20,12 @@ import android.content.Context import android.content.Intent import android.os.Parcelable import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.addFragment import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.databinding.ActivityLocationSharingBinding import im.vector.app.features.MainActivity import im.vector.lib.core.utils.compat.getParcelableCompat +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize @Parcelize @@ -45,7 +45,7 @@ class LiveLocationMapViewActivity : VectorBaseActivity : VectorBaseFragment( if (throwable.error.code == MatrixError.M_FORBIDDEN && throwable.httpCode == HttpsURLConnection.HTTP_FORBIDDEN /* 403 */) { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) - .setMessage(getString(R.string.login_registration_disabled)) - .setPositiveButton(R.string.ok, null) + .setTitle(CommonStrings.dialog_title_error) + .setMessage(getString(CommonStrings.login_registration_disabled)) + .setPositiveButton(CommonStrings.ok, null) .show() } else { onError(throwable) @@ -129,14 +129,14 @@ abstract class AbstractLoginFragment : VectorBaseFragment( displayCancelDialog && loginViewModel.isRegistrationStarted -> { // Ask for confirmation before cancelling the registration MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.login_signup_cancel_confirmation_title) - .setMessage(R.string.login_signup_cancel_confirmation_content) - .setPositiveButton(R.string.yes) { _, _ -> + .setTitle(CommonStrings.login_signup_cancel_confirmation_title) + .setMessage(CommonStrings.login_signup_cancel_confirmation_content) + .setPositiveButton(CommonStrings.yes) { _, _ -> displayCancelDialog = false @Suppress("DEPRECATION") vectorBaseActivity.onBackPressed() } - .setNegativeButton(R.string.no, null) + .setNegativeButton(CommonStrings.no, null) .show() true @@ -144,14 +144,14 @@ abstract class AbstractLoginFragment : VectorBaseFragment( displayCancelDialog && isResetPasswordStarted -> { // Ask for confirmation before cancelling the reset password MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.login_reset_password_cancel_confirmation_title) - .setMessage(R.string.login_reset_password_cancel_confirmation_content) - .setPositiveButton(R.string.yes) { _, _ -> + .setTitle(CommonStrings.login_reset_password_cancel_confirmation_title) + .setMessage(CommonStrings.login_reset_password_cancel_confirmation_content) + .setPositiveButton(CommonStrings.yes) { _, _ -> displayCancelDialog = false @Suppress("DEPRECATION") vectorBaseActivity.onBackPressed() } - .setNegativeButton(R.string.no, null) + .setNegativeButton(CommonStrings.no, null) .show() true diff --git a/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt b/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt index 9dfae7ff5f..4c9e5c3b3b 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt @@ -46,6 +46,7 @@ import im.vector.app.features.login.terms.LoginTermsFragmentArgument import im.vector.app.features.onboarding.AuthenticationDescription import im.vector.app.features.pin.UnlockedActivity import im.vector.lib.core.utils.compat.getParcelableExtraCompat +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.SSOAction import org.matrix.android.sdk.api.auth.registration.FlowResult import org.matrix.android.sdk.api.auth.registration.Stage @@ -75,7 +76,7 @@ open class LoginActivity : VectorBaseActivity(), UnlockedA // Find findViewById does not work, I do not know why // findViewById(R.id.loginLogo) ?.children - ?.firstOrNull { it.id == R.id.loginLogo } + ?.firstOrNull { it.id == im.vector.lib.ui.styles.R.id.loginLogo } ?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") } ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim) } @@ -134,9 +135,9 @@ open class LoginActivity : VectorBaseActivity(), UnlockedA } is LoginViewEvents.OutdatedHomeserver -> { MaterialAlertDialogBuilder(this) - .setTitle(R.string.login_error_outdated_homeserver_title) - .setMessage(R.string.login_error_outdated_homeserver_warning_content) - .setPositiveButton(R.string.ok, null) + .setTitle(CommonStrings.login_error_outdated_homeserver_title) + .setMessage(CommonStrings.login_error_outdated_homeserver_warning_content) + .setPositiveButton(CommonStrings.ok, null) .show() Unit } @@ -246,9 +247,9 @@ open class LoginActivity : VectorBaseActivity(), UnlockedA // And inform the user MaterialAlertDialogBuilder(this) - .setTitle(R.string.dialog_title_error) - .setMessage(getString(R.string.login_sso_error_message, onWebLoginError.description, onWebLoginError.errorCode)) - .setPositiveButton(R.string.ok, null) + .setTitle(CommonStrings.dialog_title_error) + .setMessage(getString(CommonStrings.login_sso_error_message, onWebLoginError.description, onWebLoginError.errorCode)) + .setPositiveButton(CommonStrings.ok, null) .show() } @@ -310,48 +311,48 @@ open class LoginActivity : VectorBaseActivity(), UnlockedA /** * Handle the SSO redirection here. */ - override fun onNewIntent(intent: Intent?) { + override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) - intent?.data + intent.data ?.let { tryOrNull { it.getQueryParameter("loginToken") } } ?.let { loginViewModel.handle(LoginAction.LoginWithToken(it)) } } + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() { validateBackPressed { - @Suppress("DEPRECATION") super.onBackPressed() } } private fun onRegistrationStageNotSupported() { MaterialAlertDialogBuilder(this) - .setTitle(R.string.app_name) - .setMessage(getString(R.string.login_registration_not_supported)) - .setPositiveButton(R.string.yes) { _, _ -> + .setTitle(buildMeta.applicationName) + .setMessage(getString(CommonStrings.login_registration_not_supported)) + .setPositiveButton(CommonStrings.yes) { _, _ -> addFragmentToBackstack( views.loginFragmentContainer, LoginWebFragment::class.java, option = commonOption ) } - .setNegativeButton(R.string.no, null) + .setNegativeButton(CommonStrings.no, null) .show() } private fun onLoginModeNotSupported(supportedTypes: List) { MaterialAlertDialogBuilder(this) - .setTitle(R.string.app_name) - .setMessage(getString(R.string.login_mode_not_supported, supportedTypes.joinToString { "'$it'" })) - .setPositiveButton(R.string.yes) { _, _ -> + .setTitle(buildMeta.applicationName) + .setMessage(getString(CommonStrings.login_mode_not_supported, supportedTypes.joinToString { "'$it'" })) + .setPositiveButton(CommonStrings.yes) { _, _ -> addFragmentToBackstack( views.loginFragmentContainer, LoginWebFragment::class.java, option = commonOption ) } - .setNegativeButton(R.string.no, null) + .setNegativeButton(CommonStrings.no, null) .show() } @@ -401,7 +402,7 @@ open class LoginActivity : VectorBaseActivity(), UnlockedA is Stage.Terms -> addFragmentToBackstack( views.loginFragmentContainer, LoginTermsFragment::class.java, - LoginTermsFragmentArgument(stage.policies.toLocalizedLoginTerms(getString(R.string.resources_language))), + LoginTermsFragmentArgument(stage.policies.toLocalizedLoginTerms(getString(CommonStrings.resources_language))), tag = FRAGMENT_REGISTRATION_STAGE_TAG, option = commonOption ) diff --git a/vector/src/main/java/im/vector/app/features/login/LoginCaptchaFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginCaptchaFragment.kt index b082e37933..fa6896e880 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginCaptchaFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginCaptchaFragment.kt @@ -34,9 +34,9 @@ import androidx.core.view.isVisible import com.airbnb.mvrx.args import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.utils.AssetReader import im.vector.app.databinding.FragmentLoginCaptchaBinding +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.util.MatrixJsonParser import timber.log.Timber @@ -111,12 +111,12 @@ class LoginCaptchaFragment : } MaterialAlertDialogBuilder(requireActivity()) - .setMessage(R.string.ssl_could_not_verify) - .setPositiveButton(R.string.ssl_trust) { _, _ -> + .setMessage(CommonStrings.ssl_could_not_verify) + .setPositiveButton(CommonStrings.ssl_trust) { _, _ -> Timber.d("## onReceivedSslError() : the user trusted") handler.proceed() } - .setNegativeButton(R.string.ssl_do_not_trust) { _, _ -> + .setNegativeButton(CommonStrings.ssl_do_not_trust) { _, _ -> Timber.d("## onReceivedSslError() : the user did not trust") handler.cancel() } diff --git a/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt index 5d1eed95eb..41248e1e26 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt @@ -34,6 +34,7 @@ import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.hidePassword import im.vector.app.core.extensions.toReducedUrl import im.vector.app.databinding.FragmentLoginBinding +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map @@ -120,30 +121,30 @@ class LoginFragment : if (login.isEmpty()) { views.loginFieldTil.error = getString( if (isSignupMode) { - R.string.error_empty_field_choose_user_name + CommonStrings.error_empty_field_choose_user_name } else { - R.string.error_empty_field_enter_user_name + CommonStrings.error_empty_field_enter_user_name } ) error++ } if (isSignupMode && isNumericOnlyUserIdForbidden && login.isDigitsOnly()) { - views.loginFieldTil.error = getString(R.string.error_forbidden_digits_only_username) + views.loginFieldTil.error = getString(CommonStrings.error_forbidden_digits_only_username) error++ } if (password.isEmpty()) { views.passwordFieldTil.error = getString( if (isSignupMode) { - R.string.error_empty_field_choose_password + CommonStrings.error_empty_field_choose_password } else { - R.string.error_empty_field_your_password + CommonStrings.error_empty_field_your_password } ) error++ } if (error == 0) { - loginViewModel.handle(LoginAction.LoginOrRegister(login, password, getString(R.string.login_default_session_public_name))) + loginViewModel.handle(LoginAction.LoginOrRegister(login, password, getString(CommonStrings.login_default_session_public_name))) } } @@ -157,24 +158,24 @@ class LoginFragment : views.loginFieldTil.hint = getString( when (state.signMode) { SignMode.Unknown -> error("developer error") - SignMode.SignUp -> R.string.login_signup_username_hint - SignMode.SignIn -> R.string.login_signin_username_hint - SignMode.SignInWithMatrixId -> R.string.login_signin_matrix_id_hint + SignMode.SignUp -> CommonStrings.login_signup_username_hint + SignMode.SignIn -> CommonStrings.login_signin_username_hint + SignMode.SignInWithMatrixId -> CommonStrings.login_signin_matrix_id_hint } ) // Handle direct signin first if (state.signMode == SignMode.SignInWithMatrixId) { views.loginServerIcon.isVisible = false - views.loginTitle.text = getString(R.string.login_signin_matrix_id_title) - views.loginNotice.text = getString(R.string.login_signin_matrix_id_notice) + views.loginTitle.text = getString(CommonStrings.login_signin_matrix_id_title) + views.loginNotice.text = getString(CommonStrings.login_signin_matrix_id_notice) views.loginPasswordNotice.isVisible = true } else { val resId = when (state.signMode) { SignMode.Unknown -> error("developer error") - SignMode.SignUp -> R.string.login_signup_to - SignMode.SignIn -> R.string.login_connect_to - SignMode.SignInWithMatrixId -> R.string.login_connect_to + SignMode.SignUp -> CommonStrings.login_signup_to + SignMode.SignIn -> CommonStrings.login_connect_to + SignMode.SignInWithMatrixId -> CommonStrings.login_connect_to } when (state.serverType) { @@ -182,18 +183,18 @@ class LoginFragment : views.loginServerIcon.isVisible = true views.loginServerIcon.setImageResource(R.drawable.ic_logo_matrix_org) views.loginTitle.text = getString(resId, state.homeServerUrlFromUser.toReducedUrl()) - views.loginNotice.text = getString(R.string.login_server_matrix_org_text) + views.loginNotice.text = getString(CommonStrings.login_server_matrix_org_text) } ServerType.EMS -> { views.loginServerIcon.isVisible = true views.loginServerIcon.setImageResource(R.drawable.ic_logo_element_matrix_services) views.loginTitle.text = getString(resId, "Element Matrix Services") - views.loginNotice.text = getString(R.string.login_server_modular_text) + views.loginNotice.text = getString(CommonStrings.login_server_modular_text) } ServerType.Other -> { views.loginServerIcon.isVisible = false views.loginTitle.text = getString(resId, state.homeServerUrlFromUser.toReducedUrl()) - views.loginNotice.text = getString(R.string.login_server_other_text) + views.loginNotice.text = getString(CommonStrings.login_server_other_text) } ServerType.Unknown -> Unit /* Should not happen */ } @@ -223,9 +224,9 @@ class LoginFragment : views.loginSubmit.text = getString( when (state.signMode) { SignMode.Unknown -> error("developer error") - SignMode.SignUp -> R.string.login_signup_submit + SignMode.SignUp -> CommonStrings.login_signup_submit SignMode.SignIn, - SignMode.SignInWithMatrixId -> R.string.login_signin + SignMode.SignInWithMatrixId -> CommonStrings.login_signin } ) } @@ -283,12 +284,12 @@ class LoginFragment : error.error.code == MatrixError.M_FORBIDDEN && error.error.message.isEmpty()) { // Login with email, but email unknown - views.loginFieldTil.error = getString(R.string.login_login_with_email_error) + views.loginFieldTil.error = getString(CommonStrings.login_login_with_email_error) } else { // Trick to display the error without text. views.loginFieldTil.error = " " if (error.isInvalidPassword() && spaceInPassword()) { - views.passwordFieldTil.error = getString(R.string.auth_invalid_login_param_space_in_password) + views.passwordFieldTil.error = getString(CommonStrings.auth_invalid_login_param_space_in_password) } else { views.passwordFieldTil.error = errorFormatter.toHumanReadable(error) } diff --git a/vector/src/main/java/im/vector/app/features/login/LoginGenericTextInputFormFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginGenericTextInputFormFragment.kt index 751ac79964..a118a66982 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginGenericTextInputFormFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginGenericTextInputFormFragment.kt @@ -30,10 +30,10 @@ import com.airbnb.mvrx.args import com.google.i18n.phonenumbers.NumberParseException import com.google.i18n.phonenumbers.PhoneNumberUtil import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.setTextOrHide import im.vector.app.databinding.FragmentLoginGenericTextInputFormBinding +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.parcelize.Parcelize @@ -107,35 +107,35 @@ class LoginGenericTextInputFormFragment : private fun setupUi() { when (params.mode) { TextInputFormFragmentMode.SetEmail -> { - views.loginGenericTextInputFormTitle.text = getString(R.string.login_set_email_title) - views.loginGenericTextInputFormNotice.text = getString(R.string.login_set_email_notice) + views.loginGenericTextInputFormTitle.text = getString(CommonStrings.login_set_email_title) + views.loginGenericTextInputFormNotice.text = getString(CommonStrings.login_set_email_notice) views.loginGenericTextInputFormNotice2.setTextOrHide(null) views.loginGenericTextInputFormTil.hint = - getString(if (params.mandatory) R.string.login_set_email_mandatory_hint else R.string.login_set_email_optional_hint) + getString(if (params.mandatory) CommonStrings.login_set_email_mandatory_hint else CommonStrings.login_set_email_optional_hint) views.loginGenericTextInputFormTextInput.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS views.loginGenericTextInputFormOtherButton.isVisible = false - views.loginGenericTextInputFormSubmit.text = getString(R.string.login_set_email_submit) + views.loginGenericTextInputFormSubmit.text = getString(CommonStrings.login_set_email_submit) } TextInputFormFragmentMode.SetMsisdn -> { - views.loginGenericTextInputFormTitle.text = getString(R.string.login_set_msisdn_title) - views.loginGenericTextInputFormNotice.text = getString(R.string.login_set_msisdn_notice) - views.loginGenericTextInputFormNotice2.setTextOrHide(getString(R.string.login_set_msisdn_notice2)) + views.loginGenericTextInputFormTitle.text = getString(CommonStrings.login_set_msisdn_title) + views.loginGenericTextInputFormNotice.text = getString(CommonStrings.login_set_msisdn_notice) + views.loginGenericTextInputFormNotice2.setTextOrHide(getString(CommonStrings.login_set_msisdn_notice2)) views.loginGenericTextInputFormTil.hint = - getString(if (params.mandatory) R.string.login_set_msisdn_mandatory_hint else R.string.login_set_msisdn_optional_hint) + getString(if (params.mandatory) CommonStrings.login_set_msisdn_mandatory_hint else CommonStrings.login_set_msisdn_optional_hint) views.loginGenericTextInputFormTextInput.inputType = InputType.TYPE_CLASS_PHONE views.loginGenericTextInputFormOtherButton.isVisible = false - views.loginGenericTextInputFormSubmit.text = getString(R.string.login_set_msisdn_submit) + views.loginGenericTextInputFormSubmit.text = getString(CommonStrings.login_set_msisdn_submit) } TextInputFormFragmentMode.ConfirmMsisdn -> { - views.loginGenericTextInputFormTitle.text = getString(R.string.login_msisdn_confirm_title) - views.loginGenericTextInputFormNotice.text = getString(R.string.login_msisdn_confirm_notice, params.extra) + views.loginGenericTextInputFormTitle.text = getString(CommonStrings.login_msisdn_confirm_title) + views.loginGenericTextInputFormNotice.text = getString(CommonStrings.login_msisdn_confirm_notice, params.extra) views.loginGenericTextInputFormNotice2.setTextOrHide(null) views.loginGenericTextInputFormTil.hint = - getString(R.string.login_msisdn_confirm_hint) + getString(CommonStrings.login_msisdn_confirm_hint) views.loginGenericTextInputFormTextInput.inputType = InputType.TYPE_CLASS_NUMBER views.loginGenericTextInputFormOtherButton.isVisible = true - views.loginGenericTextInputFormOtherButton.text = getString(R.string.login_msisdn_confirm_send_again) - views.loginGenericTextInputFormSubmit.text = getString(R.string.login_msisdn_confirm_submit) + views.loginGenericTextInputFormOtherButton.text = getString(CommonStrings.login_msisdn_confirm_send_again) + views.loginGenericTextInputFormSubmit.text = getString(CommonStrings.login_msisdn_confirm_submit) } } } @@ -187,10 +187,10 @@ class LoginGenericTextInputFormFragment : val phoneNumber = PhoneNumberUtil.getInstance().parse(text, null) return PhoneNumberUtil.getInstance().getRegionCodeForCountryCode(phoneNumber.countryCode) } catch (e: NumberParseException) { - views.loginGenericTextInputFormTil.error = getString(R.string.login_msisdn_error_other) + views.loginGenericTextInputFormTil.error = getString(CommonStrings.login_msisdn_error_other) } } else { - views.loginGenericTextInputFormTil.error = getString(R.string.login_msisdn_error_not_international) + views.loginGenericTextInputFormTil.error = getString(CommonStrings.login_msisdn_error_not_international) } // Error @@ -246,7 +246,7 @@ class LoginGenericTextInputFormFragment : when { throwable is Failure.SuccessError -> // The entered code is not correct - views.loginGenericTextInputFormTil.error = getString(R.string.login_validation_code_is_not_correct) + views.loginGenericTextInputFormTil.error = getString(CommonStrings.login_validation_code_is_not_correct) throwable.is401() -> // It can happen if user request again the 3pid Unit diff --git a/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordFragment.kt index a8bbbdde0b..d04c12b4f0 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordFragment.kt @@ -25,12 +25,12 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.hidePassword import im.vector.app.core.extensions.toReducedUrl import im.vector.app.databinding.FragmentLoginResetPasswordBinding import im.vector.app.features.analytics.plan.MobileScreen +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map @@ -64,7 +64,7 @@ class LoginResetPasswordFragment : } private fun setupUi(state: LoginViewState) { - views.resetPasswordTitle.text = getString(R.string.login_reset_password_on, state.homeServerUrlFromUser.toReducedUrl()) + views.resetPasswordTitle.text = getString(CommonStrings.login_reset_password_on, state.homeServerUrlFromUser.toReducedUrl()) } private fun setupSubmitButton() { @@ -90,12 +90,12 @@ class LoginResetPasswordFragment : showWarning = false // Display a warning as Riot-Web does first MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.login_reset_password_warning_title) - .setMessage(R.string.login_reset_password_warning_content) - .setPositiveButton(R.string.login_reset_password_warning_submit) { _, _ -> + .setTitle(CommonStrings.login_reset_password_warning_title) + .setMessage(CommonStrings.login_reset_password_warning_content) + .setPositiveButton(CommonStrings.login_reset_password_warning_submit) { _, _ -> doSubmit() } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } else { doSubmit() diff --git a/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordMailConfirmationFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordMailConfirmationFragment.kt index c95a778860..bb16529b65 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordMailConfirmationFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordMailConfirmationFragment.kt @@ -23,8 +23,8 @@ import android.view.ViewGroup import com.airbnb.mvrx.Fail import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.databinding.FragmentLoginResetPasswordMailConfirmationBinding +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.failure.is401 /** @@ -45,7 +45,7 @@ class LoginResetPasswordMailConfirmationFragment : } private fun setupUi(state: LoginViewState) { - views.resetPasswordMailConfirmationNotice.text = getString(R.string.login_reset_password_mail_confirmation_notice, state.resetPasswordEmail) + views.resetPasswordMailConfirmationNotice.text = getString(CommonStrings.login_reset_password_mail_confirmation_notice, state.resetPasswordEmail) } private fun submit() { @@ -63,15 +63,15 @@ class LoginResetPasswordMailConfirmationFragment : is Fail -> { // Link in email not yet clicked ? val message = if (state.asyncResetMailConfirmed.error.is401()) { - getString(R.string.auth_reset_password_error_unauthorized) + getString(CommonStrings.auth_reset_password_error_unauthorized) } else { errorFormatter.toHumanReadable(state.asyncResetMailConfirmed.error) } MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(message) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } else -> Unit diff --git a/vector/src/main/java/im/vector/app/features/login/LoginServerSelectionFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginServerSelectionFragment.kt index 0813957e99..b28b46fdff 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginServerSelectionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginServerSelectionFragment.kt @@ -21,9 +21,9 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.utils.openUrlInChromeCustomTab import im.vector.app.databinding.FragmentLoginServerSelectionBinding +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span /** @@ -58,7 +58,7 @@ class LoginServerSelectionFragment : private fun initTextViews() { views.loginServerChoiceEmsLearnMore.text = span { - text = getString(R.string.login_server_modular_learn_more) + text = getString(CommonStrings.login_server_modular_learn_more) textDecorationLine = "underline" } } diff --git a/vector/src/main/java/im/vector/app/features/login/LoginServerUrlFormFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginServerUrlFormFragment.kt index aabe0c2f2f..60da972f6b 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginServerUrlFormFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginServerUrlFormFragment.kt @@ -34,6 +34,7 @@ import im.vector.app.core.resources.BuildMeta import im.vector.app.core.utils.ensureProtocol import im.vector.app.core.utils.openUrlInChromeCustomTab import im.vector.app.databinding.FragmentLoginServerUrlFormBinding +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.failure.Failure @@ -89,19 +90,19 @@ class LoginServerUrlFormFragment : when (state.serverType) { ServerType.EMS -> { views.loginServerUrlFormIcon.isVisible = true - views.loginServerUrlFormTitle.text = getString(R.string.login_connect_to_modular) - views.loginServerUrlFormText.text = getString(R.string.login_server_url_form_modular_text) + views.loginServerUrlFormTitle.text = getString(CommonStrings.login_connect_to_modular) + views.loginServerUrlFormText.text = getString(CommonStrings.login_server_url_form_modular_text) views.loginServerUrlFormLearnMore.isVisible = true - views.loginServerUrlFormHomeServerUrlTil.hint = getText(R.string.login_server_url_form_modular_hint) - views.loginServerUrlFormNotice.text = getString(R.string.login_server_url_form_modular_notice) + views.loginServerUrlFormHomeServerUrlTil.hint = getText(CommonStrings.login_server_url_form_modular_hint) + views.loginServerUrlFormNotice.text = getString(CommonStrings.login_server_url_form_modular_notice) } else -> { views.loginServerUrlFormIcon.isVisible = false - views.loginServerUrlFormTitle.text = getString(R.string.login_server_other_title) - views.loginServerUrlFormText.text = getString(R.string.login_connect_to_a_custom_server) + views.loginServerUrlFormTitle.text = getString(CommonStrings.login_server_other_title) + views.loginServerUrlFormText.text = getString(CommonStrings.login_connect_to_a_custom_server) views.loginServerUrlFormLearnMore.isVisible = false - views.loginServerUrlFormHomeServerUrlTil.hint = getText(R.string.login_server_url_form_other_hint) - views.loginServerUrlFormNotice.text = getString(R.string.login_server_url_form_common_notice) + views.loginServerUrlFormHomeServerUrlTil.hint = getText(CommonStrings.login_server_url_form_other_hint) + views.loginServerUrlFormNotice.text = getString(CommonStrings.login_server_url_form_common_notice) } } val completions = state.knownCustomHomeServersUrls + if (buildMeta.isDebug) listOf("http://10.0.2.2:8080") else emptyList() @@ -138,7 +139,7 @@ class LoginServerUrlFormFragment : when { serverUrl.isBlank() -> { - views.loginServerUrlFormHomeServerUrlTil.error = getString(R.string.login_error_invalid_home_server) + views.loginServerUrlFormHomeServerUrlTil.error = getString(CommonStrings.login_error_invalid_home_server) } else -> { views.loginServerUrlFormHomeServerUrl.setText(serverUrl, false /* to avoid completion dialog flicker*/) @@ -156,7 +157,7 @@ class LoginServerUrlFormFragment : views.loginServerUrlFormHomeServerUrlTil.error = if (throwable is Failure.NetworkConnection && throwable.ioException is UnknownHostException) { // Invalid homeserver? - getString(R.string.login_error_homeserver_not_found) + getString(CommonStrings.login_error_homeserver_not_found) } else { errorFormatter.toHumanReadable(throwable) } diff --git a/vector/src/main/java/im/vector/app/features/login/LoginSignUpSignInSelectionFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginSignUpSignInSelectionFragment.kt index 5ed806622f..6219be4895 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginSignUpSignInSelectionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginSignUpSignInSelectionFragment.kt @@ -27,6 +27,7 @@ import im.vector.app.R import im.vector.app.core.extensions.toReducedUrl import im.vector.app.databinding.FragmentLoginSignupSigninSelectionBinding import im.vector.app.features.login.SocialLoginButtonsView.Mode +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.SSOAction /** @@ -56,19 +57,19 @@ class LoginSignUpSignInSelectionFragment : ServerType.MatrixOrg -> { views.loginSignupSigninServerIcon.setImageResource(R.drawable.ic_logo_matrix_org) views.loginSignupSigninServerIcon.isVisible = true - views.loginSignupSigninTitle.text = getString(R.string.login_connect_to, state.homeServerUrlFromUser.toReducedUrl()) - views.loginSignupSigninText.text = getString(R.string.login_server_matrix_org_text) + views.loginSignupSigninTitle.text = getString(CommonStrings.login_connect_to, state.homeServerUrlFromUser.toReducedUrl()) + views.loginSignupSigninText.text = getString(CommonStrings.login_server_matrix_org_text) } ServerType.EMS -> { views.loginSignupSigninServerIcon.setImageResource(R.drawable.ic_logo_element_matrix_services) views.loginSignupSigninServerIcon.isVisible = true - views.loginSignupSigninTitle.text = getString(R.string.login_connect_to_modular) + views.loginSignupSigninTitle.text = getString(CommonStrings.login_connect_to_modular) views.loginSignupSigninText.text = state.homeServerUrlFromUser.toReducedUrl() } ServerType.Other -> { views.loginSignupSigninServerIcon.isVisible = false - views.loginSignupSigninTitle.text = getString(R.string.login_server_other_title) - views.loginSignupSigninText.text = getString(R.string.login_connect_to, state.homeServerUrlFromUser.toReducedUrl()) + views.loginSignupSigninTitle.text = getString(CommonStrings.login_server_other_title) + views.loginSignupSigninText.text = getString(CommonStrings.login_connect_to, state.homeServerUrlFromUser.toReducedUrl()) } ServerType.Unknown -> Unit /* Should not happen */ } @@ -98,11 +99,11 @@ class LoginSignUpSignInSelectionFragment : when (state.loginMode) { is LoginMode.Sso -> { // change to only one button that is sign in with sso - views.loginSignupSigninSubmit.text = getString(R.string.login_signin_sso) + views.loginSignupSigninSubmit.text = getString(CommonStrings.login_signin_sso) views.loginSignupSigninSignIn.isVisible = false } else -> { - views.loginSignupSigninSubmit.text = getString(R.string.login_signup) + views.loginSignupSigninSubmit.text = getString(CommonStrings.login_signup) views.loginSignupSigninSignIn.isVisible = true } } diff --git a/vector/src/main/java/im/vector/app/features/login/LoginSplashFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginSplashFragment.kt index dd563483ec..344b2de8b5 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginSplashFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginSplashFragment.kt @@ -24,11 +24,11 @@ import android.view.ViewGroup import androidx.core.view.isVisible import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.resources.BuildMeta import im.vector.app.databinding.FragmentLoginSplashBinding import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.failure.Failure import java.net.UnknownHostException import javax.inject.Inject @@ -84,12 +84,12 @@ class LoginSplashFragment : // Invalid homeserver from URL config val url = loginViewModel.getInitialHomeServerUrl().orEmpty() MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) - .setMessage(getString(R.string.login_error_homeserver_from_url_not_found, url)) - .setPositiveButton(R.string.login_error_homeserver_from_url_not_found_enter_manual) { _, _ -> + .setTitle(CommonStrings.dialog_title_error) + .setMessage(getString(CommonStrings.login_error_homeserver_from_url_not_found, url)) + .setPositiveButton(CommonStrings.login_error_homeserver_from_url_not_found_enter_manual) { _, _ -> loginViewModel.handle(LoginAction.OnGetStarted(resetLoginConfig = true)) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } else { super.onError(throwable) diff --git a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt index 4da022d4bb..01ff717894 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt @@ -26,7 +26,6 @@ import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory @@ -34,6 +33,7 @@ import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.core.session.ConfigureAndStartSessionUseCase import im.vector.app.core.utils.ensureTrailingSlash +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Job import kotlinx.coroutines.launch import org.matrix.android.sdk.api.MatrixPatterns.getServerName @@ -90,7 +90,7 @@ class LoginViewModel @AssistedInject constructor( private var lastAction: LoginAction? = null private var currentHomeServerConnectionConfig: HomeServerConnectionConfig? = null - private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() + private val matrixOrgUrl = stringProvider.getString(im.vector.app.config.R.string.matrix_org_server_url).ensureTrailingSlash() val currentThreePid: String? get() = registrationWizard?.getCurrentThreePid() @@ -612,7 +612,7 @@ class LoginViewModel @AssistedInject constructor( asyncLoginAction = Uninitialized ) } - _viewEvents.post(LoginViewEvents.Failure(Exception(stringProvider.getString(R.string.autodiscover_well_known_error)))) + _viewEvents.post(LoginViewEvents.Failure(Exception(stringProvider.getString(CommonStrings.autodiscover_well_known_error)))) } private suspend fun onWellknownSuccess( diff --git a/vector/src/main/java/im/vector/app/features/login/LoginWaitForEmailFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginWaitForEmailFragment.kt index c13769e9e9..5396eed9ac 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginWaitForEmailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginWaitForEmailFragment.kt @@ -23,8 +23,8 @@ import android.view.View import android.view.ViewGroup import com.airbnb.mvrx.args import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.databinding.FragmentLoginWaitForEmailBinding +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.failure.is401 @@ -65,7 +65,7 @@ class LoginWaitForEmailFragment : } private fun setupUi() { - views.loginWaitForEmailNotice.text = getString(R.string.login_wait_for_email_notice, params.email) + views.loginWaitForEmailNotice.text = getString(CommonStrings.login_wait_for_email_notice, params.email) } override fun onError(throwable: Throwable) { diff --git a/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt index b89018ccff..df9f55e116 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt @@ -33,11 +33,11 @@ import android.webkit.WebViewClient import com.airbnb.mvrx.activityViewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.utils.AssetReader import im.vector.app.databinding.FragmentLoginWebBinding import im.vector.app.features.signout.soft.SoftLogoutAction import im.vector.app.features.signout.soft.SoftLogoutViewModel +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.util.MatrixJsonParser import timber.log.Timber @@ -83,8 +83,8 @@ class LoginWebFragment : private fun setupTitle(state: LoginViewState) { toolbar?.title = when (state.signMode) { - SignMode.SignIn -> getString(R.string.login_signin) - else -> getString(R.string.login_signup) + SignMode.SignIn -> getString(CommonStrings.login_signin) + else -> getString(CommonStrings.login_signup) } } @@ -131,9 +131,9 @@ class LoginWebFragment : error: SslError ) { MaterialAlertDialogBuilder(requireActivity()) - .setMessage(R.string.ssl_could_not_verify) - .setPositiveButton(R.string.ssl_trust) { _, _ -> handler.proceed() } - .setNegativeButton(R.string.ssl_do_not_trust) { _, _ -> handler.cancel() } + .setMessage(CommonStrings.ssl_could_not_verify) + .setPositiveButton(CommonStrings.ssl_trust) { _, _ -> handler.proceed() } + .setNegativeButton(CommonStrings.ssl_do_not_trust) { _, _ -> handler.cancel() } .setOnKeyListener(DialogInterface.OnKeyListener { dialog, keyCode, event -> if (event.action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { handler.cancel() diff --git a/vector/src/main/java/im/vector/app/features/login/SocialLoginButtonsView.kt b/vector/src/main/java/im/vector/app/features/login/SocialLoginButtonsView.kt index 4ac98d6f2d..55b4956fa1 100644 --- a/vector/src/main/java/im/vector/app/features/login/SocialLoginButtonsView.kt +++ b/vector/src/main/java/im/vector/app/features/login/SocialLoginButtonsView.kt @@ -25,6 +25,7 @@ import android.widget.LinearLayout import androidx.core.view.children import com.google.android.material.button.MaterialButton import im.vector.app.R +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.data.SsoIdentityProvider class SocialLoginButtonsView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : @@ -74,12 +75,12 @@ class SocialLoginButtonsView @JvmOverloads constructor(context: Context, attrs: removeAllViews() if (ssoIdentityProviders.isNullOrEmpty()) { // Put a default sign in with sso button - MaterialButton(context, null, R.attr.materialButtonOutlinedStyle).apply { + MaterialButton(context, null, com.google.android.material.R.attr.materialButtonOutlinedStyle).apply { transformationMethod = null textAlignment = View.TEXT_ALIGNMENT_CENTER }.let { - it.text = if (hasOidcCompatibilityFlow) context.getString(R.string.login_continue) - else getButtonTitle(context.getString(R.string.login_social_sso)) + it.text = if (hasOidcCompatibilityFlow) context.getString(CommonStrings.login_continue) + else getButtonTitle(context.getString(CommonStrings.login_social_sso)) it.textAlignment = View.TEXT_ALIGNMENT_CENTER it.setOnClickListener { listener?.onProviderSelected(null) @@ -94,26 +95,26 @@ class SocialLoginButtonsView @JvmOverloads constructor(context: Context, attrs: val button: MaterialButton = cachedViews[identityProvider.id] ?: when (identityProvider.brand) { SsoIdentityProvider.BRAND_GOOGLE -> { - MaterialButton(context, null, R.attr.vctr_social_login_button_google_style) + MaterialButton(context, null, im.vector.lib.ui.styles.R.attr.vctr_social_login_button_google_style) } SsoIdentityProvider.BRAND_GITHUB -> { - MaterialButton(context, null, R.attr.vctr_social_login_button_github_style) + MaterialButton(context, null, im.vector.lib.ui.styles.R.attr.vctr_social_login_button_github_style) } SsoIdentityProvider.BRAND_APPLE -> { - MaterialButton(context, null, R.attr.vctr_social_login_button_apple_style) + MaterialButton(context, null, im.vector.lib.ui.styles.R.attr.vctr_social_login_button_apple_style) } SsoIdentityProvider.BRAND_FACEBOOK -> { - MaterialButton(context, null, R.attr.vctr_social_login_button_facebook_style) + MaterialButton(context, null, im.vector.lib.ui.styles.R.attr.vctr_social_login_button_facebook_style) } SsoIdentityProvider.BRAND_TWITTER -> { - MaterialButton(context, null, R.attr.vctr_social_login_button_twitter_style) + MaterialButton(context, null, im.vector.lib.ui.styles.R.attr.vctr_social_login_button_twitter_style) } SsoIdentityProvider.BRAND_GITLAB -> { - MaterialButton(context, null, R.attr.vctr_social_login_button_gitlab_style) + MaterialButton(context, null, im.vector.lib.ui.styles.R.attr.vctr_social_login_button_gitlab_style) } else -> { // TODO Use iconUrl - MaterialButton(context, null, R.attr.materialButtonOutlinedStyle).apply { + MaterialButton(context, null, com.google.android.material.R.attr.materialButtonOutlinedStyle).apply { transformationMethod = null textAlignment = View.TEXT_ALIGNMENT_CENTER } @@ -130,9 +131,9 @@ class SocialLoginButtonsView @JvmOverloads constructor(context: Context, attrs: private fun getButtonTitle(providerName: String?): String { return when (mode) { - Mode.MODE_SIGN_IN -> context.getString(R.string.login_social_signin_with, providerName) - Mode.MODE_SIGN_UP -> context.getString(R.string.login_social_signup_with, providerName) - Mode.MODE_CONTINUE -> context.getString(R.string.login_social_continue_with, providerName) + Mode.MODE_SIGN_IN -> context.getString(CommonStrings.login_social_signin_with, providerName) + Mode.MODE_SIGN_UP -> context.getString(CommonStrings.login_social_signup_with, providerName) + Mode.MODE_CONTINUE -> context.getString(CommonStrings.login_social_continue_with, providerName) } } @@ -152,8 +153,8 @@ class SocialLoginButtonsView @JvmOverloads constructor(context: Context, attrs: SsoIdentityProvider("Custom_pro", "SSO", null, null) ) } - val typedArray = context.theme.obtainStyledAttributes(attrs, R.styleable.SocialLoginButtonsView, 0, 0) - val modeAttr = typedArray.getInt(R.styleable.SocialLoginButtonsView_signMode, 2) + val typedArray = context.theme.obtainStyledAttributes(attrs, im.vector.lib.ui.styles.R.styleable.SocialLoginButtonsView, 0, 0) + val modeAttr = typedArray.getInt(im.vector.lib.ui.styles.R.styleable.SocialLoginButtonsView_signMode, 2) mode = when (modeAttr) { 0 -> Mode.MODE_SIGN_IN 1 -> Mode.MODE_SIGN_UP diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginHeaderView.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginHeaderView.kt index 03478d2f50..05c7bdffad 100644 --- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginHeaderView.kt +++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginHeaderView.kt @@ -23,7 +23,6 @@ import android.util.AttributeSet import android.view.LayoutInflater import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.res.use -import im.vector.app.R import im.vector.app.core.extensions.setTextOrHide import im.vector.app.databinding.ViewQrCodeLoginHeaderBinding @@ -41,7 +40,7 @@ class QrCodeLoginHeaderView @JvmOverloads constructor( init { context.obtainStyledAttributes( attrs, - R.styleable.QrCodeLoginHeaderView, + im.vector.lib.ui.styles.R.styleable.QrCodeLoginHeaderView, 0, 0 ).use { @@ -52,18 +51,18 @@ class QrCodeLoginHeaderView @JvmOverloads constructor( } private fun setTitle(typedArray: TypedArray) { - val title = typedArray.getString(R.styleable.QrCodeLoginHeaderView_qrCodeLoginHeaderTitle) + val title = typedArray.getString(im.vector.lib.ui.styles.R.styleable.QrCodeLoginHeaderView_qrCodeLoginHeaderTitle) setTitle(title) } private fun setDescription(typedArray: TypedArray) { - val description = typedArray.getString(R.styleable.QrCodeLoginHeaderView_qrCodeLoginHeaderDescription) + val description = typedArray.getString(im.vector.lib.ui.styles.R.styleable.QrCodeLoginHeaderView_qrCodeLoginHeaderDescription) setDescription(description) } private fun setImage(typedArray: TypedArray) { - val imageResource = typedArray.getResourceId(R.styleable.QrCodeLoginHeaderView_qrCodeLoginHeaderImageResource, 0) - val backgroundTint = typedArray.getColor(R.styleable.QrCodeLoginHeaderView_qrCodeLoginHeaderImageBackgroundTint, 0) + val imageResource = typedArray.getResourceId(im.vector.lib.ui.styles.R.styleable.QrCodeLoginHeaderView_qrCodeLoginHeaderImageResource, 0) + val backgroundTint = typedArray.getColor(im.vector.lib.ui.styles.R.styleable.QrCodeLoginHeaderView_qrCodeLoginHeaderImageBackgroundTint, 0) setImage(imageResource, backgroundTint) } diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsFragment.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsFragment.kt index 40fcbbbb85..f78cae5d22 100644 --- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsFragment.kt @@ -24,11 +24,11 @@ import android.view.ViewGroup import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentQrCodeLoginInstructionsBinding import im.vector.app.features.qrcode.QrCodeScannerActivity +import im.vector.lib.strings.CommonStrings import timber.log.Timber @AndroidEntryPoint @@ -88,16 +88,16 @@ class QrCodeLoginInstructionsFragment : VectorBaseFragment() { @@ -50,20 +50,20 @@ class QrCodeLoginShowQrCodeFragment : VectorBaseFragment getString(R.string.qr_code_login_header_failed_device_is_not_supported_description) - RendezvousFailureReason.UnsupportedHomeserver -> getString(R.string.qr_code_login_header_failed_homeserver_is_not_supported_description) - RendezvousFailureReason.Expired -> getString(R.string.qr_code_login_header_failed_timeout_description) - RendezvousFailureReason.UserDeclined -> getString(R.string.qr_code_login_header_failed_denied_description) - RendezvousFailureReason.E2EESecurityIssue -> getString(R.string.qr_code_login_header_failed_e2ee_security_issue_description) - RendezvousFailureReason.OtherDeviceAlreadySignedIn -> getString(R.string.qr_code_login_header_failed_other_device_already_signed_in_description) - RendezvousFailureReason.OtherDeviceNotSignedIn -> getString(R.string.qr_code_login_header_failed_other_device_not_signed_in_description) - RendezvousFailureReason.InvalidCode -> getString(R.string.qr_code_login_header_failed_invalid_qr_code_description) - RendezvousFailureReason.UserCancelled -> getString(R.string.qr_code_login_header_failed_user_cancelled_description) - else -> getString(R.string.qr_code_login_header_failed_other_description) + RendezvousFailureReason.UnsupportedTransport -> getString(CommonStrings.qr_code_login_header_failed_device_is_not_supported_description) + RendezvousFailureReason.UnsupportedHomeserver -> getString(CommonStrings.qr_code_login_header_failed_homeserver_is_not_supported_description) + RendezvousFailureReason.Expired -> getString(CommonStrings.qr_code_login_header_failed_timeout_description) + RendezvousFailureReason.UserDeclined -> getString(CommonStrings.qr_code_login_header_failed_denied_description) + RendezvousFailureReason.E2EESecurityIssue -> getString(CommonStrings.qr_code_login_header_failed_e2ee_security_issue_description) + RendezvousFailureReason.OtherDeviceAlreadySignedIn -> + getString(CommonStrings.qr_code_login_header_failed_other_device_already_signed_in_description) + RendezvousFailureReason.OtherDeviceNotSignedIn -> getString(CommonStrings.qr_code_login_header_failed_other_device_not_signed_in_description) + RendezvousFailureReason.InvalidCode -> getString(CommonStrings.qr_code_login_header_failed_invalid_qr_code_description) + RendezvousFailureReason.UserCancelled -> getString(CommonStrings.qr_code_login_header_failed_user_cancelled_description) + else -> getString(CommonStrings.qr_code_login_header_failed_other_description) } } @@ -97,7 +99,7 @@ class QrCodeLoginStatusFragment : VectorBaseFragment handleConnectingToDevice() QrCodeLoginConnectionStatus.SigningIn -> handleSigningIn() is QrCodeLoginConnectionStatus.Failed -> handleFailed(state.connectionStatus) - null -> { /* NOOP */ } + null -> { /* NOOP */ + } } } } diff --git a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt index 97a993d4d3..571f9c7b69 100644 --- a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt @@ -28,12 +28,12 @@ import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.commitTransaction import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.databinding.BottomSheetMatrixToCardBinding import im.vector.app.features.analytics.plan.ViewRoom import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.session.permalinks.PermalinkData import javax.inject.Inject @@ -112,7 +112,7 @@ class MatrixToBottomSheet : is MatrixToViewEvents.ShowModalError -> { MaterialAlertDialogBuilder(requireContext()) .setMessage(it.error) - .setPositiveButton(getString(R.string.ok), null) + .setPositiveButton(getString(CommonStrings.ok), null) .show() } } diff --git a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt index 24a623160e..3273f9aadb 100644 --- a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt @@ -24,7 +24,6 @@ import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.error.ErrorFormatter @@ -33,6 +32,7 @@ import im.vector.app.core.resources.StringProvider import im.vector.app.features.analytics.AnalyticsTracker import im.vector.app.features.analytics.extensions.toAnalyticsJoinedRoom import im.vector.app.features.createdirect.DirectRoomHelper +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.matrix.android.sdk.api.MatrixPatterns @@ -89,7 +89,7 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor( if (permalinkData is PermalinkData.FallbackLink) { setState { copy( - matrixItem = Fail(IllegalArgumentException(stringProvider.getString(R.string.permalink_malformed))), + matrixItem = Fail(IllegalArgumentException(stringProvider.getString(CommonStrings.permalink_malformed))), startChattingState = Uninitialized ) } @@ -337,7 +337,7 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor( directRoomHelper.ensureDMExists(action.matrixItem.id) } catch (failure: Throwable) { setState { - copy(startChattingState = Fail(Exception(stringProvider.getString(R.string.invite_users_to_room_failure)))) + copy(startChattingState = Fail(Exception(stringProvider.getString(CommonStrings.invite_users_to_room_failure)))) } return@launch } diff --git a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToRoomSpaceFragment.kt b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToRoomSpaceFragment.kt index f564802b57..8f595d67d4 100644 --- a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToRoomSpaceFragment.kt +++ b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToRoomSpaceFragment.kt @@ -35,6 +35,8 @@ import im.vector.app.core.platform.ButtonStateView import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentMatrixToRoomSpaceCardBinding import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomType import javax.inject.Inject @@ -75,10 +77,10 @@ class MatrixToRoomSpaceFragment : if (peek.roomType == RoomType.SPACE) { views.matrixToAccessImage.isVisible = true if (peek.isPublic) { - views.matrixToAccessText.setTextOrHide(context?.getString(R.string.public_space)) + views.matrixToAccessText.setTextOrHide(context?.getString(CommonStrings.public_space)) views.matrixToAccessImage.setImageResource(R.drawable.ic_public_room) } else { - views.matrixToAccessText.setTextOrHide(context?.getString(R.string.private_space)) + views.matrixToAccessText.setTextOrHide(context?.getString(CommonStrings.private_space)) views.matrixToAccessImage.setImageResource(R.drawable.ic_room_private) } } @@ -88,16 +90,16 @@ class MatrixToRoomSpaceFragment : val memberCount = peek.memberCount if (memberCount != null) { views.matrixToMemberPills.isVisible = true - views.spaceChildMemberCountText.text = resources.getQuantityString(R.plurals.room_title_members, memberCount, memberCount) + views.spaceChildMemberCountText.text = resources.getQuantityString(CommonPlurals.room_title_members, memberCount, memberCount) } else { // hide the pill views.matrixToMemberPills.isVisible = false } val joinTextRes = if (peek.roomType == RoomType.SPACE) { - R.string.join_space + CommonStrings.join_space } else { - R.string.join_room + CommonStrings.join_room } when (peek.membership) { @@ -111,12 +113,12 @@ class MatrixToRoomSpaceFragment : views.matrixToCardMainButton.isVisible = true views.matrixToCardSecondaryButton.isVisible = true views.matrixToCardMainButton.button.text = getString(joinTextRes) - views.matrixToCardSecondaryButton.button.text = getString(R.string.action_decline) + views.matrixToCardSecondaryButton.button.text = getString(CommonStrings.action_decline) } Membership.JOIN -> { views.matrixToCardMainButton.isVisible = true views.matrixToCardSecondaryButton.isVisible = false - views.matrixToCardMainButton.button.text = getString(R.string.action_open) + views.matrixToCardMainButton.button.text = getString(CommonStrings.action_open) } Membership.KNOCK, Membership.BAN -> { @@ -131,9 +133,9 @@ class MatrixToRoomSpaceFragment : views.matrixToCardNameText.text = peek.roomId views.matrixToCardAliasText.isVisible = false views.matrixToMemberPills.isVisible = false - views.matrixToCardDescText.setTextOrHide(getString(R.string.room_preview_no_preview)) + views.matrixToCardDescText.setTextOrHide(getString(CommonStrings.room_preview_no_preview)) - views.matrixToCardMainButton.button.text = getString(R.string.join_anyway) + views.matrixToCardMainButton.button.text = getString(CommonStrings.join_anyway) views.matrixToCardSecondaryButton.isVisible = false } RoomInfoResult.NotFound -> { @@ -141,7 +143,7 @@ class MatrixToRoomSpaceFragment : views.matrixToCardNameText.isVisible = false views.matrixToCardAliasText.isVisible = false views.matrixToMemberPills.isVisible = false - views.matrixToCardDescText.setTextOrHide(getString(R.string.room_preview_not_found)) + views.matrixToCardDescText.setTextOrHide(getString(CommonStrings.room_preview_not_found)) views.matrixToCardMainButton.isVisible = false views.matrixToCardSecondaryButton.isVisible = false @@ -150,7 +152,7 @@ class MatrixToRoomSpaceFragment : views.matrixToCardNameText.isVisible = false views.matrixToCardAliasText.isVisible = false views.spaceChildMemberCountText.isVisible = false - views.matrixToCardDescText.setTextOrHide(getString(R.string.room_alias_preview_not_found)) + views.matrixToCardDescText.setTextOrHide(getString(CommonStrings.room_alias_preview_not_found)) views.matrixToCardMainButton.isVisible = false views.matrixToCardSecondaryButton.isVisible = false diff --git a/vector/src/main/java/im/vector/app/features/matrixto/SpaceCardRenderer.kt b/vector/src/main/java/im/vector/app/features/matrixto/SpaceCardRenderer.kt index 87ba176255..dd10ff9814 100644 --- a/vector/src/main/java/im/vector/app/features/matrixto/SpaceCardRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/matrixto/SpaceCardRenderer.kt @@ -26,6 +26,8 @@ import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod import im.vector.app.features.home.room.detail.timeline.tools.linkify +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo import org.matrix.android.sdk.api.session.user.model.User @@ -56,18 +58,18 @@ class SpaceCardRenderer @Inject constructor( inCard.matrixToCardAliasText.setTextOrHide(spaceSummary.canonicalAlias) inCard.matrixToCardDescText.setTextOrHide(spaceSummary.topic.linkify(matrixLinkCallback)) if (spaceSummary.isPublic) { - inCard.matrixToAccessText.setTextOrHide(stringProvider.getString(R.string.public_space)) + inCard.matrixToAccessText.setTextOrHide(stringProvider.getString(CommonStrings.public_space)) inCard.matrixToAccessImage.isVisible = true inCard.matrixToAccessImage.setImageResource(R.drawable.ic_public_room) } else { - inCard.matrixToAccessText.setTextOrHide(stringProvider.getString(R.string.private_space)) + inCard.matrixToAccessText.setTextOrHide(stringProvider.getString(CommonStrings.private_space)) inCard.matrixToAccessImage.isVisible = true inCard.matrixToAccessImage.setImageResource(R.drawable.ic_room_private) } val memberCount = spaceSummary.joinedMembersCount ?: 0 if (memberCount != 0) { inCard.matrixToMemberPills.isVisible = true - inCard.spaceChildMemberCountText.text = stringProvider.getQuantityString(R.plurals.room_title_members, memberCount, memberCount) + inCard.spaceChildMemberCountText.text = stringProvider.getQuantityString(CommonPlurals.room_title_members, memberCount, memberCount) } else { // hide the pill inCard.matrixToMemberPills.isVisible = false @@ -106,18 +108,18 @@ class SpaceCardRenderer @Inject constructor( inCard.matrixToCardAliasText.setTextOrHide(spaceChildInfo.canonicalAlias) inCard.matrixToCardDescText.setTextOrHide(spaceChildInfo.topic?.linkify(matrixLinkCallback)) if (spaceChildInfo.worldReadable) { - inCard.matrixToAccessText.setTextOrHide(stringProvider.getString(R.string.public_space)) + inCard.matrixToAccessText.setTextOrHide(stringProvider.getString(CommonStrings.public_space)) inCard.matrixToAccessImage.isVisible = true inCard.matrixToAccessImage.setImageResource(R.drawable.ic_public_room) } else { - inCard.matrixToAccessText.setTextOrHide(stringProvider.getString(R.string.private_space)) + inCard.matrixToAccessText.setTextOrHide(stringProvider.getString(CommonStrings.private_space)) inCard.matrixToAccessImage.isVisible = true inCard.matrixToAccessImage.setImageResource(R.drawable.ic_room_private) } val memberCount = spaceChildInfo.activeMemberCount ?: 0 if (memberCount != 0) { inCard.matrixToMemberPills.isVisible = true - inCard.spaceChildMemberCountText.text = stringProvider.getQuantityString(R.plurals.room_title_members, memberCount, memberCount) + inCard.spaceChildMemberCountText.text = stringProvider.getQuantityString(CommonPlurals.room_title_members, memberCount, memberCount) } else { // hide the pill inCard.matrixToMemberPills.isVisible = false @@ -145,7 +147,7 @@ class SpaceCardRenderer @Inject constructor( } inCard.peopleYouMayKnowText.setTextOrHide( stringProvider.getQuantityString( - R.plurals.space_people_you_know, + CommonPlurals.space_people_you_know, peopleYouKnow.count(), peopleYouKnow.count() ) diff --git a/vector/src/main/java/im/vector/app/features/media/BaseAttachmentProvider.kt b/vector/src/main/java/im/vector/app/features/media/BaseAttachmentProvider.kt index 4039ea112b..a4f2e1f969 100644 --- a/vector/src/main/java/im/vector/app/features/media/BaseAttachmentProvider.kt +++ b/vector/src/main/java/im/vector/app/features/media/BaseAttachmentProvider.kt @@ -23,7 +23,6 @@ import android.widget.ImageView import androidx.core.view.isVisible import com.bumptech.glide.request.target.CustomViewTarget import com.bumptech.glide.request.transition.Transition -import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter import im.vector.app.core.resources.StringProvider @@ -31,6 +30,7 @@ import im.vector.lib.attachmentviewer.AttachmentInfo import im.vector.lib.attachmentviewer.AttachmentSourceProvider import im.vector.lib.attachmentviewer.ImageLoaderTarget import im.vector.lib.attachmentviewer.VideoLoaderTarget +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -68,7 +68,7 @@ abstract class BaseAttachmentProvider( if (timelineEvent != null) { val dateString = dateFormatter.format(timelineEvent.root.originServerTs, DateFormatKind.DEFAULT_DATE_AND_TIME) overlayView?.updateWith( - counter = stringProvider.getString(R.string.attachment_viewer_item_x_of_y, position + 1, getItemCount()), + counter = stringProvider.getString(CommonStrings.attachment_viewer_item_x_of_y, position + 1, getItemCount()), senderInfo = "${timelineEvent.senderInfo.disambiguatedDisplayName} $dateString" ) overlayView?.views?.overlayVideoControlsGroup?.isVisible = timelineEvent.root.isVideoMessage() diff --git a/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt b/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt index 876812cea0..d0c5df84ec 100644 --- a/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt @@ -94,7 +94,7 @@ class ImageContentRenderer @Inject constructor( fun render(previewUrlData: PreviewUrlData, imageView: ImageView): Boolean { val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver() val imageUrl = contentUrlResolver.resolveFullSize(previewUrlData.mxcUrl) ?: return false - val maxHeight = dimensionConverter.resources.getDimensionPixelSize(R.dimen.preview_url_view_image_max_height) + val maxHeight = dimensionConverter.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.preview_url_view_image_max_height) val height = previewUrlData.imageHeight ?: URL_PREVIEW_IMAGE_MIN_FULL_HEIGHT_PX val width = previewUrlData.imageWidth ?: URL_PREVIEW_IMAGE_MIN_FULL_WIDTH_PX if (height < URL_PREVIEW_IMAGE_MIN_FULL_HEIGHT_PX || width < URL_PREVIEW_IMAGE_MIN_FULL_WIDTH_PX) { @@ -193,7 +193,7 @@ class ImageContentRenderer @Inject constructor( override fun onLoadFailed( e: GlideException?, model: Any?, - target: Target?, + target: Target, isFirstResource: Boolean ): Boolean { callback?.invoke(false) @@ -201,10 +201,10 @@ class ImageContentRenderer @Inject constructor( } override fun onResourceReady( - resource: Drawable?, - model: Any?, + resource: Drawable, + model: Any, target: Target?, - dataSource: DataSource?, + dataSource: DataSource, isFirstResource: Boolean ): Boolean { callback?.invoke(true) diff --git a/vector/src/main/java/im/vector/app/features/media/UCropHelper.kt b/vector/src/main/java/im/vector/app/features/media/UCropHelper.kt index 875cf15ff4..ea03e8f45e 100644 --- a/vector/src/main/java/im/vector/app/features/media/UCropHelper.kt +++ b/vector/src/main/java/im/vector/app/features/media/UCropHelper.kt @@ -20,7 +20,6 @@ import android.graphics.Color import android.net.Uri import com.yalantis.ucrop.UCrop import com.yalantis.ucrop.UCropActivity -import im.vector.app.R import im.vector.app.core.resources.ColorProvider fun createUCropWithDefaultSettings( @@ -42,12 +41,12 @@ fun createUCropWithDefaultSettings( setFreeStyleCropEnabled(true) // Color used for toolbar icon and text setToolbarColor(colorProvider.getColorFromAttribute(android.R.attr.colorBackground)) - setToolbarWidgetColor(colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + setToolbarWidgetColor(colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) // Background setRootViewBackgroundColor(colorProvider.getColorFromAttribute(android.R.attr.colorBackground)) // Status bar color (pb in dark mode, icon of the status bar are dark) - setStatusBarColor(colorProvider.getColor(R.color.android_status_bar_background_light)) - setActiveControlsWidgetColor(colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + setStatusBarColor(colorProvider.getColor(im.vector.lib.ui.styles.R.color.android_status_bar_background_light)) + setActiveControlsWidgetColor(colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) // Hide the logo (does not work) setLogoColor(Color.TRANSPARENT) } diff --git a/vector/src/main/java/im/vector/app/features/media/VectorAttachmentViewerActivity.kt b/vector/src/main/java/im/vector/app/features/media/VectorAttachmentViewerActivity.kt index 0d240b376b..626a450f27 100644 --- a/vector/src/main/java/im/vector/app/features/media/VectorAttachmentViewerActivity.kt +++ b/vector/src/main/java/im/vector/app/features/media/VectorAttachmentViewerActivity.kt @@ -35,7 +35,6 @@ import androidx.lifecycle.repeatOnLifecycle import androidx.transition.Transition import com.airbnb.mvrx.viewModel import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.extensions.singletonEntryPoint import im.vector.app.core.intent.getMimeTypeFromUri @@ -51,6 +50,7 @@ import im.vector.lib.attachmentviewer.AttachmentCommands import im.vector.lib.attachmentviewer.AttachmentViewerActivity import im.vector.lib.core.utils.compat.getParcelableArrayListExtraCompat import im.vector.lib.core.utils.compat.getParcelableExtraCompat +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -84,7 +84,7 @@ class VectorAttachmentViewerActivity : AttachmentViewerActivity(), AttachmentInt viewModel.handle(it) } } else if (deniedPermanently) { - onPermissionDeniedDialog(R.string.denied_permission_generic) + onPermissionDeniedDialog(CommonStrings.denied_permission_generic) } viewModel.pendingAction = null } @@ -147,8 +147,8 @@ class VectorAttachmentViewerActivity : AttachmentViewerActivity(), AttachmentInt } } - window.statusBarColor = ContextCompat.getColor(this, R.color.black_alpha) - window.navigationBarColor = ContextCompat.getColor(this, R.color.black_alpha) + window.statusBarColor = ContextCompat.getColor(this, im.vector.lib.ui.styles.R.color.black_alpha) + window.navigationBarColor = ContextCompat.getColor(this, im.vector.lib.ui.styles.R.color.black_alpha) observeViewEvents() } @@ -163,6 +163,7 @@ class VectorAttachmentViewerActivity : AttachmentViewerActivity(), AttachmentInt Timber.i("onPause Activity ${javaClass.simpleName}") } + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() { if (currentPosition == initialIndex) { // show back the transition view diff --git a/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt b/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt index cdfa3d2e28..05e7753de8 100644 --- a/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt @@ -21,11 +21,11 @@ import android.widget.ProgressBar import android.widget.TextView import android.widget.VideoView import androidx.core.view.isVisible -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.files.LocalFilesHelper import im.vector.app.features.session.coroutineScope +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -73,7 +73,7 @@ class VideoContentRenderer @Inject constructor( if (data.url == null) { loadingView.isVisible = false errorView.isVisible = true - errorView.setText(R.string.unknown_error) + errorView.setText(CommonStrings.unknown_error) } else if (localFilesHelper.isLocalFile(data.url) && data.allowNonMxcUrls) { thumbnailView.isVisible = false loadingView.isVisible = false @@ -121,7 +121,7 @@ class VideoContentRenderer @Inject constructor( thumbnailView.isVisible = false loadingView.isVisible = false errorView.isVisible = true - errorView.setText(R.string.unknown_error) + errorView.setText(CommonStrings.unknown_error) } else { // Temporary code, some remote videos are not played by videoview setVideoUri // So for now we download them then play 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 3496ced21c..755b9b3676 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 @@ -32,7 +32,6 @@ import androidx.core.util.Pair import androidx.core.view.ViewCompat import androidx.fragment.app.FragmentActivity 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 @@ -107,6 +106,7 @@ import im.vector.app.features.spaces.people.SpacePeopleActivity import im.vector.app.features.terms.ReviewTermsActivity import im.vector.app.features.widgets.WidgetActivity import im.vector.app.features.widgets.WidgetArgsBuilder +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -398,7 +398,7 @@ class DefaultNavigator @Inject constructor( } override fun showGroupsUnsupportedWarning(context: Context) { - Toast.makeText(context, context.getString(R.string.permalink_unsupported_groups), Toast.LENGTH_LONG).show() + Toast.makeText(context, context.getString(CommonStrings.permalink_unsupported_groups), Toast.LENGTH_LONG).show() } override fun openRoomProfile(context: Context, roomId: String, directAccess: Int?) { @@ -460,9 +460,9 @@ class DefaultNavigator @Inject constructor( // Jitsi SDK is now for API 24+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { MaterialAlertDialogBuilder(context) - .setTitle(R.string.dialog_title_error) - .setMessage(R.string.error_jitsi_not_supported_on_old_device) - .setPositiveButton(R.string.ok, null) + .setTitle(CommonStrings.dialog_title_error) + .setMessage(CommonStrings.error_jitsi_not_supported_on_old_device) + .setPositiveButton(CommonStrings.ok, null) .show() } else { val enableVideo = options?.get(JitsiCallViewModel.ENABLE_VIDEO_OPTION) == true diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventResolver.kt b/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventResolver.kt index fa7c3c3f58..8e078389f1 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventResolver.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventResolver.kt @@ -16,7 +16,6 @@ package im.vector.app.features.notifications import android.net.Uri -import im.vector.app.R import im.vector.app.core.extensions.getVectorLastMessageContent import im.vector.app.core.extensions.takeAs import im.vector.app.core.resources.BuildMeta @@ -25,6 +24,7 @@ import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.room.detail.timeline.format.DisplayableEventFormatter import im.vector.app.features.home.room.detail.timeline.format.NoticeEventFormatter import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.content.ContentUrlResolver @@ -90,7 +90,7 @@ class NotifiableEventResolver @Inject constructor( noisy = false, // will be updated timestamp = event.originServerTs ?: clock.epochMillis(), description = bodyPreview, - title = stringProvider.getString(R.string.notification_unknown_new_event), + title = stringProvider.getString(CommonStrings.notification_unknown_new_event), soundName = null, type = event.type, canBeReplaced = false @@ -138,7 +138,7 @@ class NotifiableEventResolver @Inject constructor( Timber.e("## Unable to resolve room for eventId [$event]") // Ok room is not known in store, but we can still display something val body = displayableEventFormatter.format(event, isDm = false, appendAuthor = false) - val roomName = stringProvider.getString(R.string.notification_unknown_room_name) + val roomName = stringProvider.getString(CommonStrings.notification_unknown_room_name) val senderDisplayName = event.senderInfo.disambiguatedDisplayName NotifiableMessageEvent( @@ -247,7 +247,7 @@ class NotifiableEventResolver @Inject constructor( if (Membership.INVITE == content.membership) { val roomSummary = session.getRoomSummary(roomId) val body = noticeEventFormatter.format(event, dName, isDm = roomSummary?.isDirect.orFalse()) - ?: stringProvider.getString(R.string.notification_new_invitation) + ?: stringProvider.getString(CommonStrings.notification_new_invitation) return InviteNotifiableEvent( session.myUserId, eventId = event.eventId!!, @@ -257,7 +257,7 @@ class NotifiableEventResolver @Inject constructor( roomName = roomSummary?.displayName, timestamp = event.originServerTs ?: 0, noisy = isNoisy, - title = stringProvider.getString(R.string.notification_new_invitation), + title = stringProvider.getString(CommonStrings.notification_new_invitation), description = body.toString(), soundName = null, // will be set later type = event.getClearType() diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationBroadcastReceiver.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationBroadcastReceiver.kt index 008ec7a0c9..3b96032926 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationBroadcastReceiver.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationBroadcastReceiver.kt @@ -21,13 +21,13 @@ import android.content.Context import android.content.Intent import androidx.core.app.RemoteInput import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.features.analytics.AnalyticsTracker import im.vector.app.features.analytics.extensions.toAnalyticsJoinedRoom import im.vector.app.features.analytics.plan.JoinedRoom import im.vector.app.features.session.coroutineScope import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.Session @@ -151,7 +151,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() { noisy = false, timestamp = clock.epochMillis(), senderName = session.roomService().getRoomMember(session.myUserId, room.roomId)?.displayName - ?: context?.getString(R.string.notification_sender_me), + ?: context?.getString(CommonStrings.notification_sender_me), senderId = session.myUserId, body = message, imageUriString = null, @@ -203,7 +203,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() { false, clock.epochMillis(), session.myUser?.displayname - ?: context?.getString(R.string.notification_sender_me), + ?: context?.getString(CommonStrings.notification_sender_me), session.myUserId, message, roomId, diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt index 61cb14a70f..247674dbe4 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt @@ -64,7 +64,7 @@ class NotificationDrawerManager @Inject constructor( * Lazily initializes the NotificationState as we rely on having a current session in order to fetch the persisted queue of events. */ private val notificationState by lazy { createInitialNotificationState() } - private val avatarSize = context.resources.getDimensionPixelSize(R.dimen.profile_avatar_size) + private val avatarSize = context.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.profile_avatar_size) private var currentRoomId: String? = null private var currentThreadId: String? = null private val firstThrottler = FirstThrottler(200) diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt index 908a1ed340..3acb4d287a 100755 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt @@ -48,6 +48,7 @@ import androidx.fragment.app.Fragment import im.vector.app.R import im.vector.app.core.extensions.createIgnoredUri import im.vector.app.core.platform.PendingIntentCompat +import im.vector.app.core.resources.BuildMeta import im.vector.app.core.resources.StringProvider import im.vector.app.core.services.CallAndroidService import im.vector.app.core.utils.startNotificationChannelSettingsIntent @@ -65,6 +66,8 @@ import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.troubleshoot.TestNotificationReceiver import im.vector.app.features.themes.ThemeUtils import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @@ -77,6 +80,7 @@ class NotificationUtils @Inject constructor( private val vectorPreferences: VectorPreferences, private val clock: Clock, private val actionIds: NotificationActionIds, + private val buildMeta: BuildMeta, ) { companion object { @@ -134,7 +138,7 @@ class NotificationUtils @Inject constructor( return } - val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color) + val accentColor = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.notification_accent_color) // Migration - the noisy channel was deleted and recreated when sound preference was changed (id was DEFAULT_NOISY_NOTIFICATION_CHANNEL_ID_BASE // + currentTimeMillis). @@ -160,11 +164,11 @@ class NotificationUtils @Inject constructor( */ notificationManager.createNotificationChannel(NotificationChannel( NOISY_NOTIFICATION_CHANNEL_ID, - stringProvider.getString(R.string.notification_noisy_notifications).ifEmpty { "Noisy notifications" }, + stringProvider.getString(CommonStrings.notification_noisy_notifications).ifEmpty { "Noisy notifications" }, NotificationManager.IMPORTANCE_DEFAULT ) .apply { - description = stringProvider.getString(R.string.notification_noisy_notifications) + description = stringProvider.getString(CommonStrings.notification_noisy_notifications) enableVibration(true) enableLights(true) lightColor = accentColor @@ -175,11 +179,11 @@ class NotificationUtils @Inject constructor( */ notificationManager.createNotificationChannel(NotificationChannel( SILENT_NOTIFICATION_CHANNEL_ID, - stringProvider.getString(R.string.notification_silent_notifications).ifEmpty { "Silent notifications" }, + stringProvider.getString(CommonStrings.notification_silent_notifications).ifEmpty { "Silent notifications" }, NotificationManager.IMPORTANCE_LOW ) .apply { - description = stringProvider.getString(R.string.notification_silent_notifications) + description = stringProvider.getString(CommonStrings.notification_silent_notifications) setSound(null, null) enableLights(true) lightColor = accentColor @@ -187,22 +191,22 @@ class NotificationUtils @Inject constructor( notificationManager.createNotificationChannel(NotificationChannel( LISTENING_FOR_EVENTS_NOTIFICATION_CHANNEL_ID, - stringProvider.getString(R.string.notification_listening_for_events).ifEmpty { "Listening for events" }, + stringProvider.getString(CommonStrings.notification_listening_for_events).ifEmpty { "Listening for events" }, NotificationManager.IMPORTANCE_MIN ) .apply { - description = stringProvider.getString(R.string.notification_listening_for_events) + description = stringProvider.getString(CommonStrings.notification_listening_for_events) setSound(null, null) setShowBadge(false) }) notificationManager.createNotificationChannel(NotificationChannel( CALL_NOTIFICATION_CHANNEL_ID, - stringProvider.getString(R.string.call).ifEmpty { "Call" }, + stringProvider.getString(CommonStrings.call).ifEmpty { "Call" }, NotificationManager.IMPORTANCE_HIGH ) .apply { - description = stringProvider.getString(R.string.call) + description = stringProvider.getString(CommonStrings.call) setSound(null, null) enableLights(true) lightColor = accentColor @@ -227,7 +231,7 @@ class NotificationUtils @Inject constructor( val mainIntent = MainActivity.getIntentWithNextIntent(context, i) val pi = PendingIntent.getActivity(context, 0, mainIntent, PendingIntentCompat.FLAG_IMMUTABLE) - val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color) + val accentColor = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.notification_accent_color) val builder = NotificationCompat.Builder(context, LISTENING_FOR_EVENTS_NOTIFICATION_CHANNEL_ID) .setContentTitle(stringProvider.getString(subTitleResId)) @@ -266,7 +270,7 @@ class NotificationUtils @Inject constructor( CharSequence::class.java, PendingIntent::class.java ) - deprecatedMethod.invoke(notification, context, stringProvider.getString(R.string.app_name), stringProvider.getString(subTitleResId), pi) + deprecatedMethod.invoke(notification, context, buildMeta.applicationName, stringProvider.getString(subTitleResId), pi) } catch (ex: Exception) { Timber.e(ex, "## buildNotification(): Exception - setLatestEventInfo() Msg=") } @@ -293,16 +297,16 @@ class NotificationUtils @Inject constructor( title: String, fromBg: Boolean ): Notification { - val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color) + val accentColor = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.notification_accent_color) val notificationChannel = if (fromBg) CALL_NOTIFICATION_CHANNEL_ID else SILENT_NOTIFICATION_CHANNEL_ID val builder = NotificationCompat.Builder(context, notificationChannel) .setContentTitle(ensureTitleNotEmpty(title)) .apply { if (call.mxCall.isVideoCall) { - setContentText(stringProvider.getString(R.string.incoming_video_call)) + setContentText(stringProvider.getString(CommonStrings.incoming_video_call)) setSmallIcon(R.drawable.ic_call_answer_video) } else { - setContentText(stringProvider.getString(R.string.incoming_voice_call)) + setContentText(stringProvider.getString(CommonStrings.incoming_voice_call)) setSmallIcon(R.drawable.ic_call_answer) } } @@ -342,8 +346,8 @@ class NotificationUtils @Inject constructor( builder.addAction( NotificationCompat.Action( IconCompat.createWithResource(context, R.drawable.ic_call_hangup) - .setTint(ThemeUtils.getColor(context, R.attr.colorError)), - getActionText(R.string.call_notification_reject, R.attr.colorError), + .setTint(ThemeUtils.getColor(context, com.google.android.material.R.attr.colorError)), + getActionText(CommonStrings.call_notification_reject, com.google.android.material.R.attr.colorError), rejectCallPendingIntent ) ) @@ -351,7 +355,7 @@ class NotificationUtils @Inject constructor( builder.addAction( NotificationCompat.Action( R.drawable.ic_call_answer, - getActionText(R.string.call_notification_answer, R.attr.colorPrimary), + getActionText(CommonStrings.call_notification_answer, com.google.android.material.R.attr.colorPrimary), answerCallPendingIntent ) ) @@ -367,11 +371,11 @@ class NotificationUtils @Inject constructor( call: WebRtcCall, title: String ): Notification { - val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color) + val accentColor = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.notification_accent_color) val builder = NotificationCompat.Builder(context, SILENT_NOTIFICATION_CHANNEL_ID) .setContentTitle(ensureTitleNotEmpty(title)) .apply { - setContentText(stringProvider.getString(R.string.call_ringing)) + setContentText(stringProvider.getString(CommonStrings.call_ringing)) if (call.mxCall.isVideoCall) { setSmallIcon(R.drawable.ic_call_answer_video) } else { @@ -403,8 +407,8 @@ class NotificationUtils @Inject constructor( builder.addAction( NotificationCompat.Action( IconCompat.createWithResource(context, R.drawable.ic_call_hangup) - .setTint(ThemeUtils.getColor(context, R.attr.colorError)), - getActionText(R.string.call_notification_hangup, R.attr.colorError), + .setTint(ThemeUtils.getColor(context, com.google.android.material.R.attr.colorError)), + getActionText(CommonStrings.call_notification_hangup, com.google.android.material.R.attr.colorError), rejectCallPendingIntent ) ) @@ -428,10 +432,10 @@ class NotificationUtils @Inject constructor( .setContentTitle(ensureTitleNotEmpty(title)) .apply { if (call.mxCall.isVideoCall) { - setContentText(stringProvider.getString(R.string.video_call_in_progress)) + setContentText(stringProvider.getString(CommonStrings.video_call_in_progress)) setSmallIcon(R.drawable.ic_call_answer_video) } else { - setContentText(stringProvider.getString(R.string.call_in_progress)) + setContentText(stringProvider.getString(CommonStrings.call_in_progress)) setSmallIcon(R.drawable.ic_call_answer) } } @@ -443,8 +447,8 @@ class NotificationUtils @Inject constructor( builder.addAction( NotificationCompat.Action( IconCompat.createWithResource(context, R.drawable.ic_call_hangup) - .setTint(ThemeUtils.getColor(context, R.attr.colorError)), - getActionText(R.string.call_notification_hangup, R.attr.colorError), + .setTint(ThemeUtils.getColor(context, com.google.android.material.R.attr.colorError)), + getActionText(CommonStrings.call_notification_hangup, com.google.android.material.R.attr.colorError), rejectCallPendingIntent ) ) @@ -477,7 +481,7 @@ class NotificationUtils @Inject constructor( */ fun buildCallEndedNotification(isVideoCall: Boolean): Notification { return NotificationCompat.Builder(context, SILENT_NOTIFICATION_CHANNEL_ID) - .setContentTitle(stringProvider.getString(R.string.call_ended)) + .setContentTitle(stringProvider.getString(CommonStrings.call_ended)) .apply { if (isVideoCall) { setSmallIcon(R.drawable.ic_call_answer_video) @@ -499,10 +503,10 @@ class NotificationUtils @Inject constructor( .setContentTitle(callInformation.opponentMatrixItem?.getBestName() ?: callInformation.opponentUserId) .apply { if (callInformation.isVideoCall) { - setContentText(stringProvider.getQuantityString(R.plurals.missed_video_call, 1, 1)) + setContentText(stringProvider.getQuantityString(CommonPlurals.missed_video_call, 1, 1)) setSmallIcon(R.drawable.ic_missed_video_call) } else { - setContentText(stringProvider.getQuantityString(R.plurals.missed_audio_call, 1, 1)) + setContentText(stringProvider.getQuantityString(CommonPlurals.missed_audio_call, 1, 1)) setSmallIcon(R.drawable.ic_missed_voice_call) } } @@ -525,8 +529,8 @@ class NotificationUtils @Inject constructor( */ fun buildScreenSharingNotification(): Notification { return NotificationCompat.Builder(context, SILENT_NOTIFICATION_CHANNEL_ID) - .setContentTitle(stringProvider.getString(R.string.screen_sharing_notification_title)) - .setContentText(stringProvider.getString(R.string.screen_sharing_notification_description)) + .setContentTitle(stringProvider.getString(CommonStrings.screen_sharing_notification_title)) + .setContentText(stringProvider.getString(CommonStrings.screen_sharing_notification_description)) .setSmallIcon(R.drawable.ic_share_screen) .setColor(ThemeUtils.getColor(context, android.R.attr.colorPrimary)) .setCategory(NotificationCompat.CATEGORY_SERVICE) @@ -539,7 +543,7 @@ class NotificationUtils @Inject constructor( */ fun buildStartAppNotification(): Notification { return NotificationCompat.Builder(context, LISTENING_FOR_EVENTS_NOTIFICATION_CHANNEL_ID) - .setContentTitle(stringProvider.getString(R.string.updating_your_data)) + .setContentTitle(stringProvider.getString(CommonStrings.updating_your_data)) .setSmallIcon(R.drawable.sync) .setColor(ThemeUtils.getColor(context, android.R.attr.colorPrimary)) .setCategory(NotificationCompat.CATEGORY_SERVICE) @@ -549,9 +553,9 @@ class NotificationUtils @Inject constructor( fun buildDownloadFileNotification(uri: Uri, fileName: String, mimeType: String): Notification { return NotificationCompat.Builder(context, SILENT_NOTIFICATION_CHANNEL_ID) - .setGroup(stringProvider.getString(R.string.app_name)) + .setGroup(buildMeta.applicationName) .setSmallIcon(R.drawable.ic_download) - .setContentText(stringProvider.getString(R.string.downloaded_file, fileName)) + .setContentText(stringProvider.getString(CommonStrings.downloaded_file, fileName)) .setAutoCancel(true) .apply { val intent = Intent(Intent.ACTION_VIEW).apply { @@ -582,7 +586,7 @@ class NotificationUtils @Inject constructor( senderDisplayNameForReplyCompat: String?, tickerText: String ): Notification { - val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color) + val accentColor = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.notification_accent_color) // Build the pending intent for when the notification is clicked val openIntent = when { threadId != null && vectorPreferences.areThreadMessagesEnabled() -> buildOpenThreadIntent(roomInfo, threadId) @@ -606,13 +610,15 @@ class NotificationUtils @Inject constructor( // Title for API < 16 devices. .setContentTitle(roomInfo.roomDisplayName) // Content for API < 16 devices. - .setContentText(stringProvider.getString(R.string.notification_new_messages)) + .setContentText(stringProvider.getString(CommonStrings.notification_new_messages)) // Number of new notifications for API <24 (M and below) devices. - .setSubText(stringProvider.getQuantityString(R.plurals.room_new_messages_notification, messageStyle.messages.size, messageStyle.messages.size)) + .setSubText( + stringProvider.getQuantityString(CommonPlurals.room_new_messages_notification, messageStyle.messages.size, messageStyle.messages.size) + ) // Auto-bundling is enabled for 4 or more notifications on API 24+ (N+) // devices and all Wear devices. But we want a custom grouping, so we specify the groupID // TODO Group should be current user display name - .setGroup(stringProvider.getString(R.string.app_name)) + .setGroup(buildMeta.applicationName) // In order to avoid notification making sound twice (due to the summary notification) .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_ALL) .setSmallIcon(smallIcon) @@ -648,7 +654,7 @@ class NotificationUtils @Inject constructor( NotificationCompat.Action.Builder( R.drawable.ic_material_done_all_white, - stringProvider.getString(R.string.action_mark_room_read), markRoomReadPendingIntent + stringProvider.getString(CommonStrings.action_mark_room_read), markRoomReadPendingIntent ) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ) .setShowsUserInterface(false) @@ -659,11 +665,11 @@ class NotificationUtils @Inject constructor( if (!roomInfo.hasSmartReplyError) { buildQuickReplyIntent(roomInfo.roomId, threadId, senderDisplayNameForReplyCompat)?.let { replyPendingIntent -> val remoteInput = RemoteInput.Builder(NotificationBroadcastReceiver.KEY_TEXT_REPLY) - .setLabel(stringProvider.getString(R.string.action_quick_reply)) + .setLabel(stringProvider.getString(CommonStrings.action_quick_reply)) .build() NotificationCompat.Action.Builder( R.drawable.vector_notification_quick_reply, - stringProvider.getString(R.string.action_quick_reply), replyPendingIntent + stringProvider.getString(CommonStrings.action_quick_reply), replyPendingIntent ) .addRemoteInput(remoteInput) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY) @@ -700,7 +706,7 @@ class NotificationUtils @Inject constructor( inviteNotifiableEvent: InviteNotifiableEvent, matrixId: String ): Notification { - val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color) + val accentColor = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.notification_accent_color) // Build the pending intent for when the notification is clicked val smallIcon = R.drawable.ic_notification @@ -708,9 +714,9 @@ class NotificationUtils @Inject constructor( return NotificationCompat.Builder(context, channelID) .setOnlyAlertOnce(true) - .setContentTitle(inviteNotifiableEvent.roomName ?: stringProvider.getString(R.string.app_name)) + .setContentTitle(inviteNotifiableEvent.roomName ?: buildMeta.applicationName) .setContentText(inviteNotifiableEvent.description) - .setGroup(stringProvider.getString(R.string.app_name)) + .setGroup(buildMeta.applicationName) .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_ALL) .setSmallIcon(smallIcon) .setColor(accentColor) @@ -730,7 +736,7 @@ class NotificationUtils @Inject constructor( addAction( R.drawable.vector_notification_reject_invitation, - stringProvider.getString(R.string.action_reject), + stringProvider.getString(CommonStrings.action_reject), rejectIntentPendingIntent ) @@ -747,7 +753,7 @@ class NotificationUtils @Inject constructor( ) addAction( R.drawable.vector_notification_accept_invitation, - stringProvider.getString(R.string.action_join), + stringProvider.getString(CommonStrings.action_join), joinIntentPendingIntent ) @@ -780,7 +786,7 @@ class NotificationUtils @Inject constructor( simpleNotifiableEvent: SimpleNotifiableEvent, matrixId: String ): Notification { - val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color) + val accentColor = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.notification_accent_color) // Build the pending intent for when the notification is clicked val smallIcon = R.drawable.ic_notification @@ -788,9 +794,9 @@ class NotificationUtils @Inject constructor( return NotificationCompat.Builder(context, channelID) .setOnlyAlertOnce(true) - .setContentTitle(stringProvider.getString(R.string.app_name)) + .setContentTitle(buildMeta.applicationName) .setContentText(simpleNotifiableEvent.description) - .setGroup(stringProvider.getString(R.string.app_name)) + .setGroup(buildMeta.applicationName) .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_ALL) .setSmallIcon(smallIcon) .setColor(accentColor) @@ -939,7 +945,7 @@ class NotificationUtils @Inject constructor( noisy: Boolean, lastMessageTimestamp: Long ): Notification { - val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color) + val accentColor = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.notification_accent_color) val smallIcon = R.drawable.ic_notification return NotificationCompat.Builder(context, if (noisy) NOISY_NOTIFICATION_CHANNEL_ID else SILENT_NOTIFICATION_CHANNEL_ID) @@ -947,12 +953,12 @@ class NotificationUtils @Inject constructor( // used in compat < N, after summary is built based on child notifications .setWhen(lastMessageTimestamp) .setStyle(style) - .setContentTitle(stringProvider.getString(R.string.app_name)) + .setContentTitle(buildMeta.applicationName) .setCategory(NotificationCompat.CATEGORY_MESSAGE) .setSmallIcon(smallIcon) // set content text to support devices running API level < 24 .setContentText(compatSummary) - .setGroup(stringProvider.getString(R.string.app_name)) + .setGroup(buildMeta.applicationName) // set this notification as the summary for the group .setGroupSummary(true) .setColor(accentColor) @@ -1028,11 +1034,11 @@ class NotificationUtils @Inject constructor( "DIAGNOSTIC", 888, NotificationCompat.Builder(context, NOISY_NOTIFICATION_CHANNEL_ID) - .setContentTitle(stringProvider.getString(R.string.app_name)) - .setContentText(stringProvider.getString(R.string.settings_troubleshoot_test_push_notification_content)) + .setContentTitle(buildMeta.applicationName) + .setContentText(stringProvider.getString(CommonStrings.settings_troubleshoot_test_push_notification_content)) .setSmallIcon(R.drawable.ic_notification) - .setLargeIcon(getBitmap(context, R.drawable.element_logo_green)) - .setColor(ContextCompat.getColor(context, R.color.notification_accent_color)) + .setLargeIcon(getBitmap(context, im.vector.lib.ui.styles.R.drawable.element_logo_green)) + .setColor(ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.notification_accent_color)) .setPriority(NotificationCompat.PRIORITY_MAX) .setCategory(NotificationCompat.CATEGORY_STATUS) .setAutoCancel(true) @@ -1075,7 +1081,7 @@ class NotificationUtils @Inject constructor( private fun ensureTitleNotEmpty(title: String?): CharSequence { if (title.isNullOrBlank()) { - return stringProvider.getString(R.string.app_name) + return buildMeta.applicationName } return title diff --git a/vector/src/main/java/im/vector/app/features/notifications/RoomGroupMessageCreator.kt b/vector/src/main/java/im/vector/app/features/notifications/RoomGroupMessageCreator.kt index 767f427f39..c5470ff928 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/RoomGroupMessageCreator.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/RoomGroupMessageCreator.kt @@ -19,8 +19,9 @@ package im.vector.app.features.notifications import android.graphics.Bitmap import androidx.core.app.NotificationCompat import androidx.core.app.Person -import im.vector.app.R import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.Span import me.gujun.android.span.span import timber.log.Timber @@ -49,9 +50,9 @@ class RoomGroupMessageCreator @Inject constructor( } val tickerText = if (roomIsGroup) { - stringProvider.getString(R.string.notification_ticker_text_group, roomName, events.last().senderName, events.last().description) + stringProvider.getString(CommonStrings.notification_ticker_text_group, roomName, events.last().senderName, events.last().description) } else { - stringProvider.getString(R.string.notification_ticker_text_dm, events.last().senderName, events.last().description) + stringProvider.getString(CommonStrings.notification_ticker_text_dm, events.last().senderName, events.last().description) } val largeBitmap = getRoomBitmap(events) @@ -97,7 +98,7 @@ class RoomGroupMessageCreator @Inject constructor( .build() } when { - event.isSmartReplyError() -> addMessage(stringProvider.getString(R.string.notification_inline_reply_failed), event.timestamp, senderPerson) + event.isSmartReplyError() -> addMessage(stringProvider.getString(CommonStrings.notification_inline_reply_failed), event.timestamp, senderPerson) else -> { val message = NotificationCompat.MessagingStyle.Message(event.body, event.timestamp, senderPerson).also { message -> event.imageUri?.let { @@ -116,7 +117,7 @@ class RoomGroupMessageCreator @Inject constructor( 1 -> createFirstMessageSummaryLine(events.first(), roomName, roomIsDirect) else -> { stringProvider.getQuantityString( - R.plurals.notification_compat_summary_line_for_room, + CommonPlurals.notification_compat_summary_line_for_room, events.size, roomName, events.size diff --git a/vector/src/main/java/im/vector/app/features/notifications/SummaryGroupMessageCreator.kt b/vector/src/main/java/im/vector/app/features/notifications/SummaryGroupMessageCreator.kt index d998c480d0..ea6afc9eb5 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/SummaryGroupMessageCreator.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/SummaryGroupMessageCreator.kt @@ -18,8 +18,9 @@ package im.vector.app.features.notifications import android.app.Notification import androidx.core.app.NotificationCompat -import im.vector.app.R import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import javax.inject.Inject /** @@ -65,10 +66,10 @@ class SummaryGroupMessageCreator @Inject constructor( // FIXME roomIdToEventMap.size is not correct, this is the number of rooms val nbEvents = roomNotifications.size + simpleNotifications.size - val sumTitle = stringProvider.getQuantityString(R.plurals.notification_compat_summary_title, nbEvents, nbEvents) + val sumTitle = stringProvider.getQuantityString(CommonPlurals.notification_compat_summary_title, nbEvents, nbEvents) summaryInboxStyle.setBigContentTitle(sumTitle) // TODO get latest event? - .setSummaryText(stringProvider.getQuantityString(R.plurals.notification_unread_notified_messages, nbEvents, nbEvents)) + .setSummaryText(stringProvider.getQuantityString(CommonPlurals.notification_unread_notified_messages, nbEvents, nbEvents)) return if (useCompleteNotificationFormat) { notificationUtils.buildSummaryListNotification( summaryInboxStyle, @@ -100,21 +101,21 @@ class SummaryGroupMessageCreator @Inject constructor( val messageNotificationCount = messageEventsCount + simpleEventsCount val privacyTitle = if (invitationEventsCount > 0) { - val invitationsStr = stringProvider.getQuantityString(R.plurals.notification_invitations, invitationEventsCount, invitationEventsCount) + val invitationsStr = stringProvider.getQuantityString(CommonPlurals.notification_invitations, invitationEventsCount, invitationEventsCount) if (messageNotificationCount > 0) { // Invitation and message val messageStr = stringProvider.getQuantityString( - R.plurals.room_new_messages_notification, + CommonPlurals.room_new_messages_notification, messageNotificationCount, messageNotificationCount ) if (roomCount > 1) { // In several rooms val roomStr = stringProvider.getQuantityString( - R.plurals.notification_unread_notified_messages_in_room_rooms, + CommonPlurals.notification_unread_notified_messages_in_room_rooms, roomCount, roomCount ) stringProvider.getString( - R.string.notification_unread_notified_messages_in_room_and_invitation, + CommonStrings.notification_unread_notified_messages_in_room_and_invitation, messageStr, roomStr, invitationsStr @@ -122,7 +123,7 @@ class SummaryGroupMessageCreator @Inject constructor( } else { // In one room stringProvider.getString( - R.string.notification_unread_notified_messages_and_invitation, + CommonStrings.notification_unread_notified_messages_and_invitation, messageStr, invitationsStr ) @@ -134,13 +135,13 @@ class SummaryGroupMessageCreator @Inject constructor( } else { // No invitation, only messages val messageStr = stringProvider.getQuantityString( - R.plurals.room_new_messages_notification, + CommonPlurals.room_new_messages_notification, messageNotificationCount, messageNotificationCount ) if (roomCount > 1) { // In several rooms - val roomStr = stringProvider.getQuantityString(R.plurals.notification_unread_notified_messages_in_room_rooms, roomCount, roomCount) - stringProvider.getString(R.string.notification_unread_notified_messages_in_room, messageStr, roomStr) + val roomStr = stringProvider.getQuantityString(CommonPlurals.notification_unread_notified_messages_in_room_rooms, roomCount, roomCount) + stringProvider.getString(CommonStrings.notification_unread_notified_messages_in_room, messageStr, roomStr) } else { // In one room messageStr diff --git a/vector/src/main/java/im/vector/app/features/onboarding/DirectLoginUseCase.kt b/vector/src/main/java/im/vector/app/features/onboarding/DirectLoginUseCase.kt index d8ec75a8c2..7ff90b11fd 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/DirectLoginUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/DirectLoginUseCase.kt @@ -16,10 +16,10 @@ package im.vector.app.features.onboarding -import im.vector.app.R import im.vector.app.core.extensions.andThen import im.vector.app.core.resources.StringProvider import im.vector.app.features.onboarding.OnboardingAction.AuthenticateAction.LoginDirect +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.MatrixPatterns.getServerName import org.matrix.android.sdk.api.auth.AuthenticationService import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig @@ -80,5 +80,5 @@ class DirectLoginUseCase @Inject constructor( identityServerUri = wellKnownPrompt.identityServerUrl?.let { uriFactory.parse(it) } ) - private fun onWellKnownError() = Result.failure(Exception(stringProvider.getString(R.string.autodiscover_well_known_error))) + private fun onWellKnownError() = Result.failure(Exception(stringProvider.getString(CommonStrings.autodiscover_well_known_error))) } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingActivity.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingActivity.kt index e79250d39d..f64d8a7148 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingActivity.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingActivity.kt @@ -42,14 +42,14 @@ class OnboardingActivity : VectorBaseActivity(), UnlockedA override fun getCoordinatorLayout() = views.coordinatorLayout - override fun onNewIntent(intent: Intent?) { + override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) onboardingVariant.onNewIntent(intent) } + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() { validateBackPressed { - @Suppress("DEPRECATION") super.onBackPressed() } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingVariantFactory.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingVariantFactory.kt index fec0374afb..0b9ec7b68b 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingVariantFactory.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingVariantFactory.kt @@ -18,6 +18,7 @@ package im.vector.app.features.onboarding import im.vector.app.config.OnboardingVariant import im.vector.app.core.platform.ScreenOrientationLocker +import im.vector.app.core.resources.BuildMeta import im.vector.app.databinding.ActivityLoginBinding import im.vector.app.features.VectorFeatures import im.vector.app.features.onboarding.ftueauth.FtueAuthVariant @@ -26,6 +27,7 @@ import javax.inject.Inject class OnboardingVariantFactory @Inject constructor( private val vectorFeatures: VectorFeatures, private val orientationLocker: ScreenOrientationLocker, + private val buildMeta: BuildMeta, ) { fun create( @@ -40,7 +42,8 @@ class OnboardingVariantFactory @Inject constructor( activity = activity, supportFragmentManager = activity.supportFragmentManager, vectorFeatures = vectorFeatures, - orientationLocker = orientationLocker + orientationLocker = orientationLocker, + buildMeta = buildMeta, ) } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 74427736d7..949c728aa2 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -21,7 +21,6 @@ import com.airbnb.mvrx.MavericksViewModelFactory import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory @@ -145,7 +144,7 @@ class OnboardingViewModel @AssistedInject constructor( } } - private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() + private val matrixOrgUrl = stringProvider.getString(im.vector.app.config.R.string.matrix_org_server_url).ensureTrailingSlash() private val defaultHomeserverUrl = mdmService.getData(MdmData.DefaultHomeserverUrl, matrixOrgUrl) private val registrationWizard: RegistrationWizard diff --git a/vector/src/main/java/im/vector/app/features/onboarding/RegistrationActionHandler.kt b/vector/src/main/java/im/vector/app/features/onboarding/RegistrationActionHandler.kt index 488a96beb9..0fdd81e352 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/RegistrationActionHandler.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/RegistrationActionHandler.kt @@ -16,7 +16,6 @@ package im.vector.app.features.onboarding -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.ensureTrailingSlash import im.vector.app.features.VectorFeatures @@ -39,7 +38,7 @@ class RegistrationActionHandler @Inject constructor( stringProvider: StringProvider ) { - private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() + private val matrixOrgUrl = stringProvider.getString(im.vector.app.config.R.string.matrix_org_server_url).ensureTrailingSlash() suspend fun processAction(state: SelectedHomeserverState, action: RegisterAction): Result { val result = registrationWizardActionDelegate.executeAction(action) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt index 9fd0bd08ed..7fa79535af 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt @@ -24,7 +24,6 @@ import androidx.viewbinding.ViewBinding import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder -import im.vector.app.R import im.vector.app.core.dialogs.UnrecognizedCertificateDialog import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment @@ -32,6 +31,7 @@ import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewModel import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.CancellationException /** @@ -119,14 +119,14 @@ abstract class AbstractFtueAuthFragment : VectorBaseFragment { // Ask for confirmation before cancelling the registration MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.login_signup_cancel_confirmation_title) - .setMessage(R.string.login_signup_cancel_confirmation_content) - .setPositiveButton(R.string.yes) { _, _ -> + .setTitle(CommonStrings.login_signup_cancel_confirmation_title) + .setMessage(CommonStrings.login_signup_cancel_confirmation_content) + .setPositiveButton(CommonStrings.yes) { _, _ -> displayCancelDialog = false @Suppress("DEPRECATION") vectorBaseActivity.onBackPressed() } - .setNegativeButton(R.string.no, null) + .setNegativeButton(CommonStrings.no, null) .show() true @@ -134,14 +134,14 @@ abstract class AbstractFtueAuthFragment : VectorBaseFragment { // Ask for confirmation before cancelling the reset password MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.login_reset_password_cancel_confirmation_title) - .setMessage(R.string.login_reset_password_cancel_confirmation_content) - .setPositiveButton(R.string.yes) { _, _ -> + .setTitle(CommonStrings.login_reset_password_cancel_confirmation_title) + .setMessage(CommonStrings.login_reset_password_cancel_confirmation_content) + .setPositiveButton(CommonStrings.yes) { _, _ -> displayCancelDialog = false @Suppress("DEPRECATION") vectorBaseActivity.onBackPressed() } - .setNegativeButton(R.string.no, null) + .setNegativeButton(CommonStrings.no, null) .show() true diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/CaptchaWebview.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/CaptchaWebview.kt index 11f257c4e8..8fa662ef74 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/CaptchaWebview.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/CaptchaWebview.kt @@ -31,10 +31,10 @@ import android.webkit.WebViewClient import androidx.core.view.isVisible import androidx.fragment.app.Fragment import com.google.android.material.dialog.MaterialAlertDialogBuilder -import im.vector.app.R import im.vector.app.core.utils.AssetReader import im.vector.app.features.login.JavascriptResponse import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.util.MatrixJsonParser import timber.log.Timber import java.net.URLDecoder @@ -135,12 +135,12 @@ class CaptchaWebview @Inject constructor( private fun showSslErrorDialog(container: Fragment, handler: SslErrorHandler) { MaterialAlertDialogBuilder(container.requireActivity()) - .setMessage(R.string.ssl_could_not_verify) - .setPositiveButton(R.string.ssl_trust) { _, _ -> + .setMessage(CommonStrings.ssl_could_not_verify) + .setPositiveButton(CommonStrings.ssl_trust) { _, _ -> Timber.d("## onReceivedSslError() : the user trusted") handler.proceed() } - .setNegativeButton(R.string.ssl_do_not_trust) { _, _ -> + .setNegativeButton(CommonStrings.ssl_do_not_trust) { _, _ -> Timber.d("## onReceivedSslError() : the user did not trust") handler.cancel() } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthAccountCreatedFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthAccountCreatedFragment.kt index 2089dc5ad0..3dd012d5a8 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthAccountCreatedFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthAccountCreatedFragment.kt @@ -24,7 +24,6 @@ import android.view.ViewGroup import androidx.core.text.toSpannable import androidx.core.view.isVisible import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.animations.play import im.vector.app.core.utils.isAnimationEnabled import im.vector.app.core.utils.styleMatchingText @@ -32,6 +31,7 @@ import im.vector.app.databinding.FragmentFtueAccountCreatedBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.lib.strings.CommonStrings @AndroidEntryPoint class FtueAuthAccountCreatedFragment : @@ -56,7 +56,7 @@ class FtueAuthAccountCreatedFragment : override fun updateWithState(state: OnboardingViewState) { val userId = state.personalizationState.userId - val subtitle = getString(R.string.ftue_account_created_subtitle, userId).toSpannable().styleMatchingText(userId, Typeface.BOLD) + val subtitle = getString(CommonStrings.ftue_account_created_subtitle, userId).toSpannable().styleMatchingText(userId, Typeface.BOLD) views.accountCreatedSubtitle.text = subtitle val canPersonalize = state.personalizationState.supportsPersonalization() views.personalizeButtonGroup.isVisible = canPersonalize diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt index f170868307..6340c756d4 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt @@ -25,13 +25,13 @@ import android.view.ViewStub import com.airbnb.mvrx.args import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.crawlCausesFor import im.vector.app.databinding.FragmentFtueLoginCaptchaBinding import im.vector.app.databinding.ViewStubWebviewBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewState import im.vector.app.features.onboarding.RegisterAction +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.extensions.orFalse import javax.inject.Inject @@ -70,9 +70,9 @@ class FtueAuthCaptchaFragment : private fun inflateWebViewOrShowError() { views.loginCaptchaWebViewStub.inflateWebView(onError = { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(it.localizedMessage) - .setPositiveButton(R.string.ok) { _, _ -> + .setPositiveButton(CommonStrings.ok) { _, _ -> requireActivity().recreate() } .show() diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedLoginFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedLoginFragment.kt index 69090172ea..abcfcafc64 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedLoginFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedLoginFragment.kt @@ -26,7 +26,6 @@ import androidx.core.view.isVisible import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.clearErrorOnChange import im.vector.app.core.extensions.content import im.vector.app.core.extensions.editText @@ -47,6 +46,7 @@ import im.vector.app.features.login.render import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn import org.matrix.android.sdk.api.auth.SSOAction @@ -113,7 +113,7 @@ class FtueAuthCombinedLoginFragment : .onUsernameOrIdError { views.loginInput.error = it } .onPasswordError { views.loginPasswordInput.error = it } .onValid { usernameOrId, password -> - val initialDeviceName = getString(R.string.login_default_session_public_name) + val initialDeviceName = getString(CommonStrings.login_default_session_public_name) viewModel.handle(OnboardingAction.AuthenticateAction.Login(usernameOrId, password, initialDeviceName)) } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt index 83a9a9c00b..be178c2f86 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt @@ -28,7 +28,6 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.clearErrorOnChange import im.vector.app.core.extensions.content import im.vector.app.core.extensions.editText @@ -50,6 +49,7 @@ import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingAction.AuthenticateAction import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn import org.matrix.android.sdk.api.auth.SSOAction @@ -85,7 +85,7 @@ class FtueAuthCombinedRegisterFragment : views.createAccountInput.onTextChange(viewLifecycleOwner) { viewModel.handle(OnboardingAction.ResetSelectedRegistrationUserName) - views.createAccountEntryFooter.text = "" + views.createAccountEntryFooter.text = null } views.createAccountInput.setOnFocusLostListener(viewLifecycleOwner) { @@ -119,20 +119,20 @@ class FtueAuthCombinedRegisterFragment : // This can be called by the IME action, so deal with empty cases var error = 0 if (login.isEmpty()) { - views.createAccountInput.error = getString(R.string.error_empty_field_choose_user_name) + views.createAccountInput.error = getString(CommonStrings.error_empty_field_choose_user_name) error++ } if (state.isNumericOnlyUserIdForbidden() && login.isDigitsOnly()) { - views.createAccountInput.error = getString(R.string.error_forbidden_digits_only_username) + views.createAccountInput.error = getString(CommonStrings.error_forbidden_digits_only_username) error++ } if (password.isEmpty()) { - views.createAccountPasswordInput.error = getString(R.string.error_empty_field_choose_password) + views.createAccountPasswordInput.error = getString(CommonStrings.error_empty_field_choose_password) error++ } if (error == 0) { - val initialDeviceName = getString(R.string.login_default_session_public_name) + val initialDeviceName = getString(CommonStrings.login_default_session_public_name) val registerAction = when { login.isMatrixId() -> AuthenticateAction.RegisterWithMatrixId(login, password, initialDeviceName) else -> AuthenticateAction.Register(login, password, initialDeviceName) @@ -160,22 +160,22 @@ class FtueAuthCombinedRegisterFragment : views.createAccountInput.error = errorFormatter.toHumanReadable(throwable) } throwable.isLoginEmailUnknown() -> { - views.createAccountInput.error = getString(R.string.login_login_with_email_error) + views.createAccountInput.error = getString(CommonStrings.login_login_with_email_error) } throwable.isInvalidPassword() && views.createAccountPasswordInput.hasSurroundingSpaces() -> { - views.createAccountPasswordInput.error = getString(R.string.auth_invalid_login_param_space_in_password) + views.createAccountPasswordInput.error = getString(CommonStrings.auth_invalid_login_param_space_in_password) } throwable.isWeakPassword() || throwable.isInvalidPassword() -> { views.createAccountPasswordInput.error = errorFormatter.toHumanReadable(throwable) } throwable.isHomeserverUnavailable() -> { - views.createAccountInput.error = getString(R.string.login_error_homeserver_not_found) + views.createAccountInput.error = getString(CommonStrings.login_error_homeserver_not_found) } throwable.isRegistrationDisabled() -> { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) - .setMessage(getString(R.string.login_registration_disabled)) - .setPositiveButton(R.string.ok, null) + .setTitle(CommonStrings.dialog_title_error) + .setMessage(getString(CommonStrings.login_registration_disabled)) + .setPositiveButton(CommonStrings.ok, null) .show() } else -> { @@ -199,7 +199,7 @@ class FtueAuthCombinedRegisterFragment : views.createAccountEntryFooter.text = when { state.registrationState.isUserNameAvailable -> getString( - R.string.ftue_auth_create_account_username_entry_footer, + CommonStrings.ftue_auth_create_account_username_entry_footer, state.registrationState.selectedMatrixId ) @@ -236,5 +236,6 @@ class FtueAuthCombinedRegisterFragment : } } - private fun OnboardingViewState.isNumericOnlyUserIdForbidden() = selectedHomeserver.userFacingUrl == getString(R.string.matrix_org_server_url) + private fun OnboardingViewState.isNumericOnlyUserIdForbidden() = + selectedHomeserver.userFacingUrl == getString(im.vector.app.config.R.string.matrix_org_server_url) } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedServerSelectionFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedServerSelectionFragment.kt index f39946a1d0..5649ee8385 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedServerSelectionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedServerSelectionFragment.kt @@ -21,7 +21,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.associateContentStateWith import im.vector.app.core.extensions.clearErrorOnChange import im.vector.app.core.extensions.content @@ -38,6 +37,7 @@ import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingFlow import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.failure.isHomeserverUnavailable @AndroidEntryPoint @@ -64,7 +64,7 @@ class FtueAuthCombinedServerSelectionFragment : updateServerUrl() } } - views.chooseServerGetInTouch.debouncedClicks { openUrlInExternalBrowser(requireContext(), getString(R.string.ftue_ems_url)) } + views.chooseServerGetInTouch.debouncedClicks { openUrlInExternalBrowser(requireContext(), getString(im.vector.app.config.R.string.ftue_ems_url)) } views.chooseServerSubmit.debouncedClicks { updateServerUrl() } views.chooseServerInput.clearErrorOnChange(viewLifecycleOwner) } @@ -82,8 +82,8 @@ class FtueAuthCombinedServerSelectionFragment : override fun updateWithState(state: OnboardingViewState) { views.chooseServerHeaderSubtitle.setText( when (state.onboardingFlow) { - OnboardingFlow.SignIn -> R.string.ftue_auth_choose_server_sign_in_subtitle - OnboardingFlow.SignUp -> R.string.ftue_auth_choose_server_subtitle + OnboardingFlow.SignIn -> CommonStrings.ftue_auth_choose_server_sign_in_subtitle + OnboardingFlow.SignUp -> CommonStrings.ftue_auth_choose_server_subtitle else -> throw IllegalStateException("Invalid flow state") } ) @@ -99,7 +99,7 @@ class FtueAuthCombinedServerSelectionFragment : override fun onError(throwable: Throwable) { views.chooseServerInput.error = when { - throwable.isHomeserverUnavailable() -> getString(R.string.login_error_homeserver_not_found) + throwable.isHomeserverUnavailable() -> getString(CommonStrings.login_error_homeserver_not_found) else -> errorFormatter.toHumanReadable(throwable) } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthEmailEntryFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthEmailEntryFragment.kt index 39430a0d20..bd31afbde4 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthEmailEntryFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthEmailEntryFragment.kt @@ -23,7 +23,6 @@ import android.view.View import android.view.ViewGroup import com.airbnb.mvrx.args import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.associateContentStateWith import im.vector.app.core.extensions.autofillEmail import im.vector.app.core.extensions.clearErrorOnChange @@ -36,6 +35,7 @@ import im.vector.app.databinding.FragmentFtueEmailInputBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewState import im.vector.app.features.onboarding.RegisterAction +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.auth.registration.RegisterThreePid import org.matrix.android.sdk.api.extensions.isEmail @@ -60,7 +60,7 @@ class FtueAuthEmailEntryFragment : AbstractFtueAuthFragment { - views.loginGenericTextInputFormTitle.text = getString(R.string.login_set_email_title) - views.loginGenericTextInputFormNotice.text = getString(R.string.login_set_email_notice) + views.loginGenericTextInputFormTitle.text = getString(CommonStrings.login_set_email_title) + views.loginGenericTextInputFormNotice.text = getString(CommonStrings.login_set_email_notice) views.loginGenericTextInputFormNotice2.setTextOrHide(null) views.loginGenericTextInputFormTil.hint = - getString(if (params.mandatory) R.string.login_set_email_mandatory_hint else R.string.login_set_email_optional_hint) + getString(if (params.mandatory) CommonStrings.login_set_email_mandatory_hint else CommonStrings.login_set_email_optional_hint) views.loginGenericTextInputFormTextInput.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS views.loginGenericTextInputFormOtherButton.isVisible = false - views.loginGenericTextInputFormSubmit.text = getString(R.string.login_set_email_submit) + views.loginGenericTextInputFormSubmit.text = getString(CommonStrings.login_set_email_submit) } TextInputFormFragmentMode.SetMsisdn -> { - views.loginGenericTextInputFormTitle.text = getString(R.string.login_set_msisdn_title) - views.loginGenericTextInputFormNotice.text = getString(R.string.login_set_msisdn_notice) - views.loginGenericTextInputFormNotice2.setTextOrHide(getString(R.string.login_set_msisdn_notice2)) + views.loginGenericTextInputFormTitle.text = getString(CommonStrings.login_set_msisdn_title) + views.loginGenericTextInputFormNotice.text = getString(CommonStrings.login_set_msisdn_notice) + views.loginGenericTextInputFormNotice2.setTextOrHide(getString(CommonStrings.login_set_msisdn_notice2)) views.loginGenericTextInputFormTil.hint = - getString(if (params.mandatory) R.string.login_set_msisdn_mandatory_hint else R.string.login_set_msisdn_optional_hint) + getString(if (params.mandatory) CommonStrings.login_set_msisdn_mandatory_hint else CommonStrings.login_set_msisdn_optional_hint) views.loginGenericTextInputFormTextInput.inputType = InputType.TYPE_CLASS_PHONE views.loginGenericTextInputFormOtherButton.isVisible = false - views.loginGenericTextInputFormSubmit.text = getString(R.string.login_set_msisdn_submit) + views.loginGenericTextInputFormSubmit.text = getString(CommonStrings.login_set_msisdn_submit) } TextInputFormFragmentMode.ConfirmMsisdn -> { - views.loginGenericTextInputFormTitle.text = getString(R.string.login_msisdn_confirm_title) - views.loginGenericTextInputFormNotice.text = getString(R.string.login_msisdn_confirm_notice, params.extra) + views.loginGenericTextInputFormTitle.text = getString(CommonStrings.login_msisdn_confirm_title) + views.loginGenericTextInputFormNotice.text = getString(CommonStrings.login_msisdn_confirm_notice, params.extra) views.loginGenericTextInputFormNotice2.setTextOrHide(null) views.loginGenericTextInputFormTil.hint = - getString(R.string.login_msisdn_confirm_hint) + getString(CommonStrings.login_msisdn_confirm_hint) views.loginGenericTextInputFormTextInput.inputType = InputType.TYPE_CLASS_NUMBER views.loginGenericTextInputFormOtherButton.isVisible = true - views.loginGenericTextInputFormOtherButton.text = getString(R.string.login_msisdn_confirm_send_again) - views.loginGenericTextInputFormSubmit.text = getString(R.string.login_msisdn_confirm_submit) + views.loginGenericTextInputFormOtherButton.text = getString(CommonStrings.login_msisdn_confirm_send_again) + views.loginGenericTextInputFormSubmit.text = getString(CommonStrings.login_msisdn_confirm_submit) } } } @@ -184,10 +184,10 @@ class FtueAuthGenericTextInputFormFragment : val phoneNumber = PhoneNumberUtil.getInstance().parse(text, null) return PhoneNumberUtil.getInstance().getRegionCodeForCountryCode(phoneNumber.countryCode) } catch (e: NumberParseException) { - views.loginGenericTextInputFormTil.error = getString(R.string.login_msisdn_error_other) + views.loginGenericTextInputFormTil.error = getString(CommonStrings.login_msisdn_error_other) } } else { - views.loginGenericTextInputFormTil.error = getString(R.string.login_msisdn_error_not_international) + views.loginGenericTextInputFormTil.error = getString(CommonStrings.login_msisdn_error_not_international) } // Error @@ -233,7 +233,7 @@ class FtueAuthGenericTextInputFormFragment : when { throwable is Failure.SuccessError -> // The entered code is not correct - views.loginGenericTextInputFormTil.error = getString(R.string.login_validation_code_is_not_correct) + views.loginGenericTextInputFormTil.error = getString(CommonStrings.login_validation_code_is_not_correct) throwable.is401() -> // It can happen if user request again the 3pid Unit diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLegacyWaitForEmailFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLegacyWaitForEmailFragment.kt index fb468ddeb2..9c2c4f4022 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLegacyWaitForEmailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLegacyWaitForEmailFragment.kt @@ -22,10 +22,10 @@ import android.view.View import android.view.ViewGroup import com.airbnb.mvrx.args import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.databinding.FragmentLoginWaitForEmailBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.RegisterAction +import im.vector.lib.strings.CommonStrings /** * In this screen, the user is asked to check their emails. @@ -56,7 +56,7 @@ class FtueAuthLegacyWaitForEmailFragment : } private fun setupUi() { - views.loginWaitForEmailNotice.text = getString(R.string.login_wait_for_email_notice, params.email) + views.loginWaitForEmailNotice.text = getString(CommonStrings.login_wait_for_email_notice, params.email) } override fun resetViewModel() { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt index 2d878bb308..7cca27fb4e 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt @@ -43,6 +43,7 @@ import im.vector.app.features.login.render import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map @@ -133,30 +134,30 @@ class FtueAuthLoginFragment : if (login.isEmpty()) { views.loginFieldTil.error = getString( if (isSignupMode) { - R.string.error_empty_field_choose_user_name + CommonStrings.error_empty_field_choose_user_name } else { - R.string.error_empty_field_enter_user_name + CommonStrings.error_empty_field_enter_user_name } ) error++ } if (isSignupMode && isNumericOnlyUserIdForbidden && login.isDigitsOnly()) { - views.loginFieldTil.error = getString(R.string.error_forbidden_digits_only_username) + views.loginFieldTil.error = getString(CommonStrings.error_forbidden_digits_only_username) error++ } if (password.isEmpty()) { views.passwordFieldTil.error = getString( if (isSignupMode) { - R.string.error_empty_field_choose_password + CommonStrings.error_empty_field_choose_password } else { - R.string.error_empty_field_your_password + CommonStrings.error_empty_field_your_password } ) error++ } if (error == 0) { - val initialDeviceName = getString(R.string.login_default_session_public_name) + val initialDeviceName = getString(CommonStrings.login_default_session_public_name) viewModel.handle(state.signMode.toAuthenticateAction(login, password, initialDeviceName)) } } @@ -172,24 +173,24 @@ class FtueAuthLoginFragment : views.loginFieldTil.hint = getString( when (state.signMode) { SignMode.Unknown -> error("developer error") - SignMode.SignUp -> R.string.login_signup_username_hint - SignMode.SignIn -> R.string.login_signin_username_hint - SignMode.SignInWithMatrixId -> R.string.login_signin_matrix_id_hint + SignMode.SignUp -> CommonStrings.login_signup_username_hint + SignMode.SignIn -> CommonStrings.login_signin_username_hint + SignMode.SignInWithMatrixId -> CommonStrings.login_signin_matrix_id_hint } ) // Handle direct signin first if (state.signMode == SignMode.SignInWithMatrixId) { views.loginServerIcon.isVisible = false - views.loginTitle.text = getString(R.string.login_signin_matrix_id_title) - views.loginNotice.text = getString(R.string.login_signin_matrix_id_notice) + views.loginTitle.text = getString(CommonStrings.login_signin_matrix_id_title) + views.loginNotice.text = getString(CommonStrings.login_signin_matrix_id_notice) views.loginPasswordNotice.isVisible = true } else { val resId = when (state.signMode) { SignMode.Unknown -> error("developer error") - SignMode.SignUp -> R.string.login_signup_to - SignMode.SignIn -> R.string.login_connect_to - SignMode.SignInWithMatrixId -> R.string.login_connect_to + SignMode.SignUp -> CommonStrings.login_signup_to + SignMode.SignIn -> CommonStrings.login_connect_to + SignMode.SignInWithMatrixId -> CommonStrings.login_connect_to } when (state.serverType) { @@ -197,18 +198,18 @@ class FtueAuthLoginFragment : views.loginServerIcon.isVisible = true views.loginServerIcon.setImageResource(R.drawable.ic_logo_matrix_org) views.loginTitle.text = getString(resId, state.selectedHomeserver.userFacingUrl.toReducedUrl()) - views.loginNotice.text = getString(R.string.login_server_matrix_org_text) + views.loginNotice.text = getString(CommonStrings.login_server_matrix_org_text) } ServerType.EMS -> { views.loginServerIcon.isVisible = true views.loginServerIcon.setImageResource(R.drawable.ic_logo_element_matrix_services) views.loginTitle.text = getString(resId, "Element Matrix Services") - views.loginNotice.text = getString(R.string.login_server_modular_text) + views.loginNotice.text = getString(CommonStrings.login_server_modular_text) } ServerType.Other -> { views.loginServerIcon.isVisible = false views.loginTitle.text = getString(resId, state.selectedHomeserver.userFacingUrl.toReducedUrl()) - views.loginNotice.text = getString(R.string.login_server_other_text) + views.loginNotice.text = getString(CommonStrings.login_server_other_text) } ServerType.Unknown -> Unit /* Should not happen */ } @@ -238,9 +239,9 @@ class FtueAuthLoginFragment : views.loginSubmit.text = getString( when (state.signMode) { SignMode.Unknown -> error("developer error") - SignMode.SignUp -> R.string.login_signup_submit + SignMode.SignUp -> CommonStrings.login_signup_submit SignMode.SignIn, - SignMode.SignInWithMatrixId -> R.string.login_signin + SignMode.SignInWithMatrixId -> CommonStrings.login_signin } ) } @@ -277,19 +278,19 @@ class FtueAuthLoginFragment : views.loginFieldTil.error = errorFormatter.toHumanReadable(throwable) } throwable.isLoginEmailUnknown() -> { - views.loginFieldTil.error = getString(R.string.login_login_with_email_error) + views.loginFieldTil.error = getString(CommonStrings.login_login_with_email_error) } throwable.isInvalidPassword() && spaceInPassword() -> { - views.passwordFieldTil.error = getString(R.string.auth_invalid_login_param_space_in_password) + views.passwordFieldTil.error = getString(CommonStrings.auth_invalid_login_param_space_in_password) } throwable.isWeakPassword() || throwable.isInvalidPassword() -> { views.passwordFieldTil.error = errorFormatter.toHumanReadable(throwable) } isSignupMode && throwable.isRegistrationDisabled() -> { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) - .setMessage(getString(R.string.login_registration_disabled)) - .setPositiveButton(R.string.ok, null) + .setTitle(CommonStrings.dialog_title_error) + .setMessage(getString(CommonStrings.login_registration_disabled)) + .setPositiveButton(CommonStrings.ok, null) .show() } else -> { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPhoneConfirmationFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPhoneConfirmationFragment.kt index af6c33c028..32722d5dda 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPhoneConfirmationFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPhoneConfirmationFragment.kt @@ -23,7 +23,6 @@ import android.view.View import android.view.ViewGroup import com.airbnb.mvrx.args import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.associateContentStateWith import im.vector.app.core.extensions.clearErrorOnChange import im.vector.app.core.extensions.content @@ -31,6 +30,7 @@ import im.vector.app.core.extensions.setOnImeDoneListener import im.vector.app.databinding.FragmentFtuePhoneConfirmationBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.RegisterAction +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.failure.Failure @@ -55,7 +55,7 @@ class FtueAuthPhoneConfirmationFragment : } private fun setupViews() { - views.phoneConfirmationHeaderSubtitle.text = getString(R.string.ftue_auth_phone_confirmation_subtitle, params.msisdn) + views.phoneConfirmationHeaderSubtitle.text = getString(CommonStrings.ftue_auth_phone_confirmation_subtitle, params.msisdn) views.phoneConfirmationInput.associateContentStateWith(button = views.phoneConfirmationSubmit) views.phoneConfirmationInput.setOnImeDoneListener { submitConfirmationCode() } views.phoneConfirmationInput.clearErrorOnChange(viewLifecycleOwner) @@ -71,7 +71,7 @@ class FtueAuthPhoneConfirmationFragment : override fun onError(throwable: Throwable) { views.phoneConfirmationInput.error = when (throwable) { // The entered code is not correct - is Failure.SuccessError -> getString(R.string.login_validation_code_is_not_correct) + is Failure.SuccessError -> getString(CommonStrings.login_validation_code_is_not_correct) else -> errorFormatter.toHumanReadable(throwable) } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPhoneEntryFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPhoneEntryFragment.kt index 620dd1293c..f1601f988c 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPhoneEntryFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPhoneEntryFragment.kt @@ -22,7 +22,6 @@ import android.view.View import android.view.ViewGroup import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.associateContentStateWith import im.vector.app.core.extensions.autofillPhoneNumber import im.vector.app.core.extensions.content @@ -33,6 +32,7 @@ import im.vector.app.databinding.FragmentFtuePhoneInputBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewState import im.vector.app.features.onboarding.RegisterAction +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.auth.registration.RegisterThreePid @@ -73,8 +73,9 @@ class FtueAuthPhoneEntryFragment : val number = views.phoneEntryInput.content() when (val result = phoneNumberParser.parseInternationalNumber(number)) { - PhoneNumberParser.Result.ErrorInvalidNumber -> views.phoneEntryInput.error = getString(R.string.login_msisdn_error_other) - PhoneNumberParser.Result.ErrorMissingInternationalCode -> views.phoneEntryInput.error = getString(R.string.login_msisdn_error_not_international) + PhoneNumberParser.Result.ErrorInvalidNumber -> views.phoneEntryInput.error = getString(CommonStrings.login_msisdn_error_other) + PhoneNumberParser.Result.ErrorMissingInternationalCode -> + views.phoneEntryInput.error = getString(CommonStrings.login_msisdn_error_not_international) is PhoneNumberParser.Result.Success -> { val (countryCode, phoneNumber) = result viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.AddThreePid(RegisterThreePid.Msisdn(phoneNumber, countryCode)))) @@ -83,7 +84,7 @@ class FtueAuthPhoneEntryFragment : } override fun updateWithState(state: OnboardingViewState) { - views.phoneEntryHeaderSubtitle.text = getString(R.string.ftue_auth_phone_subtitle, state.selectedHomeserver.userFacingUrl.toReducedUrl()) + views.phoneEntryHeaderSubtitle.text = getString(CommonStrings.ftue_auth_phone_subtitle, state.selectedHomeserver.userFacingUrl.toReducedUrl()) } override fun onError(throwable: Throwable) { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordBreakerFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordBreakerFragment.kt index 0daf1b3c6f..bfbe2155a6 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordBreakerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordBreakerFragment.kt @@ -23,13 +23,13 @@ import android.view.View import android.view.ViewGroup import com.airbnb.mvrx.args import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.utils.colorTerminatingFullStop import im.vector.app.databinding.FragmentFtueResetPasswordBreakerBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.themes.ThemeProvider import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import javax.inject.Inject @@ -56,9 +56,9 @@ class FtueAuthResetPasswordBreakerFragment : private fun setupUi() { views.resetPasswordBreakerGradientContainer.setBackgroundResource(themeProvider.ftueBreakerBackground()) - views.resetPasswordBreakerTitle.text = getString(R.string.ftue_auth_reset_password_breaker_title) - .colorTerminatingFullStop(ThemeUtils.getColor(requireContext(), R.attr.colorSecondary)) - views.resetPasswordBreakerSubtitle.text = getString(R.string.ftue_auth_password_reset_email_confirmation_subtitle, params.email) + views.resetPasswordBreakerTitle.text = getString(CommonStrings.ftue_auth_reset_password_breaker_title) + .colorTerminatingFullStop(ThemeUtils.getColor(requireContext(), com.google.android.material.R.attr.colorSecondary)) + views.resetPasswordBreakerSubtitle.text = getString(CommonStrings.ftue_auth_password_reset_email_confirmation_subtitle, params.email) views.resetPasswordBreakerResendEmail.debouncedClicks { viewModel.handle(OnboardingAction.ResendResetPassword) } views.resetPasswordBreakerFooter.debouncedClicks { viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnResetPasswordBreakerConfirmed)) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordEmailEntryFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordEmailEntryFragment.kt index c24f068466..159f21c167 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordEmailEntryFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordEmailEntryFragment.kt @@ -21,7 +21,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.associateContentStateWith import im.vector.app.core.extensions.clearErrorOnChange import im.vector.app.core.extensions.content @@ -30,6 +29,7 @@ import im.vector.app.core.extensions.toReducedUrl import im.vector.app.databinding.FragmentFtueResetPasswordEmailInputBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.isEmail @AndroidEntryPoint @@ -59,7 +59,7 @@ class FtueAuthResetPasswordEmailEntryFragment : override fun updateWithState(state: OnboardingViewState) { views.emailEntryHeaderSubtitle.text = getString( - R.string.ftue_auth_reset_password_email_subtitle, + CommonStrings.ftue_auth_reset_password_email_subtitle, state.selectedHomeserver.userFacingUrl.toReducedUrl() ) } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt index 70197cdcdb..282fb7f694 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt @@ -23,13 +23,13 @@ import android.view.ViewGroup import androidx.lifecycle.lifecycleScope import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.hidePassword import im.vector.app.core.extensions.toReducedUrl import im.vector.app.databinding.FragmentLoginResetPasswordBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map @@ -61,7 +61,7 @@ class FtueAuthResetPasswordFragment : } private fun setupUi(state: OnboardingViewState) { - views.resetPasswordTitle.text = getString(R.string.login_reset_password_on, state.selectedHomeserver.userFacingUrl.toReducedUrl()) + views.resetPasswordTitle.text = getString(CommonStrings.login_reset_password_on, state.selectedHomeserver.userFacingUrl.toReducedUrl()) } private fun setupSubmitButton() { @@ -87,12 +87,12 @@ class FtueAuthResetPasswordFragment : showWarning = false // Display a warning as Riot-Web does first MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.login_reset_password_warning_title) - .setMessage(R.string.login_reset_password_warning_content) - .setPositiveButton(R.string.login_reset_password_warning_submit) { _, _ -> + .setTitle(CommonStrings.login_reset_password_warning_title) + .setMessage(CommonStrings.login_reset_password_warning_content) + .setPositiveButton(CommonStrings.login_reset_password_warning_submit) { _, _ -> doSubmit() } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } else { doSubmit() diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordMailConfirmationFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordMailConfirmationFragment.kt index 301ed4fd8b..41db289518 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordMailConfirmationFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordMailConfirmationFragment.kt @@ -22,10 +22,10 @@ import android.view.View import android.view.ViewGroup import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.databinding.FragmentLoginResetPasswordMailConfirmationBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.failure.is401 /** @@ -46,7 +46,7 @@ class FtueAuthResetPasswordMailConfirmationFragment : } private fun setupUi(state: OnboardingViewState) { - views.resetPasswordMailConfirmationNotice.text = getString(R.string.login_reset_password_mail_confirmation_notice, state.resetState.email) + views.resetPasswordMailConfirmationNotice.text = getString(CommonStrings.login_reset_password_mail_confirmation_notice, state.resetState.email) } private fun submit() { @@ -64,15 +64,15 @@ class FtueAuthResetPasswordMailConfirmationFragment : override fun onError(throwable: Throwable) { // Link in email not yet clicked ? val message = if (throwable.is401()) { - getString(R.string.auth_reset_password_error_unauthorized) + getString(CommonStrings.auth_reset_password_error_unauthorized) } else { errorFormatter.toHumanReadable(throwable) } MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(message) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthServerSelectionFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthServerSelectionFragment.kt index 9977152b5a..2e02921fa2 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthServerSelectionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthServerSelectionFragment.kt @@ -21,7 +21,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.utils.openUrlInChromeCustomTab import im.vector.app.databinding.FragmentLoginServerSelectionBinding import im.vector.app.features.login.EMS_LINK @@ -29,6 +28,7 @@ import im.vector.app.features.login.ServerType import im.vector.app.features.login.SignMode import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span /** @@ -63,7 +63,7 @@ class FtueAuthServerSelectionFragment : private fun initTextViews() { views.loginServerChoiceEmsLearnMore.text = span { - text = getString(R.string.login_server_modular_learn_more) + text = getString(CommonStrings.login_server_modular_learn_more) textDecorationLine = "underline" } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthServerUrlFormFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthServerUrlFormFragment.kt index 91f176edf5..49dcea9a4b 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthServerUrlFormFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthServerUrlFormFragment.kt @@ -38,6 +38,7 @@ import im.vector.app.features.login.EMS_LINK import im.vector.app.features.login.ServerType import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.failure.Failure @@ -93,19 +94,19 @@ class FtueAuthServerUrlFormFragment : when (state.serverType) { ServerType.EMS -> { views.loginServerUrlFormIcon.isVisible = true - views.loginServerUrlFormTitle.text = getString(R.string.login_connect_to_modular) - views.loginServerUrlFormText.text = getString(R.string.login_server_url_form_modular_text) + views.loginServerUrlFormTitle.text = getString(CommonStrings.login_connect_to_modular) + views.loginServerUrlFormText.text = getString(CommonStrings.login_server_url_form_modular_text) views.loginServerUrlFormLearnMore.isVisible = true - views.loginServerUrlFormHomeServerUrlTil.hint = getText(R.string.login_server_url_form_modular_hint) - views.loginServerUrlFormNotice.text = getString(R.string.login_server_url_form_modular_notice) + views.loginServerUrlFormHomeServerUrlTil.hint = getText(CommonStrings.login_server_url_form_modular_hint) + views.loginServerUrlFormNotice.text = getString(CommonStrings.login_server_url_form_modular_notice) } else -> { views.loginServerUrlFormIcon.isVisible = false - views.loginServerUrlFormTitle.text = getString(R.string.login_server_other_title) - views.loginServerUrlFormText.text = getString(R.string.login_connect_to_a_custom_server) + views.loginServerUrlFormTitle.text = getString(CommonStrings.login_server_other_title) + views.loginServerUrlFormText.text = getString(CommonStrings.login_connect_to_a_custom_server) views.loginServerUrlFormLearnMore.isVisible = false - views.loginServerUrlFormHomeServerUrlTil.hint = getText(R.string.login_server_url_form_other_hint) - views.loginServerUrlFormNotice.text = getString(R.string.login_server_url_form_common_notice) + views.loginServerUrlFormHomeServerUrlTil.hint = getText(CommonStrings.login_server_url_form_other_hint) + views.loginServerUrlFormNotice.text = getString(CommonStrings.login_server_url_form_common_notice) } } val completions = state.knownCustomHomeServersUrls + if (buildMeta.isDebug) listOf("http://10.0.2.2:8080") else emptyList() @@ -142,7 +143,7 @@ class FtueAuthServerUrlFormFragment : when { serverUrl.isBlank() -> { - views.loginServerUrlFormHomeServerUrlTil.error = getString(R.string.login_error_invalid_home_server) + views.loginServerUrlFormHomeServerUrlTil.error = getString(CommonStrings.login_error_invalid_home_server) } else -> { views.loginServerUrlFormHomeServerUrl.setText(serverUrl, false /* to avoid completion dialog flicker*/) @@ -160,7 +161,7 @@ class FtueAuthServerUrlFormFragment : views.loginServerUrlFormHomeServerUrlTil.error = if (throwable is Failure.NetworkConnection && throwable.ioException is UnknownHostException) { // Invalid homeserver? - getString(R.string.login_error_homeserver_not_found) + getString(CommonStrings.login_error_homeserver_not_found) } else { errorFormatter.toHumanReadable(throwable) } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSignUpSignInSelectionFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSignUpSignInSelectionFragment.kt index cd387f5f6b..5707a84336 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSignUpSignInSelectionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSignUpSignInSelectionFragment.kt @@ -36,6 +36,7 @@ import im.vector.app.features.login.render import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingFlow import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.SSOAction /** @@ -64,18 +65,18 @@ class FtueAuthSignUpSignInSelectionFragment : when (state.serverType) { ServerType.MatrixOrg -> renderServerInformation( icon = R.drawable.ic_logo_matrix_org, - title = getString(R.string.login_connect_to, state.selectedHomeserver.userFacingUrl.toReducedUrl()), - subtitle = getString(R.string.login_server_matrix_org_text) + title = getString(CommonStrings.login_connect_to, state.selectedHomeserver.userFacingUrl.toReducedUrl()), + subtitle = getString(CommonStrings.login_server_matrix_org_text) ) ServerType.EMS -> renderServerInformation( icon = R.drawable.ic_logo_element_matrix_services, - title = getString(R.string.login_connect_to_modular), + title = getString(CommonStrings.login_connect_to_modular), subtitle = state.selectedHomeserver.userFacingUrl.toReducedUrl() ) ServerType.Other -> renderServerInformation( icon = null, - title = getString(R.string.login_server_other_title), - subtitle = getString(R.string.login_connect_to, state.selectedHomeserver.userFacingUrl.toReducedUrl()) + title = getString(CommonStrings.login_server_other_title), + subtitle = getString(CommonStrings.login_connect_to, state.selectedHomeserver.userFacingUrl.toReducedUrl()) ) ServerType.Unknown -> Unit /* Should not happen */ } @@ -114,11 +115,11 @@ class FtueAuthSignUpSignInSelectionFragment : is LoginMode.Sso -> { // change to only one button that is sign in with sso views.loginSignupSigninSubmit.text = - if (state.selectedHomeserver.hasOidcCompatibilityFlow) getString(R.string.login_continue) else getString(R.string.login_signin_sso) + getString(if (state.selectedHomeserver.hasOidcCompatibilityFlow) CommonStrings.login_continue else CommonStrings.login_signin_sso) views.loginSignupSigninSignIn.isVisible = false } else -> { - views.loginSignupSigninSubmit.text = getString(R.string.login_signup) + views.loginSignupSigninSubmit.text = getString(CommonStrings.login_signup) views.loginSignupSigninSignIn.isVisible = true } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt index 3d23d2b4c3..9c9cd20245 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt @@ -28,7 +28,6 @@ import androidx.lifecycle.lifecycleScope import androidx.viewpager2.widget.ViewPager2 import com.google.android.material.tabs.TabLayoutMediator import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.incrementByOneAndWrap import im.vector.app.core.extensions.setCurrentItem import im.vector.app.core.resources.BuildMeta @@ -37,6 +36,7 @@ import im.vector.app.features.VectorFeatures import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingFlow import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -83,7 +83,7 @@ class FtueAuthSplashCarouselFragment : val isAlreadyHaveAccountEnabled = vectorFeatures.isOnboardingAlreadyHaveAccountSplashEnabled() views.loginSplashSubmit.apply { - setText(if (isAlreadyHaveAccountEnabled) R.string.login_splash_create_account else R.string.login_splash_submit) + setText(if (isAlreadyHaveAccountEnabled) CommonStrings.login_splash_create_account else CommonStrings.login_splash_submit) debouncedClicks { splashSubmit(isAlreadyHaveAccountEnabled) } } views.loginSplashAlreadyHaveAccount.apply { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt index 3c8f3c25d9..721981a92c 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt @@ -23,13 +23,13 @@ import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.resources.BuildMeta import im.vector.app.databinding.FragmentFtueAuthSplashBinding import im.vector.app.features.VectorFeatures import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingFlow import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings import javax.inject.Inject /** @@ -55,7 +55,7 @@ class FtueAuthSplashFragment : private fun setupViews() { val isAlreadyHaveAccountEnabled = vectorFeatures.isOnboardingAlreadyHaveAccountSplashEnabled() views.loginSplashSubmit.apply { - setText(if (isAlreadyHaveAccountEnabled) R.string.login_splash_create_account else R.string.login_splash_submit) + setText(if (isAlreadyHaveAccountEnabled) CommonStrings.login_splash_create_account else CommonStrings.login_splash_submit) debouncedClicks { splashSubmit(isAlreadyHaveAccountEnabled) } } views.loginSplashAlreadyHaveAccount.apply { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthUseCaseFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthUseCaseFragment.kt index 6214baeb81..1b1a8435bb 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthUseCaseFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthUseCaseFragment.kt @@ -41,6 +41,7 @@ import im.vector.app.features.login.ServerType import im.vector.app.features.onboarding.FtueUseCase import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.themes.ThemeProvider +import im.vector.lib.strings.CommonStrings import javax.inject.Inject private const val DARK_MODE_ICON_BACKGROUND_ALPHA = 0.30f @@ -68,28 +69,28 @@ class FtueAuthUseCaseFragment : views.useCaseOptionOne.renderUseCase( useCase = FtueUseCase.FRIENDS_FAMILY, - label = R.string.ftue_auth_use_case_option_one, + label = CommonStrings.ftue_auth_use_case_option_one, icon = R.drawable.ic_use_case_friends, - tint = R.color.palette_grape + tint = im.vector.lib.ui.styles.R.color.palette_grape ) views.useCaseOptionTwo.renderUseCase( useCase = FtueUseCase.TEAMS, - label = R.string.ftue_auth_use_case_option_two, + label = CommonStrings.ftue_auth_use_case_option_two, icon = R.drawable.ic_use_case_teams, - tint = R.color.palette_element_green + tint = im.vector.lib.ui.styles.R.color.palette_element_green ) views.useCaseOptionThree.renderUseCase( useCase = FtueUseCase.COMMUNITIES, - label = R.string.ftue_auth_use_case_option_three, + label = CommonStrings.ftue_auth_use_case_option_three, icon = R.drawable.ic_use_case_communities, - tint = R.color.palette_azure + tint = im.vector.lib.ui.styles.R.color.palette_azure ) views.useCaseSkip.setTextWithColoredPart( - fullTextRes = R.string.ftue_auth_use_case_skip, - coloredTextRes = R.string.ftue_auth_use_case_skip_partial, + fullTextRes = CommonStrings.ftue_auth_use_case_skip, + coloredTextRes = CommonStrings.ftue_auth_use_case_skip_partial, underline = false, - colorAttribute = R.attr.colorAccent, + colorAttribute = com.google.android.material.R.attr.colorAccent, onClick = { viewModel.handle(OnboardingAction.UpdateUseCase(FtueUseCase.SKIP)) } ) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt index 7467104da1..921d1d0cfe 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt @@ -36,6 +36,7 @@ import im.vector.app.core.extensions.popBackstack import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.platform.ScreenOrientationLocker import im.vector.app.core.platform.VectorBaseActivity +import im.vector.app.core.resources.BuildMeta import im.vector.app.databinding.ActivityLoginBinding import im.vector.app.features.VectorFeatures import im.vector.app.features.home.HomeActivity @@ -55,6 +56,7 @@ import im.vector.app.features.onboarding.ftueauth.terms.FtueAuthLegacyStyleTerms import im.vector.app.features.onboarding.ftueauth.terms.FtueAuthTermsFragment import im.vector.app.features.onboarding.ftueauth.terms.FtueAuthTermsLegacyStyleFragmentArgument import im.vector.lib.core.utils.compat.getParcelableExtraCompat +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.registration.Stage import org.matrix.android.sdk.api.auth.toLocalizedLoginTerms import org.matrix.android.sdk.api.extensions.tryOrNull @@ -70,6 +72,7 @@ class FtueAuthVariant( private val supportFragmentManager: FragmentManager, private val vectorFeatures: VectorFeatures, private val orientationLocker: ScreenOrientationLocker, + private val buildMeta: BuildMeta, ) : OnboardingVariant { private val enterAnim = R.anim.enter_fade_in @@ -89,7 +92,7 @@ class FtueAuthVariant( // Find findViewById does not work, I do not know why // findViewById(R.id.loginLogo) ?.children - ?.firstOrNull { it.id == R.id.loginLogo } + ?.firstOrNull { it.id == im.vector.lib.ui.styles.R.id.loginLogo } ?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") } ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim) } @@ -133,9 +136,9 @@ class FtueAuthVariant( when (viewEvents) { is OnboardingViewEvents.OutdatedHomeserver -> { MaterialAlertDialogBuilder(activity) - .setTitle(R.string.login_error_outdated_homeserver_title) - .setMessage(R.string.login_error_outdated_homeserver_warning_content) - .setPositiveButton(R.string.ok, null) + .setTitle(CommonStrings.login_error_outdated_homeserver_title) + .setMessage(CommonStrings.login_error_outdated_homeserver_warning_content) + .setPositiveButton(CommonStrings.ok, null) .show() Unit } @@ -194,7 +197,7 @@ class FtueAuthVariant( addLoginStageFragmentToBackstack(FtueAuthResetPasswordSuccessFragment::class.java) } OnboardingViewEvents.OnResetPasswordComplete -> { - Toast.makeText(activity, R.string.ftue_auth_password_reset_confirmation, Toast.LENGTH_SHORT).show() + Toast.makeText(activity, CommonStrings.ftue_auth_password_reset_confirmation, Toast.LENGTH_SHORT).show() activity.popBackstack() } is OnboardingViewEvents.OnSendEmailSuccess -> { @@ -277,16 +280,16 @@ class FtueAuthVariant( private fun displayFallbackWebDialog() { MaterialAlertDialogBuilder(activity) - .setTitle(R.string.app_name) - .setMessage(activity.getString(R.string.login_registration_not_supported)) - .setPositiveButton(R.string.yes) { _, _ -> + .setTitle(buildMeta.applicationName) + .setMessage(activity.getString(CommonStrings.login_registration_not_supported)) + .setPositiveButton(CommonStrings.yes) { _, _ -> activity.addFragmentToBackstack( views.loginFragmentContainer, FtueAuthWebFragment::class.java, option = commonOption ) } - .setNegativeButton(R.string.no, null) + .setNegativeButton(CommonStrings.no, null) .show() } @@ -296,9 +299,9 @@ class FtueAuthVariant( // And inform the user MaterialAlertDialogBuilder(activity) - .setTitle(R.string.dialog_title_error) - .setMessage(activity.getString(R.string.login_sso_error_message, onWebLoginError.description, onWebLoginError.errorCode)) - .setPositiveButton(R.string.ok, null) + .setTitle(CommonStrings.dialog_title_error) + .setMessage(activity.getString(CommonStrings.login_sso_error_message, onWebLoginError.description, onWebLoginError.errorCode)) + .setPositiveButton(CommonStrings.ok, null) .show() } @@ -352,10 +355,10 @@ class FtueAuthVariant( private fun onLoginModeNotSupported(supportedTypes: List) { MaterialAlertDialogBuilder(activity) - .setTitle(R.string.app_name) - .setMessage(activity.getString(R.string.login_mode_not_supported, supportedTypes.joinToString { "'$it'" })) - .setPositiveButton(R.string.yes) { _, _ -> openAuthWebFragment() } - .setNegativeButton(R.string.no, null) + .setTitle(buildMeta.applicationName) + .setMessage(activity.getString(CommonStrings.login_mode_not_supported, supportedTypes.joinToString { "'$it'" })) + .setPositiveButton(CommonStrings.yes) { _, _ -> openAuthWebFragment() } + .setNegativeButton(CommonStrings.no, null) .show() } @@ -456,11 +459,11 @@ class FtueAuthVariant( when { vectorFeatures.isOnboardingCombinedRegisterEnabled() -> addRegistrationStageFragmentToBackstack( FtueAuthTermsFragment::class.java, - FtueAuthTermsLegacyStyleFragmentArgument(stage.policies.toLocalizedLoginTerms(activity.getString(R.string.resources_language))), + FtueAuthTermsLegacyStyleFragmentArgument(stage.policies.toLocalizedLoginTerms(activity.getString(CommonStrings.resources_language))), ) else -> addRegistrationStageFragmentToBackstack( FtueAuthLegacyStyleTermsFragment::class.java, - FtueAuthTermsLegacyStyleFragmentArgument(stage.policies.toLocalizedLoginTerms(activity.getString(R.string.resources_language))), + FtueAuthTermsLegacyStyleFragmentArgument(stage.policies.toLocalizedLoginTerms(activity.getString(CommonStrings.resources_language))), ) } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWaitForEmailFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWaitForEmailFragment.kt index ddd662be86..715f67336f 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWaitForEmailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWaitForEmailFragment.kt @@ -24,13 +24,13 @@ import android.view.ViewGroup import androidx.core.view.isInvisible import com.airbnb.mvrx.args import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.utils.colorTerminatingFullStop import im.vector.app.databinding.FragmentFtueWaitForEmailVerificationBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.RegisterAction import im.vector.app.features.themes.ThemeProvider import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import javax.inject.Inject @@ -65,9 +65,9 @@ class FtueAuthWaitForEmailFragment : private fun setupUi() { views.emailVerificationGradientContainer.setBackgroundResource(themeProvider.ftueBreakerBackground()) - views.emailVerificationTitle.text = getString(R.string.ftue_auth_email_verification_title) - .colorTerminatingFullStop(ThemeUtils.getColor(requireContext(), R.attr.colorSecondary)) - views.emailVerificationSubtitle.text = getString(R.string.ftue_auth_email_verification_subtitle, params.email) + views.emailVerificationTitle.text = getString(CommonStrings.ftue_auth_email_verification_title) + .colorTerminatingFullStop(ThemeUtils.getColor(requireContext(), com.google.android.material.R.attr.colorSecondary)) + views.emailVerificationSubtitle.text = getString(CommonStrings.ftue_auth_email_verification_subtitle, params.email) views.emailVerificationResendEmail.debouncedClicks { hideWaitingForVerificationLoading() viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.SendAgainThreePid)) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWebFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWebFragment.kt index 62a89e437b..95091e6a86 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWebFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWebFragment.kt @@ -32,7 +32,6 @@ import android.webkit.WebView import android.webkit.WebViewClient import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.utils.AssetReader import im.vector.app.databinding.FragmentLoginWebBinding import im.vector.app.features.login.JavascriptResponse @@ -40,6 +39,7 @@ import im.vector.app.features.login.SignMode import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.util.MatrixJsonParser import timber.log.Timber @@ -80,8 +80,8 @@ class FtueAuthWebFragment : private fun setupTitle(state: OnboardingViewState) { toolbar?.title = when (state.signMode) { - SignMode.SignIn -> getString(R.string.login_signin) - else -> getString(R.string.login_signup) + SignMode.SignIn -> getString(CommonStrings.login_signin) + else -> getString(CommonStrings.login_signup) } } @@ -128,9 +128,9 @@ class FtueAuthWebFragment : error: SslError ) { MaterialAlertDialogBuilder(requireActivity()) - .setMessage(R.string.ssl_could_not_verify) - .setPositiveButton(R.string.ssl_trust) { _, _ -> handler.proceed() } - .setNegativeButton(R.string.ssl_do_not_trust) { _, _ -> handler.cancel() } + .setMessage(CommonStrings.ssl_could_not_verify) + .setPositiveButton(CommonStrings.ssl_trust) { _, _ -> handler.proceed() } + .setNegativeButton(CommonStrings.ssl_do_not_trust) { _, _ -> handler.cancel() } .setOnKeyListener(DialogInterface.OnKeyListener { dialog, keyCode, event -> if (event.action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { handler.cancel() diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt index 682cd96b56..7d7e2cffad 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt @@ -16,10 +16,10 @@ package im.vector.app.features.onboarding.ftueauth -import im.vector.app.R import im.vector.app.features.login.SignMode import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.themes.ThemeProvider +import im.vector.lib.ui.styles.R fun SignMode.toAuthenticateAction(login: String, password: String, initialDeviceName: String): OnboardingAction.AuthenticateAction { return when (this) { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/LoginErrorParser.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/LoginErrorParser.kt index ac79419312..447c651812 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/LoginErrorParser.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/LoginErrorParser.kt @@ -16,10 +16,10 @@ package im.vector.app.features.onboarding.ftueauth -import im.vector.app.R import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.resources.StringProvider import im.vector.app.features.onboarding.ftueauth.LoginErrorParser.LoginErrorResult +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.failure.isHomeserverUnavailable import org.matrix.android.sdk.api.failure.isInvalidPassword import org.matrix.android.sdk.api.failure.isInvalidUsername @@ -36,13 +36,13 @@ class LoginErrorParser @Inject constructor( LoginErrorResult(throwable, usernameOrIdError = errorFormatter.toHumanReadable(throwable)) } throwable.isLoginEmailUnknown() -> { - LoginErrorResult(throwable, usernameOrIdError = stringProvider.getString(R.string.login_login_with_email_error)) + LoginErrorResult(throwable, usernameOrIdError = stringProvider.getString(CommonStrings.login_login_with_email_error)) } throwable.isInvalidPassword() && password.hasSurroundingSpaces() -> { - LoginErrorResult(throwable, passwordError = stringProvider.getString(R.string.auth_invalid_login_param_space_in_password)) + LoginErrorResult(throwable, passwordError = stringProvider.getString(CommonStrings.auth_invalid_login_param_space_in_password)) } throwable.isHomeserverUnavailable() -> { - LoginErrorResult(throwable, usernameOrIdError = stringProvider.getString(R.string.login_error_homeserver_not_found)) + LoginErrorResult(throwable, usernameOrIdError = stringProvider.getString(CommonStrings.login_error_homeserver_not_found)) } else -> { LoginErrorResult(throwable) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/LoginFieldsValidation.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/LoginFieldsValidation.kt index 181bd81eb2..78e305a993 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/LoginFieldsValidation.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/LoginFieldsValidation.kt @@ -16,8 +16,8 @@ package im.vector.app.features.onboarding.ftueauth -import im.vector.app.R import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class LoginFieldsValidation @Inject constructor( @@ -30,7 +30,7 @@ class LoginFieldsValidation @Inject constructor( private fun validateUsernameOrId(usernameOrId: String): String? { val accountError = when { - usernameOrId.isEmpty() -> stringProvider.getString(R.string.error_empty_field_enter_user_name) + usernameOrId.isEmpty() -> stringProvider.getString(CommonStrings.error_empty_field_enter_user_name) else -> null } return accountError @@ -38,7 +38,7 @@ class LoginFieldsValidation @Inject constructor( private fun validatePassword(password: String): String? { val passwordError = when { - password.isEmpty() -> stringProvider.getString(R.string.error_empty_field_your_password) + password.isEmpty() -> stringProvider.getString(CommonStrings.error_empty_field_your_password) else -> null } return passwordError diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselStateFactory.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselStateFactory.kt index 845a777ea4..1142ea6a32 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselStateFactory.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselStateFactory.kt @@ -28,6 +28,7 @@ import im.vector.app.features.themes.ThemeProvider import im.vector.app.features.themes.ThemeUtils import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class SplashCarouselStateFactory @Inject constructor( @@ -39,33 +40,33 @@ class SplashCarouselStateFactory @Inject constructor( fun create(): SplashCarouselState { val lightTheme = themeProvider.isLightTheme() - fun background(@DrawableRes lightDrawable: Int) = if (lightTheme) lightDrawable else R.drawable.bg_color_background + fun background(@DrawableRes lightDrawable: Int) = if (lightTheme) lightDrawable else im.vector.lib.ui.styles.R.drawable.bg_color_background fun hero(@DrawableRes lightDrawable: Int, @DrawableRes darkDrawable: Int) = if (lightTheme) lightDrawable else darkDrawable return SplashCarouselState( listOf( SplashCarouselState.Item( - R.string.ftue_auth_carousel_secure_title.colorTerminatingFullStop(R.attr.colorAccent), - R.string.ftue_auth_carousel_secure_body, + CommonStrings.ftue_auth_carousel_secure_title.colorTerminatingFullStop(com.google.android.material.R.attr.colorAccent), + CommonStrings.ftue_auth_carousel_secure_body, hero(R.drawable.ic_splash_conversations, R.drawable.ic_splash_conversations_dark), - background(R.drawable.bg_carousel_page_1) + background(im.vector.lib.ui.styles.R.drawable.bg_carousel_page_1) ), SplashCarouselState.Item( - R.string.ftue_auth_carousel_control_title.colorTerminatingFullStop(R.attr.colorAccent), - R.string.ftue_auth_carousel_control_body, + CommonStrings.ftue_auth_carousel_control_title.colorTerminatingFullStop(com.google.android.material.R.attr.colorAccent), + CommonStrings.ftue_auth_carousel_control_body, hero(R.drawable.ic_splash_control, R.drawable.ic_splash_control_dark), - background(R.drawable.bg_carousel_page_2) + background(im.vector.lib.ui.styles.R.drawable.bg_carousel_page_2) ), SplashCarouselState.Item( - R.string.ftue_auth_carousel_encrypted_title.colorTerminatingFullStop(R.attr.colorAccent), - R.string.ftue_auth_carousel_encrypted_body, + CommonStrings.ftue_auth_carousel_encrypted_title.colorTerminatingFullStop(com.google.android.material.R.attr.colorAccent), + CommonStrings.ftue_auth_carousel_encrypted_body, hero(R.drawable.ic_splash_secure, R.drawable.ic_splash_secure_dark), - background(R.drawable.bg_carousel_page_3) + background(im.vector.lib.ui.styles.R.drawable.bg_carousel_page_3) ), SplashCarouselState.Item( - collaborationTitle().colorTerminatingFullStop(R.attr.colorAccent), - R.string.ftue_auth_carousel_workplace_body, + collaborationTitle().colorTerminatingFullStop(com.google.android.material.R.attr.colorAccent), + CommonStrings.ftue_auth_carousel_workplace_body, hero(R.drawable.ic_splash_collaboration, R.drawable.ic_splash_collaboration_dark), - background(R.drawable.bg_carousel_page_4) + background(im.vector.lib.ui.styles.R.drawable.bg_carousel_page_4) ) ) ) @@ -73,8 +74,8 @@ class SplashCarouselStateFactory @Inject constructor( private fun collaborationTitle(): Int { return when { - localeProvider.isEnglishSpeaking() -> R.string.cut_the_slack_from_teams - else -> R.string.ftue_auth_carousel_workplace_title + localeProvider.isEnglishSpeaking() -> CommonStrings.cut_the_slack_from_teams + else -> CommonStrings.ftue_auth_carousel_workplace_title } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt index e9b32a1c7f..b1ce237f79 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt @@ -37,6 +37,7 @@ import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewState import im.vector.app.features.onboarding.RegisterAction import im.vector.app.features.onboarding.ftueauth.AbstractFtueAuthFragment +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms import javax.inject.Inject import kotlin.math.roundToInt @@ -118,7 +119,7 @@ class FtueAuthTermsFragment : override fun updateWithState(state: OnboardingViewState) { val homeserverName = state.selectedHomeserver.userFacingUrl.toReducedUrl() - views.termsHeaderSubtitle.text = getString(R.string.ftue_auth_terms_subtitle, homeserverName) + views.termsHeaderSubtitle.text = getString(CommonStrings.ftue_auth_terms_subtitle, homeserverName) policyController.homeServer = homeserverName renderState() } diff --git a/vector/src/main/java/im/vector/app/features/permalink/PermalinkHandler.kt b/vector/src/main/java/im/vector/app/features/permalink/PermalinkHandler.kt index f15375c09f..0e335f5375 100644 --- a/vector/src/main/java/im/vector/app/features/permalink/PermalinkHandler.kt +++ b/vector/src/main/java/im/vector/app/features/permalink/PermalinkHandler.kt @@ -19,7 +19,6 @@ package im.vector.app.features.permalink import android.content.Context import android.net.Uri import androidx.fragment.app.FragmentActivity -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.extensions.isIgnored import im.vector.app.core.resources.UserPreferencesProvider @@ -28,6 +27,7 @@ import im.vector.app.features.home.room.threads.arguments.ThreadTimelineArgs import im.vector.app.features.matrixto.OriginOfMatrixTo import im.vector.app.features.navigation.Navigator import im.vector.app.features.roomdirectory.roompreview.RoomPreviewData +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.extensions.orFalse @@ -66,7 +66,7 @@ class PermalinkHandler @Inject constructor( navigationInterceptor: NavigationInterceptor? = null, buildTask: Boolean = false ): Boolean { - val supportedHosts = fragmentActivity.resources.getStringArray(R.array.permalink_supported_hosts) + val supportedHosts = fragmentActivity.resources.getStringArray(im.vector.app.config.R.array.permalink_supported_hosts) return when { deepLink == null -> false deepLink.isIgnored() -> true @@ -198,7 +198,7 @@ class PermalinkHandler @Inject constructor( ) { val session = activeSessionHolder.getSafeActiveSession() ?: return if (roomId == null) { - fragmentActivity.toast(R.string.room_error_not_found) + fragmentActivity.toast(CommonStrings.room_error_not_found) return } val roomSummary = session.getRoomSummary(roomId) @@ -207,7 +207,7 @@ class PermalinkHandler @Inject constructor( // val roomAlias = permalinkData.getRoomAliasOrNull() val isSpace = roomSummary?.roomType == RoomType.SPACE return when { - membership == Membership.BAN -> fragmentActivity.toast(R.string.error_opening_banned_room) + membership == Membership.BAN -> fragmentActivity.toast(CommonStrings.error_opening_banned_room) membership?.isActive().orFalse() -> { if (!isSpace && membership == Membership.JOIN) { // If it's a room you're in, let's just open it, you can tap back if needed diff --git a/vector/src/main/java/im/vector/app/features/pin/PinFragment.kt b/vector/src/main/java/im/vector/app/features/pin/PinFragment.kt index 3a3a0e66fd..68a84f5dd6 100644 --- a/vector/src/main/java/im/vector/app/features/pin/PinFragment.kt +++ b/vector/src/main/java/im/vector/app/features/pin/PinFragment.kt @@ -41,6 +41,8 @@ import im.vector.app.features.pin.lockscreen.ui.AuthMethod import im.vector.app.features.pin.lockscreen.ui.LockScreenFragment import im.vector.app.features.pin.lockscreen.ui.LockScreenListener import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import timber.log.Timber import javax.inject.Inject @@ -77,7 +79,7 @@ class PinFragment : val createFragment = LockScreenFragment() createFragment.lockScreenListener = object : LockScreenListener { override fun onNewCodeValidationFailed() { - Toast.makeText(requireContext(), getString(R.string.create_pin_confirm_failure), Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(CommonStrings.create_pin_confirm_failure), Toast.LENGTH_SHORT).show() } override fun onPinCodeCreated() { @@ -87,9 +89,9 @@ class PinFragment : } createFragment.arguments = defaultConfiguration.copy( mode = LockScreenMode.CREATE, - title = getString(R.string.create_pin_title), + title = getString(CommonStrings.create_pin_title), needsNewCodeValidation = true, - newCodeConfirmationTitle = getString(R.string.create_pin_confirm_title), + newCodeConfirmationTitle = getString(CommonStrings.create_pin_confirm_title), ).asMavericksArgs() replaceFragment(R.id.pinFragmentContainer, createFragment) } @@ -128,15 +130,15 @@ class PinFragment : vectorPreferences.setUseBiometricToUnlock(false) MaterialAlertDialogBuilder(requireContext()) - .setMessage(R.string.auth_biometric_key_invalidated_message) - .setPositiveButton(R.string.ok, null) + .setMessage(CommonStrings.auth_biometric_key_invalidated_message) + .setPositiveButton(CommonStrings.ok, null) .show() } } authFragment.arguments = defaultConfiguration.copy( mode = LockScreenMode.VERIFY, - title = getString(R.string.auth_pin_title), - leftButtonTitle = getString(R.string.auth_pin_forgot), + title = getString(CommonStrings.auth_pin_title), + leftButtonTitle = getString(CommonStrings.auth_pin_forgot), clearCodeOnError = true, ).asMavericksArgs() replaceFragment(R.id.pinFragmentContainer, authFragment) @@ -146,11 +148,11 @@ class PinFragment : val remainingAttempts = pinCodeStore.onWrongPin() when { remainingAttempts > 1 -> - requireActivity().toast(resources.getQuantityString(R.plurals.wrong_pin_message_remaining_attempts, remainingAttempts, remainingAttempts)) + requireActivity().toast(resources.getQuantityString(CommonPlurals.wrong_pin_message_remaining_attempts, remainingAttempts, remainingAttempts)) remainingAttempts == 1 -> - requireActivity().toast(R.string.wrong_pin_message_last_remaining_attempt) + requireActivity().toast(CommonStrings.wrong_pin_message_last_remaining_attempt) else -> { - requireActivity().toast(R.string.too_many_pin_failures) + requireActivity().toast(CommonStrings.too_many_pin_failures) // Logout launchResetPinFlow() } @@ -159,12 +161,12 @@ class PinFragment : private fun displayForgotPinWarningDialog() { MaterialAlertDialogBuilder(requireContext()) - .setTitle(getString(R.string.auth_pin_reset_title)) - .setMessage(getString(R.string.auth_pin_reset_content)) - .setPositiveButton(getString(R.string.auth_pin_new_pin_action)) { _, _ -> + .setTitle(getString(CommonStrings.auth_pin_reset_title)) + .setMessage(getString(CommonStrings.auth_pin_reset_content)) + .setPositiveButton(getString(CommonStrings.auth_pin_new_pin_action)) { _, _ -> launchResetPinFlow() } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } diff --git a/vector/src/main/java/im/vector/app/features/pin/lockscreen/biometrics/BiometricHelper.kt b/vector/src/main/java/im/vector/app/features/pin/lockscreen/biometrics/BiometricHelper.kt index bcfd651ce2..dc751a27f1 100644 --- a/vector/src/main/java/im/vector/app/features/pin/lockscreen/biometrics/BiometricHelper.kt +++ b/vector/src/main/java/im/vector/app/features/pin/lockscreen/biometrics/BiometricHelper.kt @@ -34,7 +34,6 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import dagger.hilt.android.qualifiers.ApplicationContext -import im.vector.app.R import im.vector.app.features.pin.lockscreen.configuration.LockScreenConfiguration import im.vector.app.features.pin.lockscreen.crypto.LockScreenKeyRepository import im.vector.app.features.pin.lockscreen.ui.fallbackprompt.FallbackBiometricDialogFragment @@ -203,9 +202,9 @@ class BiometricHelper @AssistedInject constructor( val callback = createSuspendingAuthCallback(channel, executor.asCoroutineDispatcher()) val authenticators = getAvailableAuthenticators() val isUsingDeviceCredentialAuthenticator = authenticators.hasFlag(DEVICE_CREDENTIAL) - val cancelButtonTitle = configuration.biometricCancelButtonTitle ?: context.getString(R.string.lockscreen_cancel) + val cancelButtonTitle = configuration.biometricCancelButtonTitle ?: context.getString(im.vector.lib.ui.styles.R.string.lockscreen_cancel) val promptInfo = BiometricPrompt.PromptInfo.Builder() - .setTitle(configuration.biometricTitle ?: context.getString(R.string.lockscreen_sign_in)) + .setTitle(configuration.biometricTitle ?: context.getString(im.vector.lib.ui.styles.R.string.lockscreen_sign_in)) .apply { configuration.biometricSubtitle?.let { setSubtitle(it) diff --git a/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/LockScreenFragment.kt b/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/LockScreenFragment.kt index 8e9fdf4fae..83942a6a4d 100644 --- a/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/LockScreenFragment.kt +++ b/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/LockScreenFragment.kt @@ -144,9 +144,9 @@ class LockScreenFragment : private fun setupTitleView(titleView: TextView, isConfirmation: Boolean, configuration: LockScreenConfiguration) = with(titleView) { text = if (isConfirmation) { - configuration.newCodeConfirmationTitle ?: getString(R.string.lockscreen_confirm_pin) + configuration.newCodeConfirmationTitle ?: getString(im.vector.lib.ui.styles.R.string.lockscreen_confirm_pin) } else { - configuration.title ?: getString(R.string.lockscreen_title) + configuration.title ?: getString(im.vector.lib.ui.styles.R.string.lockscreen_title) } } diff --git a/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/fallbackprompt/FallbackBiometricDialogFragment.kt b/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/fallbackprompt/FallbackBiometricDialogFragment.kt index c778e880b2..1d931adac7 100644 --- a/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/fallbackprompt/FallbackBiometricDialogFragment.kt +++ b/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/fallbackprompt/FallbackBiometricDialogFragment.kt @@ -71,7 +71,7 @@ class FallbackBiometricDialogFragment : DialogFragment(R.layout.fragment_biometr parsedArgs.description?.let { fingerprintDescription.text = it } } - requireDialog().setTitle(parsedArgs.title ?: getString(R.string.lockscreen_sign_in)) + requireDialog().setTitle(parsedArgs.title ?: getString(im.vector.lib.ui.styles.R.string.lockscreen_sign_in)) } override fun onResume() { @@ -95,8 +95,8 @@ class FallbackBiometricDialogFragment : DialogFragment(R.layout.fragment_biometr val contentBinding = binding ?: return contentBinding.fingerprintIcon.setImageResource(R.drawable.ic_fingerprint_success_lockscreen) contentBinding.fingerprintStatus.apply { - setTextColor(ResourcesCompat.getColor(resources, R.color.lockscreen_success_color, null)) - setText(R.string.lockscreen_fingerprint_success) + setTextColor(ResourcesCompat.getColor(resources, im.vector.lib.ui.styles.R.color.lockscreen_success_color, null)) + setText(im.vector.lib.ui.styles.R.string.lockscreen_fingerprint_success) } viewLifecycleOwner.lifecycleScope.launch { delay(200L) @@ -108,8 +108,8 @@ class FallbackBiometricDialogFragment : DialogFragment(R.layout.fragment_biometr val contentBinding = binding ?: return contentBinding.fingerprintIcon.setImageResource(R.drawable.ic_fingerprint_error_lockscreen) contentBinding.fingerprintStatus.apply { - setTextColor(ResourcesCompat.getColor(resources, R.color.lockscreen_warning_color, null)) - setText(R.string.lockscreen_fingerprint_not_recognized) + setTextColor(ResourcesCompat.getColor(resources, im.vector.lib.ui.styles.R.color.lockscreen_warning_color, null)) + setText(im.vector.lib.ui.styles.R.string.lockscreen_fingerprint_not_recognized) } viewLifecycleOwner.lifecycleScope.launch { delay(1500L) @@ -121,8 +121,8 @@ class FallbackBiometricDialogFragment : DialogFragment(R.layout.fragment_biometr val contentBinding = binding ?: return contentBinding.fingerprintIcon.setImageResource(R.drawable.lockscreen_fingerprint_40) contentBinding.fingerprintStatus.apply { - setTextColor(ResourcesCompat.getColor(resources, R.color.lockscreen_hint_color, null)) - setText(R.string.lockscreen_fingerprint_hint) + setTextColor(ResourcesCompat.getColor(resources, im.vector.lib.ui.styles.R.color.lockscreen_hint_color, null)) + setText(im.vector.lib.ui.styles.R.string.lockscreen_fingerprint_hint) } } diff --git a/vector/src/main/java/im/vector/app/features/pin/lockscreen/views/LockScreenCodeView.kt b/vector/src/main/java/im/vector/app/features/pin/lockscreen/views/LockScreenCodeView.kt index d9d6d56737..6341d66ea6 100644 --- a/vector/src/main/java/im/vector/app/features/pin/lockscreen/views/LockScreenCodeView.kt +++ b/vector/src/main/java/im/vector/app/features/pin/lockscreen/views/LockScreenCodeView.kt @@ -73,7 +73,7 @@ class LockScreenCodeView @JvmOverloads constructor( repeat(codeLength) { index -> val checkBox = inflater.inflate(R.layout.view_code_checkbox, null) as CheckBox val params = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) - val margin = resources.getDimensionPixelSize(R.dimen.lockscreen_code_margin) + val margin = resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.lockscreen_code_margin) params.setMargins(margin) checkBox.layoutParams = params checkBox.isChecked = code.size > index diff --git a/vector/src/main/java/im/vector/app/features/poll/create/CreatePollController.kt b/vector/src/main/java/im/vector/app/features/poll/create/CreatePollController.kt index 0ef92e4d2f..6fe975d32f 100644 --- a/vector/src/main/java/im/vector/app/features/poll/create/CreatePollController.kt +++ b/vector/src/main/java/im/vector/app/features/poll/create/CreatePollController.kt @@ -28,6 +28,7 @@ import im.vector.app.core.ui.list.genericItem import im.vector.app.features.form.formEditTextItem import im.vector.app.features.form.formEditTextWithDeleteItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.message.PollType import javax.inject.Inject @@ -51,7 +52,7 @@ class CreatePollController @Inject constructor( genericItem { id("poll_type_title") style(ItemStyle.BIG_TEXT) - title(host.stringProvider.getString(R.string.poll_type_title).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.poll_type_title).toEpoxyCharSequence()) } pollTypeSelectionItem { @@ -71,7 +72,7 @@ class CreatePollController @Inject constructor( genericItem { id("question_title") style(ItemStyle.BIG_TEXT) - title(host.stringProvider.getString(R.string.create_poll_question_title).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.create_poll_question_title).toEpoxyCharSequence()) } val questionImeAction = if (currentState.options.isEmpty()) EditorInfo.IME_ACTION_DONE else EditorInfo.IME_ACTION_NEXT @@ -79,7 +80,7 @@ class CreatePollController @Inject constructor( formEditTextItem { id("question") value(currentState.question) - hint(host.stringProvider.getString(R.string.create_poll_question_hint)) + hint(host.stringProvider.getString(CommonStrings.create_poll_question_hint)) singleLine(true) imeOptions(questionImeAction) maxLength(340) @@ -91,7 +92,7 @@ class CreatePollController @Inject constructor( genericItem { id("options_title") style(ItemStyle.BIG_TEXT) - title(host.stringProvider.getString(R.string.create_poll_options_title).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.create_poll_options_title).toEpoxyCharSequence()) } currentState.options.forEachIndexed { index, option -> @@ -99,7 +100,7 @@ class CreatePollController @Inject constructor( formEditTextWithDeleteItem { id("option_$index") value(option) - hint(host.stringProvider.getString(R.string.create_poll_options_hint, (index + 1))) + hint(host.stringProvider.getString(CommonStrings.create_poll_options_hint, (index + 1))) singleLine(true) imeOptions(imeOptions) maxLength(340) @@ -115,8 +116,8 @@ class CreatePollController @Inject constructor( if (currentState.canAddMoreOptions) { genericButtonItem { id("add_option") - text(host.stringProvider.getString(R.string.create_poll_add_option)) - textColor(host.colorProvider.getColor(R.color.palette_element_green)) + text(host.stringProvider.getString(CommonStrings.create_poll_add_option)) + textColor(host.colorProvider.getColor(im.vector.lib.ui.styles.R.color.palette_element_green)) gravity(Gravity.START) bold(true) highlight(false) diff --git a/vector/src/main/java/im/vector/app/features/poll/create/CreatePollFragment.kt b/vector/src/main/java/im/vector/app/features/poll/create/CreatePollFragment.kt index 1033c8da47..d96f728124 100644 --- a/vector/src/main/java/im/vector/app/features/poll/create/CreatePollFragment.kt +++ b/vector/src/main/java/im/vector/app/features/poll/create/CreatePollFragment.kt @@ -26,12 +26,13 @@ import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.args import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentCreatePollBinding import im.vector.app.features.poll.PollMode import im.vector.app.features.poll.create.CreatePollViewModel.Companion.MAX_OPTIONS_COUNT +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.session.room.model.message.PollType import javax.inject.Inject @@ -65,12 +66,12 @@ class CreatePollFragment : when (args.mode) { PollMode.CREATE -> { - views.createPollToolbar.title = getString(R.string.create_poll_title) - views.createPollButton.text = getString(R.string.create_poll_title) + views.createPollToolbar.title = getString(CommonStrings.create_poll_title) + views.createPollButton.text = getString(CommonStrings.create_poll_title) } PollMode.EDIT -> { - views.createPollToolbar.title = getString(R.string.edit_poll_title) - views.createPollButton.text = getString(R.string.edit_poll_title) + views.createPollToolbar.title = getString(CommonStrings.edit_poll_title) + views.createPollButton.text = getString(CommonStrings.edit_poll_title) } } @@ -131,13 +132,13 @@ class CreatePollFragment : } private fun handleEmptyQuestionError() { - renderToast(getString(R.string.create_poll_empty_question_error)) + renderToast(getString(CommonStrings.create_poll_empty_question_error)) } private fun handleNotEnoughOptionsError(requiredOptionsCount: Int) { renderToast( resources.getQuantityString( - R.plurals.create_poll_not_enough_options_error, + CommonPlurals.create_poll_not_enough_options_error, requiredOptionsCount, requiredOptionsCount ) diff --git a/vector/src/main/java/im/vector/app/features/popup/IncomingCallAlert.kt b/vector/src/main/java/im/vector/app/features/popup/IncomingCallAlert.kt index 2c640cd2ca..f86b7c02a7 100644 --- a/vector/src/main/java/im/vector/app/features/popup/IncomingCallAlert.kt +++ b/vector/src/main/java/im/vector/app/features/popup/IncomingCallAlert.kt @@ -24,6 +24,7 @@ import im.vector.app.core.glide.GlideApp import im.vector.app.databinding.AlerterIncomingCallLayoutBinding import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.util.MatrixItem class IncomingCallAlert( @@ -33,7 +34,7 @@ class IncomingCallAlert( override val priority = PopupAlertManager.INCOMING_CALL_PRIORITY override val layoutRes = R.layout.alerter_incoming_call_layout - override var colorAttribute: Int? = R.attr.colorSurface + override var colorAttribute: Int? = com.google.android.material.R.attr.colorSurface override val dismissOnClick: Boolean = false override val isLight: Boolean = true @@ -48,9 +49,9 @@ class IncomingCallAlert( override fun bind(view: View) { val views = AlerterIncomingCallLayoutBinding.bind(view) val (callKindText, callKindIcon, callKindActionIcon) = if (isVideoCall) { - Triple(R.string.action_video_call, R.drawable.ic_call_video_small, R.drawable.ic_call_answer_video) + Triple(CommonStrings.action_video_call, R.drawable.ic_call_video_small, R.drawable.ic_call_answer_video) } else { - Triple(R.string.action_voice_call, R.drawable.ic_call_audio_small, R.drawable.ic_call_answer) + Triple(CommonStrings.action_voice_call, R.drawable.ic_call_audio_small, R.drawable.ic_call_answer) } views.incomingCallKindView.setText(callKindText) views.incomingCallKindView.setLeftDrawable(callKindIcon) diff --git a/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt b/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt index c59b2c7216..2e3108d5bb 100644 --- a/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt +++ b/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt @@ -35,6 +35,7 @@ import im.vector.app.features.pin.PinActivity import im.vector.app.features.signout.hard.SignedOutActivity import im.vector.app.features.themes.ThemeUtils import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import timber.log.Timber import java.lang.ref.WeakReference import javax.inject.Inject @@ -251,7 +252,7 @@ class PopupAlertManager @Inject constructor( setIcon(it) } alert.actions.forEach { action -> - addButton(action.title, R.style.Widget_Vector_Button_Text_Alerter) { + addButton(action.title, im.vector.lib.ui.styles.R.style.Widget_Vector_Button_Text_Alerter) { if (action.autoClose) { currentIsDismissed() Alerter.hide() @@ -297,7 +298,7 @@ class PopupAlertManager @Inject constructor( } else if (alert.colorAttribute != null) { setBackgroundColorInt(ThemeUtils.getColor(activity, alert.colorAttribute!!)) } else { - setBackgroundColorRes(alert.colorRes ?: R.color.notification_accent_color) + setBackgroundColorRes(alert.colorRes ?: im.vector.lib.ui.styles.R.color.notification_accent_color) } } .enableIconPulse(!noAnimation) @@ -306,14 +307,14 @@ class PopupAlertManager @Inject constructor( /* a11y */ private fun handleAccessibility(activity: Activity, giveFocus: Boolean) { - activity.window.decorView.findViewById(R.id.llAlertBackground)?.let { alertView -> + activity.window.decorView.findViewById(com.tapadoo.alerter.R.id.llAlertBackground)?.let { alertView -> alertView.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES // Add close action for a11y (same action than swipe). User can select the action by swiping on the screen vertically, // and double tap to perform the action ViewCompat.addAccessibilityAction( alertView, - stringProvider.getString(R.string.action_close) + stringProvider.getString(CommonStrings.action_close) ) { _, _ -> currentIsDismissed() Alerter.hide() diff --git a/vector/src/main/java/im/vector/app/features/popup/VectorAlert.kt b/vector/src/main/java/im/vector/app/features/popup/VectorAlert.kt index 1597d927d8..a81454d456 100644 --- a/vector/src/main/java/im/vector/app/features/popup/VectorAlert.kt +++ b/vector/src/main/java/im/vector/app/features/popup/VectorAlert.kt @@ -23,7 +23,6 @@ import androidx.annotation.ColorInt import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.annotation.LayoutRes -import im.vector.app.R import java.lang.ref.WeakReference interface VectorAlert { @@ -94,7 +93,7 @@ open class DefaultVectorAlert( override var expirationTimestamp: Long? = null @LayoutRes - override val layoutRes = R.layout.alerter_alert_default_layout + override val layoutRes = com.tapadoo.alerter.R.layout.alerter_alert_default_layout override val dismissOnClick: Boolean = true diff --git a/vector/src/main/java/im/vector/app/features/qrcode/QrCodeScannerActivity.kt b/vector/src/main/java/im/vector/app/features/qrcode/QrCodeScannerActivity.kt index 95062a64ac..61079af379 100644 --- a/vector/src/main/java/im/vector/app/features/qrcode/QrCodeScannerActivity.kt +++ b/vector/src/main/java/im/vector/app/features/qrcode/QrCodeScannerActivity.kt @@ -23,10 +23,10 @@ import android.widget.Toast import androidx.activity.result.ActivityResultLauncher import com.airbnb.mvrx.viewModel import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.databinding.ActivitySimpleBinding +import im.vector.lib.strings.CommonStrings @AndroidEntryPoint class QrCodeScannerActivity : VectorBaseActivity() { @@ -46,7 +46,7 @@ class QrCodeScannerActivity : VectorBaseActivity() { setResultAndFinish(it.result, it.isQrCode) } is QrCodeScannerEvents.ParseFailed -> { - Toast.makeText(this, R.string.qr_code_not_scanned, Toast.LENGTH_SHORT).show() + Toast.makeText(this, CommonStrings.qr_code_not_scanned, Toast.LENGTH_SHORT).show() finish() } else -> Unit @@ -54,7 +54,7 @@ class QrCodeScannerActivity : VectorBaseActivity() { } if (isFirstCreation()) { - val args = QrScannerArgs(showExtraButtons = false, R.string.verification_scan_their_code) + val args = QrScannerArgs(showExtraButtons = false, CommonStrings.verification_scan_their_code) replaceFragment(views.simpleFragmentContainer, QrCodeScannerFragment::class.java, args) } } diff --git a/vector/src/main/java/im/vector/app/features/qrcode/QrCodeScannerFragment.kt b/vector/src/main/java/im/vector/app/features/qrcode/QrCodeScannerFragment.kt index c2b81abf12..341fa44255 100644 --- a/vector/src/main/java/im/vector/app/features/qrcode/QrCodeScannerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/qrcode/QrCodeScannerFragment.kt @@ -31,7 +31,6 @@ import com.google.zxing.BarcodeFormat import com.google.zxing.Result import com.google.zxing.ResultMetadataType import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseFragment @@ -43,6 +42,7 @@ import im.vector.app.databinding.FragmentQrCodeScannerBinding import im.vector.app.features.usercode.QRCodeBitmapDecodeHelper import im.vector.lib.multipicker.MultiPicker import im.vector.lib.multipicker.utils.ImageUtils +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import me.dm7.barcodescanner.zxing.ZXingScannerView import org.matrix.android.sdk.api.extensions.tryOrNull @@ -69,7 +69,7 @@ class QrCodeScannerFragment : if (allGranted) { startCamera() } else if (deniedPermanently) { - activity?.onPermissionDeniedDialog(R.string.denied_permission_camera) + activity?.onPermissionDeniedDialog(CommonStrings.denied_permission_camera) } } @@ -84,7 +84,7 @@ class QrCodeScannerFragment : // try to see if it is a valid matrix code val bitmap = ImageUtils.getBitmap(requireContext(), uri) ?: return@let Unit.also { - Toast.makeText(requireContext(), getString(R.string.qr_code_not_scanned), Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(CommonStrings.qr_code_not_scanned), Toast.LENGTH_SHORT).show() } handleResult(tryOrNull { QRCodeBitmapDecodeHelper.decodeQRFromBitmap(bitmap) }) } diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReportActivity.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReportActivity.kt index 78d3347cbe..8225b3d824 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReportActivity.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReportActivity.kt @@ -30,6 +30,7 @@ import im.vector.app.R import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.databinding.ActivityBugReportBinding +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.tryOrNull import timber.log.Timber @@ -67,32 +68,32 @@ class BugReportActivity : // Default screen is for bug report, so modify it for suggestion when (reportType) { ReportType.BUG_REPORT -> { - supportActionBar?.setTitle(R.string.title_activity_bug_report) + supportActionBar?.setTitle(CommonStrings.title_activity_bug_report) views.bugReportButtonContactMe.isVisible = true } ReportType.SUGGESTION -> { - supportActionBar?.setTitle(R.string.send_suggestion) + supportActionBar?.setTitle(CommonStrings.send_suggestion) - views.bugReportFirstText.setText(R.string.send_suggestion_content) - views.bugReportTextInputLayout.hint = getString(R.string.send_suggestion_report_placeholder) + views.bugReportFirstText.setText(CommonStrings.send_suggestion_content) + views.bugReportTextInputLayout.hint = getString(CommonStrings.send_suggestion_report_placeholder) views.bugReportButtonContactMe.isVisible = true hideBugReportOptions() } ReportType.SPACE_BETA_FEEDBACK -> { - supportActionBar?.setTitle(R.string.send_feedback_space_title) + supportActionBar?.setTitle(CommonStrings.send_feedback_space_title) - views.bugReportFirstText.setText(R.string.send_feedback_space_info) - views.bugReportTextInputLayout.hint = getString(R.string.feedback) + views.bugReportFirstText.setText(CommonStrings.send_feedback_space_info) + views.bugReportTextInputLayout.hint = getString(CommonStrings.feedback) views.bugReportButtonContactMe.isVisible = true hideBugReportOptions() } ReportType.THREADS_BETA_FEEDBACK -> { - supportActionBar?.setTitle(R.string.send_feedback_threads_title) + supportActionBar?.setTitle(CommonStrings.send_feedback_threads_title) - views.bugReportFirstText.setText(R.string.send_feedback_threads_info) - views.bugReportTextInputLayout.hint = getString(R.string.feedback) + views.bugReportFirstText.setText(CommonStrings.send_feedback_threads_info) + views.bugReportTextInputLayout.hint = getString(CommonStrings.feedback) views.bugReportButtonContactMe.isVisible = true hideBugReportOptions() @@ -138,7 +139,7 @@ class BugReportActivity : if (views.bugReportEditText.text.toString().trim().length >= 10) { sendBugReport() } else { - views.bugReportTextInputLayout.error = getString(R.string.bug_report_error_too_short) + views.bugReportTextInputLayout.error = getString(CommonStrings.bug_report_error_too_short) } true } @@ -156,7 +157,7 @@ class BugReportActivity : invalidateOptionsMenu() views.bugReportProgressTextView.isVisible = true - views.bugReportProgressTextView.text = getString(R.string.send_bug_report_progress, "0") + views.bugReportProgressTextView.text = getString(CommonStrings.send_bug_report_progress, "0") views.bugReportProgressView.isVisible = true views.bugReportProgressView.progress = 0 @@ -179,19 +180,19 @@ class BugReportActivity : ReportType.BUG_REPORT -> { Toast.makeText( this@BugReportActivity, - getString(R.string.send_bug_report_failed, reason), Toast.LENGTH_LONG + getString(CommonStrings.send_bug_report_failed, reason), Toast.LENGTH_LONG ).show() } ReportType.SUGGESTION -> { Toast.makeText( this@BugReportActivity, - getString(R.string.send_suggestion_failed, reason), Toast.LENGTH_LONG + getString(CommonStrings.send_suggestion_failed, reason), Toast.LENGTH_LONG ).show() } ReportType.SPACE_BETA_FEEDBACK -> { Toast.makeText( this@BugReportActivity, - getString(R.string.feedback_failed, reason), Toast.LENGTH_LONG + getString(CommonStrings.feedback_failed, reason), Toast.LENGTH_LONG ).show() } else -> { @@ -219,20 +220,20 @@ class BugReportActivity : val myProgress = progress.coerceIn(0, 100) views.bugReportProgressView.progress = myProgress - views.bugReportProgressTextView.text = getString(R.string.send_bug_report_progress, myProgress.toString()) + views.bugReportProgressTextView.text = getString(CommonStrings.send_bug_report_progress, myProgress.toString()) } override fun onUploadSucceed(reportUrl: String?) { try { when (reportType) { ReportType.BUG_REPORT -> { - Toast.makeText(this@BugReportActivity, R.string.send_bug_report_sent, Toast.LENGTH_LONG).show() + Toast.makeText(this@BugReportActivity, CommonStrings.send_bug_report_sent, Toast.LENGTH_LONG).show() } ReportType.SUGGESTION -> { - Toast.makeText(this@BugReportActivity, R.string.send_suggestion_sent, Toast.LENGTH_LONG).show() + Toast.makeText(this@BugReportActivity, CommonStrings.send_suggestion_sent, Toast.LENGTH_LONG).show() } ReportType.SPACE_BETA_FEEDBACK -> { - Toast.makeText(this@BugReportActivity, R.string.feedback_sent, Toast.LENGTH_LONG).show() + Toast.makeText(this@BugReportActivity, CommonStrings.feedback_sent, Toast.LENGTH_LONG).show() } else -> { // nop @@ -263,11 +264,10 @@ class BugReportActivity : views.bugReportScreenshotPreview.isVisible = bugReporter.screenshot != null } + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() { // Ensure there is no crash status remaining, which will be sent later on by mistake bugReporter.deleteCrashFile() - - @Suppress("DEPRECATION") super.onBackPressed() } diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt index 611c210f39..2108f22b26 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt @@ -26,7 +26,7 @@ import androidx.fragment.app.DialogFragment import androidx.fragment.app.FragmentActivity import com.squareup.moshi.Types import im.vector.app.BuildConfig -import im.vector.app.R +import im.vector.app.config.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.extensions.getAllChildFragments import im.vector.app.core.extensions.toOnOff @@ -523,12 +523,12 @@ class BugReporter @Inject constructor( // As per https://github.com/matrix-org/rageshake // app: Identifier for the application (eg 'riot-web'). // Should correspond to a mapping configured in the configuration file for github issue reporting to work. - // (see R.string.bug_report_url for configured RS server) + // (see CommonStrings.bug_report_url for configured RS server) return context.getString( when (reportType) { ReportType.AUTO_UISI_SENDER, - ReportType.AUTO_UISI -> R.string.bug_report_auto_uisi_app_name - else -> R.string.bug_report_app_name + ReportType.AUTO_UISI -> im.vector.app.config.R.string.bug_report_auto_uisi_app_name + else -> im.vector.app.config.R.string.bug_report_app_name } ) } diff --git a/vector/src/main/java/im/vector/app/features/rageshake/RageShake.kt b/vector/src/main/java/im/vector/app/features/rageshake/RageShake.kt index 513f99f27d..9310d711d3 100644 --- a/vector/src/main/java/im/vector/app/features/rageshake/RageShake.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/RageShake.kt @@ -23,12 +23,12 @@ import androidx.core.content.getSystemService import androidx.fragment.app.FragmentActivity import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.squareup.seismic.ShakeDetector -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.hardware.vibrate import im.vector.app.features.navigation.Navigator import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.VectorSettingsActivity +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class RageShake @Inject constructor( @@ -77,17 +77,17 @@ class RageShake @Inject constructor( dialogDisplayed = true MaterialAlertDialogBuilder(activity) - .setMessage(R.string.send_bug_report_alert_message) - .setPositiveButton(R.string.yes) { _, _ -> openBugReportScreen() } + .setMessage(CommonStrings.send_bug_report_alert_message) + .setPositiveButton(CommonStrings.yes) { _, _ -> openBugReportScreen() } .also { if (sessionHolder.hasActiveSession()) { - it.setNeutralButton(R.string.settings) { _, _ -> openSettings() } + it.setNeutralButton(CommonStrings.settings) { _, _ -> openSettings() } } else { - it.setNeutralButton(R.string.action_disable) { _, _ -> disableRageShake() } + it.setNeutralButton(CommonStrings.action_disable) { _, _ -> disableRageShake() } } } .setOnDismissListener { dialogDisplayed = false } - .setNegativeButton(R.string.no, null) + .setNegativeButton(CommonStrings.no, null) .show() } } diff --git a/vector/src/main/java/im/vector/app/features/reactions/EmojiDrawView.kt b/vector/src/main/java/im/vector/app/features/reactions/EmojiDrawView.kt index fec185b1c3..d7dfb51d92 100644 --- a/vector/src/main/java/im/vector/app/features/reactions/EmojiDrawView.kt +++ b/vector/src/main/java/im/vector/app/features/reactions/EmojiDrawView.kt @@ -43,16 +43,16 @@ class EmojiDrawView @JvmOverloads constructor( var emoji: String? = null - override fun onDraw(canvas: Canvas?) { + override fun onDraw(canvas: Canvas) { Trace.beginSection("EmojiDrawView.onDraw") super.onDraw(canvas) - canvas?.save() + canvas.save() val space = abs((width - emojiSize) / 2f) if (mLayout != null) { - canvas?.translate(space, space) + canvas.translate(space, space) mLayout!!.draw(canvas) } - canvas?.restore() + canvas.restore() Trace.endSection() } diff --git a/vector/src/main/java/im/vector/app/features/reactions/EmojiReactionPickerActivity.kt b/vector/src/main/java/im/vector/app/features/reactions/EmojiReactionPickerActivity.kt index 24a45872d5..44a39027a6 100644 --- a/vector/src/main/java/im/vector/app/features/reactions/EmojiReactionPickerActivity.kt +++ b/vector/src/main/java/im/vector/app/features/reactions/EmojiReactionPickerActivity.kt @@ -36,6 +36,7 @@ import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.databinding.ActivityEmojiReactionPickerBinding import im.vector.app.features.reactions.data.EmojiDataSource import im.vector.lib.core.utils.flow.throttleFirst +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @@ -63,7 +64,7 @@ class EmojiReactionPickerActivity : override fun getCoordinatorLayout() = views.coordinatorLayout - override fun getTitleRes() = R.string.title_activity_emoji_reaction_picker + override fun getTitleRes() = CommonStrings.title_activity_emoji_reaction_picker @Inject lateinit var emojiCompatFontProvider: EmojiCompatFontProvider @Inject lateinit var emojiDataSource: EmojiDataSource @@ -182,7 +183,7 @@ class EmojiReactionPickerActivity : private fun getActionBarSize(): Int { return try { val typedValue = TypedValue() - theme.resolveAttribute(R.attr.actionBarSize, typedValue, true) + theme.resolveAttribute(com.google.android.material.R.attr.actionBarSize, typedValue, true) TypedValue.complexToDimensionPixelSize(typedValue.data, resources.displayMetrics) } catch (e: Exception) { // Timber.e(e, "Unable to get color") diff --git a/vector/src/main/java/im/vector/app/features/reactions/EmojiSearchResultController.kt b/vector/src/main/java/im/vector/app/features/reactions/EmojiSearchResultController.kt index f699a86d33..5010cdcef1 100644 --- a/vector/src/main/java/im/vector/app/features/reactions/EmojiSearchResultController.kt +++ b/vector/src/main/java/im/vector/app/features/reactions/EmojiSearchResultController.kt @@ -19,10 +19,10 @@ import android.graphics.Typeface import androidx.recyclerview.widget.RecyclerView import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.EmojiCompatFontProvider -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class EmojiSearchResultController @Inject constructor( @@ -53,13 +53,13 @@ class EmojiSearchResultController @Inject constructor( // display 'Type something to find' genericFooterItem { id("type.query.item") - text(host.stringProvider.getString(R.string.reaction_search_type_hint).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.reaction_search_type_hint).toEpoxyCharSequence()) } } else { // Display no search Results genericFooterItem { id("no.results.item") - text(host.stringProvider.getString(R.string.no_result_placeholder).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.no_result_placeholder).toEpoxyCharSequence()) } } } else { diff --git a/vector/src/main/java/im/vector/app/features/reactions/widget/ReactionButton.kt b/vector/src/main/java/im/vector/app/features/reactions/widget/ReactionButton.kt index 1bad4ff248..d8130690cb 100644 --- a/vector/src/main/java/im/vector/app/features/reactions/widget/ReactionButton.kt +++ b/vector/src/main/java/im/vector/app/features/reactions/widget/ReactionButton.kt @@ -38,7 +38,7 @@ class ReactionButton @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, - defStyleRes: Int = R.style.TimelineReactionView + defStyleRes: Int = im.vector.lib.ui.styles.R.style.TimelineReactionView ) : LinearLayout(context, attrs, defStyleAttr, defStyleRes), View.OnClickListener, View.OnLongClickListener { @@ -72,14 +72,14 @@ class ReactionButton @JvmOverloads constructor( layoutDirection = View.LAYOUT_DIRECTION_LOCALE views = ReactionButtonBinding.bind(this) views.reactionCount.text = TextUtils.formatCountToShortDecimal(reactionCount) - context.withStyledAttributes(attrs, R.styleable.ReactionButton, defStyleAttr) { + context.withStyledAttributes(attrs, im.vector.lib.ui.styles.R.styleable.ReactionButton, defStyleAttr) { onDrawable = ContextCompat.getDrawable(context, R.drawable.reaction_rounded_rect_shape) offDrawable = ContextCompat.getDrawable(context, R.drawable.reaction_rounded_rect_shape_off) - getString(R.styleable.ReactionButton_emoji)?.let { + getString(im.vector.lib.ui.styles.R.styleable.ReactionButton_emoji)?.let { reactionString = it } - reactionCount = getInt(R.styleable.ReactionButton_reaction_count, 0) - val status = getBoolean(R.styleable.ReactionButton_toggled, false) + reactionCount = getInt(im.vector.lib.ui.styles.R.styleable.ReactionButton_reaction_count, 0) + val status = getBoolean(im.vector.lib.ui.styles.R.styleable.ReactionButton_toggled, false) setChecked(status) } diff --git a/vector/src/main/java/im/vector/app/features/room/RequireActiveMembershipViewModel.kt b/vector/src/main/java/im/vector/app/features/room/RequireActiveMembershipViewModel.kt index 8c607a65a3..3d9cd96924 100644 --- a/vector/src/main/java/im/vector/app/features/room/RequireActiveMembershipViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/room/RequireActiveMembershipViewModel.kt @@ -20,11 +20,11 @@ import com.airbnb.mvrx.MavericksViewModelFactory import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flatMapLatest @@ -100,19 +100,19 @@ class RequireActiveMembershipViewModel @AssistedInject constructor( val viewEvent = when (roomSummary.membership) { Membership.LEAVE -> { val message = senderDisplayName?.let { - stringProvider.getString(R.string.has_been_removed, roomSummary.displayName, it) + stringProvider.getString(CommonStrings.has_been_removed, roomSummary.displayName, it) } RequireActiveMembershipViewEvents.RoomLeft(message) } Membership.KNOCK -> { val message = senderDisplayName?.let { - stringProvider.getString(R.string.has_been_removed, roomSummary.displayName, it) + stringProvider.getString(CommonStrings.has_been_removed, roomSummary.displayName, it) } RequireActiveMembershipViewEvents.RoomLeft(message) } Membership.BAN -> { val message = senderDisplayName?.let { - stringProvider.getString(R.string.has_been_banned, roomSummary.displayName, it) + stringProvider.getString(CommonStrings.has_been_banned, roomSummary.displayName, it) } RequireActiveMembershipViewEvents.RoomLeft(message) } diff --git a/vector/src/main/java/im/vector/app/features/room/VectorRoomDisplayNameFallbackProvider.kt b/vector/src/main/java/im/vector/app/features/room/VectorRoomDisplayNameFallbackProvider.kt index 57967d7a05..976e13ba25 100644 --- a/vector/src/main/java/im/vector/app/features/room/VectorRoomDisplayNameFallbackProvider.kt +++ b/vector/src/main/java/im/vector/app/features/room/VectorRoomDisplayNameFallbackProvider.kt @@ -17,9 +17,10 @@ package im.vector.app.features.room import android.content.Context -import im.vector.app.R import im.vector.app.config.Config import im.vector.app.core.di.ActiveSessionHolder +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.provider.RoomDisplayNameFallbackProvider import org.matrix.android.sdk.api.session.getRoom import javax.inject.Inject @@ -41,12 +42,12 @@ class VectorRoomDisplayNameFallbackProvider @Inject constructor( } override fun getNameForRoomInvite(): String { - return context.getString(R.string.room_displayname_room_invite) + return context.getString(CommonStrings.room_displayname_room_invite) } override fun getNameForEmptyRoom(isDirect: Boolean, leftMemberNames: List): String { return if (leftMemberNames.isEmpty()) { - context.getString(R.string.room_displayname_empty_room) + context.getString(CommonStrings.room_displayname_empty_room) } else { val was = when (val size = leftMemberNames.size) { 1 -> getNameFor1member(leftMemberNames[0]) @@ -55,27 +56,27 @@ class VectorRoomDisplayNameFallbackProvider @Inject constructor( 4 -> getNameFor4members(leftMemberNames[0], leftMemberNames[1], leftMemberNames[2], leftMemberNames[3]) else -> getNameFor4membersAndMore(leftMemberNames[0], leftMemberNames[1], leftMemberNames[2], size - 3) } - context.getString(R.string.room_displayname_empty_room_was, was) + context.getString(CommonStrings.room_displayname_empty_room_was, was) } } override fun getNameFor1member(name: String) = name override fun getNameFor2members(name1: String, name2: String): String { - return context.getString(R.string.room_displayname_two_members, name1, name2) + return context.getString(CommonStrings.room_displayname_two_members, name1, name2) } override fun getNameFor3members(name1: String, name2: String, name3: String): String { - return context.getString(R.string.room_displayname_3_members, name1, name2, name3) + return context.getString(CommonStrings.room_displayname_3_members, name1, name2, name3) } override fun getNameFor4members(name1: String, name2: String, name3: String, name4: String): String { - return context.getString(R.string.room_displayname_4_members, name1, name2, name3, name4) + return context.getString(CommonStrings.room_displayname_4_members, name1, name2, name3, name4) } override fun getNameFor4membersAndMore(name1: String, name2: String, name3: String, remainingCount: Int): String { return context.resources.getQuantityString( - R.plurals.room_displayname_four_and_more_members, + CommonPlurals.room_displayname_four_and_more_members, remainingCount, name1, name2, diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomItem.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomItem.kt index e542277d4c..2f000bc9d4 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomItem.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomItem.kt @@ -16,6 +16,7 @@ package im.vector.app.features.roomdirectory +import android.annotation.SuppressLint import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView @@ -58,6 +59,7 @@ abstract class PublicRoomItem : VectorEpoxyModel(R.layout @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var joinListener: ClickListener? = null + @SuppressLint("SetTextI18n") override fun bind(holder: Holder) { super.bind(holder) holder.rootView.onClick(globalListener) @@ -67,7 +69,7 @@ abstract class PublicRoomItem : VectorEpoxyModel(R.layout holder.aliasView.setTextOrHide(roomAlias) holder.topicView.setTextOrHide(roomTopic) // TODO Use formatter for big numbers? - holder.counterView.text = nbOfMembers.toString() + holder.counterView.text = "$nbOfMembers" holder.buttonState.render( when (joinState) { diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsController.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsController.kt index 1d741cd4eb..76f1bfe724 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsController.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsController.kt @@ -21,13 +21,13 @@ import com.airbnb.epoxy.VisibilityState import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Incomplete import com.airbnb.mvrx.Success -import im.vector.app.R import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.MatrixPatterns import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoom @@ -54,7 +54,7 @@ class PublicRoomsController @Inject constructor( // No result noResultItem { id("noResult") - text(host.stringProvider.getString(R.string.no_result_placeholder)) + text(host.stringProvider.getString(CommonStrings.no_result_placeholder)) } } else { publicRooms.forEach { diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt index e541e7f879..023c29e510 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt @@ -39,6 +39,7 @@ import im.vector.app.features.analytics.plan.ViewRoom import im.vector.app.features.permalink.NavigationInterceptor import im.vector.app.features.permalink.PermalinkFactory import im.vector.app.features.permalink.PermalinkHandler +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -138,7 +139,7 @@ class PublicRoomsFragment : }) if (!isHandled) { - requireContext().toast(R.string.room_error_not_found) + requireContext().toast(CommonStrings.room_error_not_found) } } } diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomController.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomController.kt index 56d04aeaa1..4ab1df0dfd 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomController.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomController.kt @@ -19,7 +19,6 @@ package im.vector.app.features.roomdirectory.createroom import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading -import im.vector.app.R import im.vector.app.core.epoxy.dividerItem import im.vector.app.core.epoxy.profiles.buildProfileAction import im.vector.app.core.resources.StringProvider @@ -29,6 +28,7 @@ import im.vector.app.features.form.formEditTextItem import im.vector.app.features.form.formEditableAvatarItem import im.vector.app.features.form.formSubmitButtonItem import im.vector.app.features.form.formSwitchItem +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.MatrixConstants import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure @@ -60,13 +60,13 @@ class CreateRoomController @Inject constructor( } settingsSectionTitleItem { id("nameSection") - titleResId(R.string.create_room_name_section) + titleResId(CommonStrings.create_room_name_section) } formEditTextItem { id("name") enabled(enableFormElement) value(viewState.roomName) - hint(host.stringProvider.getString(R.string.create_room_name_hint)) + hint(host.stringProvider.getString(CommonStrings.create_room_name_hint)) autoCapitalize(true) onTextChange { text -> @@ -75,14 +75,14 @@ class CreateRoomController @Inject constructor( } settingsSectionTitleItem { id("topicSection") - titleResId(R.string.create_room_topic_section) + titleResId(CommonStrings.create_room_topic_section) } formEditTextItem { id("topic") enabled(enableFormElement) value(viewState.roomTopic) singleLine(false) - hint(host.stringProvider.getString(R.string.create_room_topic_hint)) + hint(host.stringProvider.getString(CommonStrings.create_room_topic_hint)) onTextChange { text -> host.listener?.onTopicChange(text) @@ -91,15 +91,15 @@ class CreateRoomController @Inject constructor( settingsSectionTitleItem { id("visibility") - titleResId(R.string.room_settings_room_access_title) + titleResId(CommonStrings.room_settings_room_access_title) } when (viewState.roomJoinRules) { RoomJoinRules.INVITE -> { buildProfileAction( id = "joinRule", - title = stringProvider.getString(R.string.room_settings_room_access_private_title), - subtitle = stringProvider.getString(R.string.room_settings_room_access_private_description), + title = stringProvider.getString(CommonStrings.room_settings_room_access_private_title), + subtitle = stringProvider.getString(CommonStrings.room_settings_room_access_private_description), divider = false, editable = true, action = { host.listener?.selectVisibility() } @@ -108,8 +108,8 @@ class CreateRoomController @Inject constructor( RoomJoinRules.PUBLIC -> { buildProfileAction( id = "joinRule", - title = stringProvider.getString(R.string.room_settings_room_access_public_title), - subtitle = stringProvider.getString(R.string.room_settings_room_access_public_description), + title = stringProvider.getString(CommonStrings.room_settings_room_access_public_title), + subtitle = stringProvider.getString(CommonStrings.room_settings_room_access_public_description), divider = false, editable = true, action = { host.listener?.selectVisibility() } @@ -118,8 +118,8 @@ class CreateRoomController @Inject constructor( RoomJoinRules.RESTRICTED -> { buildProfileAction( id = "joinRule", - title = stringProvider.getString(R.string.room_settings_room_access_restricted_title), - subtitle = stringProvider.getString(R.string.room_create_member_of_space_name_can_join, viewState.parentSpaceSummary?.displayName), + title = stringProvider.getString(CommonStrings.room_settings_room_access_restricted_title), + subtitle = stringProvider.getString(CommonStrings.room_create_member_of_space_name_can_join, viewState.parentSpaceSummary?.displayName), divider = false, editable = true, action = { host.listener?.selectVisibility() } @@ -132,7 +132,7 @@ class CreateRoomController @Inject constructor( settingsSectionTitleItem { id("settingsSection") - titleResId(R.string.create_room_settings_section) + titleResId(CommonStrings.create_room_settings_section) } if (viewState.roomJoinRules == RoomJoinRules.PUBLIC) { @@ -144,7 +144,7 @@ class CreateRoomController @Inject constructor( suffixText(":" + viewState.homeServerName) prefixText("#") maxLength(MatrixConstants.maxAliasLocalPartLength(viewState.homeServerName)) - hint(host.stringProvider.getString(R.string.room_alias_address_hint)) + hint(host.stringProvider.getString(CommonStrings.room_alias_address_hint)) errorMessage( host.roomAliasErrorFormatter.format( (((viewState.asyncCreateRoomRequest as? Fail)?.error) as? CreateRoomFailure.AliasError)?.aliasError @@ -162,12 +162,12 @@ class CreateRoomController @Inject constructor( formSwitchItem { id("encryption") enabled(enableFormElement) - title(host.stringProvider.getString(R.string.create_room_encryption_title)) + title(host.stringProvider.getString(CommonStrings.create_room_encryption_title)) summary( if (viewState.hsAdminHasDisabledE2E) { - host.stringProvider.getString(R.string.settings_hs_admin_e2e_disabled) + host.stringProvider.getString(CommonStrings.settings_hs_admin_e2e_disabled) } else { - host.stringProvider.getString(R.string.create_room_encryption_description) + host.stringProvider.getString(CommonStrings.create_room_encryption_description) } ) @@ -184,7 +184,7 @@ class CreateRoomController @Inject constructor( // } formAdvancedToggleItem { id("showAdvanced") - title(host.stringProvider.getString(if (viewState.showAdvanced) R.string.hide_advanced else R.string.show_advanced)) + title(host.stringProvider.getString(if (viewState.showAdvanced) CommonStrings.hide_advanced else CommonStrings.show_advanced)) expanded(!viewState.showAdvanced) listener { host.listener?.toggleShowAdvanced() } } @@ -192,8 +192,8 @@ class CreateRoomController @Inject constructor( formSwitchItem { id("federation") enabled(enableFormElement) - title(host.stringProvider.getString(R.string.create_room_disable_federation_title, viewState.homeServerName)) - summary(host.stringProvider.getString(R.string.create_room_disable_federation_description)) + title(host.stringProvider.getString(CommonStrings.create_room_disable_federation_title, viewState.homeServerName)) + summary(host.stringProvider.getString(CommonStrings.create_room_disable_federation_description)) switchChecked(viewState.disableFederation) listener { value -> host.listener?.setDisableFederation(value) } } @@ -201,7 +201,7 @@ class CreateRoomController @Inject constructor( formSubmitButtonItem { id("submit") enabled(enableFormElement) - buttonTitleId(R.string.create_room_action_create) + buttonTitleId(CommonStrings.create_room_action_create) buttonClickListener { host.listener?.submit() } } } diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomFragment.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomFragment.kt index 59657aae35..d5da7e844d 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomFragment.kt @@ -31,7 +31,6 @@ import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.dialogs.GalleryOrCameraDialogHelper import im.vector.app.core.dialogs.GalleryOrCameraDialogHelperFactory import im.vector.app.core.extensions.cleanup @@ -46,6 +45,7 @@ import im.vector.app.features.roomdirectory.RoomDirectorySharedActionViewModel import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleBottomSheet import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleSharedActionViewModel import im.vector.app.features.roomprofile.settings.joinrule.toOption +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.parcelize.Parcelize @@ -96,7 +96,7 @@ class CreateRoomFragment : setupWaitingView() setupRecyclerView() setupToolbar(views.createRoomToolbar) - .setTitle(if (args.isSpace) R.string.create_new_space else R.string.create_new_room) + .setTitle(if (args.isSpace) CommonStrings.create_new_space else CommonStrings.create_new_room) .allowBack(useCross = true) viewModel.observeViewEvents { when (it) { @@ -129,7 +129,7 @@ class CreateRoomFragment : private fun setupWaitingView() { views.waitingView.waitingStatusText.isVisible = true views.waitingView.waitingStatusText.setText( - if (args.isSpace) R.string.create_space_in_progress else R.string.create_room_in_progress + if (args.isSpace) CommonStrings.create_space_in_progress else CommonStrings.create_room_in_progress ) } @@ -214,12 +214,12 @@ class CreateRoomFragment : return withState(viewModel) { return@withState if (!it.isEmpty()) { MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.dialog_title_warning) - .setMessage(R.string.warning_room_not_created_yet) - .setPositiveButton(R.string.yes) { _, _ -> + .setTitle(CommonStrings.dialog_title_warning) + .setMessage(CommonStrings.warning_room_not_created_yet) + .setPositiveButton(CommonStrings.yes) { _, _ -> viewModel.handle(CreateRoomAction.Reset) } - .setNegativeButton(R.string.no, null) + .setNegativeButton(CommonStrings.no, null) .show() true } else { diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateSubSpaceController.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateSubSpaceController.kt index 07f35956d7..944baa23f0 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateSubSpaceController.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateSubSpaceController.kt @@ -29,6 +29,7 @@ import im.vector.app.features.form.formEditableSquareAvatarItem import im.vector.app.features.form.formMultiLineEditTextItem import im.vector.app.features.form.formSubmitButtonItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.MatrixConstants import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure import org.matrix.android.sdk.api.session.room.model.RoomJoinRules @@ -53,7 +54,7 @@ class CreateSubSpaceController @Inject constructor( id("beta") imageRes(R.drawable.ic_beta_pill) tintIcon(false) - text(host.stringProvider.getString(R.string.space_add_space_to_any_space_you_manage).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.space_add_space_to_any_space_you_manage).toEpoxyCharSequence()) } formEditableSquareAvatarItem { @@ -69,7 +70,7 @@ class CreateSubSpaceController @Inject constructor( enabled(enableFormElement) enabled(true) value(data.roomName) - hint(host.stringProvider.getString(R.string.create_room_name_hint)) + hint(host.stringProvider.getString(CommonStrings.create_room_name_hint)) onTextChange { text -> host.listener?.onNameChange(text) } @@ -80,7 +81,7 @@ class CreateSubSpaceController @Inject constructor( id("alias") enabled(enableFormElement) value(data.aliasLocalPart) - hint(host.stringProvider.getString(R.string.create_space_alias_hint)) + hint(host.stringProvider.getString(CommonStrings.create_space_alias_hint)) suffixText(":" + data.homeServerName) prefixText("#") maxLength(MatrixConstants.maxAliasLocalPartLength(data.homeServerName)) @@ -99,7 +100,7 @@ class CreateSubSpaceController @Inject constructor( id("topic") enabled(enableFormElement) value(data.roomTopic) - hint(host.stringProvider.getString(R.string.create_space_topic_hint)) + hint(host.stringProvider.getString(CommonStrings.create_space_topic_hint)) textSizeSp(16) onTextChange { text -> host.listener?.onTopicChange(text) @@ -108,15 +109,15 @@ class CreateSubSpaceController @Inject constructor( settingsSectionTitleItem { id("visibility") - titleResId(R.string.room_settings_space_access_title) + titleResId(CommonStrings.room_settings_space_access_title) } when (data.roomJoinRules) { RoomJoinRules.INVITE -> { buildProfileAction( id = "joinRule", - title = stringProvider.getString(R.string.room_settings_room_access_private_title), - subtitle = stringProvider.getString(R.string.room_settings_room_access_private_description), + title = stringProvider.getString(CommonStrings.room_settings_room_access_private_title), + subtitle = stringProvider.getString(CommonStrings.room_settings_room_access_private_description), divider = false, editable = true, action = { host.listener?.selectVisibility() } @@ -125,8 +126,8 @@ class CreateSubSpaceController @Inject constructor( RoomJoinRules.PUBLIC -> { buildProfileAction( id = "joinRule", - title = stringProvider.getString(R.string.room_settings_room_access_public_title), - subtitle = stringProvider.getString(R.string.room_settings_room_access_public_description), + title = stringProvider.getString(CommonStrings.room_settings_room_access_public_title), + subtitle = stringProvider.getString(CommonStrings.room_settings_room_access_public_description), divider = false, editable = true, action = { host.listener?.selectVisibility() } @@ -135,8 +136,8 @@ class CreateSubSpaceController @Inject constructor( RoomJoinRules.RESTRICTED -> { buildProfileAction( id = "joinRule", - title = stringProvider.getString(R.string.room_settings_room_access_restricted_title), - subtitle = stringProvider.getString(R.string.room_create_member_of_space_name_can_join, data.parentSpaceSummary?.displayName), + title = stringProvider.getString(CommonStrings.room_settings_room_access_restricted_title), + subtitle = stringProvider.getString(CommonStrings.room_create_member_of_space_name_can_join, data.parentSpaceSummary?.displayName), divider = false, editable = true, action = { host.listener?.selectVisibility() } @@ -150,7 +151,7 @@ class CreateSubSpaceController @Inject constructor( formSubmitButtonItem { id("submit") enabled(enableFormElement && data.roomName.isNullOrBlank().not()) - buttonTitleId(R.string.create_room_action_create) + buttonTitleId(CommonStrings.create_room_action_create) buttonClickListener { host.listener?.submit() } } } diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/RoomAliasErrorFormatter.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/RoomAliasErrorFormatter.kt index d339cfcd4f..afbb4380eb 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/RoomAliasErrorFormatter.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/RoomAliasErrorFormatter.kt @@ -16,8 +16,8 @@ package im.vector.app.features.roomdirectory.createroom -import im.vector.app.R import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.alias.RoomAliasError import javax.inject.Inject @@ -26,9 +26,9 @@ class RoomAliasErrorFormatter @Inject constructor( ) { fun format(roomAliasError: RoomAliasError?): String? { return when (roomAliasError) { - is RoomAliasError.AliasIsBlank -> R.string.create_room_alias_empty - is RoomAliasError.AliasNotAvailable -> R.string.create_room_alias_already_in_use - is RoomAliasError.AliasInvalid -> R.string.create_room_alias_invalid + is RoomAliasError.AliasIsBlank -> CommonStrings.create_room_alias_empty + is RoomAliasError.AliasNotAvailable -> CommonStrings.create_room_alias_already_in_use + is RoomAliasError.AliasInvalid -> CommonStrings.create_room_alias_invalid else -> null } ?.let { stringProvider.getString(it) } diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryListCreator.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryListCreator.kt index 0e8c3efa97..5337f0be8b 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryListCreator.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryListCreator.kt @@ -85,7 +85,7 @@ class RoomDirectoryListCreator @Inject constructor( ) // Add custom directory servers, form the config file, excluding the current user homeserver - stringArrayProvider.getStringArray(R.array.room_directory_servers) + stringArrayProvider.getStringArray(im.vector.app.config.R.array.room_directory_servers) .filter { it != userHsName } .forEach { // Use the server name as a default display name diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerController.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerController.kt index 7dd87a442f..6efa5976b1 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerController.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerController.kt @@ -41,6 +41,7 @@ import im.vector.app.features.discovery.settingsInformationItem import im.vector.app.features.form.formEditTextItem import im.vector.app.features.roomdirectory.RoomDirectoryData import im.vector.app.features.roomdirectory.RoomDirectoryServer +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.failure.Failure import javax.inject.Inject import javax.net.ssl.HttpsURLConnection @@ -96,8 +97,8 @@ class RoomDirectoryPickerController @Inject constructor( } settingsInformationItem { id("form_notice") - message(host.stringProvider.getString(R.string.directory_add_a_new_server_prompt)) - textColor(host.colorProvider.getColor(R.color.vector_info_color)) + message(host.stringProvider.getString(CommonStrings.directory_add_a_new_server_prompt)) + textColor(host.colorProvider.getColor(im.vector.lib.ui.styles.R.color.vector_info_color)) } verticalMarginItem { id("form_space_2") @@ -118,7 +119,7 @@ class RoomDirectoryPickerController @Inject constructor( return false } }) - hint(host.stringProvider.getString(R.string.directory_server_placeholder)) + hint(host.stringProvider.getString(CommonStrings.directory_server_placeholder)) inputType(InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_URI) onTextChange { text -> host.callback?.onEnterServerChange(text) @@ -137,7 +138,7 @@ class RoomDirectoryPickerController @Inject constructor( Uninitialized, is Fail -> settingsContinueCancelItem { id("continueCancel") - continueText(host.stringProvider.getString(R.string.ok)) + continueText(host.stringProvider.getString(CommonStrings.ok)) canContinue(data.enteredServer.isNotEmpty()) continueOnClick { host.callback?.onSubmitServer() } cancelOnClick { host.callback?.onCancelEnterServer() } @@ -150,8 +151,8 @@ class RoomDirectoryPickerController @Inject constructor( } else { genericButtonItem { id("add") - text(host.stringProvider.getString(R.string.directory_add_a_new_server)) - textColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + text(host.stringProvider.getString(CommonStrings.directory_add_a_new_server)) + textColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) buttonClickAction { host.callback?.onStartEnterServer() } @@ -162,7 +163,7 @@ class RoomDirectoryPickerController @Inject constructor( private fun getErrorMessage(error: Throwable): String { return if (error is Failure.ServerError && error.httpCode == HttpsURLConnection.HTTP_INTERNAL_ERROR /* 500 */) { - stringProvider.getString(R.string.directory_add_a_new_server_error) + stringProvider.getString(CommonStrings.directory_add_a_new_server_error) } else { errorFormatter.toHumanReadable(error) } @@ -183,7 +184,7 @@ class RoomDirectoryPickerController @Inject constructor( removeListener { host.callback?.onRemoveServer(roomDirectoryServer) } if (roomDirectoryServer.isUserServer) { - serverDescription(host.stringProvider.getString(R.string.directory_your_server)) + serverDescription(host.stringProvider.getString(CommonStrings.directory_your_server)) } } @@ -192,14 +193,14 @@ class RoomDirectoryPickerController @Inject constructor( id("server_${roomDirectoryServer}_proto_$roomDirectoryData") directoryName( if (roomDirectoryData.includeAllNetworks) { - host.stringProvider.getString(R.string.directory_server_all_rooms_on_server, roomDirectoryServer.serverName) + host.stringProvider.getString(CommonStrings.directory_server_all_rooms_on_server, roomDirectoryServer.serverName) } else { roomDirectoryData.displayName } ) if (roomDirectoryData.displayName == RoomDirectoryData.MATRIX_PROTOCOL_NAME && !roomDirectoryData.includeAllNetworks) { directoryDescription( - host.stringProvider.getString(R.string.directory_server_native_rooms, roomDirectoryServer.serverName) + host.stringProvider.getString(CommonStrings.directory_server_native_rooms, roomDirectoryServer.serverName) ) } directoryAvatarUrl(roomDirectoryData.avatarUrl) diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt index 32be4e076f..e1c6e102b2 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt @@ -24,7 +24,6 @@ import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.OnBackPressed @@ -37,6 +36,7 @@ import im.vector.app.features.roomdirectory.RoomDirectoryServer import im.vector.app.features.roomdirectory.RoomDirectorySharedAction import im.vector.app.features.roomdirectory.RoomDirectorySharedActionViewModel import im.vector.app.features.roomdirectory.RoomDirectoryViewModel +import im.vector.lib.strings.CommonStrings import timber.log.Timber import javax.inject.Inject @@ -65,7 +65,7 @@ class RoomDirectoryPickerFragment : super.onViewCreated(view, savedInstanceState) setupToolbar(views.toolbar) - .setTitle(R.string.select_room_directory) + .setTitle(CommonStrings.select_room_directory) .allowBack() sharedActionViewModel = activityViewModelProvider.get(RoomDirectorySharedActionViewModel::class.java) diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt index 8c5aca00fe..c20e03d92b 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt @@ -24,13 +24,13 @@ import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R 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.core.resources.StringProvider import im.vector.app.features.ui.UiStateRepository +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams @@ -142,7 +142,7 @@ class RoomDirectoryPickerViewModel @AssistedInject constructor( if (enteredServer in existingServerList) { setState { - copy(addServerAsync = Fail(Throwable(stringProvider.getString(R.string.directory_add_a_new_server_error_already_added)))) + copy(addServerAsync = Fail(Throwable(stringProvider.getString(CommonStrings.directory_add_a_new_server_error_already_added)))) } return@withState } diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt index 7c639dde99..7ea5ba74db 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt @@ -45,6 +45,7 @@ import im.vector.app.features.navigation.Navigator import im.vector.app.features.roomdirectory.JoinState import im.vector.app.features.settings.VectorSettingsActivity import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span import org.matrix.android.sdk.api.session.room.model.RoomType import org.matrix.android.sdk.api.util.MatrixItem @@ -131,11 +132,11 @@ class RoomPreviewNoPreviewFragment : views.roomPreviewNoPreviewLabel.text = span { span { - textColor = ThemeUtils.getColor(requireContext(), R.attr.vctr_content_primary) + textColor = ThemeUtils.getColor(requireContext(), im.vector.lib.ui.styles.R.attr.vctr_content_primary) text = if (state.roomType == RoomType.SPACE) { - getString(R.string.this_invite_to_this_space_was_sent, state.fromEmailInvite.email) + getString(CommonStrings.this_invite_to_this_space_was_sent, state.fromEmailInvite.email) } else { - getString(R.string.this_invite_to_this_room_was_sent, state.fromEmailInvite.email) + getString(CommonStrings.this_invite_to_this_room_was_sent, state.fromEmailInvite.email) } .toSpannable() .styleMatchingText(state.fromEmailInvite.email, Typeface.BOLD) @@ -143,11 +144,11 @@ class RoomPreviewNoPreviewFragment : +"\n" span { text = getString( - R.string.link_this_email_with_your_account, - getString(R.string.link_this_email_settings_link) + CommonStrings.link_this_email_with_your_account, + getString(CommonStrings.link_this_email_settings_link) ) .toSpannable() - .tappableMatchingText(getString(R.string.link_this_email_settings_link), object : ClickableSpan() { + .tappableMatchingText(getString(CommonStrings.link_this_email_settings_link), object : ClickableSpan() { override fun onClick(widget: View) { navigator.openSettings( requireContext(), @@ -166,13 +167,13 @@ class RoomPreviewNoPreviewFragment : PeekingState.NO_ACCESS -> { views.roomPreviewNoPreviewJoin.isVisible = true views.roomPreviewNoPreviewLabel.isVisible = true - views.roomPreviewNoPreviewLabel.setText(R.string.room_preview_no_preview_join) + views.roomPreviewNoPreviewLabel.setText(CommonStrings.room_preview_no_preview_join) renderState(bestName, state.matrixItem().takeIf { state.roomAlias != null }, state.roomTopic) } else -> { views.roomPreviewNoPreviewJoin.isVisible = false views.roomPreviewNoPreviewLabel.isVisible = true - views.roomPreviewNoPreviewLabel.setText(R.string.room_preview_not_found) + views.roomPreviewNoPreviewLabel.setText(CommonStrings.room_preview_not_found) renderState(bestName, null, state.roomTopic) } } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileController.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileController.kt index e74bad1acb..02ef43a332 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileController.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileController.kt @@ -24,6 +24,7 @@ import im.vector.app.core.epoxy.profiles.buildProfileSection import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper @@ -68,7 +69,7 @@ class RoomMemberProfileController @Inject constructor( private fun buildUserActions(state: RoomMemberProfileViewState) { val ignoreActionTitle = state.buildIgnoreActionTitle() ?: return // More - buildProfileSection(stringProvider.getString(R.string.room_profile_section_more)) + buildProfileSection(stringProvider.getString(CommonStrings.room_profile_section_more)) buildProfileAction( id = "ignore", title = ignoreActionTitle, @@ -81,7 +82,7 @@ class RoomMemberProfileController @Inject constructor( buildProfileAction( id = "direct", editable = false, - title = stringProvider.getString(R.string.room_member_open_or_create_dm), + title = stringProvider.getString(CommonStrings.room_member_open_or_create_dm), action = { callback?.onOpenDmClicked() } ) } @@ -104,14 +105,14 @@ class RoomMemberProfileController @Inject constructor( // TODO find sensible message to display here // For now we just remove the verify actions as well as the Security status } else if (state.userMXCrossSigningInfo != null) { - buildProfileSection(stringProvider.getString(R.string.room_profile_section_security)) + buildProfileSection(stringProvider.getString(CommonStrings.room_profile_section_security)) // Cross signing is enabled for this user if (state.userMXCrossSigningInfo.isTrusted()) { // User is trusted val (icon, titleRes) = if (state.allDevicesAreCrossSignedTrusted) { - Pair(R.drawable.ic_shield_trusted, R.string.verification_profile_verified) + Pair(R.drawable.ic_shield_trusted, CommonStrings.verification_profile_verified) } else { - Pair(R.drawable.ic_shield_warning, R.string.verification_profile_warning) + Pair(R.drawable.ic_shield_warning, CommonStrings.verification_profile_warning) } buildProfileAction( @@ -128,7 +129,7 @@ class RoomMemberProfileController @Inject constructor( if (!state.isMine) { buildProfileAction( id = "learn_more", - title = stringProvider.getString(R.string.verification_profile_verify), + title = stringProvider.getString(CommonStrings.verification_profile_verify), editable = true, icon = R.drawable.ic_shield_black, divider = false, @@ -137,7 +138,7 @@ class RoomMemberProfileController @Inject constructor( } else { buildProfileAction( id = "learn_more", - title = stringProvider.getString(R.string.room_profile_section_security_learn_more), + title = stringProvider.getString(CommonStrings.room_profile_section_security_learn_more), editable = false, divider = false, action = { callback?.onShowDeviceListNoCrossSigning() } @@ -146,28 +147,28 @@ class RoomMemberProfileController @Inject constructor( genericFooterItem { id("verify_footer") - text(host.stringProvider.getString(R.string.room_profile_encrypted_subtitle).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.room_profile_encrypted_subtitle).toEpoxyCharSequence()) centered(false) } } } else { - buildProfileSection(stringProvider.getString(R.string.room_profile_section_security)) + buildProfileSection(stringProvider.getString(CommonStrings.room_profile_section_security)) buildProfileAction( id = "learn_more", - title = stringProvider.getString(R.string.room_profile_section_security_learn_more), + title = stringProvider.getString(CommonStrings.room_profile_section_security_learn_more), editable = false, divider = false, - subtitle = stringProvider.getString(R.string.room_profile_encrypted_subtitle), + subtitle = stringProvider.getString(CommonStrings.room_profile_encrypted_subtitle), action = { callback?.onShowDeviceListNoCrossSigning() } ) } } else { - buildProfileSection(stringProvider.getString(R.string.room_profile_section_security)) + buildProfileSection(stringProvider.getString(CommonStrings.room_profile_section_security)) genericFooterItem { id("verify_footer_not_encrypted") - text(host.stringProvider.getString(R.string.room_profile_not_encrypted_subtitle).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.room_profile_not_encrypted_subtitle).toEpoxyCharSequence()) centered(false) } } @@ -175,13 +176,13 @@ class RoomMemberProfileController @Inject constructor( private fun buildMoreSection(state: RoomMemberProfileViewState) { // More - buildProfileSection(stringProvider.getString(R.string.room_profile_section_more)) + buildProfileSection(stringProvider.getString(CommonStrings.room_profile_section_more)) if (!state.isMine) { buildProfileAction( id = "direct", editable = false, - title = stringProvider.getString(R.string.room_member_open_or_create_dm), + title = stringProvider.getString(CommonStrings.room_member_open_or_create_dm), action = { callback?.onOpenDmClicked() } ) } @@ -189,7 +190,7 @@ class RoomMemberProfileController @Inject constructor( buildProfileAction( id = "overrideColor", editable = false, - title = stringProvider.getString(R.string.room_member_override_nick_color), + title = stringProvider.getString(CommonStrings.room_member_override_nick_color), subtitle = state.userColorOverride, divider = !state.isMine, action = { callback?.onOverrideColorClicked() } @@ -202,7 +203,7 @@ class RoomMemberProfileController @Inject constructor( buildProfileAction( id = "read_receipt", editable = false, - title = stringProvider.getString(R.string.room_member_jump_to_read_receipt), + title = stringProvider.getString(CommonStrings.room_member_jump_to_read_receipt), action = { callback?.onJumpToReadReceiptClicked() } ) } @@ -211,7 +212,7 @@ class RoomMemberProfileController @Inject constructor( if (!state.isSpace) { buildProfileAction( id = "mention", - title = stringProvider.getString(R.string.room_participants_action_mention), + title = stringProvider.getString(CommonStrings.room_participants_action_mention), editable = false, divider = ignoreActionTitle != null, action = { callback?.onMentionClicked() } @@ -223,7 +224,7 @@ class RoomMemberProfileController @Inject constructor( if (canInvite && (membership == Membership.LEAVE || membership == Membership.KNOCK)) { buildProfileAction( id = "invite", - title = stringProvider.getString(R.string.room_participants_action_invite), + title = stringProvider.getString(CommonStrings.room_participants_action_invite), destructive = false, editable = false, divider = true, @@ -242,7 +243,7 @@ class RoomMemberProfileController @Inject constructor( } buildProfileAction( id = "report", - title = stringProvider.getString(R.string.message_report_user), + title = stringProvider.getString(CommonStrings.message_report_user), destructive = true, editable = false, divider = false, @@ -265,13 +266,13 @@ class RoomMemberProfileController @Inject constructor( val canBan = !state.isMine && state.actionPermissions.canBan val canEditPowerLevel = state.actionPermissions.canEditPowerLevel if (canKick || canBan || canEditPowerLevel) { - buildProfileSection(stringProvider.getString(R.string.room_profile_section_admin)) + buildProfileSection(stringProvider.getString(CommonStrings.room_profile_section_admin)) } if (canEditPowerLevel) { buildProfileAction( id = "edit_power_level", editable = true, - title = stringProvider.getString(R.string.power_level_title), + title = stringProvider.getString(CommonStrings.power_level_title), subtitle = powerLevelsStr, divider = canKick || canBan, editableRes = R.drawable.ic_edit, @@ -287,14 +288,14 @@ class RoomMemberProfileController @Inject constructor( editable = false, divider = canBan, destructive = true, - title = stringProvider.getString(R.string.room_participants_action_remove), + title = stringProvider.getString(CommonStrings.room_participants_action_remove), action = { callback?.onKickClicked(state.isSpace) } ) } Membership.INVITE -> { buildProfileAction( id = "cancel_invite", - title = stringProvider.getString(R.string.room_participants_action_cancel_invite), + title = stringProvider.getString(CommonStrings.room_participants_action_cancel_invite), divider = canBan, destructive = true, editable = false, @@ -306,9 +307,9 @@ class RoomMemberProfileController @Inject constructor( } if (canBan) { val banActionTitle = if (membership == Membership.BAN) { - stringProvider.getString(R.string.room_participants_action_unban) + stringProvider.getString(CommonStrings.room_participants_action_unban) } else { - stringProvider.getString(R.string.room_participants_action_ban) + stringProvider.getString(CommonStrings.room_participants_action_ban) } buildProfileAction( id = "ban", @@ -323,9 +324,9 @@ class RoomMemberProfileController @Inject constructor( private fun RoomMemberProfileViewState.buildIgnoreActionTitle(): String? { val isIgnored = isIgnored() ?: return null return if (isIgnored) { - stringProvider.getString(R.string.room_participants_action_unignore_title) + stringProvider.getString(CommonStrings.room_participants_action_unignore_title) } else { - stringProvider.getString(R.string.room_participants_action_ignore_title) + stringProvider.getString(CommonStrings.room_participants_action_ignore_title) } } } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt index 7ac5bfea0c..4f451eb3fb 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt @@ -58,6 +58,7 @@ import im.vector.app.features.home.room.detail.RoomDetailPendingActionStore import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheet import im.vector.app.features.roommemberprofile.powerlevel.EditPowerLevelDialogs +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.session.crypto.model.UserVerificationLevel import org.matrix.android.sdk.api.session.room.powerlevels.Role @@ -148,9 +149,9 @@ class RoomMemberProfileFragment : private fun handleReportSuccess() { MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.user_reported_as_inappropriate_title) - .setMessage(R.string.user_reported_as_inappropriate_content) - .setPositiveButton(R.string.ok, null) + .setTitle(CommonStrings.user_reported_as_inappropriate_title) + .setMessage(CommonStrings.user_reported_as_inappropriate_content) + .setPositiveButton(CommonStrings.ok, null) .show() } @@ -192,14 +193,14 @@ class RoomMemberProfileFragment : .show(parentFragmentManager, "VERIF") } else { MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.dialog_title_warning) - .setMessage(R.string.verify_cannot_cross_sign) - .setPositiveButton(R.string.verification_profile_verify) { _, _ -> + .setTitle(CommonStrings.dialog_title_warning) + .setMessage(CommonStrings.verify_cannot_cross_sign) + .setPositiveButton(CommonStrings.verification_profile_verify) { _, _ -> UserVerificationBottomSheet .verifyUser(otherUserId = startVerification.userId) .show(parentFragmentManager, "VERIF") } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } } @@ -289,13 +290,13 @@ class RoomMemberProfileFragment : val positiveButtonRes: Int val confirmationRes: Int if (isIgnored) { - confirmationRes = R.string.room_participants_action_unignore_prompt_msg - titleRes = R.string.room_participants_action_unignore_title - positiveButtonRes = R.string.room_participants_action_unignore + confirmationRes = CommonStrings.room_participants_action_unignore_prompt_msg + titleRes = CommonStrings.room_participants_action_unignore_title + positiveButtonRes = CommonStrings.room_participants_action_unignore } else { - confirmationRes = R.string.room_participants_action_ignore_prompt_msg - titleRes = R.string.room_participants_action_ignore_title - positiveButtonRes = R.string.room_participants_action_ignore + confirmationRes = CommonStrings.room_participants_action_ignore_prompt_msg + titleRes = CommonStrings.room_participants_action_ignore_title + positiveButtonRes = CommonStrings.room_participants_action_ignore } ConfirmationDialogBuilder .show( @@ -351,8 +352,8 @@ class RoomMemberProfileFragment : views.itemShareQrCodeImage.setData(permalink) MaterialAlertDialogBuilder(requireContext()) .setView(view) - .setNeutralButton(R.string.ok, null) - .setPositiveButton(R.string.share_by_text) { _, _ -> + .setNeutralButton(CommonStrings.ok, null) + .setPositiveButton(CommonStrings.share_by_text) { _, _ -> startSharePlainTextIntent( context = requireContext(), activityResultLauncher = null, @@ -374,20 +375,20 @@ class RoomMemberProfileFragment : views.editText.hint = "#000000" MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.room_member_override_nick_color) + .setTitle(CommonStrings.room_member_override_nick_color) .setView(layout) - .setPositiveButton(R.string.ok) { _, _ -> + .setPositiveButton(CommonStrings.ok) { _, _ -> val newColor = views.editText.text.toString() if (newColor != state.userColorOverride) { viewModel.handle(RoomMemberProfileAction.SetUserColorOverride(newColor)) } } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } override fun onEditPowerLevel(currentRole: Role) { - EditPowerLevelDialogs.showChoice(requireActivity(), R.string.power_level_edit_title, currentRole) { newPowerLevel -> + EditPowerLevelDialogs.showChoice(requireActivity(), CommonStrings.power_level_edit_title, currentRole) { newPowerLevel -> viewModel.handle(RoomMemberProfileAction.SetPowerLevel(currentRole.value, newPowerLevel, true)) } } @@ -397,11 +398,11 @@ class RoomMemberProfileFragment : .show( activity = requireActivity(), askForReason = true, - confirmationRes = if (isSpace) R.string.space_participants_remove_prompt_msg - else R.string.room_participants_remove_prompt_msg, - positiveRes = R.string.room_participants_action_remove, - reasonHintRes = R.string.room_participants_remove_reason, - titleRes = R.string.room_participants_remove_title + confirmationRes = if (isSpace) CommonStrings.space_participants_remove_prompt_msg + else CommonStrings.room_participants_remove_prompt_msg, + positiveRes = CommonStrings.room_participants_action_remove, + reasonHintRes = CommonStrings.room_participants_remove_reason, + titleRes = CommonStrings.room_participants_remove_title ) { reason -> viewModel.handle(RoomMemberProfileAction.KickUser(reason)) } @@ -412,15 +413,15 @@ class RoomMemberProfileFragment : val positiveButtonRes: Int val confirmationRes: Int if (isUserBanned) { - confirmationRes = if (isSpace) R.string.space_participants_unban_prompt_msg - else R.string.room_participants_unban_prompt_msg - titleRes = R.string.room_participants_unban_title - positiveButtonRes = R.string.room_participants_action_unban + confirmationRes = if (isSpace) CommonStrings.space_participants_unban_prompt_msg + else CommonStrings.room_participants_unban_prompt_msg + titleRes = CommonStrings.room_participants_unban_title + positiveButtonRes = CommonStrings.room_participants_action_unban } else { - confirmationRes = if (isSpace) R.string.space_participants_ban_prompt_msg - else R.string.room_participants_ban_prompt_msg - titleRes = R.string.room_participants_ban_title - positiveButtonRes = R.string.room_participants_action_ban + confirmationRes = if (isSpace) CommonStrings.space_participants_ban_prompt_msg + else CommonStrings.room_participants_ban_prompt_msg + titleRes = CommonStrings.room_participants_ban_title + positiveButtonRes = CommonStrings.room_participants_action_ban } ConfirmationDialogBuilder .show( @@ -428,7 +429,7 @@ class RoomMemberProfileFragment : askForReason = !isUserBanned, confirmationRes = confirmationRes, positiveRes = positiveButtonRes, - reasonHintRes = R.string.room_participants_ban_reason, + reasonHintRes = CommonStrings.room_participants_ban_reason, titleRes = titleRes ) { reason -> viewModel.handle(RoomMemberProfileAction.BanOrUnbanUser(reason)) @@ -440,10 +441,10 @@ class RoomMemberProfileFragment : .show( activity = requireActivity(), askForReason = false, - confirmationRes = R.string.room_participants_action_cancel_invite_prompt_msg, - positiveRes = R.string.room_participants_action_cancel_invite, + confirmationRes = CommonStrings.room_participants_action_cancel_invite_prompt_msg, + positiveRes = CommonStrings.room_participants_action_cancel_invite, reasonHintRes = 0, - titleRes = R.string.room_participants_action_cancel_invite_title + titleRes = CommonStrings.room_participants_action_cancel_invite_title ) { viewModel.handle(RoomMemberProfileAction.KickUser(null)) } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt index 614cb159d9..96e4fcb036 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt @@ -25,7 +25,6 @@ import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.mvrx.runCatchingToAsync @@ -35,6 +34,7 @@ import im.vector.app.features.createdirect.DirectRoomHelper import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider import im.vector.app.features.powerlevel.PowerLevelsFlowFactory +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn @@ -402,10 +402,10 @@ class RoomMemberProfileViewModel @AssistedInject constructor( val roomName = roomSummary.toMatrixItem().getBestName() val powerLevelsHelper = PowerLevelsHelper(powerLevelsContent) when (val userPowerLevel = powerLevelsHelper.getUserRole(initialState.userId)) { - Role.Admin -> stringProvider.getString(R.string.room_member_power_level_admin_in, roomName) - Role.Moderator -> stringProvider.getString(R.string.room_member_power_level_moderator_in, roomName) - Role.Default -> stringProvider.getString(R.string.room_member_power_level_default_in, roomName) - is Role.Custom -> stringProvider.getString(R.string.room_member_power_level_custom_in, userPowerLevel.value, roomName) + Role.Admin -> stringProvider.getString(CommonStrings.room_member_power_level_admin_in, roomName) + Role.Moderator -> stringProvider.getString(CommonStrings.room_member_power_level_moderator_in, roomName) + Role.Default -> stringProvider.getString(CommonStrings.room_member_power_level_default_in, roomName) + is Role.Custom -> stringProvider.getString(CommonStrings.room_member_power_level_custom_in, userPowerLevel.value, roomName) } }.execute { copy(userPowerLevelString = it) diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt index 764268e6a5..ddf87d6db3 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt @@ -34,6 +34,7 @@ import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.devices.TrustUtils import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo @@ -63,7 +64,7 @@ class DeviceListEpoxyController @Inject constructor( is Loading -> { loadingItem { id("loading") - loadingText(host.stringProvider.getString(R.string.loading)) + loadingText(host.stringProvider.getString(CommonStrings.loading)) } } is Success -> { @@ -92,10 +93,10 @@ class DeviceListEpoxyController @Inject constructor( titleIconResourceId(if (allGreen) R.drawable.ic_shield_trusted else R.drawable.ic_shield_warning) title( host.stringProvider - .getString(if (allGreen) R.string.verification_profile_verified else R.string.verification_profile_warning) + .getString(if (allGreen) CommonStrings.verification_profile_verified else CommonStrings.verification_profile_warning) .toEpoxyCharSequence() ) - description(host.stringProvider.getString(R.string.verification_conclusion_ok_notice).toEpoxyCharSequence()) + description(host.stringProvider.getString(CommonStrings.verification_conclusion_ok_notice).toEpoxyCharSequence()) } if (vectorPreferences.developerMode()) { @@ -106,13 +107,13 @@ class DeviceListEpoxyController @Inject constructor( genericItem { id("sessions") style(ItemStyle.BIG_TEXT) - title(host.stringProvider.getString(R.string.room_member_profile_sessions_section_title).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.room_member_profile_sessions_section_title).toEpoxyCharSequence()) } if (deviceList.isEmpty()) { // Can this really happen? genericFooterItem { id("empty") - text(host.stringProvider.getString(R.string.search_no_results).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.search_no_results).toEpoxyCharSequence()) } } else { // Build list of device with status @@ -140,7 +141,7 @@ class DeviceListEpoxyController @Inject constructor( +"\n" span { text = "(${device.deviceId})" - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(14) } } @@ -152,12 +153,16 @@ class DeviceListEpoxyController @Inject constructor( } value( host.stringProvider.getString( - if (trustLevel == RoomEncryptionTrustLevel.Trusted) R.string.trusted else R.string.not_trusted + if (trustLevel == RoomEncryptionTrustLevel.Trusted) CommonStrings.trusted else CommonStrings.not_trusted ) ) valueColorInt( host.colorProvider.getColorFromAttribute( - if (trustLevel == RoomEncryptionTrustLevel.Trusted) R.attr.colorPrimary else R.attr.colorError + if (trustLevel == RoomEncryptionTrustLevel.Trusted) { + com.google.android.material.R.attr.colorPrimary + } else { + com.google.android.material.R.attr.colorError + } ) ) itemClickAction { @@ -170,7 +175,7 @@ class DeviceListEpoxyController @Inject constructor( is Fail -> { errorWithRetryItem { id("error") - text(host.stringProvider.getString(R.string.room_member_profile_failed_to_get_devices)) + text(host.stringProvider.getString(CommonStrings.room_member_profile_failed_to_get_devices)) listener { // TODO } @@ -190,7 +195,7 @@ class DeviceListEpoxyController @Inject constructor( +"Master Key:\n" span { text = it.unpaddedBase64PublicKey ?: "" - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(12) } }.toEpoxyCharSequence() @@ -206,7 +211,7 @@ class DeviceListEpoxyController @Inject constructor( +"User Key:\n" span { text = it.unpaddedBase64PublicKey ?: "" - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(12) } }.toEpoxyCharSequence() @@ -222,7 +227,7 @@ class DeviceListEpoxyController @Inject constructor( +"Self Signed Key:\n" span { text = it.unpaddedBase64PublicKey ?: "" - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(12) } }.toEpoxyCharSequence() diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt index 0f39fc889c..6f85596ed2 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt @@ -27,6 +27,7 @@ import im.vector.app.core.ui.list.genericWithValueItem import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.settings.devices.TrustUtils import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel @@ -68,20 +69,20 @@ class DeviceTrustInfoEpoxyController @Inject constructor( titleIconResourceId(shield) title( host.stringProvider - .getString(if (isVerified) R.string.verification_profile_verified else R.string.verification_profile_warning) + .getString(if (isVerified) CommonStrings.verification_profile_verified else CommonStrings.verification_profile_warning) .toEpoxyCharSequence() ) } genericFooterItem { id("desc") centered(false) - textColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + textColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) apply { if (isVerified) { // TODO FORMAT text( host.stringProvider.getString( - R.string.verification_profile_device_verified_because, + CommonStrings.verification_profile_device_verified_because, data.userItem?.displayName ?: "", data.userItem?.id ?: "" ).toEpoxyCharSequence() @@ -90,14 +91,14 @@ class DeviceTrustInfoEpoxyController @Inject constructor( // TODO what if mine text( host.stringProvider.getString( - R.string.verification_profile_device_new_signing, + CommonStrings.verification_profile_device_new_signing, data.userItem?.displayName ?: "", data.userItem?.id ?: "" ).toEpoxyCharSequence() ) } } -// text(stringProvider.getString(R.string.verification_profile_device_untrust_info)) +// text(stringProvider.getString(CommonStrings.verification_profile_device_untrust_info)) } genericWithValueItem { @@ -108,7 +109,7 @@ class DeviceTrustInfoEpoxyController @Inject constructor( +(cryptoDeviceInfo.displayName() ?: "") span { text = " (${cryptoDeviceInfo.deviceId})" - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(14) } }.toEpoxyCharSequence() @@ -119,8 +120,8 @@ class DeviceTrustInfoEpoxyController @Inject constructor( genericFooterItem { id("warn") centered(false) - textColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - text(host.stringProvider.getString(R.string.verification_profile_other_device_untrust_info).toEpoxyCharSequence()) + textColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) + text(host.stringProvider.getString(CommonStrings.verification_profile_other_device_untrust_info).toEpoxyCharSequence()) } } } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/powerlevel/EditPowerLevelDialogs.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/powerlevel/EditPowerLevelDialogs.kt index 8b56b9219a..512135157c 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/powerlevel/EditPowerLevelDialogs.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/powerlevel/EditPowerLevelDialogs.kt @@ -16,6 +16,7 @@ package im.vector.app.features.roommemberprofile.powerlevel +import android.annotation.SuppressLint import android.app.Activity import android.content.DialogInterface import android.view.KeyEvent @@ -25,10 +26,12 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.core.extensions.hideKeyboard import im.vector.app.databinding.DialogEditPowerLevelBinding +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.powerlevels.Role object EditPowerLevelDialogs { + @SuppressLint("SetTextI18n") fun showChoice( activity: Activity, @StringRes titleRes: Int, @@ -40,7 +43,7 @@ object EditPowerLevelDialogs { views.powerLevelRadioGroup.setOnCheckedChangeListener { _, checkedId -> views.powerLevelCustomEditLayout.isVisible = checkedId == R.id.powerLevelCustomRadio } - views.powerLevelCustomEdit.setText(currentRole.value.toString()) + views.powerLevelCustomEdit.setText("${currentRole.value}") when (currentRole) { Role.Admin -> views.powerLevelAdminRadio.isChecked = true @@ -52,7 +55,7 @@ object EditPowerLevelDialogs { MaterialAlertDialogBuilder(activity) .setTitle(titleRes) .setView(dialogLayout) - .setPositiveButton(R.string.edit) { _, _ -> + .setPositiveButton(CommonStrings.edit) { _, _ -> val newValue = when (views.powerLevelRadioGroup.checkedRadioButtonId) { R.id.powerLevelAdminRadio -> Role.Admin.value R.id.powerLevelModeratorRadio -> Role.Moderator.value @@ -63,7 +66,7 @@ object EditPowerLevelDialogs { } listener(newValue) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .setOnKeyListener(DialogInterface.OnKeyListener { dialog, keyCode, event -> if (event.action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { @@ -82,23 +85,23 @@ object EditPowerLevelDialogs { fun showValidation(activity: Activity, onValidate: () -> Unit) { // Ask to the user the confirmation to upgrade. MaterialAlertDialogBuilder(activity) - .setMessage(R.string.room_participants_power_level_prompt) - .setPositiveButton(R.string.yes) { _, _ -> + .setMessage(CommonStrings.room_participants_power_level_prompt) + .setPositiveButton(CommonStrings.yes) { _, _ -> onValidate() } - .setNegativeButton(R.string.no, null) + .setNegativeButton(CommonStrings.no, null) .show() } fun showDemoteWarning(activity: Activity, onValidate: () -> Unit) { // Ask to the user the confirmation to downgrade his own role. MaterialAlertDialogBuilder(activity) - .setTitle(R.string.room_participants_power_level_demote_warning_title) - .setMessage(R.string.room_participants_power_level_demote_warning_prompt) - .setPositiveButton(R.string.room_participants_power_level_demote) { _, _ -> + .setTitle(CommonStrings.room_participants_power_level_demote_warning_title) + .setMessage(CommonStrings.room_participants_power_level_demote_warning_prompt) + .setPositiveButton(CommonStrings.room_participants_power_level_demote) { _, _ -> onValidate() } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt index 1fbfaba2bb..3ff189458c 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt @@ -33,6 +33,8 @@ import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod import im.vector.app.features.settings.VectorPreferences import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.image import me.gujun.android.span.span import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel @@ -82,7 +84,7 @@ class RoomProfileController @Inject constructor( .topic .takeIf { it.isNotEmpty() } ?.let { - buildProfileSection(stringProvider.getString(R.string.room_settings_topic)) + buildProfileSection(stringProvider.getString(CommonStrings.room_settings_topic)) expandableTextItem { id("topic") content(it) @@ -101,7 +103,7 @@ class RoomProfileController @Inject constructor( } // Security - buildProfileSection(stringProvider.getString(R.string.room_profile_section_security)) + buildProfileSection(stringProvider.getString(CommonStrings.room_profile_section_security)) // Upgrade warning val roomVersion = data.roomCreateContent()?.roomVersion @@ -112,14 +114,14 @@ class RoomProfileController @Inject constructor( data.recommendedRoomVersion != null) { genericFooterItem { id("version_warning") - text(host.stringProvider.getString(R.string.room_using_unstable_room_version, roomVersion).toEpoxyCharSequence()) - textColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) + text(host.stringProvider.getString(CommonStrings.room_using_unstable_room_version, roomVersion).toEpoxyCharSequence()) + textColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError)) centered(false) } genericPositiveButtonItem { id("migrate_button") - text(host.stringProvider.getString(R.string.room_upgrade_to_recommended_version)) + text(host.stringProvider.getString(CommonStrings.room_upgrade_to_recommended_version)) buttonClickAction { host.callback?.doMigrateToVersion(data.recommendedRoomVersion) } } } @@ -128,25 +130,25 @@ class RoomProfileController @Inject constructor( val e2eInfoText = if (roomSummary.isEncrypted) { if (roomSummary.roomEncryptionAlgorithm is RoomEncryptionAlgorithm.SupportedAlgorithm) { stringProvider.getString( - if (roomSummary.isDirect) R.string.direct_room_profile_encrypted_subtitle - else R.string.room_profile_encrypted_subtitle + if (roomSummary.isDirect) CommonStrings.direct_room_profile_encrypted_subtitle + else CommonStrings.room_profile_encrypted_subtitle ) } else { encryptionMisconfigured = true buildString { - append(stringProvider.getString(R.string.encryption_has_been_misconfigured)) + append(stringProvider.getString(CommonStrings.encryption_has_been_misconfigured)) append(" ") apply { if (!data.canUpdateRoomState) { - append(stringProvider.getString(R.string.contact_admin_to_restore_encryption)) + append(stringProvider.getString(CommonStrings.contact_admin_to_restore_encryption)) } } } } } else { stringProvider.getString( - if (roomSummary.isDirect) R.string.direct_room_profile_not_encrypted_subtitle - else R.string.room_profile_not_encrypted_subtitle + if (roomSummary.isDirect) CommonStrings.direct_room_profile_not_encrypted_subtitle + else CommonStrings.room_profile_not_encrypted_subtitle ) } genericFooterItem { @@ -170,7 +172,7 @@ class RoomProfileController @Inject constructor( if (encryptionMisconfigured && data.canUpdateRoomState) { genericPositiveButtonItem { id("restore_encryption") - text(host.stringProvider.getString(R.string.room_profile_section_restore_security)) + text(host.stringProvider.getString(CommonStrings.room_profile_section_restore_security)) iconRes(R.drawable.ic_shield_black_no_border) buttonClickAction { host.callback?.restoreEncryptionState() @@ -187,11 +189,11 @@ class RoomProfileController @Inject constructor( centered(false) text( span { - +host.stringProvider.getString(R.string.room_settings_global_block_unverified_info_text) + +host.stringProvider.getString(CommonStrings.room_settings_global_block_unverified_info_text) apply { if (data.unverifiedDevicesInTheRoom.invoke() == true) { +"\n" - +host.stringProvider.getString(R.string.some_devices_will_not_be_able_to_decrypt) + +host.stringProvider.getString(CommonStrings.some_devices_will_not_be_able_to_decrypt) } } }.toEpoxyCharSequence() @@ -206,14 +208,14 @@ class RoomProfileController @Inject constructor( formSwitchItem { id("send_to_unverified") enabled(shouldBlockUnverified != null) - title(host.stringProvider.getString(R.string.encryption_never_send_to_unverified_devices_in_room)) + title(host.stringProvider.getString(CommonStrings.encryption_never_send_to_unverified_devices_in_room)) switchChecked(shouldBlockUnverified ?: false) apply { if (shouldBlockUnverified == true && data.unverifiedDevicesInTheRoom.invoke() == true) { summary( - host.stringProvider.getString(R.string.some_devices_will_not_be_able_to_decrypt) + host.stringProvider.getString(CommonStrings.some_devices_will_not_be_able_to_decrypt) ) } else { summary(null) @@ -227,14 +229,14 @@ class RoomProfileController @Inject constructor( } } // More - buildProfileSection(stringProvider.getString(R.string.room_profile_section_more)) + buildProfileSection(stringProvider.getString(CommonStrings.room_profile_section_more)) buildProfileAction( id = "settings", title = stringProvider.getString( if (roomSummary.isDirect) { - R.string.direct_room_profile_section_more_settings + CommonStrings.direct_room_profile_section_more_settings } else { - R.string.room_profile_section_more_settings + CommonStrings.room_profile_section_more_settings } ), icon = R.drawable.ic_room_profile_settings, @@ -242,7 +244,7 @@ class RoomProfileController @Inject constructor( ) buildProfileAction( id = "notifications", - title = stringProvider.getString(R.string.room_profile_section_more_notifications), + title = stringProvider.getString(CommonStrings.room_profile_section_more_notifications), icon = R.drawable.ic_room_profile_notification, action = { callback?.onNotificationsClicked() } ) @@ -250,7 +252,7 @@ class RoomProfileController @Inject constructor( val hasWarning = roomSummary.isEncrypted && roomSummary.roomEncryptionTrustLevel == RoomEncryptionTrustLevel.Warning buildProfileAction( id = "member_list", - title = stringProvider.getQuantityString(R.plurals.room_profile_section_more_member_list, numberOfMembers, numberOfMembers), + title = stringProvider.getQuantityString(CommonPlurals.room_profile_section_more_member_list, numberOfMembers, numberOfMembers), icon = R.drawable.ic_room_profile_member_list, accessory = R.drawable.ic_shield_warning.takeIf { hasWarning } ?: 0, action = { callback?.onMemberListClicked() } @@ -259,7 +261,7 @@ class RoomProfileController @Inject constructor( if (data.bannedMembership.invoke()?.isNotEmpty() == true) { buildProfileAction( id = "banned_list", - title = stringProvider.getString(R.string.room_settings_banned_users_title), + title = stringProvider.getString(CommonStrings.room_settings_banned_users_title), icon = R.drawable.ic_settings_root_labs, action = { callback?.onBannedMemberListClicked() } ) @@ -267,21 +269,21 @@ class RoomProfileController @Inject constructor( buildProfileAction( id = "poll_history", - title = stringProvider.getString(R.string.room_profile_section_more_polls), + title = stringProvider.getString(CommonStrings.room_profile_section_more_polls), icon = R.drawable.ic_attachment_poll, action = { callback?.onPollHistoryClicked() } ) buildProfileAction( id = "uploads", - title = stringProvider.getString(R.string.room_profile_section_more_uploads), + title = stringProvider.getString(CommonStrings.room_profile_section_more_uploads), icon = R.drawable.ic_room_profile_uploads, action = { callback?.onUploadsClicked() } ) if (shortcutCreator.canCreateShortcut()) { buildProfileAction( id = "shortcut", - title = stringProvider.getString(R.string.room_settings_add_homescreen_shortcut), + title = stringProvider.getString(CommonStrings.room_settings_add_homescreen_shortcut), editable = false, icon = R.drawable.ic_add_to_home_screen_24dp, action = { callback?.createShortcut() } @@ -291,9 +293,9 @@ class RoomProfileController @Inject constructor( id = "leave", title = stringProvider.getString( if (roomSummary.isDirect) { - R.string.direct_room_profile_section_more_leave + CommonStrings.direct_room_profile_section_more_leave } else { - R.string.room_profile_section_more_leave + CommonStrings.room_profile_section_more_leave } ), divider = false, @@ -304,12 +306,12 @@ class RoomProfileController @Inject constructor( ) // Advanced - buildProfileSection(stringProvider.getString(R.string.room_settings_category_advanced_title)) + buildProfileSection(stringProvider.getString(CommonStrings.room_settings_category_advanced_title)) buildProfileAction( id = "alias", - title = stringProvider.getString(R.string.room_settings_alias_title), - subtitle = stringProvider.getString(R.string.room_settings_alias_subtitle), + title = stringProvider.getString(CommonStrings.room_settings_alias_title), + subtitle = stringProvider.getString(CommonStrings.room_settings_alias_subtitle), divider = true, editable = true, action = { callback?.onRoomAliasesClicked() } @@ -317,8 +319,8 @@ class RoomProfileController @Inject constructor( buildProfileAction( id = "permissions", - title = stringProvider.getString(R.string.room_settings_permissions_title), - subtitle = stringProvider.getString(R.string.room_settings_permissions_subtitle), + title = stringProvider.getString(CommonStrings.room_settings_permissions_title), + subtitle = stringProvider.getString(CommonStrings.room_settings_permissions_subtitle), divider = vectorPreferences.developerMode(), editable = true, action = { callback?.onRoomPermissionsClicked() } @@ -327,7 +329,7 @@ class RoomProfileController @Inject constructor( if (vectorPreferences.developerMode()) { buildProfileAction( id = "roomId", - title = stringProvider.getString(R.string.room_settings_room_internal_id), + title = stringProvider.getString(CommonStrings.room_settings_room_internal_id), subtitle = roomSummary.roomId, divider = true, editable = false, @@ -336,7 +338,7 @@ class RoomProfileController @Inject constructor( roomVersion?.let { buildProfileAction( id = "roomVersion", - title = stringProvider.getString(R.string.room_settings_room_version_title), + title = stringProvider.getString(CommonStrings.room_settings_room_version_title), subtitle = it, divider = true, editable = false @@ -344,7 +346,7 @@ class RoomProfileController @Inject constructor( } buildProfileAction( id = "devTools", - title = stringProvider.getString(R.string.dev_tools_menu_name), + title = stringProvider.getString(CommonStrings.dev_tools_menu_name), divider = false, editable = true, action = { callback?.onRoomDevToolsClicked() } @@ -357,7 +359,7 @@ class RoomProfileController @Inject constructor( if (actionPermissions.canEnableEncryption) { buildProfileAction( id = "enableEncryption", - title = stringProvider.getString(R.string.room_settings_enable_encryption), + title = stringProvider.getString(CommonStrings.room_settings_enable_encryption), icon = R.drawable.ic_shield_black, divider = false, editable = false, @@ -366,7 +368,7 @@ class RoomProfileController @Inject constructor( } else { buildProfileAction( id = "enableEncryption", - title = stringProvider.getString(R.string.room_settings_enable_encryption_no_permission), + title = stringProvider.getString(CommonStrings.room_settings_enable_encryption_no_permission), icon = R.drawable.ic_shield_black, divider = false, editable = false diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt index 9436bafc03..a7b7061388 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt @@ -54,6 +54,7 @@ import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel import im.vector.app.features.navigation.SettingsActivityPayload +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.parcelize.Parcelize @@ -143,7 +144,7 @@ class RoomProfileFragment : } private fun setupWaitingView() { - views.waitingView.waitingStatusText.setText(R.string.please_wait) + views.waitingView.waitingStatusText.setText(CommonStrings.please_wait) views.waitingView.waitingStatusText.isVisible = true } @@ -245,10 +246,10 @@ class RoomProfileFragment : override fun onEnableEncryptionClicked() { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.room_settings_enable_encryption_dialog_title) - .setMessage(R.string.room_settings_enable_encryption_dialog_content) - .setNegativeButton(R.string.action_cancel, null) - .setPositiveButton(R.string.room_settings_enable_encryption_dialog_submit) { _, _ -> + .setTitle(CommonStrings.room_settings_enable_encryption_dialog_title) + .setMessage(CommonStrings.room_settings_enable_encryption_dialog_content) + .setNegativeButton(CommonStrings.action_cancel, null) + .setPositiveButton(CommonStrings.room_settings_enable_encryption_dialog_submit) { _, _ -> roomProfileViewModel.handle(RoomProfileAction.EnableEncryption) } .show() @@ -298,19 +299,22 @@ class RoomProfileFragment : override fun onLeaveRoomClicked() { val isPublicRoom = roomProfileViewModel.isPublicRoom() val message = buildString { - append(getString(R.string.room_participants_leave_prompt_msg)) + append(getString(CommonStrings.room_participants_leave_prompt_msg)) if (!isPublicRoom) { append("\n\n") - append(getString(R.string.room_participants_leave_private_warning)) + append(getString(CommonStrings.room_participants_leave_private_warning)) } } - MaterialAlertDialogBuilder(requireContext(), if (isPublicRoom) 0 else R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) - .setTitle(R.string.room_participants_leave_prompt_title) + MaterialAlertDialogBuilder( + requireContext(), + if (isPublicRoom) 0 else im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive + ) + .setTitle(CommonStrings.room_participants_leave_prompt_title) .setMessage(message) - .setPositiveButton(R.string.action_leave) { _, _ -> + .setPositiveButton(CommonStrings.action_leave) { _, _ -> roomProfileViewModel.handle(RoomProfileAction.LeaveRoom) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileViewModel.kt index 215a1e1e9c..4c9e0aaadf 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileViewModel.kt @@ -22,7 +22,6 @@ import com.airbnb.mvrx.MavericksViewModelFactory import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel @@ -32,6 +31,7 @@ import im.vector.app.features.analytics.plan.Interaction import im.vector.app.features.home.ShortcutCreator import im.vector.app.features.powerlevel.PowerLevelsFlowFactory import im.vector.app.features.session.coroutineScope +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flatMapLatest @@ -232,7 +232,7 @@ class RoomProfileViewModel @AssistedInject constructor( } private fun handleLeaveRoom() { - _viewEvents.post(RoomProfileViewEvents.Loading(stringProvider.getString(R.string.room_profile_leaving_room))) + _viewEvents.post(RoomProfileViewEvents.Loading(stringProvider.getString(CommonStrings.room_profile_leaving_room))) viewModelScope.launch { try { session.roomService().leaveRoom(room.roomId) diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasController.kt index 40bb4401b9..8f08adafa9 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasController.kt @@ -22,7 +22,6 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized -import im.vector.app.R import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.profiles.buildProfileSection @@ -36,6 +35,7 @@ import im.vector.app.features.discovery.settingsInfoItem import im.vector.app.features.form.formEditTextItem import im.vector.app.features.form.formSwitchItem import im.vector.app.features.roomdirectory.createroom.RoomAliasErrorFormatter +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.MatrixConstants import org.matrix.android.sdk.api.session.room.alias.RoomAliasError import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility @@ -84,7 +84,7 @@ class RoomAliasController @Inject constructor( is Success -> { formSwitchItem { id("roomVisibility") - title(host.stringProvider.getString(R.string.room_alias_publish_to_directory, data.homeServerName)) + title(host.stringProvider.getString(CommonStrings.room_alias_publish_to_directory, data.homeServerName)) switchChecked(data.roomDirectoryVisibility() == RoomDirectoryVisibility.PUBLIC) listener { if (it) { @@ -100,7 +100,7 @@ class RoomAliasController @Inject constructor( id("rd_error") text( host.stringProvider.getString( - R.string.room_alias_publish_to_directory_error, + CommonStrings.room_alias_publish_to_directory_error, host.errorFormatter.toHumanReadable(data.roomDirectoryVisibility.error) ) ) @@ -113,11 +113,11 @@ class RoomAliasController @Inject constructor( private fun buildPublishInfo(data: RoomAliasViewState) { val host = this buildProfileSection( - stringProvider.getString(R.string.room_alias_published_alias_title) + stringProvider.getString(CommonStrings.room_alias_published_alias_title) ) settingsInfoItem { id("publishedInfo") - helperTextResId(R.string.room_alias_published_alias_subtitle) + helperTextResId(CommonStrings.room_alias_published_alias_subtitle) } data.canonicalAlias @@ -126,7 +126,7 @@ class RoomAliasController @Inject constructor( profileActionItem { id("canonical") title(data.canonicalAlias) - subtitle(host.stringProvider.getString(R.string.room_alias_published_alias_main)) + subtitle(host.stringProvider.getString(CommonStrings.room_alias_published_alias_main)) listener { host.callback?.openAliasDetail(canonicalAlias) } } } @@ -135,15 +135,15 @@ class RoomAliasController @Inject constructor( settingsInfoItem { id("otherPublishedEmpty") if (data.actionPermissions.canChangeCanonicalAlias) { - helperTextResId(R.string.room_alias_address_empty_can_add) + helperTextResId(CommonStrings.room_alias_address_empty_can_add) } else { - helperTextResId(R.string.room_alias_address_empty) + helperTextResId(CommonStrings.room_alias_address_empty) } } } else { settingsInfoItem { id("otherPublished") - helperTextResId(R.string.room_alias_published_other) + helperTextResId(CommonStrings.room_alias_published_other) } data.alternativeAliases.forEachIndexed { idx, altAlias -> profileActionItem { @@ -167,7 +167,7 @@ class RoomAliasController @Inject constructor( settingsButtonItem { id("publishManually") colorProvider(host.colorProvider) - buttonTitleId(R.string.room_alias_published_alias_add_manually) + buttonTitleId(CommonStrings.room_alias_published_alias_add_manually) buttonClickListener { host.callback?.toggleManualPublishForm() } } } @@ -176,7 +176,7 @@ class RoomAliasController @Inject constructor( id("publishManuallyEdit") value(data.publishManuallyState.value) maxLength(MatrixConstants.ALIAS_MAX_LENGTH) - hint(host.stringProvider.getString(R.string.room_alias_address_hint)) + hint(host.stringProvider.getString(CommonStrings.room_alias_address_hint)) inputType(InputType.TYPE_CLASS_TEXT) onTextChange { text -> host.callback?.setNewAlias(text) @@ -184,7 +184,7 @@ class RoomAliasController @Inject constructor( } settingsContinueCancelItem { id("publishManuallySubmit") - continueText(host.stringProvider.getString(R.string.room_alias_published_alias_add_manually_submit)) + continueText(host.stringProvider.getString(CommonStrings.room_alias_published_alias_add_manually_submit)) continueOnClick { host.callback?.addAlias() } cancelOnClick { host.callback?.toggleManualPublishForm() } } @@ -195,11 +195,11 @@ class RoomAliasController @Inject constructor( private fun buildLocalInfo(data: RoomAliasViewState) { val host = this buildProfileSection( - stringProvider.getString(R.string.room_alias_local_address_title) + stringProvider.getString(CommonStrings.room_alias_local_address_title) ) settingsInfoItem { id("localInfo") - helperText(host.stringProvider.getString(R.string.room_alias_local_address_subtitle, data.homeServerName)) + helperText(host.stringProvider.getString(CommonStrings.room_alias_local_address_subtitle, data.homeServerName)) } when (val localAliases = data.localAliases) { @@ -213,7 +213,7 @@ class RoomAliasController @Inject constructor( if (localAliases().isEmpty()) { settingsInfoItem { id("locEmpty") - helperTextResId(R.string.room_alias_local_address_empty) + helperTextResId(CommonStrings.room_alias_local_address_empty) } } else { localAliases().forEachIndexed { idx, localAlias -> @@ -246,7 +246,7 @@ class RoomAliasController @Inject constructor( settingsButtonItem { id("newLocalAliasButton") colorProvider(host.colorProvider) - buttonTitleId(R.string.room_alias_local_address_add) + buttonTitleId(CommonStrings.room_alias_local_address_add) buttonClickListener { host.callback?.toggleLocalAliasForm() } } } @@ -257,7 +257,7 @@ class RoomAliasController @Inject constructor( suffixText(":" + data.homeServerName) prefixText("#") maxLength(MatrixConstants.maxAliasLocalPartLength(data.homeServerName)) - hint(host.stringProvider.getString(R.string.room_alias_address_hint)) + hint(host.stringProvider.getString(CommonStrings.room_alias_address_hint)) errorMessage(host.roomAliasErrorFormatter.format((data.newLocalAliasState.asyncRequest as? Fail)?.error as? RoomAliasError)) onTextChange { value -> host.callback?.setNewLocalAliasLocalPart(value) @@ -265,7 +265,7 @@ class RoomAliasController @Inject constructor( } settingsContinueCancelItem { id("newLocalAliasSubmit") - continueText(host.stringProvider.getString(R.string.action_add)) + continueText(host.stringProvider.getString(CommonStrings.action_add)) continueOnClick { host.callback?.addLocalAlias() } cancelOnClick { host.callback?.toggleLocalAliasForm() } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasFragment.kt index b9b0f604c7..a232b9adc7 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasFragment.kt @@ -27,7 +27,6 @@ import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment @@ -40,6 +39,7 @@ import im.vector.app.features.roomprofile.RoomProfileArgs import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheet import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheetSharedAction import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheetSharedActionViewModel +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.session.room.alias.RoomAliasError @@ -77,7 +77,7 @@ class RoomAliasFragment : setupToolbar(views.roomSettingsToolbar) .allowBack() views.roomSettingsRecyclerView.configureWith(controller, hasFixedSize = true) - views.waitingView.waitingStatusText.setText(R.string.please_wait) + views.waitingView.waitingStatusText.setText(CommonStrings.please_wait) views.waitingView.waitingStatusText.isVisible = true viewModel.observeViewEvents { @@ -116,7 +116,7 @@ class RoomAliasFragment : } private fun showSuccess() { - activity?.toast(R.string.room_settings_save_success) + activity?.toast(CommonStrings.room_settings_save_success) } override fun onDestroyView() { @@ -140,11 +140,11 @@ class RoomAliasFragment : } private fun unpublishAlias(alias: String) { - MaterialAlertDialogBuilder(requireContext(), R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) - .setTitle(R.string.dialog_title_confirmation) - .setMessage(getString(R.string.room_alias_unpublish_confirmation, alias)) - .setNegativeButton(R.string.action_cancel, null) - .setPositiveButton(R.string.action_unpublish) { _, _ -> + MaterialAlertDialogBuilder(requireContext(), im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) + .setTitle(CommonStrings.dialog_title_confirmation) + .setMessage(getString(CommonStrings.room_alias_unpublish_confirmation, alias)) + .setNegativeButton(CommonStrings.action_cancel, null) + .setPositiveButton(CommonStrings.action_unpublish) { _, _ -> viewModel.handle(RoomAliasAction.UnpublishAlias(alias)) } .show() @@ -195,11 +195,11 @@ class RoomAliasFragment : } private fun removeLocalAlias(alias: String) { - MaterialAlertDialogBuilder(requireContext(), R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) - .setTitle(R.string.dialog_title_confirmation) - .setMessage(getString(R.string.room_alias_delete_confirmation, alias)) - .setNegativeButton(R.string.action_cancel, null) - .setPositiveButton(R.string.action_delete) { _, _ -> + MaterialAlertDialogBuilder(requireContext(), im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) + .setTitle(CommonStrings.dialog_title_confirmation) + .setMessage(getString(CommonStrings.room_alias_delete_confirmation, alias)) + .setNegativeButton(CommonStrings.action_cancel, null) + .setPositiveButton(CommonStrings.action_delete) { _, _ -> viewModel.handle(RoomAliasAction.RemoveLocalAlias(alias)) } .show() diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/alias/detail/RoomAliasBottomSheetSharedAction.kt b/vector/src/main/java/im/vector/app/features/roomprofile/alias/detail/RoomAliasBottomSheetSharedAction.kt index ea18e0ff8f..2722b6bfb1 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/alias/detail/RoomAliasBottomSheetSharedAction.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/alias/detail/RoomAliasBottomSheetSharedAction.kt @@ -20,6 +20,7 @@ import androidx.annotation.DrawableRes import androidx.annotation.StringRes import im.vector.app.R import im.vector.app.core.platform.VectorSharedAction +import im.vector.lib.strings.CommonStrings sealed class RoomAliasBottomSheetSharedAction( @StringRes val titleRes: Int, @@ -29,29 +30,29 @@ sealed class RoomAliasBottomSheetSharedAction( VectorSharedAction { data class ShareAlias(val matrixTo: String) : RoomAliasBottomSheetSharedAction( - R.string.action_share, + CommonStrings.action_share, R.drawable.ic_material_share ) data class PublishAlias(val alias: String) : RoomAliasBottomSheetSharedAction( - R.string.room_alias_action_publish + CommonStrings.room_alias_action_publish ) data class UnPublishAlias(val alias: String) : RoomAliasBottomSheetSharedAction( - R.string.room_alias_action_unpublish + CommonStrings.room_alias_action_unpublish ) data class DeleteAlias(val alias: String) : RoomAliasBottomSheetSharedAction( - R.string.action_delete, + CommonStrings.action_delete, R.drawable.ic_trash_24, true ) data class SetMainAlias(val alias: String) : RoomAliasBottomSheetSharedAction( - R.string.room_settings_set_main_address + CommonStrings.room_settings_set_main_address ) object UnsetMainAlias : RoomAliasBottomSheetSharedAction( - R.string.room_settings_unset_main_address + CommonStrings.room_settings_unset_main_address ) } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListController.kt index cc332c0ba2..ac1333de29 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListController.kt @@ -17,7 +17,6 @@ package im.vector.app.features.roomprofile.banned import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.epoxy.dividerItem import im.vector.app.core.epoxy.profiles.buildProfileSection import im.vector.app.core.epoxy.profiles.profileMatrixItemWithProgress @@ -27,6 +26,8 @@ import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roomprofile.members.RoomMemberSummaryFilter import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject @@ -47,10 +48,10 @@ class RoomBannedMemberListController @Inject constructor( val bannedList = data?.bannedMemberSummaries?.invoke() ?: return val host = this - val quantityString = stringProvider.getQuantityString(R.plurals.room_settings_banned_users_count, bannedList.size, bannedList.size) + val quantityString = stringProvider.getQuantityString(CommonPlurals.room_settings_banned_users_count, bannedList.size, bannedList.size) if (bannedList.isEmpty()) { - buildProfileSection(stringProvider.getString(R.string.room_settings_banned_users_title)) + buildProfileSection(stringProvider.getString(CommonStrings.room_settings_banned_users_title)) genericFooterItem { id("footer") diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListFragment.kt index a8e34d0117..112fee9c71 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListFragment.kt @@ -27,7 +27,6 @@ import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment @@ -35,6 +34,7 @@ import im.vector.app.core.utils.toast import im.vector.app.databinding.FragmentRoomSettingGenericBinding import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roomprofile.RoomProfileArgs +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject @@ -71,12 +71,12 @@ class RoomBannedMemberListFragment : is RoomBannedMemberListViewEvents.ShowBannedInfo -> { val canBan = withState(viewModel) { state -> state.canUserBan } MaterialAlertDialogBuilder(requireActivity()) - .setTitle(getString(R.string.member_banned_by, it.bannedByUserId)) - .setMessage(getString(R.string.reason_colon, it.banReason)) - .setPositiveButton(R.string.ok, null) + .setTitle(getString(CommonStrings.member_banned_by, it.bannedByUserId)) + .setMessage(getString(CommonStrings.reason_colon, it.banReason)) + .setPositiveButton(CommonStrings.ok, null) .apply { if (canBan) { - setNegativeButton(R.string.room_participants_action_unban) { _, _ -> + setNegativeButton(CommonStrings.room_participants_action_unban) { _, _ -> viewModel.handle(RoomBannedMemberListAction.UnBanUser(it.roomMemberSummary)) } } @@ -97,7 +97,7 @@ class RoomBannedMemberListFragment : private fun setupSearchView() { views.searchViewAppBarLayout.isVisible = true - views.searchView.queryHint = getString(R.string.search_banned_user_hint) + views.searchView.queryHint = getString(CommonStrings.search_banned_user_hint) views.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String): Boolean { return true diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListViewModel.kt index 15db3c300e..88a56807db 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListViewModel.kt @@ -20,12 +20,12 @@ import com.airbnb.mvrx.MavericksViewModelFactory import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.features.powerlevel.PowerLevelsFlowFactory +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.matrix.android.sdk.api.query.QueryStringValue @@ -120,7 +120,7 @@ class RoomBannedMemberListViewModel @AssistedInject constructor( try { room.membershipService().unban(roomMemberSummary.userId, null) } catch (failure: Throwable) { - _viewEvents.post(RoomBannedMemberListViewEvents.ToastError(stringProvider.getString(R.string.failed_to_unban))) + _viewEvents.post(RoomBannedMemberListViewEvents.ToastError(stringProvider.getString(CommonStrings.failed_to_unban))) } finally { setState { copy( diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListController.kt index 9adfeb2a0e..27874a250a 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListController.kt @@ -17,7 +17,6 @@ package im.vector.app.features.roomprofile.members import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.epoxy.dividerItem import im.vector.app.core.epoxy.profiles.buildProfileSection import im.vector.app.core.epoxy.profiles.profileMatrixItem @@ -139,7 +138,7 @@ class RoomMemberListController @Inject constructor( powerLevelLabel( span { span(powerLabel) { - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) } } ) diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListFragment.kt index 8ed8db8c6b..02d5c7e12a 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListFragment.kt @@ -29,7 +29,6 @@ import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment @@ -37,6 +36,7 @@ import im.vector.app.databinding.FragmentRoomMemberListBinding import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roomprofile.RoomProfileArgs +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary @@ -99,7 +99,7 @@ class RoomMemberListFragment : } private fun setupSearchView() { - views.roomSettingGeneric.searchView.queryHint = getString(R.string.search_members_hint) + views.roomSettingGeneric.searchView.queryHint = getString(CommonStrings.search_members_hint) views.roomSettingGeneric.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String): Boolean { return true @@ -136,10 +136,10 @@ class RoomMemberListFragment : val stateKey = event.stateKey ?: return if (withState(viewModel) { it.actionsPermissions.canRevokeThreePidInvite }) { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.three_pid_revoke_invite_dialog_title) - .setMessage(getString(R.string.three_pid_revoke_invite_dialog_content, content.displayName)) - .setNegativeButton(R.string.action_cancel, null) - .setPositiveButton(R.string.action_revoke) { _, _ -> + .setTitle(CommonStrings.three_pid_revoke_invite_dialog_title) + .setMessage(getString(CommonStrings.three_pid_revoke_invite_dialog_content, content.displayName)) + .setNegativeButton(CommonStrings.action_cancel, null) + .setPositiveButton(CommonStrings.action_revoke) { _, _ -> viewModel.handle(RoomMemberListAction.RevokeThreePidInvite(stateKey)) } .show() diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewState.kt b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewState.kt index 7861970c28..c23df3b27a 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewState.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewState.kt @@ -20,9 +20,9 @@ import androidx.annotation.StringRes import com.airbnb.mvrx.Async import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.Uninitialized -import im.vector.app.R import im.vector.app.core.platform.GenericIdArgs import im.vector.app.features.roomprofile.RoomProfileArgs +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.crypto.model.UserVerificationLevel import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary @@ -53,9 +53,9 @@ data class ActionPermissions( typealias RoomMemberSummaries = List>> enum class RoomMemberListCategories(@StringRes val titleRes: Int) { - ADMIN(R.string.room_member_power_level_admins), - MODERATOR(R.string.room_member_power_level_moderators), - CUSTOM(R.string.room_member_power_level_custom), - INVITE(R.string.room_member_power_level_invites), - USER(R.string.room_member_power_level_users) + ADMIN(CommonStrings.room_member_power_level_admins), + MODERATOR(CommonStrings.room_member_power_level_moderators), + CUSTOM(CommonStrings.room_member_power_level_custom), + INVITE(CommonStrings.room_member_power_level_invites), + USER(CommonStrings.room_member_power_level_users) } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsController.kt index 07d975c88d..3aa41ed91d 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsController.kt @@ -18,10 +18,10 @@ package im.vector.app.features.roomprofile.notifications import androidx.annotation.StringRes import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.epoxy.profiles.notifications.notificationSettingsFooterItem import im.vector.app.core.epoxy.profiles.notifications.radioButtonItem import im.vector.app.core.epoxy.profiles.notifications.textHeaderItem +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState import javax.inject.Inject @@ -40,7 +40,7 @@ class RoomNotificationSettingsController @Inject constructor() : TypedEpoxyContr textHeaderItem { id("roomNotificationSettingsHeader") - textRes(R.string.room_settings_room_notifications_notify_me) + textRes(CommonStrings.room_settings_room_notifications_notify_me) } data.notificationOptions.forEach { notificationState -> val title = titleForNotificationState(notificationState) @@ -64,9 +64,9 @@ class RoomNotificationSettingsController @Inject constructor() : TypedEpoxyContr @StringRes private fun titleForNotificationState(notificationState: RoomNotificationState): Int? = when (notificationState) { - RoomNotificationState.ALL_MESSAGES_NOISY -> R.string.room_settings_all_messages - RoomNotificationState.MENTIONS_ONLY -> R.string.room_settings_mention_and_keyword_only - RoomNotificationState.MUTE -> R.string.room_settings_none + RoomNotificationState.ALL_MESSAGES_NOISY -> CommonStrings.room_settings_all_messages + RoomNotificationState.MENTIONS_ONLY -> CommonStrings.room_settings_mention_and_keyword_only + RoomNotificationState.MUTE -> CommonStrings.room_settings_none else -> null } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsFragment.kt index 7afd696332..2389f20a1a 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/notifications/RoomNotificationSettingsFragment.kt @@ -24,7 +24,6 @@ import androidx.core.view.isVisible import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment @@ -32,6 +31,7 @@ import im.vector.app.databinding.FragmentRoomSettingGenericBinding import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.settings.VectorSettingsActivity +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject @@ -73,7 +73,7 @@ class RoomNotificationSettingsFragment : } private fun setupWaitingView() { - views.waitingView.waitingStatusText.setText(R.string.please_wait) + views.waitingView.waitingStatusText.setText(CommonStrings.please_wait) views.waitingView.waitingStatusText.isVisible = true } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/EditablePermission.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/EditablePermission.kt index d9c1bca2da..f2aee8c946 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/EditablePermission.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/EditablePermission.kt @@ -17,7 +17,7 @@ package im.vector.app.features.roomprofile.permissions import androidx.annotation.StringRes -import im.vector.app.R +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.events.model.EventType /** @@ -34,80 +34,80 @@ sealed class EditablePermission(@StringRes val labelResId: Int, @StringRes val s class ModifyWidgets : EventTypeEditablePermission( // Note: Element Web still use legacy value EventType.STATE_ROOM_WIDGET_LEGACY, - R.string.room_permissions_modify_widgets + CommonStrings.room_permissions_modify_widgets ) class ChangeRoomAvatar : EventTypeEditablePermission( EventType.STATE_ROOM_AVATAR, - R.string.room_permissions_change_room_avatar, - R.string.room_permissions_change_space_avatar + CommonStrings.room_permissions_change_room_avatar, + CommonStrings.room_permissions_change_space_avatar ) class ChangeMainAddressForTheRoom : EventTypeEditablePermission( EventType.STATE_ROOM_CANONICAL_ALIAS, - R.string.room_permissions_change_main_address_for_the_room, - R.string.room_permissions_change_main_address_for_the_space + CommonStrings.room_permissions_change_main_address_for_the_room, + CommonStrings.room_permissions_change_main_address_for_the_space ) class EnableRoomEncryption : EventTypeEditablePermission( EventType.STATE_ROOM_ENCRYPTION, - R.string.room_permissions_enable_room_encryption, - R.string.room_permissions_enable_space_encryption + CommonStrings.room_permissions_enable_room_encryption, + CommonStrings.room_permissions_enable_space_encryption ) class ChangeHistoryVisibility : EventTypeEditablePermission( EventType.STATE_ROOM_HISTORY_VISIBILITY, - R.string.room_permissions_change_history_visibility + CommonStrings.room_permissions_change_history_visibility ) class ChangeRoomName : EventTypeEditablePermission( EventType.STATE_ROOM_NAME, - R.string.room_permissions_change_room_name, - R.string.room_permissions_change_space_name + CommonStrings.room_permissions_change_room_name, + CommonStrings.room_permissions_change_space_name ) class ChangePermissions : EventTypeEditablePermission( EventType.STATE_ROOM_POWER_LEVELS, - R.string.room_permissions_change_permissions + CommonStrings.room_permissions_change_permissions ) class SendRoomServerAclEvents : EventTypeEditablePermission( EventType.STATE_ROOM_SERVER_ACL, - R.string.room_permissions_send_m_room_server_acl_events + CommonStrings.room_permissions_send_m_room_server_acl_events ) class UpgradeTheRoom : EventTypeEditablePermission( EventType.STATE_ROOM_TOMBSTONE, - R.string.room_permissions_upgrade_the_room, - R.string.room_permissions_upgrade_the_space + CommonStrings.room_permissions_upgrade_the_room, + CommonStrings.room_permissions_upgrade_the_space ) class ChangeTopic : EventTypeEditablePermission( EventType.STATE_ROOM_TOPIC, - R.string.room_permissions_change_topic + CommonStrings.room_permissions_change_topic ) // Updates `content.users_default` - class DefaultRole : EditablePermission(R.string.room_permissions_default_role) + class DefaultRole : EditablePermission(CommonStrings.room_permissions_default_role) // Updates `content.events_default` - class SendMessages : EditablePermission(R.string.room_permissions_send_messages) + class SendMessages : EditablePermission(CommonStrings.room_permissions_send_messages) // Updates `content.invites` - class InviteUsers : EditablePermission(R.string.room_permissions_invite_users) + class InviteUsers : EditablePermission(CommonStrings.room_permissions_invite_users) // Updates `content.state_default` - class ChangeSettings : EditablePermission(R.string.room_permissions_change_settings) + class ChangeSettings : EditablePermission(CommonStrings.room_permissions_change_settings) // Updates `content.kick` - class KickUsers : EditablePermission(R.string.room_permissions_remove_users) + class KickUsers : EditablePermission(CommonStrings.room_permissions_remove_users) // Updates `content.ban` - class BanUsers : EditablePermission(R.string.room_permissions_ban_users) + class BanUsers : EditablePermission(CommonStrings.room_permissions_ban_users) // Updates `content.redact` - class RemoveMessagesSentByOthers : EditablePermission(R.string.room_permissions_remove_messages_sent_by_others) + class RemoveMessagesSentByOthers : EditablePermission(CommonStrings.room_permissions_remove_messages_sent_by_others) // Updates `content.notification.room` - class NotifyEveryone : EditablePermission(R.string.room_permissions_notify_everyone) + class NotifyEveryone : EditablePermission(CommonStrings.room_permissions_notify_everyone) } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoleFormatter.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoleFormatter.kt index 2362c74b37..0c49ffc27f 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoleFormatter.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoleFormatter.kt @@ -16,8 +16,8 @@ package im.vector.app.features.roomprofile.permissions -import im.vector.app.R import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.powerlevels.Role import javax.inject.Inject @@ -26,10 +26,10 @@ class RoleFormatter @Inject constructor( ) { fun format(role: Role): String { return when (role) { - Role.Admin -> stringProvider.getString(R.string.power_level_admin) - Role.Moderator -> stringProvider.getString(R.string.power_level_moderator) - Role.Default -> stringProvider.getString(R.string.power_level_default) - is Role.Custom -> stringProvider.getString(R.string.power_level_custom, role.value) + Role.Admin -> stringProvider.getString(CommonStrings.power_level_admin) + Role.Moderator -> stringProvider.getString(CommonStrings.power_level_moderator) + Role.Default -> stringProvider.getString(CommonStrings.power_level_default) + is Role.Custom -> stringProvider.getString(CommonStrings.power_level_custom, role.value) } } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsController.kt index c6fa007306..18569cc14c 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsController.kt @@ -18,13 +18,13 @@ package im.vector.app.features.roomprofile.permissions import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.mvrx.Success -import im.vector.app.R import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.profiles.buildProfileAction import im.vector.app.core.epoxy.profiles.buildProfileSection import im.vector.app.core.resources.StringProvider import im.vector.app.features.discovery.settingsInfoItem import im.vector.app.features.form.formAdvancedToggleItem +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent import org.matrix.android.sdk.api.session.room.model.RoomType import org.matrix.android.sdk.api.session.room.model.banOrDefault @@ -111,7 +111,7 @@ class RoomPermissionsController @Inject constructor( override fun buildModels(data: RoomPermissionsViewState?) { val host = this buildProfileSection( - stringProvider.getString(R.string.room_permissions_title) + stringProvider.getString(CommonStrings.room_permissions_title) ) when (val content = data?.currentPowerLevelsContent) { @@ -119,7 +119,7 @@ class RoomPermissionsController @Inject constructor( else -> { loadingItem { id("loading") - loadingText(host.stringProvider.getString(R.string.loading)) + loadingText(host.stringProvider.getString(CommonStrings.loading)) } } } @@ -135,9 +135,9 @@ class RoomPermissionsController @Inject constructor( helperText( host.stringProvider.getString( if (editable) { - if (isSpace) R.string.space_permissions_notice else R.string.room_permissions_notice + if (isSpace) CommonStrings.space_permissions_notice else CommonStrings.room_permissions_notice } else { - if (isSpace) R.string.space_permissions_notice_read_only else R.string.room_permissions_notice_read_only + if (isSpace) CommonStrings.space_permissions_notice_read_only else CommonStrings.room_permissions_notice_read_only } ) ) @@ -153,7 +153,7 @@ class RoomPermissionsController @Inject constructor( // Toggle formAdvancedToggleItem { id("showAdvanced") - title(host.stringProvider.getString(if (data.showAdvancedPermissions) R.string.hide_advanced else R.string.show_advanced)) + title(host.stringProvider.getString(if (data.showAdvancedPermissions) CommonStrings.hide_advanced else CommonStrings.show_advanced)) expanded(!data.showAdvancedPermissions) listener { host.callback?.toggleShowAllPermissions() } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsFragment.kt index 06b9343dbf..0debf35b9f 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsFragment.kt @@ -25,7 +25,6 @@ import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment @@ -35,6 +34,7 @@ import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roommemberprofile.powerlevel.EditPowerLevelDialogs import im.vector.app.features.roomprofile.RoomProfileArgs +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.powerlevels.Role import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject @@ -67,7 +67,7 @@ class RoomPermissionsFragment : setupToolbar(views.roomSettingsToolbar) .allowBack() views.roomSettingsRecyclerView.configureWith(controller, hasFixedSize = true) - views.waitingView.waitingStatusText.setText(R.string.please_wait) + views.waitingView.waitingStatusText.setText(CommonStrings.please_wait) views.waitingView.waitingStatusText.isVisible = true viewModel.observeViewEvents { @@ -79,7 +79,7 @@ class RoomPermissionsFragment : } private fun showSuccess() { - activity?.toast(R.string.room_settings_save_success) + activity?.toast(CommonStrings.room_settings_save_success) } override fun onDestroyView() { diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsFragment.kt index 9f7e704135..f9e71b13f3 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsFragment.kt @@ -24,10 +24,10 @@ import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.google.android.material.tabs.TabLayoutMediator import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentRoomPollsBinding import im.vector.app.features.roomprofile.RoomProfileArgs +import im.vector.lib.strings.CommonStrings @AndroidEntryPoint class RoomPollsFragment : VectorBaseFragment() { @@ -66,8 +66,8 @@ class RoomPollsFragment : VectorBaseFragment() { tabLayoutMediator = TabLayoutMediator(views.roomPollsTabs, views.roomPollsViewPager) { tab, position -> when (position) { - RoomPollsType.ACTIVE.ordinal -> tab.text = getString(R.string.room_polls_active) - RoomPollsType.ENDED.ordinal -> tab.text = getString(R.string.room_polls_ended) + RoomPollsType.ACTIVE.ordinal -> tab.text = getString(CommonStrings.room_polls_active) + RoomPollsType.ENDED.ordinal -> tab.text = getString(CommonStrings.room_polls_ended) } }.also { it.attach() } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/active/RoomActivePollsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/active/RoomActivePollsFragment.kt index 441a4489b3..54e9605bdb 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/active/RoomActivePollsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/active/RoomActivePollsFragment.kt @@ -17,18 +17,19 @@ package im.vector.app.features.roomprofile.polls.active import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.features.roomprofile.polls.RoomPollsType import im.vector.app.features.roomprofile.polls.list.ui.RoomPollsListFragment +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings @AndroidEntryPoint class RoomActivePollsFragment : RoomPollsListFragment() { override fun getEmptyListTitle(canLoadMore: Boolean, nbLoadedDays: Int): String { return if (canLoadMore) { - stringProvider.getQuantityString(R.plurals.room_polls_active_no_item_for_loaded_period, nbLoadedDays, nbLoadedDays) + stringProvider.getQuantityString(CommonPlurals.room_polls_active_no_item_for_loaded_period, nbLoadedDays, nbLoadedDays) } else { - getString(R.string.room_polls_active_no_item) + getString(CommonStrings.room_polls_active_no_item) } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailFragment.kt index 9c118bb897..77e3cdd02b 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailFragment.kt @@ -25,11 +25,11 @@ import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentRoomPollDetailBinding +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import javax.inject.Inject @@ -77,8 +77,8 @@ class RoomPollDetailFragment : private fun setupToolbar(isEnded: Boolean) { val title = when (isEnded) { - true -> getString(R.string.room_polls_ended) - false -> getString(R.string.room_polls_active) + true -> getString(CommonStrings.room_polls_ended) + false -> getString(CommonStrings.room_polls_active) } setupToolbar(views.roomPollDetailToolbar) diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/ended/RoomEndedPollsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/ended/RoomEndedPollsFragment.kt index 53f61126b5..949726f784 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/ended/RoomEndedPollsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/ended/RoomEndedPollsFragment.kt @@ -17,18 +17,19 @@ package im.vector.app.features.roomprofile.polls.ended import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.features.roomprofile.polls.RoomPollsType import im.vector.app.features.roomprofile.polls.list.ui.RoomPollsListFragment +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings @AndroidEntryPoint class RoomEndedPollsFragment : RoomPollsListFragment() { override fun getEmptyListTitle(canLoadMore: Boolean, nbLoadedDays: Int): String { return if (canLoadMore) { - stringProvider.getQuantityString(R.plurals.room_polls_ended_no_item_for_loaded_period, nbLoadedDays, nbLoadedDays) + stringProvider.getQuantityString(CommonPlurals.room_polls_ended_no_item_for_loaded_period, nbLoadedDays, nbLoadedDays) } else { - getString(R.string.room_polls_ended_no_item) + getString(CommonStrings.room_polls_ended_no_item) } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/ui/RoomPollsController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/ui/RoomPollsController.kt index dceb61063c..494d47623d 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/ui/RoomPollsController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/list/ui/RoomPollsController.kt @@ -17,11 +17,11 @@ package im.vector.app.features.roomprofile.polls.list.ui import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter import im.vector.app.core.resources.StringProvider import im.vector.app.features.roomprofile.polls.RoomPollsViewState +import im.vector.lib.strings.CommonPlurals import java.util.UUID import javax.inject.Inject @@ -74,7 +74,7 @@ class RoomPollsController @Inject constructor( formattedDate(host.dateFormatter.format(poll.creationTimestamp, DateFormatKind.TIMELINE_DAY_DIVIDER)) title(poll.title) winnerOptions(poll.winnerOptions) - totalVotesStatus(host.stringProvider.getQuantityString(R.plurals.poll_total_vote_count_after_ended, poll.totalVotes, poll.totalVotes)) + totalVotesStatus(host.stringProvider.getQuantityString(CommonPlurals.poll_total_vote_count_after_ended, poll.totalVotes, poll.totalVotes)) clickListener { host.listener?.onPollClicked(poll.id) } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsController.kt index f8efe73ebf..955d57131a 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsController.kt @@ -17,7 +17,6 @@ package im.vector.app.features.roomprofile.settings import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.epoxy.dividerItem import im.vector.app.core.epoxy.profiles.buildProfileAction import im.vector.app.core.epoxy.profiles.buildProfileSection @@ -30,6 +29,7 @@ import im.vector.app.features.form.formSwitchItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.format.RoomHistoryVisibilityFormatter import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.session.room.model.RoomJoinRules import org.matrix.android.sdk.api.util.toMatrixItem @@ -78,7 +78,7 @@ class RoomSettingsController @Inject constructor( } buildProfileSection( - stringProvider.getString(R.string.settings) + stringProvider.getString(CommonStrings.settings) ) verticalMarginItem { @@ -90,7 +90,7 @@ class RoomSettingsController @Inject constructor( id("name") enabled(data.actionPermissions.canChangeName) value(data.newName ?: roomSummary.displayName) - hint(host.stringProvider.getString(R.string.room_settings_name_hint)) + hint(host.stringProvider.getString(CommonStrings.room_settings_name_hint)) autoCapitalize(true) onTextChange { text -> @@ -102,7 +102,7 @@ class RoomSettingsController @Inject constructor( enabled(data.actionPermissions.canChangeTopic) value(data.newTopic ?: roomSummary.topic) singleLine(false) - hint(host.stringProvider.getString(R.string.room_settings_topic_hint)) + hint(host.stringProvider.getString(CommonStrings.room_settings_topic_hint)) onTextChange { text -> host.callback?.onTopicChanged(text) @@ -113,7 +113,7 @@ class RoomSettingsController @Inject constructor( } buildProfileAction( id = "historyReadability", - title = stringProvider.getString(R.string.room_settings_room_read_history_rules_pref_title), + title = stringProvider.getString(CommonStrings.room_settings_room_read_history_rules_pref_title), subtitle = roomHistoryVisibilityFormatter.getSetting(data.newHistoryVisibility ?: data.currentHistoryVisibility), divider = true, editable = data.actionPermissions.canChangeHistoryVisibility, @@ -122,7 +122,7 @@ class RoomSettingsController @Inject constructor( buildProfileAction( id = "joinRule", - title = stringProvider.getString(R.string.room_settings_room_access_title), + title = stringProvider.getString(CommonStrings.room_settings_room_access_title), subtitle = data.getJoinRuleWording(stringProvider), divider = true, editable = data.actionPermissions.canChangeJoinRule, @@ -135,7 +135,7 @@ class RoomSettingsController @Inject constructor( // add guest access option? formSwitchItem { id("guest_access") - title(host.stringProvider.getString(R.string.room_settings_guest_access_title)) + title(host.stringProvider.getString(CommonStrings.room_settings_guest_access_title)) switchChecked(guestAccess == GuestAccess.CanJoin) listener { host.callback?.onToggleGuestAccess() diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt index 26da1a45d2..a261ad4206 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt @@ -49,6 +49,7 @@ import im.vector.app.features.roomprofile.settings.historyvisibility.RoomHistory import im.vector.app.features.roomprofile.settings.historyvisibility.RoomHistoryVisibilitySharedActionViewModel import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleActivity import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleSharedActionViewModel +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.session.room.model.GuestAccess @@ -97,7 +98,7 @@ class RoomSettingsFragment : setupToolbar(views.roomSettingsToolbar) .allowBack() views.roomSettingsRecyclerView.configureWith(controller, hasFixedSize = true) - views.waitingView.waitingStatusText.setText(R.string.please_wait) + views.waitingView.waitingStatusText.setText(CommonStrings.please_wait) views.waitingView.waitingStatusText.isVisible = true viewModel.observeViewEvents { @@ -134,7 +135,7 @@ class RoomSettingsFragment : } private fun showSuccess() { - activity?.toast(R.string.room_settings_save_success) + activity?.toast(CommonStrings.room_settings_save_success) } override fun onDestroyView() { @@ -241,12 +242,12 @@ class RoomSettingsFragment : return withState(viewModel) { return@withState if (it.showSaveAction) { MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.dialog_title_warning) - .setMessage(R.string.warning_unsaved_change) - .setPositiveButton(R.string.warning_unsaved_change_discard) { _, _ -> + .setTitle(CommonStrings.dialog_title_warning) + .setMessage(CommonStrings.warning_unsaved_change) + .setPositiveButton(CommonStrings.warning_unsaved_change_discard) { _, _ -> viewModel.handle(RoomSettingsAction.Cancel) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() true } else { diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewState.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewState.kt index 10465b03ea..405bb64a3a 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewState.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewState.kt @@ -20,9 +20,9 @@ import android.net.Uri import com.airbnb.mvrx.Async import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.Uninitialized -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.roomprofile.RoomProfileArgs +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility import org.matrix.android.sdk.api.session.room.model.RoomJoinRules @@ -78,19 +78,19 @@ data class RoomSettingsViewState( fun getJoinRuleWording(stringProvider: StringProvider): String { return when (val joinRule = newRoomJoinRules.newJoinRules ?: currentRoomJoinRules) { RoomJoinRules.INVITE -> { - stringProvider.getString(R.string.room_settings_room_access_private_title) + stringProvider.getString(CommonStrings.room_settings_room_access_private_title) } RoomJoinRules.PUBLIC -> { - stringProvider.getString(R.string.room_settings_room_access_public_title) + stringProvider.getString(CommonStrings.room_settings_room_access_public_title) } RoomJoinRules.KNOCK -> { - stringProvider.getString(R.string.room_settings_room_access_entry_knock) + stringProvider.getString(CommonStrings.room_settings_room_access_entry_knock) } RoomJoinRules.RESTRICTED -> { - stringProvider.getString(R.string.room_settings_room_access_restricted_title) + stringProvider.getString(CommonStrings.room_settings_room_access_restricted_title) } else -> { - stringProvider.getString(R.string.room_settings_room_access_entry_unknown, joinRule.value) + stringProvider.getString(CommonStrings.room_settings_room_access_entry_unknown, joinRule.value) } } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/historyvisibility/RoomHistoryVisibilityController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/historyvisibility/RoomHistoryVisibilityController.kt index 16aa456f69..76b148f10c 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/historyvisibility/RoomHistoryVisibilityController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/historyvisibility/RoomHistoryVisibilityController.kt @@ -16,10 +16,10 @@ package im.vector.app.features.roomprofile.settings.historyvisibility -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.bottomsheet.BottomSheetGenericController import im.vector.app.features.home.room.detail.timeline.format.RoomHistoryVisibilityFormatter +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility import javax.inject.Inject @@ -28,9 +28,9 @@ class RoomHistoryVisibilityController @Inject constructor( private val stringProvider: StringProvider ) : BottomSheetGenericController() { - override fun getTitle() = stringProvider.getString(R.string.room_settings_room_read_history_rules_pref_dialog_title) + override fun getTitle() = stringProvider.getString(CommonStrings.room_settings_room_read_history_rules_pref_dialog_title) - override fun getSubTitle() = stringProvider.getString(R.string.room_settings_room_read_history_dialog_subtitle) + override fun getSubTitle() = stringProvider.getString(CommonStrings.room_settings_room_read_history_dialog_subtitle) override fun getActions(state: RoomHistoryVisibilityState): List { return listOf( diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt index caf4b1843a..c598ccb57b 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt @@ -17,7 +17,6 @@ package im.vector.app.features.roomprofile.settings.joinrule import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.ItemStyle @@ -26,6 +25,7 @@ import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedState import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.RoomJoinRules import timber.log.Timber import javax.inject.Inject @@ -50,23 +50,23 @@ class RoomJoinRuleAdvancedController @Inject constructor( genericFooterItem { id("header") - text(host.stringProvider.getString(R.string.room_settings_room_access_title).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.room_settings_room_access_title).toEpoxyCharSequence()) centered(false) style(ItemStyle.TITLE) - textColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + textColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) } genericFooterItem { id("desc") - text(host.stringProvider.getString(R.string.decide_who_can_find_and_join).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.decide_who_can_find_and_join).toEpoxyCharSequence()) centered(false) } // invite only RoomJoinRuleRadioAction( roomJoinRule = RoomJoinRules.INVITE, - description = stringProvider.getString(R.string.room_settings_room_access_private_description), - title = stringProvider.getString(R.string.room_settings_room_access_private_invite_only_title), + description = stringProvider.getString(CommonStrings.room_settings_room_access_private_description), + title = stringProvider.getString(CommonStrings.room_settings_room_access_private_invite_only_title), isSelected = state.currentRoomJoinRules == RoomJoinRules.INVITE ).toRadioBottomSheetItem().let { it.listener { @@ -92,8 +92,8 @@ class RoomJoinRuleAdvancedController @Inject constructor( // Public RoomJoinRuleRadioAction( roomJoinRule = RoomJoinRules.PUBLIC, - description = stringProvider.getString(R.string.room_settings_room_access_public_description), - title = stringProvider.getString(R.string.room_settings_room_access_public_title), + description = stringProvider.getString(CommonStrings.room_settings_room_access_public_description), + title = stringProvider.getString(CommonStrings.room_settings_room_access_public_title), isSelected = state.currentRoomJoinRules == RoomJoinRules.PUBLIC ).toRadioBottomSheetItem().let { it.listener { diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleController.kt index 2552a2568c..5da145fca4 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleController.kt @@ -16,10 +16,10 @@ package im.vector.app.features.roomprofile.settings.joinrule -import im.vector.app.R import im.vector.app.core.resources.DrawableProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.bottomsheet.BottomSheetGenericController +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.RoomJoinRules import javax.inject.Inject @@ -31,34 +31,34 @@ class RoomJoinRuleController @Inject constructor( override fun getTitle() = stringProvider.getString( // generic title for both room and space - R.string.room_settings_access_rules_pref_dialog_title + CommonStrings.room_settings_access_rules_pref_dialog_title ) override fun getActions(state: RoomJoinRuleState): List { return listOf( RoomJoinRuleRadioAction( roomJoinRule = RoomJoinRules.INVITE, - description = stringProvider.getString(R.string.room_settings_room_access_private_description), - title = stringProvider.getString(R.string.room_settings_room_access_private_title), + description = stringProvider.getString(CommonStrings.room_settings_room_access_private_description), + title = stringProvider.getString(CommonStrings.room_settings_room_access_private_title), isSelected = state.currentRoomJoinRule == RoomJoinRules.INVITE ), RoomJoinRuleRadioAction( roomJoinRule = RoomJoinRules.PUBLIC, description = stringProvider.getString( - if (state.isSpace) R.string.room_settings_space_access_public_description - else R.string.room_settings_room_access_public_description + if (state.isSpace) CommonStrings.room_settings_space_access_public_description + else CommonStrings.room_settings_room_access_public_description ), - title = stringProvider.getString(R.string.room_settings_room_access_public_title), + title = stringProvider.getString(CommonStrings.room_settings_room_access_public_title), isSelected = state.currentRoomJoinRule == RoomJoinRules.PUBLIC ), RoomJoinRuleRadioAction( roomJoinRule = RoomJoinRules.RESTRICTED, description = if (state.parentSpaceName != null) { - stringProvider.getString(R.string.room_create_member_of_space_name_can_join, state.parentSpaceName) + stringProvider.getString(CommonStrings.room_create_member_of_space_name_can_join, state.parentSpaceName) } else { - stringProvider.getString(R.string.room_settings_room_access_restricted_description) + stringProvider.getString(CommonStrings.room_settings_room_access_restricted_description) }, - title = stringProvider.getString(R.string.room_settings_room_access_restricted_title), + title = stringProvider.getString(CommonStrings.room_settings_room_access_restricted_title), isSelected = state.currentRoomJoinRule == RoomJoinRules.RESTRICTED ) ).filter { state.allowedJoinedRules.map { it.rule }.contains(it.roomJoinRule) } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleFragment.kt index 1c4f93f49a..e747dcb2ee 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleFragment.kt @@ -26,7 +26,6 @@ import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.OnBackPressed @@ -35,6 +34,7 @@ import im.vector.app.databinding.FragmentJoinRulesRecyclerBinding import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedActions import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedViewModel +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.RoomJoinRules import javax.inject.Inject @@ -59,12 +59,12 @@ class RoomJoinRuleFragment : requireActivity().finish() } else { MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.dialog_title_warning) - .setMessage(R.string.warning_unsaved_change) - .setPositiveButton(R.string.warning_unsaved_change_discard) { _, _ -> + .setTitle(CommonStrings.dialog_title_warning) + .setMessage(CommonStrings.warning_unsaved_change) + .setPositiveButton(CommonStrings.warning_unsaved_change_discard) { _, _ -> requireActivity().finish() } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() return true } @@ -77,16 +77,16 @@ class RoomJoinRuleFragment : if (state.hasUnsavedChanges) { // show discard and save views.cancelButton.isVisible = true - views.positiveButton.text = getString(R.string.warning_unsaved_change_discard) + views.positiveButton.text = getString(CommonStrings.warning_unsaved_change_discard) views.positiveButton.isVisible = true - views.positiveButton.text = getString(R.string.action_save) + views.positiveButton.text = getString(CommonStrings.action_save) views.positiveButton.debouncedClicks { viewModel.handle(RoomJoinRuleChooseRestrictedActions.DoUpdateJoinRules) } } else { views.cancelButton.isVisible = false views.positiveButton.isVisible = true - views.positiveButton.text = getString(R.string.ok) + views.positiveButton.text = getString(CommonStrings.ok) views.positiveButton.debouncedClicks { requireActivity().finish() } } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/SpaceJoinRuleItem.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/SpaceJoinRuleItem.kt index eaba1a5fef..f239b8cc74 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/SpaceJoinRuleItem.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/SpaceJoinRuleItem.kt @@ -31,6 +31,7 @@ import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setAttributeTintedImageResource import im.vector.app.core.utils.DebouncedClickListener import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.util.MatrixItem @EpoxyModelClass @@ -58,11 +59,11 @@ abstract class SpaceJoinRuleItem : VectorEpoxyModel(R. holder.upgradeRequiredButton.setOnClickListener(DebouncedClickListener(listener)) if (selected) { - holder.radioImage.setAttributeTintedImageResource(R.drawable.ic_radio_on, R.attr.colorPrimary) - holder.radioImage.contentDescription = holder.view.context.getString(R.string.a11y_checked) + holder.radioImage.setAttributeTintedImageResource(R.drawable.ic_radio_on, com.google.android.material.R.attr.colorPrimary) + holder.radioImage.contentDescription = holder.view.context.getString(CommonStrings.a11y_checked) } else { holder.radioImage.setImageDrawable(ContextCompat.getDrawable(holder.view.context, R.drawable.ic_radio_off)) - holder.radioImage.contentDescription = holder.view.context.getString(R.string.a11y_unchecked) + holder.radioImage.contentDescription = holder.view.context.getString(CommonStrings.a11y_unchecked) } holder.upgradeRequiredButton.isVisible = needUpgrade diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/ChooseRestrictedController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/ChooseRestrictedController.kt index ed71b910c7..7972ac3249 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/ChooseRestrictedController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/ChooseRestrictedController.kt @@ -21,7 +21,6 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized -import im.vector.app.R import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.resources.StringProvider @@ -29,6 +28,7 @@ import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.spaces.manage.roomSelectionItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.util.MatrixItem import javax.inject.Inject @@ -56,7 +56,7 @@ class ChooseRestrictedController @Inject constructor( if (results.invoke().isEmpty()) { noResultItem { id("empty") - text(host.stringProvider.getString(R.string.no_result_placeholder)) + text(host.stringProvider.getString(CommonStrings.no_result_placeholder)) } } else { results.invoke().forEach { matrixItem -> @@ -77,7 +77,7 @@ class ChooseRestrictedController @Inject constructor( // when no filters genericFooterItem { id("h1") - text(host.stringProvider.getString(R.string.space_you_know_that_contains_this_room).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.space_you_know_that_contains_this_room).toEpoxyCharSequence()) centered(false) } @@ -94,7 +94,7 @@ class ChooseRestrictedController @Inject constructor( if (data.unknownRestricted.isNotEmpty()) { genericFooterItem { id("others") - text(host.stringProvider.getString(R.string.other_spaces_or_rooms_you_might_not_know).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.other_spaces_or_rooms_you_might_not_know).toEpoxyCharSequence()) centered(false) } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedViewModel.kt index 3e414e2e71..63db9c1336 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedViewModel.kt @@ -26,7 +26,6 @@ import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel @@ -35,6 +34,7 @@ import im.vector.app.core.utils.styleMatchingText import im.vector.app.features.displayname.getBestName import im.vector.app.features.roomprofile.settings.joinrule.toOption import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.Session @@ -219,11 +219,11 @@ class RoomJoinRuleChooseRestrictedViewModel @AssistedInject constructor( session.getRoomSummary(it)?.toMatrixItem() }?.firstOrNull() val description = if (candidate != null) { - stringProvider.getString(R.string.upgrade_room_for_restricted, candidate.getBestName()).toSpannable().let { + stringProvider.getString(CommonStrings.upgrade_room_for_restricted, candidate.getBestName()).toSpannable().let { it.styleMatchingText(candidate.getBestName(), Typeface.BOLD) } } else { - stringProvider.getString(R.string.upgrade_room_for_restricted_no_param) + stringProvider.getString(CommonStrings.upgrade_room_for_restricted_no_param) } if (action.rules == RoomJoinRules.RESTRICTED && state.upgradeNeededForRestricted) { diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsFragment.kt index f318ecc638..27e1654bf0 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsFragment.kt @@ -28,7 +28,6 @@ import com.airbnb.mvrx.withState import com.google.android.material.appbar.AppBarLayout import com.google.android.material.tabs.TabLayoutMediator import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.intent.getMimeTypeFromUri import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.saveMedia @@ -39,6 +38,7 @@ import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.notifications.NotificationUtils import im.vector.app.features.roomprofile.RoomProfileArgs import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject @@ -72,8 +72,8 @@ class RoomUploadsFragment : TabLayoutMediator(views.roomUploadsTabs, views.roomUploadsViewPager) { tab, position -> when (position) { - 0 -> tab.text = getString(R.string.uploads_media_title) - 1 -> tab.text = getString(R.string.uploads_files_title) + 0 -> tab.text = getString(CommonStrings.uploads_media_title) + 1 -> tab.text = getString(CommonStrings.uploads_files_title) } }.attach() diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/files/RoomUploadsFilesFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/files/RoomUploadsFilesFragment.kt index e7ee47020a..0f32773a3e 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/files/RoomUploadsFilesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/files/RoomUploadsFilesFragment.kt @@ -36,6 +36,7 @@ import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentGenericStateViewRecyclerBinding import im.vector.app.features.roomprofile.uploads.RoomUploadsAction import im.vector.app.features.roomprofile.uploads.RoomUploadsViewModel +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.uploads.UploadEvent import javax.inject.Inject @@ -106,7 +107,7 @@ class RoomUploadsFilesFragment : loadMore() } else { views.genericStateViewListStateView.state = StateView.State.Empty( - title = getString(R.string.uploads_files_no_result), + title = getString(CommonStrings.uploads_files_no_result), image = ContextCompat.getDrawable(requireContext(), R.drawable.ic_file) ) } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/files/UploadsFileController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/files/UploadsFileController.kt index b741b5c652..c3d93abef7 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/files/UploadsFileController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/files/UploadsFileController.kt @@ -18,12 +18,12 @@ package im.vector.app.features.roomprofile.uploads.files import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.epoxy.VisibilityState -import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.resources.StringProvider import im.vector.app.features.roomprofile.uploads.RoomUploadsViewState +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.uploads.UploadEvent import javax.inject.Inject @@ -70,7 +70,7 @@ class UploadsFileController @Inject constructor( title(uploadEvent.contentWithAttachmentContent.body) subtitle( host.stringProvider.getString( - R.string.uploads_files_subtitle, + CommonStrings.uploads_files_subtitle, uploadEvent.senderInfo.disambiguatedDisplayName, host.dateFormatter.format(uploadEvent.root.originServerTs, DateFormatKind.DEFAULT_DATE_AND_TIME) ) diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt index 98a28557ae..8fefc6c74e 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt @@ -47,6 +47,7 @@ import im.vector.app.features.roomprofile.uploads.RoomUploadsAction import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment import im.vector.app.features.roomprofile.uploads.RoomUploadsViewModel import im.vector.app.features.roomprofile.uploads.RoomUploadsViewState +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.crypto.attachments.toElementToDecrypt import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent @@ -206,7 +207,7 @@ class RoomUploadsMediaFragment : loadMore() } else { views.genericStateViewListStateView.state = StateView.State.Empty( - title = getString(R.string.uploads_media_no_result), + title = getString(CommonStrings.uploads_media_no_result), image = ContextCompat.getDrawable(requireContext(), R.drawable.ic_image) ) } diff --git a/vector/src/main/java/im/vector/app/features/settings/BackgroundSyncModeChooserDialog.kt b/vector/src/main/java/im/vector/app/features/settings/BackgroundSyncModeChooserDialog.kt index c64ade96c0..4d4f2fb707 100644 --- a/vector/src/main/java/im/vector/app/features/settings/BackgroundSyncModeChooserDialog.kt +++ b/vector/src/main/java/im/vector/app/features/settings/BackgroundSyncModeChooserDialog.kt @@ -22,6 +22,7 @@ import androidx.fragment.app.DialogFragment import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.databinding.DialogBackgroundSyncModeBinding +import im.vector.lib.strings.CommonStrings class BackgroundSyncModeChooserDialog : DialogFragment() { @@ -33,9 +34,9 @@ class BackgroundSyncModeChooserDialog : DialogFragment() { val view = requireActivity().layoutInflater.inflate(R.layout.dialog_background_sync_mode, null) val views = DialogBackgroundSyncModeBinding.bind(view) val dialog = MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.settings_background_fdroid_sync_mode) + .setTitle(CommonStrings.settings_background_fdroid_sync_mode) .setView(view) - .setPositiveButton(R.string.action_cancel, null) + .setPositiveButton(CommonStrings.action_cancel, null) .create() views.backgroundSyncModeBattery.setOnClickListener { diff --git a/vector/src/main/java/im/vector/app/features/settings/FontScalePreferences.kt b/vector/src/main/java/im/vector/app/features/settings/FontScalePreferences.kt index 34862adc4f..b9cda34278 100644 --- a/vector/src/main/java/im/vector/app/features/settings/FontScalePreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/FontScalePreferences.kt @@ -19,9 +19,9 @@ package im.vector.app.features.settings import android.content.SharedPreferences import androidx.annotation.StringRes import androidx.core.content.edit -import im.vector.app.R import im.vector.app.core.di.DefaultPreferences import im.vector.app.core.utils.SystemSettingsProvider +import im.vector.lib.strings.CommonStrings import javax.inject.Inject /** @@ -83,13 +83,13 @@ class FontScalePreferencesImpl @Inject constructor( } private val fontScaleValues = listOf( - FontScaleValue(0, "FONT_SCALE_TINY", FontScalePreferences.SCALE_TINY, R.string.tiny), - FontScaleValue(1, "FONT_SCALE_SMALL", FontScalePreferences.SCALE_SMALL, R.string.small), - FontScaleValue(2, "FONT_SCALE_NORMAL", FontScalePreferences.SCALE_NORMAL, R.string.normal), - FontScaleValue(3, "FONT_SCALE_LARGE", FontScalePreferences.SCALE_LARGE, R.string.large), - FontScaleValue(4, "FONT_SCALE_LARGER", FontScalePreferences.SCALE_LARGER, R.string.larger), - FontScaleValue(5, "FONT_SCALE_LARGEST", FontScalePreferences.SCALE_LARGEST, R.string.largest), - FontScaleValue(6, "FONT_SCALE_HUGE", FontScalePreferences.SCALE_HUGE, R.string.huge) + FontScaleValue(0, "FONT_SCALE_TINY", FontScalePreferences.SCALE_TINY, CommonStrings.tiny), + FontScaleValue(1, "FONT_SCALE_SMALL", FontScalePreferences.SCALE_SMALL, CommonStrings.small), + FontScaleValue(2, "FONT_SCALE_NORMAL", FontScalePreferences.SCALE_NORMAL, CommonStrings.normal), + FontScaleValue(3, "FONT_SCALE_LARGE", FontScalePreferences.SCALE_LARGE, CommonStrings.large), + FontScaleValue(4, "FONT_SCALE_LARGER", FontScalePreferences.SCALE_LARGER, CommonStrings.larger), + FontScaleValue(5, "FONT_SCALE_LARGEST", FontScalePreferences.SCALE_LARGEST, CommonStrings.largest), + FontScaleValue(6, "FONT_SCALE_HUGE", FontScalePreferences.SCALE_HUGE, CommonStrings.huge) ) private val normalFontScaleValue = fontScaleValues[2] diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorLocale.kt b/vector/src/main/java/im/vector/app/features/settings/VectorLocale.kt index b1a3fa9566..a7465d96f5 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorLocale.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorLocale.kt @@ -20,9 +20,9 @@ import android.content.Context import android.content.SharedPreferences import android.content.res.Configuration import androidx.core.content.edit -import im.vector.app.R import im.vector.app.core.di.DefaultPreferences import im.vector.app.core.resources.BuildMeta +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import timber.log.Timber @@ -76,8 +76,8 @@ class VectorLocale @Inject constructor( applicationLocale = Locale.getDefault() // detect if the default language is used - val defaultStringValue = getString(context, defaultLocale, R.string.resources_country_code) - if (defaultStringValue == getString(context, applicationLocale, R.string.resources_country_code)) { + val defaultStringValue = getString(context, defaultLocale, CommonStrings.resources_country_code) + if (defaultStringValue == getString(context, applicationLocale, CommonStrings.resources_country_code)) { applicationLocale = defaultLocale } @@ -154,9 +154,9 @@ class VectorLocale @Inject constructor( for (locale in availableLocales) { knownLocalesSet.add( Triple( - getString(context, locale, R.string.resources_language), - getString(context, locale, R.string.resources_country_code), - getString(context, locale, R.string.resources_script) + getString(context, locale, CommonStrings.resources_language), + getString(context, locale, CommonStrings.resources_country_code), + getString(context, locale, CommonStrings.resources_script) ) ) } @@ -164,9 +164,9 @@ class VectorLocale @Inject constructor( Timber.e(e, "## getApplicationLocales() : failed") knownLocalesSet.add( Triple( - context.getString(R.string.resources_language), - context.getString(R.string.resources_country_code), - context.getString(R.string.resources_script) + context.getString(CommonStrings.resources_language), + context.getString(CommonStrings.resources_country_code), + context.getString(CommonStrings.resources_script) ) ) } 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 ed6f993e51..b2b76e9ee5 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 @@ -23,7 +23,6 @@ import android.provider.MediaStore import androidx.annotation.BoolRes import androidx.core.content.edit import com.squareup.seismic.ShakeDetector -import im.vector.app.R import im.vector.app.core.di.DefaultPreferences import im.vector.app.core.resources.BuildMeta import im.vector.app.core.resources.StringProvider @@ -32,6 +31,7 @@ import im.vector.app.features.home.ShortcutsHandler import im.vector.app.features.homeserver.ServerUrlsRepository import im.vector.app.features.themes.ThemeUtils import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.tryOrNull import timber.log.Timber import javax.inject.Inject @@ -719,10 +719,10 @@ class VectorPreferences @Inject constructor( */ fun getSelectedMediasSavingPeriodString(): String { return when (getSelectedMediasSavingPeriod()) { - MEDIA_SAVING_3_DAYS -> stringProvider.getString(R.string.media_saving_period_3_days) - MEDIA_SAVING_1_WEEK -> stringProvider.getString(R.string.media_saving_period_1_week) - MEDIA_SAVING_1_MONTH -> stringProvider.getString(R.string.media_saving_period_1_month) - MEDIA_SAVING_FOREVER -> stringProvider.getString(R.string.media_saving_period_forever) + MEDIA_SAVING_3_DAYS -> stringProvider.getString(CommonStrings.media_saving_period_3_days) + MEDIA_SAVING_1_WEEK -> stringProvider.getString(CommonStrings.media_saving_period_1_week) + MEDIA_SAVING_1_MONTH -> stringProvider.getString(CommonStrings.media_saving_period_1_month) + MEDIA_SAVING_FOREVER -> stringProvider.getString(CommonStrings.media_saving_period_forever) else -> "?" } } @@ -760,7 +760,7 @@ class VectorPreferences @Inject constructor( * @return true if the text formatting is enabled */ fun isTextFormattingEnabled(): Boolean = - defaultPrefs.getBoolean(SETTINGS_ENABLE_RICH_TEXT_FORMATTING_KEY, true) + defaultPrefs.getBoolean(SETTINGS_ENABLE_RICH_TEXT_FORMATTING_KEY, true) /** * Update whether text formatting is enabled within the rich text editor. @@ -768,9 +768,9 @@ class VectorPreferences @Inject constructor( * @param isEnabled true to enable the text formatting */ fun setTextFormattingEnabled(isEnabled: Boolean) = - defaultPrefs.edit { - putBoolean(SETTINGS_ENABLE_RICH_TEXT_FORMATTING_KEY, isEnabled) - } + defaultPrefs.edit { + putBoolean(SETTINGS_ENABLE_RICH_TEXT_FORMATTING_KEY, isEnabled) + } /** * Tells if a confirmation dialog should be displayed before staring a call. @@ -930,7 +930,7 @@ class VectorPreferences @Inject constructor( * @return true to show timeline message in bubble. */ fun useMessageBubblesLayout(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_INTERFACE_BUBBLE_KEY, getDefault(R.bool.settings_interface_bubble_default)) + return defaultPrefs.getBoolean(SETTINGS_INTERFACE_BUBBLE_KEY, getDefault(im.vector.app.config.R.bool.settings_interface_bubble_default)) } /** @@ -941,7 +941,7 @@ class VectorPreferences @Inject constructor( fun userAlwaysAppearsOffline(): Boolean { return defaultPrefs.getBoolean( SETTINGS_PRESENCE_USER_ALWAYS_APPEARS_OFFLINE, - getDefault(R.bool.settings_presence_user_always_appears_offline_default) + getDefault(im.vector.app.config.R.bool.settings_presence_user_always_appears_offline_default) ) } @@ -1123,7 +1123,7 @@ class VectorPreferences @Inject constructor( * Indicates whether or not thread messages are enabled. */ fun areThreadMessagesEnabled(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_THREAD_MESSAGES, getDefault(R.bool.settings_labs_thread_messages_default)) + return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_THREAD_MESSAGES, getDefault(im.vector.app.config.R.bool.settings_labs_thread_messages_default)) } /** @@ -1214,45 +1214,62 @@ class VectorPreferences @Inject constructor( */ fun isNewAppLayoutEnabled(): Boolean { return vectorFeatures.isNewAppLayoutFeatureEnabled() && - defaultPrefs.getBoolean(SETTINGS_LABS_NEW_APP_LAYOUT_KEY, getDefault(R.bool.settings_labs_new_app_layout_default)) + defaultPrefs.getBoolean(SETTINGS_LABS_NEW_APP_LAYOUT_KEY, getDefault(im.vector.app.config.R.bool.settings_labs_new_app_layout_default)) } /** * Indicates whether or not deferred DMs are enabled. */ fun isDeferredDmEnabled(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_LABS_DEFERRED_DM_KEY, getDefault(R.bool.settings_labs_deferred_dm_default)) + return defaultPrefs.getBoolean(SETTINGS_LABS_DEFERRED_DM_KEY, getDefault(im.vector.app.config.R.bool.settings_labs_deferred_dm_default)) } /** * Indicates whether or not new session manager screens are enabled. */ fun isNewSessionManagerEnabled(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_LABS_NEW_SESSION_MANAGER_KEY, getDefault(R.bool.settings_labs_new_session_manager_default)) + return defaultPrefs.getBoolean(SETTINGS_LABS_NEW_SESSION_MANAGER_KEY, getDefault(im.vector.app.config.R.bool.settings_labs_new_session_manager_default)) } /** * Indicates whether or not client info recording is enabled. */ fun isClientInfoRecordingEnabled(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_LABS_CLIENT_INFO_RECORDING_KEY, getDefault(R.bool.settings_labs_client_info_recording_default)) + return defaultPrefs.getBoolean( + SETTINGS_LABS_CLIENT_INFO_RECORDING_KEY, + getDefault( + im.vector.app.config.R.bool.settings_labs_client_info_recording_default + ) + ) } fun showLiveSenderInfo(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_TIMELINE_SHOW_LIVE_SENDER_INFO, getDefault(R.bool.settings_timeline_show_live_sender_info_default)) + return defaultPrefs.getBoolean( + SETTINGS_TIMELINE_SHOW_LIVE_SENDER_INFO, + getDefault(im.vector.app.config.R.bool.settings_timeline_show_live_sender_info_default) + ) } fun isRichTextEditorEnabled(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_LABS_RICH_TEXT_EDITOR_KEY, getDefault(R.bool.settings_labs_rich_text_editor_default)) + return defaultPrefs.getBoolean( + SETTINGS_LABS_RICH_TEXT_EDITOR_KEY, + getDefault(im.vector.app.config.R.bool.settings_labs_rich_text_editor_default) + ) } fun isVoiceBroadcastEnabled(): Boolean { return vectorFeatures.isVoiceBroadcastEnabled() && - defaultPrefs.getBoolean(SETTINGS_LABS_VOICE_BROADCAST_KEY, getDefault(R.bool.settings_labs_enable_voice_broadcast_default)) + defaultPrefs.getBoolean( + SETTINGS_LABS_VOICE_BROADCAST_KEY, + getDefault(im.vector.app.config.R.bool.settings_labs_enable_voice_broadcast_default) + ) } fun showIpAddressInSessionManagerScreens(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_SESSION_MANAGER_SHOW_IP_ADDRESS, getDefault(R.bool.settings_session_manager_show_ip_address)) + return defaultPrefs.getBoolean( + SETTINGS_SESSION_MANAGER_SHOW_IP_ADDRESS, + getDefault(im.vector.app.config.R.bool.settings_session_manager_show_ip_address) + ) } fun setIpAddressVisibilityInDeviceManagerScreens(isVisible: Boolean) { diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsActivity.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsActivity.kt index 33557fabef..ea111f850a 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsActivity.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsActivity.kt @@ -35,6 +35,7 @@ import im.vector.app.features.settings.devices.VectorSettingsDevicesFragment import im.vector.app.features.settings.notifications.VectorSettingsNotificationFragment import im.vector.app.features.settings.threepids.ThreePidsSettingsFragment import im.vector.lib.core.utils.compat.getParcelableExtraCompat +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.failure.GlobalError import org.matrix.android.sdk.api.session.Session import timber.log.Timber @@ -55,7 +56,7 @@ class VectorSettingsActivity : VectorBaseActivity override fun getCoordinatorLayout() = views.coordinatorLayout - override fun getTitleRes() = R.string.title_activity_settings + override fun getTitleRes() = CommonStrings.title_activity_settings private var keyToHighlight: String? = null @@ -122,7 +123,7 @@ class VectorSettingsActivity : VectorBaseActivity supportFragmentManager.fragmentFactory.instantiate(classLoader, it) } } catch (e: Throwable) { - showSnackbar(getString(R.string.not_implemented)) + showSnackbar(getString(CommonStrings.not_implemented)) Timber.e(e) null } 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 0a9350fdef..32d811ebe8 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 @@ -29,13 +29,14 @@ import im.vector.app.core.utils.copyToClipboard import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.home.NightlyProxy import im.vector.app.features.rageshake.RageShake +import im.vector.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint class VectorSettingsAdvancedSettingsFragment : VectorSettingsBaseFragment() { - override var titleRes = R.string.settings_advanced_settings + override var titleRes = CommonStrings.settings_advanced_settings override val preferenceXmlRes = R.xml.vector_settings_advanced_settings @Inject lateinit var nightlyProxy: NightlyProxy @@ -52,7 +53,7 @@ class VectorSettingsAdvancedSettingsFragment : rageshake = (activity as? VectorBaseActivity<*>)?.rageShake rageshake?.interceptor = { - (activity as? VectorBaseActivity<*>)?.showSnackbar(getString(R.string.rageshake_detected)) + (activity as? VectorBaseActivity<*>)?.showSnackbar(getString(CommonStrings.rageshake_detected)) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsBaseFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsBaseFragment.kt index 724807a81e..2f991ba0d3 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsBaseFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsBaseFragment.kt @@ -35,6 +35,7 @@ import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.utils.toast import im.vector.app.features.analytics.AnalyticsTracker import im.vector.app.features.analytics.plan.MobileScreen +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @@ -131,8 +132,8 @@ abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat(), Maverick protected fun notImplemented() { // Snackbar cannot be display on PreferenceFragment. TODO It's maybe because the show() method is not used... - // Snackbar.make(requireView(), R.string.not_implemented, Snackbar.LENGTH_SHORT) - activity?.toast(R.string.not_implemented) + // Snackbar.make(requireView(), CommonStrings.not_implemented, Snackbar.LENGTH_SHORT) + activity?.toast(CommonStrings.not_implemented) } /** @@ -178,9 +179,9 @@ abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat(), Maverick protected fun displayErrorDialog(errorMessage: String) { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(errorMessage) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt index a883d22334..102f7020ef 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt @@ -58,6 +58,7 @@ import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.discovery.DiscoverySettingsFragment import im.vector.app.features.navigation.SettingsActivityPayload import im.vector.app.features.workers.signout.SignOutUiWorker +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChangedBy @@ -85,7 +86,7 @@ class VectorSettingsGeneralFragment : @Inject lateinit var galleryOrCameraDialogHelperFactory: GalleryOrCameraDialogHelperFactory - override var titleRes = R.string.settings_general_title + override var titleRes = CommonStrings.settings_general_title override val preferenceXmlRes = R.xml.vector_settings_general private lateinit var galleryOrCameraDialogHelper: GalleryOrCameraDialogHelper @@ -232,7 +233,7 @@ class VectorSettingsGeneralFragment : val hostname = URL(homeServerCapabilities.externalAccountManagementUrl).host mExternalAccountManagementPreference.summary = requireContext().getString( - R.string.settings_external_account_management, + CommonStrings.settings_external_account_management, hostname ) } else { @@ -296,7 +297,7 @@ class VectorSettingsGeneralFragment : // clear medias cache findPreference(VectorPreferences.SETTINGS_CLEAR_MEDIA_CACHE_PREFERENCE_KEY)!!.let { lifecycleScope.launch(Dispatchers.Main) { - it.summary = getString(R.string.loading) + it.summary = getString(CommonStrings.loading) val size = getCacheSize() it.summary = TextUtils.formatFileSize(requireContext(), size) it.onPreferenceClickListener = Preference.OnPreferenceClickListener { @@ -338,7 +339,7 @@ class VectorSettingsGeneralFragment : override fun onResume() { super.onResume() // Refresh identity server summary - mIdentityServerPreference.summary = session.identityService().getCurrentIdentityServerUrl() ?: getString(R.string.identity_server_not_defined) + mIdentityServerPreference.summary = session.identityService().getCurrentIdentityServerUrl() ?: getString(CommonStrings.identity_server_not_defined) refreshIntegrationManagerSettings() session.integrationManagerService().addListener(integrationServiceListener) } @@ -431,8 +432,8 @@ class VectorSettingsGeneralFragment : val dialog = MaterialAlertDialogBuilder(activity) .setView(view) .setCancelable(false) - .setPositiveButton(R.string.settings_change_password, null) - .setNegativeButton(R.string.action_cancel, null) + .setPositiveButton(CommonStrings.settings_change_password, null) + .setNegativeButton(CommonStrings.action_cancel, null) .setOnDismissListener { view.hideKeyboard() } @@ -500,12 +501,12 @@ class VectorSettingsGeneralFragment : showPasswordLoadingView(false) result.fold({ dialog.dismiss() - activity.toast(R.string.settings_password_updated) + activity.toast(CommonStrings.settings_password_updated) }, { failure -> if (failure.isInvalidPassword()) { - views.changePasswordOldPwdTil.error = getString(R.string.settings_fail_to_update_password_invalid_current_password) + views.changePasswordOldPwdTil.error = getString(CommonStrings.settings_fail_to_update_password_invalid_current_password) } else { - views.changePasswordOldPwdTil.error = getString(R.string.settings_fail_to_update_password) + views.changePasswordOldPwdTil.error = getString(CommonStrings.settings_fail_to_update_password) } }) } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt index 359cc041f8..c6bbf68238 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt @@ -29,6 +29,7 @@ import im.vector.app.core.utils.openAppSettingsPage import im.vector.app.core.utils.openUrlInChromeCustomTab import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.version.VersionProvider +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.Matrix import javax.inject.Inject @@ -39,7 +40,7 @@ class VectorSettingsHelpAboutFragment : @Inject lateinit var versionProvider: VersionProvider @Inject lateinit var buildMeta: BuildMeta - override var titleRes = R.string.preference_root_help_about + override var titleRes = CommonStrings.preference_root_help_about override val preferenceXmlRes = R.xml.vector_settings_help_about private val firstThrottler = FirstThrottler(1000) diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPinFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPinFragment.kt index f86095e12d..ca06e75eb7 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPinFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPinFragment.kt @@ -31,6 +31,7 @@ import im.vector.app.features.pin.PinMode 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 +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import org.matrix.android.sdk.api.extensions.orFalse @@ -47,7 +48,7 @@ class VectorSettingsPinFragment : @Inject lateinit var biometricHelperFactory: BiometricHelper.BiometricHelperFactory @Inject lateinit var defaultLockScreenConfiguration: LockScreenConfiguration - override var titleRes = R.string.settings_security_application_protection_screen_title + override var titleRes = CommonStrings.settings_security_application_protection_screen_title override val preferenceXmlRes = R.xml.vector_settings_pin private val biometricHelper by lazy { @@ -160,7 +161,7 @@ class VectorSettingsPinFragment : } private fun showEnableBiometricErrorMessage() { - context?.toast(R.string.settings_security_pin_code_use_biometrics_error) + context?.toast(CommonStrings.settings_security_pin_code_use_biometrics_error) } private val pinActivityResultLauncher = registerStartForActivityResult { diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt index 01dd014f92..42841e43d5 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt @@ -35,6 +35,7 @@ import im.vector.app.features.VectorFeatures import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.settings.font.FontScaleSettingActivity import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.presence.model.PresenceEnum import javax.inject.Inject @@ -48,7 +49,7 @@ class VectorSettingsPreferencesFragment : @Inject lateinit var vectorFeatures: VectorFeatures @Inject lateinit var vectorLocale: VectorLocale - override var titleRes = R.string.settings_preferences + override var titleRes = CommonStrings.settings_preferences override val preferenceXmlRes = R.xml.vector_settings_preferences private val selectedLanguagePreference by lazy { @@ -155,7 +156,7 @@ class VectorSettingsPreferencesFragment : context?.let { context: Context -> MaterialAlertDialogBuilder(context) .setSingleChoiceItems( - R.array.media_saving_choice, + im.vector.lib.strings.R.array.media_saving_choice, vectorPreferences.getSelectedMediasSavingPeriod() ) { d, n -> vectorPreferences.setSelectedMediasSavingPeriod(n) @@ -185,10 +186,10 @@ class VectorSettingsPreferencesFragment : private fun updateTakePhotoOrVideoPreferenceSummary() { takePhotoOrVideoPreference.summary = getString( when (vectorPreferences.getTakePhotoVideoMode()) { - VectorPreferences.TAKE_PHOTO_VIDEO_MODE_PHOTO -> R.string.option_take_photo - VectorPreferences.TAKE_PHOTO_VIDEO_MODE_VIDEO -> R.string.option_take_video + VectorPreferences.TAKE_PHOTO_VIDEO_MODE_PHOTO -> CommonStrings.option_take_photo + VectorPreferences.TAKE_PHOTO_VIDEO_MODE_VIDEO -> CommonStrings.option_take_video /* VectorPreferences.TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK */ - else -> R.string.option_always_ask + else -> CommonStrings.option_always_ask } ) } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsRootFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsRootFragment.kt index 0b3dcfa2ac..4bb4f270b3 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsRootFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsRootFragment.kt @@ -21,12 +21,13 @@ import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R import im.vector.app.core.preference.VectorPreference import im.vector.app.features.analytics.plan.MobileScreen +import im.vector.lib.strings.CommonStrings @AndroidEntryPoint class VectorSettingsRootFragment : VectorSettingsBaseFragment() { - override var titleRes: Int = R.string.title_activity_settings + override var titleRes: Int = CommonStrings.title_activity_settings override val preferenceXmlRes = R.xml.vector_settings_root override fun onCreate(savedInstanceState: Bundle?) { 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 da0f2e46e2..ff580e2e5d 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 @@ -48,6 +48,7 @@ import im.vector.app.core.platform.SimpleTextWatcher import im.vector.app.core.preference.VectorPreference import im.vector.app.core.preference.VectorPreferenceCategory import im.vector.app.core.preference.VectorSwitchPreference +import im.vector.app.core.resources.BuildMeta import im.vector.app.core.utils.copyToClipboard import im.vector.app.core.utils.openFileSelection import im.vector.app.core.utils.toast @@ -68,6 +69,8 @@ import im.vector.app.features.pin.PinMode import im.vector.app.features.raw.wellknown.getElementWellknown import im.vector.app.features.raw.wellknown.isE2EByDefault import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -93,8 +96,9 @@ class VectorSettingsSecurityPrivacyFragment : @Inject lateinit var navigator: Navigator @Inject lateinit var analyticsConfig: AnalyticsConfig @Inject lateinit var vectorPreferences: VectorPreferences + @Inject lateinit var buildMeta: BuildMeta - override var titleRes = R.string.settings_security_and_privacy + override var titleRes = CommonStrings.settings_security_and_privacy override val preferenceXmlRes = R.xml.vector_settings_security_privacy private val analyticsConsentViewModel: AnalyticsConsentViewModel by fragmentViewModel() @@ -221,7 +225,7 @@ class VectorSettingsSecurityPrivacyFragment : if (info.isCrossSigningEnabled && info.allPrivateKeysKnown) { // You can setup recovery! secureBackupCategory.isVisible = true - secureBackupPreference.title = getString(R.string.settings_secure_backup_setup) + secureBackupPreference.title = getString(CommonStrings.settings_secure_backup_setup) secureBackupPreference.onPreferenceClickListener = Preference.OnPreferenceClickListener { BootstrapBottomSheet.show(parentFragmentManager, SetupMode.NORMAL) true @@ -240,7 +244,7 @@ class VectorSettingsSecurityPrivacyFragment : // Only option here is to create a new backup if you want? // aka reset secureBackupCategory.isVisible = true - secureBackupPreference.title = getString(R.string.settings_secure_backup_reset) + secureBackupPreference.title = getString(CommonStrings.settings_secure_backup_reset) secureBackupPreference.onPreferenceClickListener = Preference.OnPreferenceClickListener { BootstrapBottomSheet.show(parentFragmentManager, SetupMode.PASSPHRASE_RESET) true @@ -249,7 +253,7 @@ class VectorSettingsSecurityPrivacyFragment : // megolm backup is available but we don't have key // you could try to synchronize to get missing megolm key ? secureBackupCategory.isVisible = true - secureBackupPreference.title = getString(R.string.settings_secure_backup_enter_to_setup) + secureBackupPreference.title = getString(CommonStrings.settings_secure_backup_enter_to_setup) secureBackupPreference.onPreferenceClickListener = Preference.OnPreferenceClickListener { vectorActivity.let { it.navigator.requestSelfSessionVerification(it) @@ -263,7 +267,7 @@ class VectorSettingsSecurityPrivacyFragment : // there is a backup, but this session is not trusted, or is missing some secrets // you should enter passphrase to get them or verify against another session secureBackupCategory.isVisible = true - secureBackupPreference.title = getString(R.string.settings_secure_backup_enter_to_setup) + secureBackupPreference.title = getString(CommonStrings.settings_secure_backup_enter_to_setup) secureBackupPreference.onPreferenceClickListener = Preference.OnPreferenceClickListener { vectorActivity.let { it.navigator.requestSelfSessionVerification(it) @@ -294,25 +298,25 @@ class VectorSettingsSecurityPrivacyFragment : secureBackupPreference.icon = activity?.let { ThemeUtils.tintDrawable( it, - ContextCompat.getDrawable(it, R.drawable.ic_secure_backup)!!, R.attr.vctr_content_primary + ContextCompat.getDrawable(it, R.drawable.ic_secure_backup)!!, im.vector.lib.ui.styles.R.attr.vctr_content_primary ) } ignoredUsersPreference.icon = activity?.let { ThemeUtils.tintDrawable( it, - ContextCompat.getDrawable(it, R.drawable.ic_settings_root_ignored_users)!!, R.attr.vctr_content_primary + ContextCompat.getDrawable(it, R.drawable.ic_settings_root_ignored_users)!!, im.vector.lib.ui.styles.R.attr.vctr_content_primary ) } findPreference(VectorPreferences.SETTINGS_CRYPTOGRAPHY_HS_ADMIN_DISABLED_E2E_DEFAULT)?.let { it.icon = ThemeUtils.tintDrawableWithColor( ContextCompat.getDrawable(requireContext(), R.drawable.ic_notification_privacy_warning)!!, - ThemeUtils.getColor(requireContext(), R.attr.colorError) + ThemeUtils.getColor(requireContext(), com.google.android.material.R.attr.colorError) ) it.summary = span { - text = getString(R.string.settings_hs_admin_e2e_disabled) - textColor = ThemeUtils.getColor(requireContext(), R.attr.colorError) + text = getString(CommonStrings.settings_hs_admin_e2e_disabled) + textColor = ThemeUtils.getColor(requireContext(), com.google.android.material.R.attr.colorError) } } } @@ -360,19 +364,19 @@ class VectorSettingsSecurityPrivacyFragment : when { xSigningKeyCanSign -> { mCrossSigningStatePreference.setIcon(R.drawable.ic_shield_trusted) - mCrossSigningStatePreference.summary = getString(R.string.encryption_information_dg_xsigning_complete) + mCrossSigningStatePreference.summary = getString(CommonStrings.encryption_information_dg_xsigning_complete) } xSigningKeysAreTrusted -> { mCrossSigningStatePreference.setIcon(R.drawable.ic_shield_custom) - mCrossSigningStatePreference.summary = getString(R.string.encryption_information_dg_xsigning_trusted) + mCrossSigningStatePreference.summary = getString(CommonStrings.encryption_information_dg_xsigning_trusted) } xSigningIsEnableInAccount -> { mCrossSigningStatePreference.setIcon(R.drawable.ic_shield_black) - mCrossSigningStatePreference.summary = getString(R.string.encryption_information_dg_xsigning_not_trusted) + mCrossSigningStatePreference.summary = getString(CommonStrings.encryption_information_dg_xsigning_not_trusted) } else -> { mCrossSigningStatePreference.setIcon(android.R.color.transparent) - mCrossSigningStatePreference.summary = getString(R.string.encryption_information_dg_xsigning_disabled) + mCrossSigningStatePreference.summary = getString(CommonStrings.encryption_information_dg_xsigning_disabled) } } mCrossSigningStatePreference.isVisible = true @@ -396,7 +400,7 @@ class VectorSettingsSecurityPrivacyFragment : lifecycleScope.launch { try { keysExporter.export(passphrase, uri) - requireActivity().toast(getString(R.string.encryption_exported_successfully)) + requireActivity().toast(getString(CommonStrings.encryption_exported_successfully)) } catch (failure: Throwable) { requireActivity().toast(errorFormatter.toHumanReadable(failure)) } @@ -451,7 +455,11 @@ class VectorSettingsSecurityPrivacyFragment : } exportPref.onPreferenceClickListener = Preference.OnPreferenceClickListener { - queryExportKeys(activeSessionHolder.getSafeActiveSession()?.myUserId ?: "", saveMegolmStartForActivityResult) + queryExportKeys( + userId = activeSessionHolder.getSafeActiveSession()?.myUserId ?: "", + applicationName = buildMeta.applicationName, + activityResultLauncher = saveMegolmStartForActivityResult, + ) true } @@ -511,11 +519,11 @@ class VectorSettingsSecurityPrivacyFragment : views.dialogE2eKeysPassphraseFilename.isVisible = false } else { views.dialogE2eKeysPassphraseFilename.isVisible = true - views.dialogE2eKeysPassphraseFilename.text = getString(R.string.import_e2e_keys_from_file, filename) + views.dialogE2eKeysPassphraseFilename.text = getString(CommonStrings.import_e2e_keys_from_file, filename) } val builder = MaterialAlertDialogBuilder(thisActivity) - .setTitle(R.string.encryption_import_room_keys) + .setTitle(CommonStrings.encryption_import_room_keys) .setView(dialogLayout) views.dialogE2eKeysPassphraseEditText.addTextChangedListener(object : SimpleTextWatcher() { @@ -544,13 +552,13 @@ class VectorSettingsSecurityPrivacyFragment : MaterialAlertDialogBuilder(thisActivity) .setMessage( resources.getQuantityString( - R.plurals.encryption_import_room_keys_success, + CommonPlurals.encryption_import_room_keys_success, data.successfullyNumberOfImportedKeys, data.successfullyNumberOfImportedKeys, data.totalNumberOfKeys ) ) - .setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() } + .setPositiveButton(CommonStrings.ok) { dialog, _ -> dialog.dismiss() } .show() } } @@ -569,11 +577,11 @@ class VectorSettingsSecurityPrivacyFragment : private suspend fun refreshCryptographyPreference(devices: List) { showDeviceListPref.isVisible = !vectorPreferences.isNewSessionManagerEnabled() showDeviceListPref.isEnabled = devices.isNotEmpty() - showDeviceListPref.summary = resources.getQuantityString(R.plurals.settings_active_sessions_count, devices.size, devices.size) + showDeviceListPref.summary = resources.getQuantityString(CommonPlurals.settings_active_sessions_count, devices.size, devices.size) showDevicesListV2Pref.isVisible = vectorPreferences.isNewSessionManagerEnabled() showDevicesListV2Pref.isEnabled = devices.isNotEmpty() - showDevicesListV2Pref.summary = resources.getQuantityString(R.plurals.settings_active_sessions_count, devices.size, devices.size) + showDevicesListV2Pref.summary = resources.getQuantityString(CommonPlurals.settings_active_sessions_count, devices.size, devices.size) val userId = session.myUserId val deviceId = session.sessionParams.deviceId diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsVoiceVideoFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsVoiceVideoFragment.kt index 1cb7dcbf28..4548c2283f 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsVoiceVideoFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsVoiceVideoFragment.kt @@ -30,6 +30,7 @@ import im.vector.app.core.preference.VectorPreference import im.vector.app.core.utils.RingtoneUtils import im.vector.app.features.analytics.plan.MobileScreen import im.vector.lib.core.utils.compat.getParcelableExtraCompat +import im.vector.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint @@ -37,7 +38,7 @@ class VectorSettingsVoiceVideoFragment : VectorSettingsBaseFragment() { @Inject lateinit var ringtoneUtils: RingtoneUtils - override var titleRes = R.string.preference_voice_and_video + override var titleRes = CommonStrings.preference_voice_and_video override val preferenceXmlRes = R.xml.vector_settings_voice_video private val mUseRiotCallRingtonePreference by lazy { @@ -80,7 +81,7 @@ class VectorSettingsVoiceVideoFragment : VectorSettingsBaseFragment() { private fun displayRingtonePicker() { val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER).apply { - putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, getString(R.string.settings_call_ringtone_dialog_title)) + putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, getString(CommonStrings.settings_call_ringtone_dialog_title)) putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false) putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true) putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE) diff --git a/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountFragment.kt b/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountFragment.kt index c9a43c5e31..5ad6e895c8 100644 --- a/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountFragment.kt @@ -25,7 +25,6 @@ import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity import com.airbnb.mvrx.fragmentViewModel import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentDeactivateAccountBinding @@ -34,6 +33,7 @@ import im.vector.app.features.MainActivityArgs import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.auth.ReAuthActivity import im.vector.app.features.settings.VectorSettingsActivity +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.session.uia.exceptions.UiaCancelledException @@ -73,7 +73,7 @@ class DeactivateAccountFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.deactivate_account_title) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.deactivate_account_title) } private var settingsActivity: VectorSettingsActivity? = null @@ -131,7 +131,7 @@ class DeactivateAccountFragment : requireContext(), it.registrationFlowResponse, it.lastErrorCode, - getString(R.string.deactivate_account_title) + getString(CommonStrings.deactivate_account_title) ).let { intent -> reAuthActivityResultLauncher.launch(intent) } diff --git a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsController.kt b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsController.kt index 7ab30f9459..f484c68dfb 100644 --- a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsController.kt @@ -25,6 +25,7 @@ import im.vector.app.core.ui.list.genericPositiveButtonItem import im.vector.app.core.ui.list.genericWithValueItem import im.vector.app.core.utils.DimensionConverter import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span import javax.inject.Inject @@ -48,11 +49,11 @@ class CrossSigningSettingsController @Inject constructor( genericItem { id("can") titleIconResourceId(R.drawable.ic_shield_trusted) - title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_complete).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.encryption_information_dg_xsigning_complete).toEpoxyCharSequence()) } genericButtonItem { id("Reset") - text(host.stringProvider.getString(R.string.reset_cross_signing)) + text(host.stringProvider.getString(CommonStrings.reset_cross_signing)) buttonClickAction { host.interactionListener?.didTapInitializeCrossSigning() } @@ -62,11 +63,11 @@ class CrossSigningSettingsController @Inject constructor( genericItem { id("trusted") titleIconResourceId(R.drawable.ic_shield_custom) - title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_trusted).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.encryption_information_dg_xsigning_trusted).toEpoxyCharSequence()) } genericButtonItem { id("Reset") - text(host.stringProvider.getString(R.string.reset_cross_signing)) + text(host.stringProvider.getString(CommonStrings.reset_cross_signing)) buttonClickAction { host.interactionListener?.didTapInitializeCrossSigning() } @@ -76,11 +77,11 @@ class CrossSigningSettingsController @Inject constructor( genericItem { id("enable") titleIconResourceId(R.drawable.ic_shield_black) - title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_not_trusted).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.encryption_information_dg_xsigning_not_trusted).toEpoxyCharSequence()) } genericButtonItem { id("Reset") - text(host.stringProvider.getString(R.string.reset_cross_signing)) + text(host.stringProvider.getString(CommonStrings.reset_cross_signing)) buttonClickAction { host.interactionListener?.didTapInitializeCrossSigning() } @@ -89,12 +90,12 @@ class CrossSigningSettingsController @Inject constructor( else -> { genericItem { id("not") - title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_disabled).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.encryption_information_dg_xsigning_disabled).toEpoxyCharSequence()) } genericPositiveButtonItem { id("Initialize") - text(host.stringProvider.getString(R.string.initialize_cross_signing)) + text(host.stringProvider.getString(CommonStrings.initialize_cross_signing)) buttonClickAction { host.interactionListener?.didTapInitializeCrossSigning() } @@ -113,7 +114,7 @@ class CrossSigningSettingsController @Inject constructor( +"Master Key:\n" span { text = it.unpaddedBase64PublicKey ?: "" - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(12) } }.toEpoxyCharSequence() @@ -129,7 +130,7 @@ class CrossSigningSettingsController @Inject constructor( +"User Key:\n" span { text = it.unpaddedBase64PublicKey ?: "" - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(12) } }.toEpoxyCharSequence() @@ -145,7 +146,7 @@ class CrossSigningSettingsController @Inject constructor( +"Self Signed Key:\n" span { text = it.unpaddedBase64PublicKey ?: "" - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(12) } }.toEpoxyCharSequence() diff --git a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsFragment.kt index c0cefc9bcf..c5d510b278 100644 --- a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsFragment.kt @@ -26,7 +26,6 @@ import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.registerStartForActivityResult @@ -34,6 +33,7 @@ import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentGenericRecyclerBinding import im.vector.app.features.auth.ReAuthActivity +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import javax.inject.Inject @@ -81,9 +81,9 @@ class CrossSigningSettingsFragment : when (event) { is CrossSigningSettingsViewEvents.Failure -> { MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(errorFormatter.toHumanReadable(event.throwable)) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() Unit } @@ -92,7 +92,7 @@ class CrossSigningSettingsFragment : requireContext(), event.registrationFlowResponse, event.lastErrorCode, - getString(R.string.initialize_cross_signing) + getString(CommonStrings.initialize_cross_signing) ).let { intent -> reAuthActivityResultLauncher.launch(intent) } @@ -110,7 +110,7 @@ class CrossSigningSettingsFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.encryption_information_cross_signing_state) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.encryption_information_cross_signing_state) } override fun invalidate() = withState(viewModel) { state -> diff --git a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt index 3ea66b5dfe..469013bc38 100644 --- a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt @@ -19,13 +19,13 @@ import com.airbnb.mvrx.MavericksViewModelFactory import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.features.auth.PendingAuthHandler import im.vector.app.features.login.ReAuthHelper +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.flow.launchIn @@ -140,7 +140,7 @@ class CrossSigningSettingsViewModel @AssistedInject constructor( private fun handleInitializeXSigningError(failure: Throwable) { Timber.e(failure, "## CrossSigning - Failed to initialize cross signing") - _viewEvents.post(CrossSigningSettingsViewEvents.Failure(Exception(stringProvider.getString(R.string.failed_to_initialize_cross_signing)))) + _viewEvents.post(CrossSigningSettingsViewEvents.Failure(Exception(stringProvider.getString(CommonStrings.failed_to_initialize_cross_signing)))) } companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceItem.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceItem.kt index 5924742c26..81f4326e9a 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceItem.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceItem.kt @@ -30,6 +30,7 @@ import im.vector.app.core.epoxy.onClick import im.vector.app.core.resources.ColorProvider import im.vector.app.core.ui.views.ShieldImageView import im.vector.app.core.utils.DimensionConverter +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo @@ -108,7 +109,7 @@ abstract class DeviceItem : VectorEpoxyModel(R.layout.item_de val lastSeenTime = lastSeenFormatted ?: "-" - holder.deviceLastSeenText.text = holder.root.context.getString(R.string.devices_details_last_seen_format, lastSeenIp, lastSeenTime) + holder.deviceLastSeenText.text = holder.root.context.getString(CommonStrings.devices_details_last_seen_format, lastSeenIp, lastSeenTime) detailedModeLabels.map { it.isVisible = true @@ -125,7 +126,7 @@ abstract class DeviceItem : VectorEpoxyModel(R.layout.item_de span { text = "${deviceInfo.deviceId}" apply { - colorProvider?.getColorFromAttribute(R.attr.vctr_content_secondary)?.let { + colorProvider?.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary)?.let { textColor = it } dimensionConverter?.spToPx(12)?.let { diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt index c91c0f457b..4ad57707b2 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt @@ -27,6 +27,7 @@ import im.vector.app.core.ui.list.genericItem import im.vector.app.core.ui.views.toDrawableRes import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import timber.log.Timber @@ -90,8 +91,8 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( id("trust${cryptoDeviceInfo.deviceId}") style(ItemStyle.BIG_TEXT) titleIconResourceId(shield) - title(host.stringProvider.getString(R.string.encryption_information_verified).toEpoxyCharSequence()) - description(host.stringProvider.getString(R.string.settings_active_sessions_verified_device_desc).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.encryption_information_verified).toEpoxyCharSequence()) + description(host.stringProvider.getString(CommonStrings.settings_active_sessions_verified_device_desc).toEpoxyCharSequence()) } } else if (data.canVerifySession) { // You need to complete security, only if there are other session(s) available, or if 4S contains secrets @@ -99,10 +100,10 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( id("trust${cryptoDeviceInfo.deviceId}") style(ItemStyle.BIG_TEXT) titleIconResourceId(shield) - title(host.stringProvider.getString(R.string.crosssigning_verify_this_session).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.crosssigning_verify_this_session).toEpoxyCharSequence()) description( host.stringProvider - .getString(if (data.hasOtherSessions) R.string.confirm_your_identity else R.string.confirm_your_identity_quad_s) + .getString(if (data.hasOtherSessions) CommonStrings.confirm_your_identity else CommonStrings.confirm_your_identity_quad_s) .toEpoxyCharSequence() ) } @@ -111,10 +112,10 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( id("reset${cryptoDeviceInfo.deviceId}") style(ItemStyle.BIG_TEXT) titleIconResourceId(shield) - title(host.stringProvider.getString(R.string.crosssigning_cannot_verify_this_session).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.crosssigning_cannot_verify_this_session).toEpoxyCharSequence()) description( host.stringProvider - .getString(R.string.crosssigning_cannot_verify_this_session_desc) + .getString(CommonStrings.crosssigning_cannot_verify_this_session_desc) .toEpoxyCharSequence() ) } @@ -131,16 +132,16 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( id("trust${cryptoDeviceInfo.deviceId}") style(ItemStyle.BIG_TEXT) titleIconResourceId(shield) - title(host.stringProvider.getString(R.string.encryption_information_verified).toEpoxyCharSequence()) - description(host.stringProvider.getString(R.string.settings_active_sessions_verified_device_desc).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.encryption_information_verified).toEpoxyCharSequence()) + description(host.stringProvider.getString(CommonStrings.settings_active_sessions_verified_device_desc).toEpoxyCharSequence()) } } else { genericItem { id("trust${cryptoDeviceInfo.deviceId}") titleIconResourceId(shield) style(ItemStyle.BIG_TEXT) - title(host.stringProvider.getString(R.string.encryption_information_not_verified).toEpoxyCharSequence()) - description(host.stringProvider.getString(R.string.settings_active_sessions_unverified_device_desc).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.encryption_information_not_verified).toEpoxyCharSequence()) + description(host.stringProvider.getString(CommonStrings.settings_active_sessions_unverified_device_desc).toEpoxyCharSequence()) } } } @@ -162,10 +163,10 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( } bottomSheetVerificationActionItem { id("completeSecurity") - title(host.stringProvider.getString(R.string.crosssigning_verify_this_session)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + title(host.stringProvider.getString(CommonStrings.crosssigning_verify_this_session)) + titleColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + iconColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) listener { host.callback?.onAction(DevicesAction.CompleteSecurity) } @@ -176,10 +177,10 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( } bottomSheetVerificationActionItem { id("resetSecurity") - title(host.stringProvider.getString(R.string.secure_backup_reset_all)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + title(host.stringProvider.getString(CommonStrings.secure_backup_reset_all)) + titleColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + iconColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) listener { host.callback?.onAction(DevicesAction.ResetSecurity) } @@ -210,16 +211,16 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( id("trust${cryptoDeviceInfo.deviceId}") style(ItemStyle.BIG_TEXT) titleIconResourceId(shield) - title(host.stringProvider.getString(R.string.encryption_information_verified).toEpoxyCharSequence()) - description(host.stringProvider.getString(R.string.settings_active_sessions_verified_device_desc).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.encryption_information_verified).toEpoxyCharSequence()) + description(host.stringProvider.getString(CommonStrings.settings_active_sessions_verified_device_desc).toEpoxyCharSequence()) } } else { genericItem { id("trust${cryptoDeviceInfo.deviceId}") titleIconResourceId(shield) style(ItemStyle.BIG_TEXT) - title(host.stringProvider.getString(R.string.encryption_information_not_verified).toEpoxyCharSequence()) - description(host.stringProvider.getString(R.string.settings_active_sessions_unverified_device_desc).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.encryption_information_not_verified).toEpoxyCharSequence()) + description(host.stringProvider.getString(CommonStrings.settings_active_sessions_unverified_device_desc).toEpoxyCharSequence()) } } @@ -239,10 +240,10 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( } bottomSheetVerificationActionItem { id("verify${cryptoDeviceInfo.deviceId}") - title(host.stringProvider.getString(R.string.verification_verify_device)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + title(host.stringProvider.getString(CommonStrings.verification_verify_device)) + titleColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + iconColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) listener { host.callback?.onAction(DevicesAction.VerifyMyDevice(cryptoDeviceInfo.deviceId)) } @@ -257,10 +258,10 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( } bottomSheetVerificationActionItem { id("verify_text") - title(host.stringProvider.getString(R.string.cross_signing_verify_by_text)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + title(host.stringProvider.getString(CommonStrings.cross_signing_verify_by_text)) + titleColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + iconColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) listener { host.callback?.onAction(DevicesAction.VerifyMyDeviceManually(cryptoDeviceInfo.deviceId)) } @@ -270,10 +271,10 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( } bottomSheetVerificationActionItem { id("verify_emoji") - title(host.stringProvider.getString(R.string.cross_signing_verify_by_emoji)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + title(host.stringProvider.getString(CommonStrings.cross_signing_verify_by_emoji)) + titleColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + iconColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) listener { host.callback?.onAction(DevicesAction.VerifyMyDevice(cryptoDeviceInfo.deviceId)) } @@ -290,10 +291,10 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( } bottomSheetVerificationActionItem { id("delete") - title(host.stringProvider.getString(R.string.settings_active_sessions_signout_device)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) + title(host.stringProvider.getString(CommonStrings.settings_active_sessions_signout_device)) + titleColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) + iconColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError)) listener { host.callback?.onAction(DevicesAction.Delete(deviceId)) } @@ -306,10 +307,10 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( } bottomSheetVerificationActionItem { id("rename") - title(host.stringProvider.getString(R.string.action_rename)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + title(host.stringProvider.getString(CommonStrings.action_rename)) + titleColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + iconColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) listener { host.callback?.onAction(DevicesAction.PromptRename(deviceId)) } @@ -327,7 +328,7 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( genericFooterItem { id("infoCrypto${info.deviceId}") - text(host.stringProvider.getString(R.string.settings_failed_to_get_crypto_device_info).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.settings_failed_to_get_crypto_device_info).toEpoxyCharSequence()) } info.deviceId?.let { addGenericDeviceManageActions(data, it) } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesController.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesController.kt index c2f333a862..0dc3407c1d 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesController.kt @@ -21,7 +21,6 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized -import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter import im.vector.app.core.epoxy.errorWithRetryItem @@ -32,6 +31,7 @@ import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericHeaderItem import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import javax.inject.Inject @@ -92,7 +92,7 @@ class DevicesController @Inject constructor( // Current device genericHeaderItem { id("current") - text(host.stringProvider.getString(R.string.devices_current_device)) + text(host.stringProvider.getString(CommonStrings.devices_current_device)) } deviceItem { @@ -116,7 +116,7 @@ class DevicesController @Inject constructor( // genericButtonItem { // id("complete_security") // iconRes(R.drawable.ic_shield_warning) -// text(stringProvider.getString(R.string.complete_security)) +// text(stringProvider.getString(CommonStrings.complete_security)) // buttonClickAction(DebouncedClickListener(View.OnClickListener { _ -> // callback?.completeSecurity() // })) @@ -128,7 +128,7 @@ class DevicesController @Inject constructor( if (devices.size > 1) { genericHeaderItem { id("others") - text(host.stringProvider.getString(R.string.devices_other_devices)) + text(host.stringProvider.getString(CommonStrings.devices_other_devices)) } devices diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt index 5a1e602808..945112707d 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt @@ -26,7 +26,6 @@ import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel @@ -38,6 +37,7 @@ import im.vector.app.features.login.ReAuthHelper import im.vector.app.features.settings.devices.v2.list.CheckIfSessionIsInactiveUseCase import im.vector.app.features.settings.devices.v2.verification.GetEncryptionTrustLevelForDeviceUseCase import im.vector.lib.core.utils.flow.throttleFirst +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.launchIn @@ -394,9 +394,9 @@ class DevicesViewModel @AssistedInject constructor( copy(request = Fail(failure)) } if (failure is Failure.OtherServerError && failure.httpCode == HttpsURLConnection.HTTP_UNAUTHORIZED) { - _viewEvents.post(DevicesViewEvents.Failure(Exception(stringProvider.getString(R.string.authentication_error)))) + _viewEvents.post(DevicesViewEvents.Failure(Exception(stringProvider.getString(CommonStrings.authentication_error)))) } else { - _viewEvents.post(DevicesViewEvents.Failure(Exception(stringProvider.getString(R.string.matrix_error)))) + _viewEvents.post(DevicesViewEvents.Failure(Exception(stringProvider.getString(CommonStrings.matrix_error)))) } // ... Timber.e(failure, "failed to delete session") diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt index 9cb314b2b7..43f0f3bfc4 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt @@ -40,6 +40,7 @@ import im.vector.app.databinding.DialogBaseEditTextBinding import im.vector.app.databinding.FragmentGenericRecyclerBinding import im.vector.app.features.auth.ReAuthActivity import im.vector.app.features.crypto.recover.SetupMode +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import javax.inject.Inject @@ -67,7 +68,7 @@ class VectorSettingsDevicesFragment : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - views.waitingView.waitingStatusText.setText(R.string.please_wait) + views.waitingView.waitingStatusText.setText(CommonStrings.please_wait) views.waitingView.waitingStatusText.isVisible = true devicesController.callback = this views.genericRecyclerView.configureWith(devicesController, dividerDrawable = R.drawable.divider_horizontal) @@ -111,7 +112,7 @@ class VectorSettingsDevicesFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.settings_active_sessions_manage) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.settings_active_sessions_manage) viewModel.handle(DevicesAction.Refresh) } @@ -138,14 +139,14 @@ class VectorSettingsDevicesFragment : views.editText.setText(deviceInfo.displayName) MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.devices_details_device_name) + .setTitle(CommonStrings.devices_details_device_name) .setView(layout) - .setPositiveButton(R.string.ok) { _, _ -> + .setPositiveButton(CommonStrings.ok) { _, _ -> val newName = views.editText.text.toString() viewModel.handle(DevicesAction.Rename(deviceInfo.deviceId!!, newName)) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } @@ -176,7 +177,7 @@ class VectorSettingsDevicesFragment : requireContext(), reAuthReq.registrationFlowResponse, reAuthReq.lastErrorCode, - getString(R.string.devices_delete_dialog_title) + getString(CommonStrings.devices_delete_dialog_title) ).let { intent -> reAuthActivityResultLauncher.launch(intent) } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/SessionWarningInfoView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/SessionWarningInfoView.kt index 938c6c99ab..1c8af4c4b1 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/SessionWarningInfoView.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/SessionWarningInfoView.kt @@ -22,9 +22,9 @@ import android.util.AttributeSet import android.view.LayoutInflater import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.res.use -import im.vector.app.R import im.vector.app.core.extensions.setTextWithColoredPart import im.vector.app.databinding.ViewSessionWarningInfoBinding +import im.vector.lib.strings.CommonStrings class SessionWarningInfoView @JvmOverloads constructor( context: Context, @@ -42,7 +42,7 @@ class SessionWarningInfoView @JvmOverloads constructor( init { context.obtainStyledAttributes( attrs, - R.styleable.SessionWarningInfoView, + im.vector.lib.ui.styles.R.styleable.SessionWarningInfoView, 0, 0 ).use { @@ -51,10 +51,10 @@ class SessionWarningInfoView @JvmOverloads constructor( } private fun setDescription(typedArray: TypedArray) { - val description = typedArray.getString(R.styleable.SessionWarningInfoView_sessionsWarningInfoDescription) - val hasLearnMore = typedArray.getBoolean(R.styleable.SessionWarningInfoView_sessionsWarningInfoHasLearnMore, false) + val description = typedArray.getString(im.vector.lib.ui.styles.R.styleable.SessionWarningInfoView_sessionsWarningInfoDescription) + val hasLearnMore = typedArray.getBoolean(im.vector.lib.ui.styles.R.styleable.SessionWarningInfoView_sessionsWarningInfoHasLearnMore, false) if (hasLearnMore) { - val learnMore = context.getString(R.string.action_learn_more) + val learnMore = context.getString(CommonStrings.action_learn_more) val fullDescription = buildString { append(description) append(" ") 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 index bf90120b96..d680de8aa3 100644 --- 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 @@ -52,6 +52,8 @@ import im.vector.app.features.settings.devices.v2.list.SecurityRecommendationVie import im.vector.app.features.settings.devices.v2.list.SessionInfoViewState import im.vector.app.features.settings.devices.v2.signout.BuildConfirmSignoutDialogUseCase import im.vector.app.features.workers.signout.SignOutUiWorker +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.extensions.orFalse import javax.inject.Inject @@ -92,7 +94,7 @@ class VectorSettingsDevicesFragment : private fun initToolbar() { (activity as? AppCompatActivity) ?.supportActionBar - ?.setTitle(R.string.settings_sessions_list) + ?.setTitle(CommonStrings.settings_sessions_list) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -138,7 +140,7 @@ class VectorSettingsDevicesFragment : } private fun initWaitingView() { - views.waitingView.waitingStatusText.setText(R.string.please_wait) + views.waitingView.waitingStatusText.setText(CommonStrings.please_wait) views.waitingView.waitingStatusText.isVisible = true } @@ -316,13 +318,13 @@ class VectorSettingsDevicesFragment : views.deviceListUnverifiedSessionsRecommendation.isVisible = isUnverifiedSectionVisible views.deviceListInactiveSessionsRecommendation.isVisible = isInactiveSectionVisible val unverifiedSessionsViewState = SecurityRecommendationViewState( - description = getString(R.string.device_manager_unverified_sessions_description), + description = getString(CommonStrings.device_manager_unverified_sessions_description), sessionsCount = unverifiedSessionsCount, ) views.deviceListUnverifiedSessionsRecommendation.render(unverifiedSessionsViewState) val inactiveSessionsViewState = SecurityRecommendationViewState( description = resources.getQuantityString( - R.plurals.device_manager_inactive_sessions_description, + CommonPlurals.device_manager_inactive_sessions_description, SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS, SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS ), @@ -353,12 +355,12 @@ class VectorSettingsDevicesFragment : hideOtherSessionsView() } else { views.deviceListHeaderOtherSessions.isVisible = true - val colorDestructive = colorProvider.getColorFromAttribute(R.attr.colorError) + val colorDestructive = colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError) val multiSignoutItem = views.deviceListHeaderOtherSessions.menu.findItem(R.id.otherSessionsHeaderMultiSignout) // Hide multi signout if the homeserver delegates the account management multiSignoutItem.isVisible = state.delegatedOidcAuthEnabled.not() val nbDevices = otherDevices.size - multiSignoutItem.title = stringProvider.getQuantityString(R.plurals.device_manager_other_sessions_multi_signout_all, nbDevices, nbDevices) + multiSignoutItem.title = stringProvider.getQuantityString(CommonPlurals.device_manager_other_sessions_multi_signout_all, nbDevices, nbDevices) multiSignoutItem.setTextColor(colorDestructive) views.deviceListOtherSessions.isVisible = true val devices = if (isShowingIpAddress) otherDevices else otherDevices.map { it.copy(deviceInfo = it.deviceInfo.copy(lastSeenIp = null)) } @@ -368,9 +370,9 @@ class VectorSettingsDevicesFragment : showViewAll = devices.size > NUMBER_OF_OTHER_DEVICES_TO_RENDER ) views.deviceListHeaderOtherSessions.menu.findItem(R.id.otherSessionsHeaderToggleIpAddress).title = if (isShowingIpAddress) { - stringProvider.getString(R.string.device_manager_other_sessions_hide_ip_address) + stringProvider.getString(CommonStrings.device_manager_other_sessions_hide_ip_address) } else { - stringProvider.getString(R.string.device_manager_other_sessions_show_ip_address) + stringProvider.getString(CommonStrings.device_manager_other_sessions_show_ip_address) } } } @@ -391,7 +393,7 @@ class VectorSettingsDevicesFragment : private fun renderCurrentSessionHeaderView(hasOtherDevices: Boolean, state: DevicesViewState) { views.deviceListHeaderCurrentSession.isVisible = true - val colorDestructive = colorProvider.getColorFromAttribute(R.attr.colorError) + val colorDestructive = colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError) val signoutSessionItem = views.deviceListHeaderCurrentSession.menu.findItem(R.id.currentSessionHeaderSignout) signoutSessionItem.setTextColor(colorDestructive) val signoutOtherSessionsItem = views.deviceListHeaderCurrentSession.menu.findItem(R.id.currentSessionHeaderSignoutOtherSessions) @@ -481,7 +483,7 @@ class VectorSettingsDevicesFragment : requireContext(), reAuthReq.registrationFlowResponse, reAuthReq.lastErrorCode, - getString(R.string.devices_delete_dialog_title) + getString(CommonStrings.devices_delete_dialog_title) ).let { intent -> reAuthActivityResultLauncher.launch(intent) } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/SessionDetailsController.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/SessionDetailsController.kt index 8d780925df..7b691fdb37 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/SessionDetailsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/SessionDetailsController.kt @@ -19,7 +19,6 @@ package im.vector.app.features.settings.devices.v2.details import android.view.View import androidx.annotation.StringRes import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter import im.vector.app.core.resources.StringProvider @@ -27,6 +26,7 @@ import im.vector.app.core.session.clientinfo.MatrixClientInfoContent import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.settings.devices.v2.DeviceFullInfo import im.vector.app.features.settings.devices.v2.list.DeviceType +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import javax.inject.Inject @@ -98,20 +98,20 @@ class SessionDetailsController @Inject constructor( val sessionId = data.deviceId.orEmpty() val sessionLastSeenTs = data.lastSeenTs ?: -1 - buildHeaderItem(R.string.device_manager_session_title) + buildHeaderItem(CommonStrings.device_manager_session_title) if (sessionName.isNotEmpty()) { val hasDivider = sessionId.isNotEmpty() || sessionLastSeenTs > 0 - buildContentItem(R.string.device_manager_session_details_session_name, sessionName, hasDivider) + buildContentItem(CommonStrings.device_manager_session_details_session_name, sessionName, hasDivider) } if (sessionId.isNotEmpty()) { val hasDivider = sessionLastSeenTs > 0 - buildContentItem(R.string.device_manager_session_details_session_id, sessionId, hasDivider) + buildContentItem(CommonStrings.device_manager_session_details_session_id, sessionId, hasDivider) } if (sessionLastSeenTs > 0) { val formattedDate = dateFormatter.format(sessionLastSeenTs, DateFormatKind.MESSAGE_DETAIL) val hasDivider = false - buildContentItem(R.string.device_manager_session_details_session_last_activity, formattedDate, hasDivider) + buildContentItem(CommonStrings.device_manager_session_details_session_last_activity, formattedDate, hasDivider) } } @@ -124,19 +124,19 @@ class SessionDetailsController @Inject constructor( val version = matrixClientInfoContent.version.orEmpty() val url = matrixClientInfoContent.url.orEmpty() - buildHeaderItem(R.string.device_manager_session_details_application, addExtraTopMargin) + buildHeaderItem(CommonStrings.device_manager_session_details_application, addExtraTopMargin) if (name.isNotEmpty()) { val hasDivider = version.isNotEmpty() || url.isNotEmpty() - buildContentItem(R.string.device_manager_session_details_application_name, name, hasDivider) + buildContentItem(CommonStrings.device_manager_session_details_application_name, name, hasDivider) } if (version.isNotEmpty()) { val hasDivider = url.isNotEmpty() - buildContentItem(R.string.device_manager_session_details_application_version, version, hasDivider) + buildContentItem(CommonStrings.device_manager_session_details_application_version, version, hasDivider) } if (url.isNotEmpty()) { val hasDivider = false - buildContentItem(R.string.device_manager_session_details_application_url, url, hasDivider) + buildContentItem(CommonStrings.device_manager_session_details_application_url, url, hasDivider) } } @@ -145,7 +145,7 @@ class SessionDetailsController @Inject constructor( } private fun buildSectionDevice(data: DeviceFullInfo, addExtraTopMargin: Boolean) { - buildHeaderItem(R.string.device_manager_device_title, addExtraTopMargin) + buildHeaderItem(CommonStrings.device_manager_device_title, addExtraTopMargin) when (data.deviceExtendedInfo.deviceType) { DeviceType.MOBILE -> buildSectionDeviceMobile(data) @@ -164,12 +164,12 @@ class SessionDetailsController @Inject constructor( if (browser.isNotEmpty()) { val hasDivider = operatingSystem.isNotEmpty() || lastSeenIp.isNotEmpty() - buildContentItem(R.string.device_manager_session_details_device_browser, browser, hasDivider) + buildContentItem(CommonStrings.device_manager_session_details_device_browser, browser, hasDivider) } if (operatingSystem.isNotEmpty()) { val hasDivider = lastSeenIp.isNotEmpty() - buildContentItem(R.string.device_manager_session_details_device_operating_system, operatingSystem, hasDivider) + buildContentItem(CommonStrings.device_manager_session_details_device_operating_system, operatingSystem, hasDivider) } buildIpAddressContentItem(lastSeenIp) @@ -181,7 +181,7 @@ class SessionDetailsController @Inject constructor( if (operatingSystem.isNotEmpty()) { val hasDivider = lastSeenIp.isNotEmpty() - buildContentItem(R.string.device_manager_session_details_device_operating_system, operatingSystem, hasDivider) + buildContentItem(CommonStrings.device_manager_session_details_device_operating_system, operatingSystem, hasDivider) } buildIpAddressContentItem(lastSeenIp) @@ -194,12 +194,12 @@ class SessionDetailsController @Inject constructor( if (model.isNotEmpty()) { val hasDivider = operatingSystem.isNotEmpty() || lastSeenIp.isNotEmpty() - buildContentItem(R.string.device_manager_session_details_device_model, model, hasDivider) + buildContentItem(CommonStrings.device_manager_session_details_device_model, model, hasDivider) } if (operatingSystem.isNotEmpty()) { val hasDivider = lastSeenIp.isNotEmpty() - buildContentItem(R.string.device_manager_session_details_device_operating_system, operatingSystem, hasDivider) + buildContentItem(CommonStrings.device_manager_session_details_device_operating_system, operatingSystem, hasDivider) } buildIpAddressContentItem(lastSeenIp) @@ -213,7 +213,7 @@ class SessionDetailsController @Inject constructor( private fun buildIpAddressContentItem(lastSeenIp: String) { if (lastSeenIp.isNotEmpty()) { val hasDivider = false - buildContentItem(R.string.device_manager_session_details_device_ip_address, lastSeenIp, hasDivider) + buildContentItem(CommonStrings.device_manager_session_details_device_ip_address, lastSeenIp, hasDivider) } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/SessionDetailsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/SessionDetailsFragment.kt index c5296929a6..67e659868e 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/SessionDetailsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/SessionDetailsFragment.kt @@ -27,13 +27,13 @@ import com.airbnb.mvrx.Success import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.showOptimizedSnackbar import im.vector.app.databinding.FragmentSessionDetailsBinding import im.vector.app.features.settings.devices.v2.DeviceFullInfo +import im.vector.lib.strings.CommonStrings import javax.inject.Inject /** @@ -61,7 +61,7 @@ class SessionDetailsFragment : private fun initToolbar() { (activity as? AppCompatActivity) ?.supportActionBar - ?.setTitle(R.string.device_manager_session_details_title) + ?.setTitle(CommonStrings.device_manager_session_details_title) } private fun initSessionDetails() { @@ -76,7 +76,7 @@ class SessionDetailsFragment : private fun observeViewEvents() { viewModel.observeViewEvents { viewEvent -> when (viewEvent) { - SessionDetailsViewEvent.ContentCopiedToClipboard -> view?.showOptimizedSnackbar(getString(R.string.copied_to_clipboard)) + SessionDetailsViewEvent.ContentCopiedToClipboard -> view?.showOptimizedSnackbar(getString(CommonStrings.copied_to_clipboard)) } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/filter/DeviceManagerFilterBottomSheet.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/filter/DeviceManagerFilterBottomSheet.kt index 28c7045a82..4b3bdb6c2a 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/filter/DeviceManagerFilterBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/filter/DeviceManagerFilterBottomSheet.kt @@ -28,6 +28,7 @@ import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment.ResultListener.Companion.RESULT_OK import im.vector.app.databinding.BottomSheetDeviceManagerFilterBinding import im.vector.app.features.settings.devices.v2.list.SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS +import im.vector.lib.strings.CommonPlurals import kotlinx.parcelize.Parcelize @Parcelize @@ -51,7 +52,7 @@ class DeviceManagerFilterBottomSheet : VectorBaseBottomSheetDialogFragment @@ -57,11 +59,11 @@ class OtherSessionsController @Inject constructor( val formattedLastActivityDate = host.dateFormatter.format(device.deviceInfo.lastSeenTs, dateFormatKind) val description = buildDescription(device, formattedLastActivityDate) val descriptionColor = if (device.isCurrentDevice) { - host.colorProvider.getColorFromAttribute(R.attr.colorError) + host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError) } else { - host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) } - val drawableColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + val drawableColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) val descriptionDrawable = if (device.isInactive) host.drawableProvider.getDrawable(R.drawable.ic_inactive_sessions, drawableColor) else null val sessionName = device.deviceInfo.displayName ?: device.deviceInfo.deviceId @@ -92,23 +94,23 @@ class OtherSessionsController @Inject constructor( return when { device.isInactive -> { stringProvider.getQuantityString( - R.plurals.device_manager_other_sessions_description_inactive, + CommonPlurals.device_manager_other_sessions_description_inactive, SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS, SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS, formattedLastActivityDate ) } device.roomEncryptionTrustLevel == RoomEncryptionTrustLevel.Trusted -> { - stringProvider.getString(R.string.device_manager_other_sessions_description_verified, formattedLastActivityDate) + stringProvider.getString(CommonStrings.device_manager_other_sessions_description_verified, formattedLastActivityDate) } device.isCurrentDevice -> { - stringProvider.getString(R.string.device_manager_other_sessions_description_unverified_current_session) + stringProvider.getString(CommonStrings.device_manager_other_sessions_description_unverified_current_session) } device.roomEncryptionTrustLevel == RoomEncryptionTrustLevel.Default -> { - stringProvider.getString(R.string.device_manager_session_last_activity, formattedLastActivityDate) + stringProvider.getString(CommonStrings.device_manager_session_last_activity, formattedLastActivityDate) } else -> { - stringProvider.getString(R.string.device_manager_other_sessions_description_unverified, formattedLastActivityDate) + stringProvider.getString(CommonStrings.device_manager_other_sessions_description_unverified, formattedLastActivityDate) } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/OtherSessionsView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/OtherSessionsView.kt index a4f8bb64db..fd88d2cee9 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/OtherSessionsView.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/OtherSessionsView.kt @@ -30,6 +30,7 @@ import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.databinding.ViewOtherSessionsBinding import im.vector.app.features.settings.devices.v2.DeviceFullInfo +import im.vector.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint @@ -89,7 +90,7 @@ class OtherSessionsView @JvmOverloads constructor( fun render(devices: List, totalNumberOfDevices: Int, showViewAll: Boolean) { if (showViewAll) { views.otherSessionsViewAllButton.isVisible = true - views.otherSessionsViewAllButton.text = context.getString(R.string.device_manager_other_sessions_view_all, totalNumberOfDevices) + views.otherSessionsViewAllButton.text = context.getString(CommonStrings.device_manager_other_sessions_view_all, totalNumberOfDevices) } else { views.otherSessionsViewAllButton.isVisible = false } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SecurityRecommendationView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SecurityRecommendationView.kt index 2a43a9aade..516e874502 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SecurityRecommendationView.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SecurityRecommendationView.kt @@ -24,6 +24,7 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.res.use import im.vector.app.R import im.vector.app.databinding.ViewSecurityRecommendationBinding +import im.vector.lib.strings.CommonStrings class SecurityRecommendationView @JvmOverloads constructor( context: Context, @@ -44,7 +45,7 @@ class SecurityRecommendationView @JvmOverloads constructor( context.obtainStyledAttributes( attrs, - R.styleable.SecurityRecommendationView, + im.vector.lib.ui.styles.R.styleable.SecurityRecommendationView, 0, 0 ).use { @@ -62,18 +63,18 @@ class SecurityRecommendationView @JvmOverloads constructor( } private fun setTitle(typedArray: TypedArray) { - val title = typedArray.getString(R.styleable.SecurityRecommendationView_recommendationTitle) + val title = typedArray.getString(im.vector.lib.ui.styles.R.styleable.SecurityRecommendationView_recommendationTitle) views.recommendationTitleTextView.text = title } private fun setDescription(typedArray: TypedArray) { - val description = typedArray.getString(R.styleable.SecurityRecommendationView_recommendationDescription) + val description = typedArray.getString(im.vector.lib.ui.styles.R.styleable.SecurityRecommendationView_recommendationDescription) setDescription(description) } private fun setImage(typedArray: TypedArray) { - val imageResource = typedArray.getResourceId(R.styleable.SecurityRecommendationView_recommendationImageResource, 0) - val backgroundTint = typedArray.getColor(R.styleable.SecurityRecommendationView_recommendationImageBackgroundTint, 0) + val imageResource = typedArray.getResourceId(im.vector.lib.ui.styles.R.styleable.SecurityRecommendationView_recommendationImageResource, 0) + val backgroundTint = typedArray.getColor(im.vector.lib.ui.styles.R.styleable.SecurityRecommendationView_recommendationImageBackgroundTint, 0) views.recommendationShieldImageView.setImageResource(imageResource) views.recommendationShieldImageView.backgroundTintList = ColorStateList.valueOf(backgroundTint) } @@ -83,7 +84,7 @@ class SecurityRecommendationView @JvmOverloads constructor( } private fun setCount(sessionsCount: Int) { - views.recommendationViewAllButton.text = context.getString(R.string.device_manager_other_sessions_view_all, sessionsCount) + views.recommendationViewAllButton.text = context.getString(CommonStrings.device_manager_other_sessions_view_all, sessionsCount) } fun render(viewState: SecurityRecommendationViewState) { diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt index 81a8aae666..f579d7f769 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt @@ -31,6 +31,8 @@ import im.vector.app.core.resources.DrawableProvider import im.vector.app.core.resources.StringProvider import im.vector.app.databinding.ViewSessionInfoBinding import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel @@ -105,7 +107,7 @@ class SessionInfoView @JvmOverloads constructor( private fun appendLearnMoreToVerificationStatus() { val status = views.sessionInfoVerificationStatusDetailTextView.text - val learnMore = context.getString(R.string.action_learn_more) + val learnMore = context.getString(CommonStrings.action_learn_more) val statusText = buildString { append(status) append(" ") @@ -122,40 +124,42 @@ class SessionInfoView @JvmOverloads constructor( } private fun renderCrossSigningVerified(isCurrentSession: Boolean) { - views.sessionInfoVerificationStatusTextView.text = context.getString(R.string.device_manager_verification_status_verified) - views.sessionInfoVerificationStatusTextView.setTextColor(ThemeUtils.getColor(context, R.attr.colorPrimary)) + views.sessionInfoVerificationStatusTextView.text = context.getString(CommonStrings.device_manager_verification_status_verified) + views.sessionInfoVerificationStatusTextView.setTextColor(ThemeUtils.getColor(context, com.google.android.material.R.attr.colorPrimary)) val statusResId = if (isCurrentSession) { - R.string.device_manager_verification_status_detail_current_session_verified + CommonStrings.device_manager_verification_status_detail_current_session_verified } else { - R.string.device_manager_verification_status_detail_other_session_verified + CommonStrings.device_manager_verification_status_detail_other_session_verified } views.sessionInfoVerificationStatusDetailTextView.text = context.getString(statusResId) views.sessionInfoVerifySessionButton.isVisible = false } private fun renderCrossSigningUnverified(isCurrentSession: Boolean, isVerifyButtonVisible: Boolean) { - views.sessionInfoVerificationStatusTextView.text = context.getString(R.string.device_manager_verification_status_unverified) - views.sessionInfoVerificationStatusTextView.setTextColor(ThemeUtils.getColor(context, R.attr.colorError)) + views.sessionInfoVerificationStatusTextView.text = context.getString(CommonStrings.device_manager_verification_status_unverified) + views.sessionInfoVerificationStatusTextView.setTextColor(ThemeUtils.getColor(context, com.google.android.material.R.attr.colorError)) val statusResId = if (isCurrentSession) { - R.string.device_manager_verification_status_detail_current_session_unverified + CommonStrings.device_manager_verification_status_detail_current_session_unverified } else { - R.string.device_manager_verification_status_detail_other_session_unverified + CommonStrings.device_manager_verification_status_detail_other_session_unverified } views.sessionInfoVerificationStatusDetailTextView.text = context.getString(statusResId) views.sessionInfoVerifySessionButton.isVisible = isVerifyButtonVisible } private fun renderCrossSigningUnknown() { - views.sessionInfoVerificationStatusTextView.text = context.getString(R.string.device_manager_verification_status_unknown) - views.sessionInfoVerificationStatusDetailTextView.text = context.getString(R.string.device_manager_verification_status_detail_other_session_unknown) + views.sessionInfoVerificationStatusTextView.text = context.getString(CommonStrings.device_manager_verification_status_unknown) + views.sessionInfoVerificationStatusDetailTextView.text = context.getString( + CommonStrings.device_manager_verification_status_detail_other_session_unknown + ) views.sessionInfoVerifySessionButton.isVisible = false } private fun renderCrossSigningEncryptionNotSupported() { - views.sessionInfoVerificationStatusTextView.text = context.getString(R.string.device_manager_verification_status_unverified) - views.sessionInfoVerificationStatusTextView.setTextColor(ThemeUtils.getColor(context, R.attr.colorError)) + views.sessionInfoVerificationStatusTextView.text = context.getString(CommonStrings.device_manager_verification_status_unverified) + views.sessionInfoVerificationStatusTextView.setTextColor(ThemeUtils.getColor(context, com.google.android.material.R.attr.colorError)) views.sessionInfoVerificationStatusDetailTextView.text = - context.getString(R.string.device_manager_verification_status_detail_session_encryption_not_supported) + context.getString(CommonStrings.device_manager_verification_status_detail_session_encryption_not_supported) views.sessionInfoVerifySessionButton.isVisible = false } @@ -179,17 +183,17 @@ class SessionInfoView @JvmOverloads constructor( views.sessionInfoLastActivityTextView.text = if (isInactive) { val formattedTs = dateFormatter.format(timestamp, DateFormatKind.TIMELINE_DAY_DIVIDER) context.resources.getQuantityString( - R.plurals.device_manager_other_sessions_description_inactive, + CommonPlurals.device_manager_other_sessions_description_inactive, SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS, SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS, formattedTs ) } else { val formattedTs = dateFormatter.format(timestamp, DateFormatKind.DEFAULT_DATE_AND_TIME) - context.getString(R.string.device_manager_session_last_activity, formattedTs) + context.getString(CommonStrings.device_manager_session_last_activity, formattedTs) } val drawable = if (isInactive) { - val drawableColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + val drawableColor = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) drawableProvider.getDrawable(R.drawable.ic_inactive_sessions, drawableColor) } else { null diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionsListHeaderView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionsListHeaderView.kt index 42d9f01595..0f828070e0 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionsListHeaderView.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionsListHeaderView.kt @@ -27,10 +27,10 @@ import androidx.appcompat.widget.ActionMenuView.OnMenuItemClickListener import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.res.use import androidx.core.view.isVisible -import im.vector.app.R import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.extensions.setTextWithColoredPart import im.vector.app.databinding.ViewSessionsListHeaderBinding +import im.vector.lib.strings.CommonStrings class SessionsListHeaderView @JvmOverloads constructor( context: Context, @@ -49,7 +49,7 @@ class SessionsListHeaderView @JvmOverloads constructor( init { context.obtainStyledAttributes( attrs, - R.styleable.SessionsListHeaderView, + im.vector.lib.ui.styles.R.styleable.SessionsListHeaderView, 0, 0 ).use { @@ -60,18 +60,18 @@ class SessionsListHeaderView @JvmOverloads constructor( } private fun setTitle(typedArray: TypedArray) { - val title = typedArray.getString(R.styleable.SessionsListHeaderView_sessionsListHeaderTitle) + val title = typedArray.getString(im.vector.lib.ui.styles.R.styleable.SessionsListHeaderView_sessionsListHeaderTitle) binding.sessionsListHeaderTitle.setTextOrHide(title) } private fun setDescription(typedArray: TypedArray) { - val description = typedArray.getString(R.styleable.SessionsListHeaderView_sessionsListHeaderDescription) + val description = typedArray.getString(im.vector.lib.ui.styles.R.styleable.SessionsListHeaderView_sessionsListHeaderDescription) if (description.isNullOrEmpty()) { binding.sessionsListHeaderDescription.isVisible = false return } - val hasLearnMoreLink = typedArray.getBoolean(R.styleable.SessionsListHeaderView_sessionsListHeaderHasLearnMoreLink, true) + val hasLearnMoreLink = typedArray.getBoolean(im.vector.lib.ui.styles.R.styleable.SessionsListHeaderView_sessionsListHeaderHasLearnMoreLink, true) if (hasLearnMoreLink) { setDescriptionWithLearnMore(description) } else { @@ -82,7 +82,7 @@ class SessionsListHeaderView @JvmOverloads constructor( } private fun setDescriptionWithLearnMore(description: String) { - val learnMore = context.getString(R.string.action_learn_more) + val learnMore = context.getString(CommonStrings.action_learn_more) val fullDescription = buildString { append(description) append(" ") @@ -99,7 +99,7 @@ class SessionsListHeaderView @JvmOverloads constructor( @Suppress("RestrictedApi") private fun setMenu(typedArray: TypedArray) { - val menuResId = typedArray.getResourceId(R.styleable.SessionsListHeaderView_sessionsListHeaderMenu, -1) + val menuResId = typedArray.getResourceId(im.vector.lib.ui.styles.R.styleable.SessionsListHeaderView_sessionsListHeaderMenu, -1) if (menuResId == -1) { binding.sessionsListHeaderMenu.isVisible = false } else { diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SetDeviceTypeIconUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SetDeviceTypeIconUseCase.kt index 49ff46779e..47732a6bf1 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SetDeviceTypeIconUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SetDeviceTypeIconUseCase.kt @@ -19,6 +19,7 @@ package im.vector.app.features.settings.devices.v2.list import android.widget.ImageView import im.vector.app.R import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings class SetDeviceTypeIconUseCase { @@ -26,19 +27,19 @@ class SetDeviceTypeIconUseCase { when (deviceType) { DeviceType.MOBILE -> { imageView.setImageResource(R.drawable.ic_device_type_mobile) - imageView.contentDescription = stringProvider.getString(R.string.a11y_device_manager_device_type_mobile) + imageView.contentDescription = stringProvider.getString(CommonStrings.a11y_device_manager_device_type_mobile) } DeviceType.WEB -> { imageView.setImageResource(R.drawable.ic_device_type_web) - imageView.contentDescription = stringProvider.getString(R.string.a11y_device_manager_device_type_web) + imageView.contentDescription = stringProvider.getString(CommonStrings.a11y_device_manager_device_type_web) } DeviceType.DESKTOP -> { imageView.setImageResource(R.drawable.ic_device_type_desktop) - imageView.contentDescription = stringProvider.getString(R.string.a11y_device_manager_device_type_desktop) + imageView.contentDescription = stringProvider.getString(CommonStrings.a11y_device_manager_device_type_desktop) } DeviceType.UNKNOWN -> { imageView.setImageResource(R.drawable.ic_device_type_unknown) - imageView.contentDescription = stringProvider.getString(R.string.a11y_device_manager_device_type_unknown) + imageView.contentDescription = stringProvider.getString(CommonStrings.a11y_device_manager_device_type_unknown) } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsFragment.kt index a5897be58c..202e396f00 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsFragment.kt @@ -51,6 +51,8 @@ import im.vector.app.features.settings.devices.v2.list.SESSION_IS_MARKED_AS_INAC import im.vector.app.features.settings.devices.v2.more.SessionLearnMoreBottomSheet import im.vector.app.features.settings.devices.v2.signout.BuildConfirmSignoutDialogUseCase import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.extensions.orFalse import javax.inject.Inject @@ -87,9 +89,9 @@ class OtherSessionsFragment : menu.findItem(R.id.otherSessionsSelect).isVisible = !isSelectModeEnabled && state.devices()?.isNotEmpty().orFalse() menu.findItem(R.id.otherSessionsToggleIpAddress).isVisible = !isSelectModeEnabled menu.findItem(R.id.otherSessionsToggleIpAddress).title = if (state.isShowingIpAddress) { - getString(R.string.device_manager_other_sessions_hide_ip_address) + getString(CommonStrings.device_manager_other_sessions_hide_ip_address) } else { - getString(R.string.device_manager_other_sessions_show_ip_address) + getString(CommonStrings.device_manager_other_sessions_show_ip_address) } updateMultiSignoutMenuItem(menu, state) } @@ -98,10 +100,10 @@ class OtherSessionsFragment : private fun updateMultiSignoutMenuItem(menu: Menu, viewState: OtherSessionsViewState) { val multiSignoutItem = menu.findItem(R.id.otherSessionsMultiSignout) multiSignoutItem.title = if (viewState.isSelectModeEnabled) { - getString(R.string.device_manager_other_sessions_multi_signout_selection).uppercase() + getString(CommonStrings.device_manager_other_sessions_multi_signout_selection).uppercase() } else { val nbDevices = viewState.devices()?.size ?: 0 - stringProvider.getQuantityString(R.plurals.device_manager_other_sessions_multi_signout_all, nbDevices, nbDevices) + stringProvider.getQuantityString(CommonPlurals.device_manager_other_sessions_multi_signout_all, nbDevices, nbDevices) } multiSignoutItem.isVisible = if (viewState.delegatedOidcAuthEnabled) { // Hide multi signout if the homeserver delegates the account management @@ -119,7 +121,7 @@ class OtherSessionsFragment : } private fun changeTextColorOfDestructiveAction(menuItem: MenuItem) { - val titleColor = colorProvider.getColorFromAttribute(R.attr.colorError) + val titleColor = colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorError) menuItem.setTextColor(titleColor) } @@ -188,7 +190,7 @@ class OtherSessionsFragment : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setupToolbar(views.otherSessionsToolbar) - .setTitle(R.string.device_manager_sessions_other_title) + .setTitle(CommonStrings.device_manager_sessions_other_title) .allowBack() observeViewEvents() initFilterView() @@ -256,9 +258,9 @@ class OtherSessionsFragment : invalidateOptionsMenu() val title = if (isSelectModeEnabled) { val selection = devices.count { it.isSelected } - stringProvider.getQuantityString(R.plurals.x_selected, selection, selection) + stringProvider.getQuantityString(CommonPlurals.x_selected, selection, selection) } else { - getString(R.string.device_manager_sessions_other_title) + getString(CommonStrings.device_manager_sessions_other_title) } toolbar?.title = title } @@ -272,50 +274,50 @@ class OtherSessionsFragment : DeviceManagerFilterType.VERIFIED -> { views.otherSessionsSecurityRecommendationView.render( OtherSessionsSecurityRecommendationViewState( - title = getString(R.string.device_manager_other_sessions_recommendation_title_verified), - description = getString(R.string.device_manager_other_sessions_recommendation_description_verified), + title = getString(CommonStrings.device_manager_other_sessions_recommendation_title_verified), + description = getString(CommonStrings.device_manager_other_sessions_recommendation_description_verified), imageResourceId = R.drawable.ic_shield_trusted_no_border, - imageTintColorResourceId = colorProvider.getColor(R.color.shield_color_trust_background) + imageTintColorResourceId = colorProvider.getColor(im.vector.lib.ui.styles.R.color.shield_color_trust_background) ) ) - views.otherSessionsNotFoundTextView.text = getString(R.string.device_manager_other_sessions_no_verified_sessions_found) + views.otherSessionsNotFoundTextView.text = getString(CommonStrings.device_manager_other_sessions_no_verified_sessions_found) updateSecurityLearnMoreButton( - R.string.device_manager_learn_more_sessions_verified_title, - R.string.device_manager_learn_more_sessions_verified_description + CommonStrings.device_manager_learn_more_sessions_verified_title, + CommonStrings.device_manager_learn_more_sessions_verified_description ) } DeviceManagerFilterType.UNVERIFIED -> { views.otherSessionsSecurityRecommendationView.render( OtherSessionsSecurityRecommendationViewState( - title = getString(R.string.device_manager_other_sessions_recommendation_title_unverified), - description = getString(R.string.device_manager_other_sessions_recommendation_description_unverified), + title = getString(CommonStrings.device_manager_other_sessions_recommendation_title_unverified), + description = getString(CommonStrings.device_manager_other_sessions_recommendation_description_unverified), imageResourceId = R.drawable.ic_shield_warning_no_border, - imageTintColorResourceId = colorProvider.getColor(R.color.shield_color_warning_background) + imageTintColorResourceId = colorProvider.getColor(im.vector.lib.ui.styles.R.color.shield_color_warning_background) ) ) - views.otherSessionsNotFoundTextView.text = getString(R.string.device_manager_other_sessions_no_unverified_sessions_found) + views.otherSessionsNotFoundTextView.text = getString(CommonStrings.device_manager_other_sessions_no_unverified_sessions_found) updateSecurityLearnMoreButton( - R.string.device_manager_learn_more_sessions_unverified_title, - R.string.device_manager_learn_more_sessions_unverified + CommonStrings.device_manager_learn_more_sessions_unverified_title, + CommonStrings.device_manager_learn_more_sessions_unverified ) } DeviceManagerFilterType.INACTIVE -> { views.otherSessionsSecurityRecommendationView.render( OtherSessionsSecurityRecommendationViewState( - title = getString(R.string.device_manager_other_sessions_recommendation_title_inactive), + title = getString(CommonStrings.device_manager_other_sessions_recommendation_title_inactive), description = resources.getQuantityString( - R.plurals.device_manager_other_sessions_recommendation_description_inactive, + CommonPlurals.device_manager_other_sessions_recommendation_description_inactive, SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS, SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS ), imageResourceId = R.drawable.ic_inactive_sessions, - imageTintColorResourceId = ThemeUtils.getColor(requireContext(), R.attr.vctr_system) + imageTintColorResourceId = ThemeUtils.getColor(requireContext(), im.vector.lib.ui.styles.R.attr.vctr_system) ) ) - views.otherSessionsNotFoundTextView.text = getString(R.string.device_manager_other_sessions_no_inactive_sessions_found) + views.otherSessionsNotFoundTextView.text = getString(CommonStrings.device_manager_other_sessions_no_inactive_sessions_found) updateSecurityLearnMoreButton( - R.string.device_manager_learn_more_sessions_inactive_title, - R.string.device_manager_learn_more_sessions_inactive + CommonStrings.device_manager_learn_more_sessions_inactive_title, + CommonStrings.device_manager_learn_more_sessions_inactive ) } DeviceManagerFilterType.ALL_SESSIONS -> { /* NOOP. View is not visible */ @@ -403,7 +405,7 @@ class OtherSessionsFragment : requireContext(), reAuthReq.registrationFlowResponse, reAuthReq.lastErrorCode, - getString(R.string.devices_delete_dialog_title) + getString(CommonStrings.devices_delete_dialog_title) ).let { intent -> reAuthActivityResultLauncher.launch(intent) } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsSecurityRecommendationView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsSecurityRecommendationView.kt index 5a7d1fa910..19739a504a 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsSecurityRecommendationView.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsSecurityRecommendationView.kt @@ -26,6 +26,7 @@ import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R import im.vector.app.core.extensions.setTextWithColoredPart import im.vector.app.databinding.ViewOtherSessionSecurityRecommendationBinding +import im.vector.lib.strings.CommonStrings @AndroidEntryPoint class OtherSessionsSecurityRecommendationView @JvmOverloads constructor( @@ -43,7 +44,7 @@ class OtherSessionsSecurityRecommendationView @JvmOverloads constructor( context.obtainStyledAttributes( attrs, - R.styleable.OtherSessionsSecurityRecommendationView, + im.vector.lib.ui.styles.R.styleable.OtherSessionsSecurityRecommendationView, 0, 0 ).use { @@ -54,7 +55,7 @@ class OtherSessionsSecurityRecommendationView @JvmOverloads constructor( } private fun setTitle(typedArray: TypedArray) { - val title = typedArray.getString(R.styleable.OtherSessionsSecurityRecommendationView_otherSessionsRecommendationTitle) + val title = typedArray.getString(im.vector.lib.ui.styles.R.styleable.OtherSessionsSecurityRecommendationView_otherSessionsRecommendationTitle) setTitle(title) } @@ -63,13 +64,18 @@ class OtherSessionsSecurityRecommendationView @JvmOverloads constructor( } private fun setDescription(typedArray: TypedArray) { - val description = typedArray.getString(R.styleable.OtherSessionsSecurityRecommendationView_otherSessionsRecommendationDescription) + val description = + typedArray.getString(im.vector.lib.ui.styles.R.styleable.OtherSessionsSecurityRecommendationView_otherSessionsRecommendationDescription) setDescription(description) } private fun setImage(typedArray: TypedArray) { - val imageResource = typedArray.getResourceId(R.styleable.OtherSessionsSecurityRecommendationView_otherSessionsRecommendationImageResource, 0) - val backgroundTint = typedArray.getColor(R.styleable.OtherSessionsSecurityRecommendationView_otherSessionsRecommendationImageBackgroundTint, 0) + val imageResource = typedArray.getResourceId( + im.vector.lib.ui.styles.R.styleable.OtherSessionsSecurityRecommendationView_otherSessionsRecommendationImageResource, 0 + ) + val backgroundTint = typedArray.getColor( + im.vector.lib.ui.styles.R.styleable.OtherSessionsSecurityRecommendationView_otherSessionsRecommendationImageBackgroundTint, 0 + ) setImageResource(imageResource) setImageBackgroundTint(backgroundTint) } @@ -83,7 +89,7 @@ class OtherSessionsSecurityRecommendationView @JvmOverloads constructor( } private fun setDescription(description: String?) { - val learnMore = context.getString(R.string.action_learn_more) + val learnMore = context.getString(CommonStrings.action_learn_more) val formattedDescription = buildString { append(description) append(" ") diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewEntrySwitchView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewEntrySwitchView.kt index 24c7725f29..2826cd3887 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewEntrySwitchView.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewEntrySwitchView.kt @@ -23,7 +23,6 @@ import android.view.LayoutInflater import android.widget.CompoundButton import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.res.use -import im.vector.app.R import im.vector.app.core.extensions.setAttributeBackground import im.vector.app.databinding.ViewSessionOverviewEntrySwitchBinding @@ -42,7 +41,7 @@ class SessionOverviewEntrySwitchView @JvmOverloads constructor( initBackground() context.obtainStyledAttributes( attrs, - R.styleable.SessionOverviewEntrySwitchView, + im.vector.lib.ui.styles.R.styleable.SessionOverviewEntrySwitchView, 0, 0 ).use { @@ -58,17 +57,17 @@ class SessionOverviewEntrySwitchView @JvmOverloads constructor( } private fun setTitle(typedArray: TypedArray) { - val title = typedArray.getString(R.styleable.SessionOverviewEntrySwitchView_sessionOverviewEntrySwitchTitle) + val title = typedArray.getString(im.vector.lib.ui.styles.R.styleable.SessionOverviewEntrySwitchView_sessionOverviewEntrySwitchTitle) binding.sessionsOverviewEntryTitle.text = title } private fun setDescription(typedArray: TypedArray) { - val description = typedArray.getString(R.styleable.SessionOverviewEntrySwitchView_sessionOverviewEntrySwitchDescription) + val description = typedArray.getString(im.vector.lib.ui.styles.R.styleable.SessionOverviewEntrySwitchView_sessionOverviewEntrySwitchDescription) binding.sessionsOverviewEntryDescription.text = description } private fun setSwitchedEnabled(typedArray: TypedArray) { - val enabled = typedArray.getBoolean(R.styleable.SessionOverviewEntrySwitchView_sessionOverviewEntrySwitchEnabled, false) + val enabled = typedArray.getBoolean(im.vector.lib.ui.styles.R.styleable.SessionOverviewEntrySwitchView_sessionOverviewEntrySwitchEnabled, false) binding.sessionsOverviewEntrySwitch.isChecked = enabled } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewEntryView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewEntryView.kt index 5c4f0047ce..ddc8b122c3 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewEntryView.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewEntryView.kt @@ -22,7 +22,6 @@ import android.util.AttributeSet import android.view.LayoutInflater import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.res.use -import im.vector.app.R import im.vector.app.core.extensions.setAttributeBackground import im.vector.app.databinding.ViewSessionOverviewEntryBinding @@ -41,7 +40,7 @@ class SessionOverviewEntryView @JvmOverloads constructor( initBackground() context.obtainStyledAttributes( attrs, - R.styleable.SessionOverviewEntryView, + im.vector.lib.ui.styles.R.styleable.SessionOverviewEntryView, 0, 0 ).use { @@ -55,12 +54,12 @@ class SessionOverviewEntryView @JvmOverloads constructor( } private fun setTitle(typedArray: TypedArray) { - val title = typedArray.getString(R.styleable.SessionOverviewEntryView_sessionOverviewEntryTitle) + val title = typedArray.getString(im.vector.lib.ui.styles.R.styleable.SessionOverviewEntryView_sessionOverviewEntryTitle) binding.sessionsOverviewEntryTitle.text = title } private fun setDescription(typedArray: TypedArray) { - val description = typedArray.getString(R.styleable.SessionOverviewEntryView_sessionOverviewEntryDescription) + val description = typedArray.getString(im.vector.lib.ui.styles.R.styleable.SessionOverviewEntryView_sessionOverviewEntryDescription) binding.sessionsOverviewEntryDescription.text = description } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt index 7b10939072..9cbfbb06f8 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt @@ -48,6 +48,7 @@ import im.vector.app.features.settings.devices.v2.more.SessionLearnMoreBottomShe import im.vector.app.features.settings.devices.v2.notification.NotificationsStatus import im.vector.app.features.settings.devices.v2.signout.BuildConfirmSignoutDialogUseCase import im.vector.app.features.workers.signout.SignOutUiWorker +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel @@ -170,9 +171,9 @@ class SessionOverviewFragment : override fun handlePrepareMenu(menu: Menu) { withState(viewModel) { state -> menu.findItem(R.id.sessionOverviewToggleIpAddress).title = if (state.isShowingIpAddress) { - getString(R.string.device_manager_other_sessions_hide_ip_address) + getString(CommonStrings.device_manager_other_sessions_hide_ip_address) } else { - getString(R.string.device_manager_other_sessions_show_ip_address) + getString(CommonStrings.device_manager_other_sessions_show_ip_address) } } } @@ -209,8 +210,11 @@ class SessionOverviewFragment : private fun updateToolbar(viewState: SessionOverviewViewState) { if (viewState.deviceInfo is Success) { - val titleResId = - if (viewState.deviceInfo.invoke().isCurrentDevice) R.string.device_manager_current_session_title else R.string.device_manager_session_title + val titleResId = if (viewState.deviceInfo.invoke().isCurrentDevice) { + CommonStrings.device_manager_current_session_title + } else { + CommonStrings.device_manager_session_title + } (activity as? AppCompatActivity) ?.supportActionBar ?.setTitle(titleResId) @@ -297,7 +301,7 @@ class SessionOverviewFragment : requireContext(), reAuthReq.registrationFlowResponse, reAuthReq.lastErrorCode, - getString(R.string.devices_delete_dialog_title) + getString(CommonStrings.devices_delete_dialog_title) ).let { intent -> reAuthActivityResultLauncher.launch(intent) } @@ -308,20 +312,20 @@ class SessionOverviewFragment : null -> { // encryption not supported SessionLearnMoreBottomSheet.Args( - title = getString(R.string.device_manager_verification_status_unverified), - description = getString(R.string.device_manager_learn_more_sessions_encryption_not_supported), + title = getString(CommonStrings.device_manager_verification_status_unverified), + description = getString(CommonStrings.device_manager_learn_more_sessions_encryption_not_supported), ) } RoomEncryptionTrustLevel.Trusted -> { SessionLearnMoreBottomSheet.Args( - title = getString(R.string.device_manager_verification_status_verified), - description = getString(R.string.device_manager_learn_more_sessions_verified_description), + title = getString(CommonStrings.device_manager_verification_status_verified), + description = getString(CommonStrings.device_manager_learn_more_sessions_verified_description), ) } else -> { SessionLearnMoreBottomSheet.Args( - title = getString(R.string.device_manager_verification_status_unverified), - description = getString(R.string.device_manager_learn_more_sessions_unverified), + title = getString(CommonStrings.device_manager_verification_status_unverified), + description = getString(CommonStrings.device_manager_learn_more_sessions_unverified), ) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt index d2cbbbdee5..b616b19ae6 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt @@ -25,11 +25,11 @@ import androidx.core.widget.doOnTextChanged import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.showKeyboard import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentSessionRenameBinding import im.vector.app.features.settings.devices.v2.more.SessionLearnMoreBottomSheet +import im.vector.lib.strings.CommonStrings import javax.inject.Inject /** @@ -99,8 +99,8 @@ class RenameSessionFragment : private fun showLearnMoreInfo() { val args = SessionLearnMoreBottomSheet.Args( - title = getString(R.string.device_manager_learn_more_session_rename_title), - description = getString(R.string.device_manager_learn_more_session_rename), + title = getString(CommonStrings.device_manager_learn_more_session_rename_title), + description = getString(CommonStrings.device_manager_learn_more_session_rename), ) SessionLearnMoreBottomSheet .show(childFragmentManager, args) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/signout/BuildConfirmSignoutDialogUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/signout/BuildConfirmSignoutDialogUseCase.kt index 4edfc2febe..cb36a71978 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/signout/BuildConfirmSignoutDialogUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/signout/BuildConfirmSignoutDialogUseCase.kt @@ -18,18 +18,18 @@ package im.vector.app.features.settings.devices.v2.signout import android.content.Context import com.google.android.material.dialog.MaterialAlertDialogBuilder -import im.vector.app.R +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class BuildConfirmSignoutDialogUseCase @Inject constructor() { fun execute(context: Context, onConfirm: () -> Unit) = MaterialAlertDialogBuilder(context) - .setTitle(R.string.action_sign_out) - .setMessage(R.string.action_sign_out_confirmation_simple) - .setPositiveButton(R.string.action_sign_out) { _, _ -> + .setTitle(CommonStrings.action_sign_out) + .setMessage(CommonStrings.action_sign_out_confirmation_simple) + .setPositiveButton(CommonStrings.action_sign_out) { _, _ -> onConfirm() } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .create() } diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt index a5db2fc5ef..fa1b21e9e7 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt @@ -21,12 +21,12 @@ import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success -import im.vector.app.R import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.core.ui.list.genericWithValueItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import javax.inject.Inject @@ -48,7 +48,7 @@ class AccountDataEpoxyController @Inject constructor( is Loading -> { loadingItem { id("loading") - loadingText(host.stringProvider.getString(R.string.loading)) + loadingText(host.stringProvider.getString(CommonStrings.loading)) } } is Fail -> { @@ -62,7 +62,7 @@ class AccountDataEpoxyController @Inject constructor( if (dataList.isEmpty()) { genericFooterItem { id("noResults") - text(host.stringProvider.getString(R.string.no_result_placeholder).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.no_result_placeholder).toEpoxyCharSequence()) } } else { dataList.forEach { accountData -> diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataFragment.kt index 2f8dd84ddd..fff02ce324 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataFragment.kt @@ -32,6 +32,7 @@ import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.resources.ColorProvider import im.vector.app.core.utils.createJSonViewerStyleProvider import im.vector.app.databinding.FragmentGenericRecyclerBinding +import im.vector.lib.strings.CommonStrings import org.billcarsonfr.jsonviewer.JSonViewerDialog import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.api.util.MatrixJsonParser @@ -53,7 +54,7 @@ class AccountDataFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.settings_account_data) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.settings_account_data) } override fun invalidate() = withState(viewModel) { state -> @@ -84,11 +85,11 @@ class AccountDataFragment : } override fun didLongTap(data: UserAccountDataEvent) { - MaterialAlertDialogBuilder(requireActivity(), R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) - .setTitle(R.string.action_delete) - .setMessage(getString(R.string.delete_account_data_warning, data.type)) - .setNegativeButton(R.string.action_cancel, null) - .setPositiveButton(R.string.action_delete) { _, _ -> + MaterialAlertDialogBuilder(requireActivity(), im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) + .setTitle(CommonStrings.action_delete) + .setMessage(getString(CommonStrings.delete_account_data_warning, data.type)) + .setNegativeButton(CommonStrings.action_cancel, null) + .setPositiveButton(CommonStrings.action_delete) { _, _ -> viewModel.handle(AccountDataAction.DeleteAccountData(data.type)) } .show() diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestsFragment.kt index a07013ea57..a701dd7c8f 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestsFragment.kt @@ -39,6 +39,7 @@ import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.utils.selectTxtFileToWrite import im.vector.app.databinding.FragmentDevtoolKeyrequestsBinding import im.vector.lib.core.utils.timer.Clock +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.tryOrNull import javax.inject.Inject @@ -55,7 +56,7 @@ class KeyRequestsFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.key_share_request) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.key_share_request) } private var mPagerAdapter: KeyReqPagerAdapter? = null diff --git a/vector/src/main/java/im/vector/app/features/settings/font/FontScaleSettingController.kt b/vector/src/main/java/im/vector/app/features/settings/font/FontScaleSettingController.kt index d9a1361ee8..6f3b7470e1 100644 --- a/vector/src/main/java/im/vector/app/features/settings/font/FontScaleSettingController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/font/FontScaleSettingController.kt @@ -17,12 +17,12 @@ package im.vector.app.features.settings.font import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.epoxy.fontScaleItem import im.vector.app.core.epoxy.fontScaleSectionItem import im.vector.app.core.epoxy.fontScaleUseSystemSettingsItem import im.vector.app.core.resources.StringProvider import im.vector.app.features.settings.FontScaleValue +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class FontScaleSettingController @Inject constructor( @@ -42,7 +42,7 @@ class FontScaleSettingController @Inject constructor( val host = this fontScaleSectionItem { id("section_automatically") - sectionName(host.stringProvider.getString(R.string.font_size_section_auto)) + sectionName(host.stringProvider.getString(CommonStrings.font_size_section_auto)) } fontScaleUseSystemSettingsItem { @@ -58,7 +58,7 @@ class FontScaleSettingController @Inject constructor( val host = this fontScaleSectionItem { id("section_manually") - sectionName(host.stringProvider.getString(R.string.font_size_section_manually)) + sectionName(host.stringProvider.getString(CommonStrings.font_size_section_manually)) } scales.forEachIndexed { index, scaleItem -> diff --git a/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsController.kt b/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsController.kt index 96d55664fc..c111c5edd9 100644 --- a/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsController.kt @@ -32,6 +32,7 @@ import im.vector.app.features.discovery.settingsInfoItem import im.vector.app.features.discovery.settingsSectionTitleItem import im.vector.app.features.settings.VectorPreferences import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.federation.FederationVersion import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities import org.matrix.android.sdk.api.session.homeserver.RoomVersionStatus @@ -79,7 +80,7 @@ class HomeserverSettingsController @Inject constructor( } settingsSectionTitleItem { id("urlTitle") - titleResId(R.string.hs_url) + titleResId(CommonStrings.hs_url) } settingsInfoItem { id("urlValue") @@ -88,7 +89,7 @@ class HomeserverSettingsController @Inject constructor( if (vectorPreferences.developerMode()) { settingsSectionTitleItem { id("urlApiTitle") - titleResId(R.string.hs_client_url) + titleResId(CommonStrings.hs_client_url) } settingsInfoItem { id("urlApiValue") @@ -100,7 +101,7 @@ class HomeserverSettingsController @Inject constructor( private fun buildFederationVersion(federationVersion: FederationVersion) { settingsSectionTitleItem { id("nameTitle") - titleResId(R.string.settings_server_name) + titleResId(CommonStrings.settings_server_name) } settingsInfoItem { id("nameValue") @@ -108,7 +109,7 @@ class HomeserverSettingsController @Inject constructor( } settingsSectionTitleItem { id("versionTitle") - titleResId(R.string.settings_server_version) + titleResId(CommonStrings.settings_server_version) } settingsInfoItem { id("versionValue") @@ -120,7 +121,7 @@ class HomeserverSettingsController @Inject constructor( val host = this settingsSectionTitleItem { id("uploadTitle") - titleResId(R.string.settings_server_upload_size_title) + titleResId(CommonStrings.settings_server_upload_size_title) } val limit = data.homeServerCapabilities.maxUploadFileSize @@ -128,9 +129,9 @@ class HomeserverSettingsController @Inject constructor( settingsInfoItem { id("uploadValue") if (limit == HomeServerCapabilities.MAX_UPLOAD_FILE_SIZE_UNKNOWN) { - helperTextResId(R.string.settings_server_upload_size_unknown) + helperTextResId(CommonStrings.settings_server_upload_size_unknown) } else { - helperText(host.stringProvider.getString(R.string.settings_server_upload_size_content, "${limit / 1048576L} MB")) + helperText(host.stringProvider.getString(CommonStrings.settings_server_upload_size_content, "${limit / 1048576L} MB")) } } @@ -139,12 +140,12 @@ class HomeserverSettingsController @Inject constructor( if (roomCapabilities != null) { settingsSectionTitleItem { id("room_versions") - titleResId(R.string.settings_server_room_versions) + titleResId(CommonStrings.settings_server_room_versions) } genericWithValueItem { id("room_version_default") - title(host.stringProvider.getString(R.string.settings_server_default_room_version).toEpoxyCharSequence()) + title(host.stringProvider.getString(CommonStrings.settings_server_default_room_version).toEpoxyCharSequence()) value(roomCapabilities.defaultRoomVersion) } @@ -155,8 +156,8 @@ class HomeserverSettingsController @Inject constructor( value( host.stringProvider.getString( when (it.status) { - RoomVersionStatus.STABLE -> R.string.settings_server_room_version_stable - RoomVersionStatus.UNSTABLE -> R.string.settings_server_room_version_unstable + RoomVersionStatus.STABLE -> CommonStrings.settings_server_room_version_stable + RoomVersionStatus.UNSTABLE -> CommonStrings.settings_server_room_version_unstable } ) ) diff --git a/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsFragment.kt index eb342209bf..030c4ffccc 100644 --- a/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsFragment.kt @@ -24,11 +24,11 @@ import androidx.appcompat.app.AppCompatActivity import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentGenericRecyclerBinding +import im.vector.lib.strings.CommonStrings import javax.inject.Inject /** @@ -62,7 +62,7 @@ class HomeserverSettingsFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.settings_home_server) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.settings_home_server) } override fun retry() { diff --git a/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersController.kt b/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersController.kt index c0ab0bb02f..1415b031b7 100644 --- a/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersController.kt @@ -17,10 +17,10 @@ package im.vector.app.features.settings.ignored import com.airbnb.epoxy.EpoxyController -import im.vector.app.R import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.user.model.User import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject @@ -48,7 +48,7 @@ class IgnoredUsersController @Inject constructor( if (users.isEmpty()) { noResultItem { id("empty") - text(host.stringProvider.getString(R.string.no_ignored_users)) + text(host.stringProvider.getString(CommonStrings.no_ignored_users)) } } else { users.forEach { user -> diff --git a/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt b/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt index 4cf8982085..b5fc2c6b4d 100644 --- a/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt @@ -26,12 +26,12 @@ import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentGenericRecyclerBinding import im.vector.app.features.analytics.plan.MobileScreen +import im.vector.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint @@ -55,7 +55,7 @@ class VectorSettingsIgnoredUsersFragment : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - views.waitingView.waitingStatusText.setText(R.string.please_wait) + views.waitingView.waitingStatusText.setText(CommonStrings.please_wait) views.waitingView.waitingStatusText.isVisible = true ignoredUsersController.callback = this views.genericRecyclerView.configureWith(ignoredUsersController) @@ -77,17 +77,17 @@ class VectorSettingsIgnoredUsersFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.settings_ignored_users) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.settings_ignored_users) } override fun onUserIdClicked(userId: String) { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.room_participants_action_unignore_title) - .setMessage(getString(R.string.settings_unignore_user, userId)) - .setPositiveButton(R.string.unignore) { _, _ -> + .setTitle(CommonStrings.room_participants_action_unignore_title) + .setMessage(getString(CommonStrings.settings_unignore_user, userId)) + .setPositiveButton(CommonStrings.unignore) { _, _ -> viewModel.handle(IgnoredUsersAction.UnIgnore(userId)) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } diff --git a/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsFragment.kt index 73a2eb1b73..b8b5a3ebf9 100644 --- a/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsFragment.kt @@ -35,6 +35,7 @@ import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.home.room.threads.ThreadsManager import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.VectorSettingsBaseFragment +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.settings.LightweightSettingsStorage import javax.inject.Inject @@ -49,7 +50,7 @@ class VectorSettingsLabsFragment : @Inject lateinit var threadsManager: ThreadsManager @Inject lateinit var vectorFeatures: VectorFeatures - override var titleRes = R.string.room_settings_labs_pref_title + override var titleRes = CommonStrings.room_settings_labs_pref_title override val preferenceXmlRes = R.xml.vector_settings_labs override fun onCreate(savedInstanceState: Bundle?) { @@ -120,13 +121,13 @@ class VectorSettingsLabsFragment : if (!session.homeServerCapabilitiesService().getHomeServerCapabilities().canUseThreading && userEnabledThreads) { activity?.let { MaterialAlertDialogBuilder(it) - .setTitle(R.string.threads_labs_enable_notice_title) + .setTitle(CommonStrings.threads_labs_enable_notice_title) .setMessage(threadsManager.getLabsEnableThreadsMessage()) .setCancelable(true) - .setNegativeButton(R.string.action_not_now) { _, _ -> + .setNegativeButton(CommonStrings.action_not_now) { _, _ -> vectorSwitchPreference.isChecked = false } - .setPositiveButton(R.string.action_try_it_out) { _, _ -> + .setPositiveButton(CommonStrings.action_try_it_out) { _, _ -> onThreadsPreferenceClicked() } .show() diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/ElementLegals.kt b/vector/src/main/java/im/vector/app/features/settings/legals/ElementLegals.kt index 0dcea1433a..1641dee31f 100644 --- a/vector/src/main/java/im/vector/app/features/settings/legals/ElementLegals.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/ElementLegals.kt @@ -16,10 +16,10 @@ package im.vector.app.features.settings.legals -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.discovery.ServerPolicy import im.vector.app.features.settings.VectorSettingsUrls +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class ElementLegals @Inject constructor( @@ -30,9 +30,9 @@ class ElementLegals @Inject constructor( */ fun getData(): List { return listOf( - ServerPolicy(stringProvider.getString(R.string.settings_copyright), VectorSettingsUrls.COPYRIGHT), - ServerPolicy(stringProvider.getString(R.string.settings_acceptable_use_policy), VectorSettingsUrls.ACCEPTABLE_USE_POLICY), - ServerPolicy(stringProvider.getString(R.string.settings_privacy_policy), VectorSettingsUrls.PRIVACY_POLICY) + ServerPolicy(stringProvider.getString(CommonStrings.settings_copyright), VectorSettingsUrls.COPYRIGHT), + ServerPolicy(stringProvider.getString(CommonStrings.settings_acceptable_use_policy), VectorSettingsUrls.ACCEPTABLE_USE_POLICY), + ServerPolicy(stringProvider.getString(CommonStrings.settings_privacy_policy), VectorSettingsUrls.PRIVACY_POLICY) ) } } 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 a1d01024da..e5987d2a39 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 @@ -22,7 +22,6 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized -import im.vector.app.R import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.error.ErrorFormatter @@ -32,6 +31,7 @@ import im.vector.app.features.discovery.ServerPolicy import im.vector.app.features.discovery.discoveryPolicyItem import im.vector.app.features.discovery.settingsInfoItem import im.vector.app.features.discovery.settingsSectionTitleItem +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class LegalsController @Inject constructor( @@ -54,7 +54,7 @@ class LegalsController @Inject constructor( private fun buildAppSection() { settingsSectionTitleItem { id("appTitle") - titleResId(R.string.legals_application_title) + titleResId(CommonStrings.legals_application_title) } buildPolicies("el", elementLegals.getData()) @@ -63,7 +63,7 @@ class LegalsController @Inject constructor( private fun buildHomeserverSection(data: LegalsState) { settingsSectionTitleItem { id("hsServerTitle") - titleResId(R.string.legals_home_server_title) + titleResId(CommonStrings.legals_home_server_title) } buildPolicyAsync("hs", data.homeServer) @@ -73,7 +73,7 @@ class LegalsController @Inject constructor( if (data.hasIdentityServer) { settingsSectionTitleItem { id("idServerTitle") - titleResId(R.string.legals_identity_server_title) + titleResId(CommonStrings.legals_identity_server_title) } buildPolicyAsync("is", data.identityServer) @@ -93,7 +93,7 @@ class LegalsController @Inject constructor( if (policies.isNullOrEmpty()) { settingsInfoItem { id("emptyPolicy") - helperText(host.stringProvider.getString(R.string.legals_no_policy_provided)) + helperText(host.stringProvider.getString(CommonStrings.legals_no_policy_provided)) } } else { buildPolicies(tag, policies) @@ -126,19 +126,19 @@ class LegalsController @Inject constructor( val host = this settingsSectionTitleItem { id("thirdTitle") - titleResId(R.string.legals_third_party_notices) + titleResId(CommonStrings.legals_third_party_notices) } discoveryPolicyItem { id("eltpn1") - name(host.stringProvider.getString(R.string.settings_third_party_notices)) + name(host.stringProvider.getString(CommonStrings.settings_third_party_notices)) clickListener { host.listener?.openThirdPartyNotice() } } // Only on Gplay if (flavorLegals.hasThirdPartyNotices()) { discoveryPolicyItem { id("eltpn2") - name(host.stringProvider.getString(R.string.settings_other_third_party_notices)) + name(host.stringProvider.getString(CommonStrings.settings_other_third_party_notices)) clickListener { host.listener?.openThirdPartyNoticeGplay() } } } 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 6ed3cd9156..d668e8783f 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 @@ -23,7 +23,6 @@ import androidx.appcompat.app.AppCompatActivity import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment @@ -34,6 +33,7 @@ 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.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint @@ -75,7 +75,7 @@ class LegalsFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.preference_root_legals) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.preference_root_legals) viewModel.handle(LegalsAction.Refresh) } diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt index 1497c793c2..db458fe282 100644 --- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt @@ -22,7 +22,6 @@ import com.airbnb.mvrx.Success import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.EmptyViewEvents @@ -30,6 +29,7 @@ import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.features.discovery.fetchHomeserverWithTerms import im.vector.app.features.discovery.fetchIdentityServerWithTerms +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.Session @@ -67,7 +67,7 @@ class LegalsViewModel @AssistedInject constructor( if (state.homeServer !is Success) { setState { copy(homeServer = Loading()) } viewModelScope.launch { - runCatching { session.fetchHomeserverWithTerms(stringProvider.getString(R.string.resources_language)) } + runCatching { session.fetchHomeserverWithTerms(stringProvider.getString(CommonStrings.resources_language)) } .fold( onSuccess = { setState { copy(homeServer = Success(it)) } }, onFailure = { setState { copy(homeServer = Fail(it)) } } @@ -80,7 +80,7 @@ class LegalsViewModel @AssistedInject constructor( if (state.identityServer !is Success) { setState { copy(identityServer = Loading()) } viewModelScope.launch { - runCatching { session.fetchIdentityServerWithTerms(stringProvider.getString(R.string.resources_language)) } + runCatching { session.fetchIdentityServerWithTerms(stringProvider.getString(CommonStrings.resources_language)) } .fold( onSuccess = { setState { copy(identityServer = Success(it)) } }, onFailure = { setState { copy(identityServer = Fail(it)) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerController.kt b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerController.kt index 0cbfef7495..69faa693c5 100644 --- a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerController.kt @@ -21,7 +21,6 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized -import im.vector.app.R import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem @@ -31,6 +30,7 @@ import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.safeCapitalize import im.vector.app.features.settings.VectorLocale import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings import java.util.Locale import javax.inject.Inject @@ -50,7 +50,7 @@ class LocalePickerController @Inject constructor( profileSectionItem { id("currentTitle") - title(host.stringProvider.getString(R.string.choose_locale_current_locale_title)) + title(host.stringProvider.getString(CommonStrings.choose_locale_current_locale_title)) } localeItem { id(currentLocale.toString()) @@ -62,21 +62,21 @@ class LocalePickerController @Inject constructor( } profileSectionItem { id("otherTitle") - title(host.stringProvider.getString(R.string.choose_locale_other_locales_title)) + title(host.stringProvider.getString(CommonStrings.choose_locale_other_locales_title)) } when (list) { Uninitialized, is Loading -> { loadingItem { id("loading") - loadingText(host.stringProvider.getString(R.string.choose_locale_loading_locales)) + loadingText(host.stringProvider.getString(CommonStrings.choose_locale_loading_locales)) } } is Success -> if (list().isEmpty()) { noResultItem { id("noResult") - text(host.stringProvider.getString(R.string.no_result_placeholder)) + text(host.stringProvider.getString(CommonStrings.no_result_placeholder)) } } else { list() diff --git a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerFragment.kt b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerFragment.kt index 39d41f9cfc..e4a9465cd2 100644 --- a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerFragment.kt @@ -24,12 +24,12 @@ import androidx.appcompat.app.AppCompatActivity import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.restart import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentLocalePickerBinding +import im.vector.lib.strings.CommonStrings import java.util.Locale import javax.inject.Inject @@ -81,6 +81,6 @@ class LocalePickerFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.settings_select_language) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.settings_select_language) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationFragment.kt index dab7a9ed3a..44ad9ff70b 100644 --- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationFragment.kt @@ -59,6 +59,8 @@ import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.VectorSettingsBaseFragment import im.vector.app.features.settings.VectorSettingsFragmentInteractionListener import im.vector.lib.core.utils.compat.getParcelableExtraCompat +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.matrix.android.sdk.api.extensions.tryOrNull @@ -85,7 +87,7 @@ class VectorSettingsNotificationFragment : @Inject lateinit var notificationPermissionManager: NotificationPermissionManager @Inject lateinit var ensureFcmTokenIsRetrievedUseCase: EnsureFcmTokenIsRetrievedUseCase - override var titleRes: Int = R.string.settings_notifications + override var titleRes: Int = CommonStrings.settings_notifications override val preferenceXmlRes = R.xml.vector_settings_notifications private var interactionListener: VectorSettingsFragmentInteractionListener? = null @@ -259,7 +261,7 @@ class VectorSettingsNotificationFragment : category.removeAll() if (emails.isEmpty()) { val vectorPreference = VectorPreference(requireContext()) - vectorPreference.title = resources.getString(R.string.settings_notification_emails_no_emails) + vectorPreference.title = resources.getString(CommonStrings.settings_notification_emails_no_emails) category.addPreference(vectorPreference) vectorPreference.setOnPreferenceClickListener { interactionListener?.navigateToEmailAndPhoneNumbers() @@ -268,7 +270,7 @@ class VectorSettingsNotificationFragment : } else { emails.forEach { (emailPid, isEnabled) -> val pref = VectorSwitchPreference(requireContext()) - pref.title = resources.getString(R.string.settings_notification_emails_enable_for_email, emailPid.email) + pref.title = resources.getString(CommonStrings.settings_notification_emails_enable_for_email, emailPid.email) pref.isChecked = isEnabled pref.setTransactionalSwitchChangeListener(lifecycleScope) { isChecked -> if (isChecked) { @@ -305,9 +307,9 @@ class VectorSettingsNotificationFragment : private fun refreshBackgroundSyncPrefs() { findPreference(VectorPreferences.SETTINGS_FDROID_BACKGROUND_SYNC_MODE)?.let { it.summary = when (vectorPreferences.getFdroidSyncBackgroundMode()) { - BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_BATTERY -> getString(R.string.settings_background_fdroid_sync_mode_battery) - BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME -> getString(R.string.settings_background_fdroid_sync_mode_real_time) - BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_DISABLED -> getString(R.string.settings_background_fdroid_sync_mode_disabled) + BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_BATTERY -> getString(CommonStrings.settings_background_fdroid_sync_mode_battery) + BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME -> getString(CommonStrings.settings_background_fdroid_sync_mode_real_time) + BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_DISABLED -> getString(CommonStrings.settings_background_fdroid_sync_mode_disabled) } } @@ -337,7 +339,7 @@ class VectorSettingsNotificationFragment : * @return the text */ private fun secondsToText(seconds: Int): String { - return resources.getQuantityString(R.plurals.seconds, seconds, seconds) + return resources.getQuantityString(CommonPlurals.seconds, seconds, seconds) } private fun handleSystemPreference() { @@ -476,7 +478,7 @@ class VectorSettingsNotificationFragment : // revert the check box switchPref.isChecked = !switchPref.isChecked - Toast.makeText(activity, R.string.unknown_error, Toast.LENGTH_SHORT).show() + Toast.makeText(activity, CommonStrings.unknown_error, Toast.LENGTH_SHORT).show() } } } @@ -492,7 +494,7 @@ private fun SwitchPreference.setTransactionalSwitchChangeListener(scope: Corouti transaction(isChecked as Boolean) } catch (failure: Throwable) { switchPreference.isChecked = originalState - Toast.makeText(switchPreference.context, R.string.unknown_error, Toast.LENGTH_SHORT).show() + Toast.makeText(switchPreference.context, CommonStrings.unknown_error, Toast.LENGTH_SHORT).show() } } true diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationFragment.kt index b7264f6cb3..eb435c510c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsPushRuleNotificationFragment.kt @@ -21,10 +21,10 @@ import android.view.View import androidx.preference.Preference import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState -import im.vector.app.R import im.vector.app.core.preference.VectorCheckboxPreference import im.vector.app.features.settings.VectorSettingsBaseFragment import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings abstract class VectorSettingsPushRuleNotificationFragment : VectorSettingsBaseFragment() { @@ -84,8 +84,8 @@ abstract class VectorSettingsPushRuleNotificationFragment : prefKeyToPushRuleId.forEach { (preferenceKey, ruleId) -> findPreference(preferenceKey)?.apply { if (ruleId in rulesWithError) { - summaryTextColor = ThemeUtils.getColor(context, R.attr.colorError) - setSummary(R.string.settings_notification_error_on_update) + summaryTextColor = ThemeUtils.getColor(context, com.google.android.material.R.attr.colorError) + setSummary(CommonStrings.settings_notification_error_on_update) } else { summaryTextColor = null summary = null diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/advanced/VectorSettingsAdvancedNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/advanced/VectorSettingsAdvancedNotificationPreferenceFragment.kt index 44d7330d39..a5ca19845d 100644 --- a/vector/src/main/java/im/vector/app/features/settings/notifications/advanced/VectorSettingsAdvancedNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/notifications/advanced/VectorSettingsAdvancedNotificationPreferenceFragment.kt @@ -27,6 +27,7 @@ import im.vector.app.features.settings.notifications.NotificationIndex import im.vector.app.features.settings.notifications.StandardActions import im.vector.app.features.settings.notifications.getStandardAction import im.vector.app.features.settings.notifications.notificationIndex +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.pushrules.RuleIds import org.matrix.android.sdk.api.session.pushrules.rest.PushRuleAndKind @@ -36,7 +37,7 @@ import org.matrix.android.sdk.api.session.pushrules.rest.PushRuleAndKind class VectorSettingsAdvancedNotificationPreferenceFragment : VectorSettingsBaseFragment() { - override var titleRes: Int = R.string.settings_notification_advanced + override var titleRes: Int = CommonStrings.settings_notification_advanced override val preferenceXmlRes = R.xml.vector_settings_notification_advanced_preferences diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/defaults/VectorSettingsDefaultNotificationFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/defaults/VectorSettingsDefaultNotificationFragment.kt index 009213ceff..db8c34e584 100644 --- a/vector/src/main/java/im/vector/app/features/settings/notifications/defaults/VectorSettingsDefaultNotificationFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/notifications/defaults/VectorSettingsDefaultNotificationFragment.kt @@ -21,12 +21,13 @@ import im.vector.app.R import im.vector.app.core.preference.VectorPreferenceCategory import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.settings.notifications.VectorSettingsPushRuleNotificationFragment +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.pushrules.RuleIds class VectorSettingsDefaultNotificationFragment : VectorSettingsPushRuleNotificationFragment() { - override var titleRes: Int = R.string.settings_notification_default + override var titleRes: Int = CommonStrings.settings_notification_default override val preferenceXmlRes = R.xml.vector_settings_notification_default diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/keywordandmentions/VectorSettingsKeywordAndMentionsNotificationFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/keywordandmentions/VectorSettingsKeywordAndMentionsNotificationFragment.kt index c408b8ea91..9b836ec60e 100644 --- a/vector/src/main/java/im/vector/app/features/settings/notifications/keywordandmentions/VectorSettingsKeywordAndMentionsNotificationFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/notifications/keywordandmentions/VectorSettingsKeywordAndMentionsNotificationFragment.kt @@ -30,6 +30,7 @@ import im.vector.app.features.settings.notifications.NotificationIndex import im.vector.app.features.settings.notifications.StandardActions import im.vector.app.features.settings.notifications.VectorSettingsPushRuleNotificationFragment import im.vector.app.features.settings.notifications.getStandardAction +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -41,7 +42,7 @@ import org.matrix.android.sdk.api.session.pushrules.toJson class VectorSettingsKeywordAndMentionsNotificationFragment : VectorSettingsPushRuleNotificationFragment() { - override var titleRes: Int = R.string.settings_notification_mentions_and_keywords + override var titleRes: Int = CommonStrings.settings_notification_mentions_and_keywords override val preferenceXmlRes = R.xml.vector_settings_notification_mentions_and_keywords diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/other/VectorSettingsOtherNotificationFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/other/VectorSettingsOtherNotificationFragment.kt index 5f8ad08a80..d878ed1202 100644 --- a/vector/src/main/java/im/vector/app/features/settings/notifications/other/VectorSettingsOtherNotificationFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/notifications/other/VectorSettingsOtherNotificationFragment.kt @@ -19,12 +19,13 @@ package im.vector.app.features.settings.notifications.other import im.vector.app.R import im.vector.app.core.preference.VectorPreferenceCategory import im.vector.app.features.settings.notifications.VectorSettingsPushRuleNotificationFragment +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.pushrules.RuleIds class VectorSettingsOtherNotificationFragment : VectorSettingsPushRuleNotificationFragment() { - override var titleRes: Int = R.string.settings_notification_other + override var titleRes: Int = CommonStrings.settings_notification_other override val preferenceXmlRes = R.xml.vector_settings_notification_other diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/troubleshoot/VectorSettingsNotificationsTroubleshootFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/troubleshoot/VectorSettingsNotificationsTroubleshootFragment.kt index b814c981c9..72d7c5e525 100644 --- a/vector/src/main/java/im/vector/app/features/settings/notifications/troubleshoot/VectorSettingsNotificationsTroubleshootFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/notifications/troubleshoot/VectorSettingsNotificationsTroubleshootFragment.kt @@ -30,7 +30,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.transition.TransitionManager import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseFragment @@ -43,6 +42,7 @@ 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.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.tryOrNull import javax.inject.Inject @@ -84,14 +84,14 @@ class VectorSettingsNotificationsTroubleshootFragment : } private fun startUI() { - views.toubleshootSummDescription.text = getString(R.string.settings_troubleshoot_diagnostic_running_status, 0, 0) + views.toubleshootSummDescription.text = getString(CommonStrings.settings_troubleshoot_diagnostic_running_status, 0, 0) testManager = testManagerFactory.create(this) testManager?.statusListener = { troubleshootTestManager -> if (isAdded) { TransitionManager.beginDelayedTransition(views.troubleshootBottomView) when (troubleshootTestManager.diagStatus) { TroubleshootTest.TestStatus.NOT_STARTED -> { - views.toubleshootSummDescription.text = "" + views.toubleshootSummDescription.text = null views.troubleshootSummButton.visibility = View.GONE views.troubleshootRunButton.visibility = View.VISIBLE } @@ -100,7 +100,7 @@ class VectorSettingsNotificationsTroubleshootFragment : val size = troubleshootTestManager.testListSize val currentTestIndex = troubleshootTestManager.currentTestIndex views.toubleshootSummDescription.text = getString( - R.string.settings_troubleshoot_diagnostic_running_status, + CommonStrings.settings_troubleshoot_diagnostic_running_status, currentTestIndex, size ) @@ -111,15 +111,15 @@ class VectorSettingsNotificationsTroubleshootFragment : // check if there are quick fixes val hasQuickFix = testManager?.hasQuickFix().orFalse() if (hasQuickFix) { - views.toubleshootSummDescription.text = getString(R.string.settings_troubleshoot_diagnostic_failure_status_with_quickfix) + views.toubleshootSummDescription.text = getString(CommonStrings.settings_troubleshoot_diagnostic_failure_status_with_quickfix) } else { - views.toubleshootSummDescription.text = getString(R.string.settings_troubleshoot_diagnostic_failure_status_no_quickfix) + views.toubleshootSummDescription.text = getString(CommonStrings.settings_troubleshoot_diagnostic_failure_status_no_quickfix) } views.troubleshootSummButton.visibility = View.VISIBLE views.troubleshootRunButton.visibility = View.VISIBLE } TroubleshootTest.TestStatus.SUCCESS -> { - views.toubleshootSummDescription.text = getString(R.string.settings_troubleshoot_diagnostic_success_status) + views.toubleshootSummDescription.text = getString(CommonStrings.settings_troubleshoot_diagnostic_success_status) views.troubleshootSummButton.visibility = View.VISIBLE views.troubleshootRunButton.visibility = View.VISIBLE } @@ -162,7 +162,7 @@ class VectorSettingsNotificationsTroubleshootFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.settings_notification_troubleshoot) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.settings_notification_troubleshoot) tryOrNull("Unable to register the receiver") { LocalBroadcastManager.getInstance(requireContext()) diff --git a/vector/src/main/java/im/vector/app/features/settings/push/PushGateWayController.kt b/vector/src/main/java/im/vector/app/features/settings/push/PushGateWayController.kt index 68c3e960c7..f5d77a316c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/push/PushGateWayController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/push/PushGateWayController.kt @@ -17,10 +17,10 @@ package im.vector.app.features.settings.push import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class PushGateWayController @Inject constructor( @@ -35,7 +35,7 @@ class PushGateWayController @Inject constructor( if (pushers.isEmpty()) { genericFooterItem { id("footer") - text(host.stringProvider.getString(R.string.settings_push_gateway_no_pushers).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.settings_push_gateway_no_pushers).toEpoxyCharSequence()) } } else { pushers.forEach { @@ -51,7 +51,7 @@ class PushGateWayController @Inject constructor( } ?: run { genericFooterItem { id("loading") - text(host.stringProvider.getString(R.string.loading).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.loading).toEpoxyCharSequence()) } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysFragment.kt b/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysFragment.kt index 2bbb93e63c..a6e3e23b5a 100644 --- a/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysFragment.kt @@ -32,6 +32,7 @@ import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.databinding.FragmentGenericRecyclerBinding +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.pushers.Pusher import javax.inject.Inject @@ -63,7 +64,7 @@ class PushGatewaysFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.settings_notifications_targets) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.settings_notifications_targets) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -76,7 +77,7 @@ class PushGatewaysFragment : when (it) { is PushGatewayViewEvents.RemovePusherFailed -> { MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(errorFormatter.toHumanReadable(it.cause)) .setPositiveButton(android.R.string.ok, null) .show() diff --git a/vector/src/main/java/im/vector/app/features/settings/push/PushRuleItem.kt b/vector/src/main/java/im/vector/app/features/settings/push/PushRuleItem.kt index 57b2595590..30811510cc 100644 --- a/vector/src/main/java/im/vector/app/features/settings/push/PushRuleItem.kt +++ b/vector/src/main/java/im/vector/app/features/settings/push/PushRuleItem.kt @@ -30,6 +30,7 @@ import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel import im.vector.app.features.notifications.toNotificationAction import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.pushrules.getActions import org.matrix.android.sdk.api.session.pushrules.rest.PushRule @@ -48,7 +49,7 @@ abstract class PushRuleItem : VectorEpoxyModel(R.layout.ite holder.view.setBackgroundColor(Color.TRANSPARENT) holder.ruleId.text = pushRule.ruleId } else { - holder.view.setBackgroundColor(ThemeUtils.getColor(context, R.attr.vctr_header_background)) + holder.view.setBackgroundColor(ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_header_background)) holder.ruleId.text = "[Disabled] ${pushRule.ruleId}" } val actions = pushRule.getActions() @@ -60,13 +61,13 @@ abstract class PushRuleItem : VectorEpoxyModel(R.layout.ite if (notifAction.shouldNotify && !notifAction.soundName.isNullOrBlank()) { holder.actionIcon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_action_notify_noisy)) - holder.actionIcon.contentDescription = context.getString(R.string.a11y_rule_notify_noisy) + holder.actionIcon.contentDescription = context.getString(CommonStrings.a11y_rule_notify_noisy) } else if (notifAction.shouldNotify) { holder.actionIcon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_action_notify_silent)) - holder.actionIcon.contentDescription = context.getString(R.string.a11y_rule_notify_silent) + holder.actionIcon.contentDescription = context.getString(CommonStrings.a11y_rule_notify_silent) } else { holder.actionIcon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_action_dont_notify)) - holder.actionIcon.contentDescription = context.getString(R.string.a11y_rule_notify_off) + holder.actionIcon.contentDescription = context.getString(CommonStrings.a11y_rule_notify_off) } val description = StringBuffer() diff --git a/vector/src/main/java/im/vector/app/features/settings/push/PushRulesController.kt b/vector/src/main/java/im/vector/app/features/settings/push/PushRulesController.kt index 68f288ffd3..7098e5e084 100644 --- a/vector/src/main/java/im/vector/app/features/settings/push/PushRulesController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/push/PushRulesController.kt @@ -17,10 +17,10 @@ package im.vector.app.features.settings.push import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class PushRulesController @Inject constructor( @@ -39,7 +39,7 @@ class PushRulesController @Inject constructor( } ?: run { genericFooterItem { id("footer") - text(host.stringProvider.getString(R.string.settings_push_rules_no_rules).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.settings_push_rules_no_rules).toEpoxyCharSequence()) } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/push/PushRulesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/push/PushRulesFragment.kt index 6e4c049202..ba111c4af0 100644 --- a/vector/src/main/java/im/vector/app/features/settings/push/PushRulesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/push/PushRulesFragment.kt @@ -28,6 +28,7 @@ import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentGenericRecyclerBinding +import im.vector.lib.strings.CommonStrings import javax.inject.Inject // Referenced in vector_settings_notifications.xml @@ -45,7 +46,7 @@ class PushRulesFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.settings_push_rules) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.settings_push_rules) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { diff --git a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsController.kt b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsController.kt index 32868783d2..22cceb4a3c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsController.kt @@ -21,7 +21,6 @@ import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success -import im.vector.app.R import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.error.ErrorFormatter @@ -37,6 +36,7 @@ import im.vector.app.features.discovery.settingsInfoItem import im.vector.app.features.discovery.settingsInformationItem import im.vector.app.features.discovery.settingsSectionTitleItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.api.session.identity.ThreePid @@ -80,7 +80,7 @@ class ThreePidsSettingsController @Inject constructor( is Loading -> { loadingItem { id("loading") - loadingText(host.stringProvider.getString(R.string.loading)) + loadingText(host.stringProvider.getString(CommonStrings.loading)) } } is Fail -> { @@ -105,7 +105,7 @@ class ThreePidsSettingsController @Inject constructor( settingsSectionTitleItem { id("email") - title(host.stringProvider.getString(R.string.settings_emails)) + title(host.stringProvider.getString(CommonStrings.settings_emails)) } emails.forEach { buildThreePid("email ", it) } @@ -118,7 +118,7 @@ class ThreePidsSettingsController @Inject constructor( if (pendingList.isEmpty() && emails.isEmpty()) { noResultItem { id("noEmail") - text(host.stringProvider.getString(R.string.settings_emails_empty)) + text(host.stringProvider.getString(CommonStrings.settings_emails_empty)) } } @@ -129,15 +129,15 @@ class ThreePidsSettingsController @Inject constructor( ThreePidsSettingsUiState.Idle -> genericButtonItem { id("addEmail") - text(host.stringProvider.getString(R.string.settings_add_email_address)) - textColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + text(host.stringProvider.getString(CommonStrings.settings_add_email_address)) + textColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) buttonClickAction { host.interactionListener?.addEmail() } } is ThreePidsSettingsUiState.AddingEmail -> { settingsEditTextItem { id("addingEmail") inputType(InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS) - hint(host.stringProvider.getString(R.string.medium_email)) + hint(host.stringProvider.getString(CommonStrings.medium_email)) if (data.editTextReinitiator.isTrue()) { value("") requestFocus(true) @@ -164,7 +164,7 @@ class ThreePidsSettingsController @Inject constructor( settingsSectionTitleItem { id("msisdn") - title(host.stringProvider.getString(R.string.settings_phone_numbers)) + title(host.stringProvider.getString(CommonStrings.settings_phone_numbers)) } msisdn.forEach { buildThreePid("msisdn ", it) } @@ -177,7 +177,7 @@ class ThreePidsSettingsController @Inject constructor( if (pendingList.isEmpty() && msisdn.isEmpty()) { noResultItem { id("noMsisdn") - text(host.stringProvider.getString(R.string.settings_phone_number_empty)) + text(host.stringProvider.getString(CommonStrings.settings_phone_number_empty)) } } @@ -188,20 +188,20 @@ class ThreePidsSettingsController @Inject constructor( ThreePidsSettingsUiState.Idle -> genericButtonItem { id("addMsisdn") - text(host.stringProvider.getString(R.string.settings_add_phone_number)) - textColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + text(host.stringProvider.getString(CommonStrings.settings_add_phone_number)) + textColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) buttonClickAction { host.interactionListener?.addMsisdn() } } is ThreePidsSettingsUiState.AddingEmail -> Unit is ThreePidsSettingsUiState.AddingPhoneNumber -> { settingsInfoItem { id("addingMsisdnInfo") - helperText(host.stringProvider.getString(R.string.login_msisdn_notice)) + helperText(host.stringProvider.getString(CommonStrings.login_msisdn_notice)) } settingsEditTextItem { id("addingMsisdn") inputType(InputType.TYPE_CLASS_PHONE) - hint(host.stringProvider.getString(R.string.medium_phone_number)) + hint(host.stringProvider.getString(CommonStrings.medium_phone_number)) if (data.editTextReinitiator.isTrue()) { value("") requestFocus(true) @@ -250,8 +250,8 @@ class ThreePidsSettingsController @Inject constructor( is ThreePid.Email -> { settingsInformationItem { id("info" + idPrefix + threePid.value) - message(host.stringProvider.getString(R.string.account_email_validation_message)) - textColor(host.colorProvider.getColor(R.color.vector_info_color)) + message(host.stringProvider.getString(CommonStrings.account_email_validation_message)) + textColor(host.colorProvider.getColor(im.vector.lib.ui.styles.R.color.vector_info_color)) } settingsContinueCancelItem { id("cont" + idPrefix + threePid.value) @@ -262,13 +262,13 @@ class ThreePidsSettingsController @Inject constructor( is ThreePid.Msisdn -> { settingsInformationItem { id("info" + idPrefix + threePid.value) - message(host.stringProvider.getString(R.string.settings_text_message_sent, threePid.getFormattedValue())) - textColor(host.colorProvider.getColor(R.color.vector_info_color)) + message(host.stringProvider.getString(CommonStrings.settings_text_message_sent, threePid.getFormattedValue())) + textColor(host.colorProvider.getColor(im.vector.lib.ui.styles.R.color.vector_info_color)) } settingsEditTextItem { id("msisdnVerification${threePid.value}") inputType(InputType.TYPE_CLASS_NUMBER) - hint(host.stringProvider.getString(R.string.settings_text_message_sent_hint)) + hint(host.stringProvider.getString(CommonStrings.settings_text_message_sent_hint)) if (data.msisdnValidationReinitiator[threePid]?.isTrue() == true) { value("") } @@ -299,7 +299,7 @@ class ThreePidsSettingsController @Inject constructor( return if (failure is Failure.ServerError && failure.httpCode == 400 && failure.error.code == MatrixError.M_UNKNOWN) { - stringProvider.getString(R.string.settings_text_message_sent_wrong_code) + stringProvider.getString(CommonStrings.settings_text_message_sent_wrong_code) } else { errorFormatter.toHumanReadable(failure) } diff --git a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsFragment.kt index 7fe4fad844..bbd6a0991a 100644 --- a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsFragment.kt @@ -26,7 +26,6 @@ import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.getFormattedValue @@ -37,6 +36,7 @@ import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentGenericRecyclerBinding import im.vector.app.features.auth.ReAuthActivity +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.extensions.isEmail import org.matrix.android.sdk.api.session.identity.ThreePid @@ -74,7 +74,7 @@ class ThreePidsSettingsFragment : requireContext(), event.registrationFlowResponse, event.lastErrorCode, - getString(R.string.settings_add_email_address) + getString(CommonStrings.settings_add_email_address) ).let { intent -> reAuthActivityResultLauncher.launch(intent) } @@ -107,7 +107,7 @@ class ThreePidsSettingsFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.settings_emails_and_phone_numbers_title) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.settings_emails_and_phone_numbers_title) } override fun invalidate() = withState(viewModel) { state -> @@ -130,7 +130,7 @@ class ThreePidsSettingsFragment : // Check that email is valid if (!safeEmail.isEmail()) { - viewModel.handle(ThreePidsSettingsAction.ChangeUiState(ThreePidsSettingsUiState.AddingEmail(getString(R.string.auth_invalid_email)))) + viewModel.handle(ThreePidsSettingsAction.ChangeUiState(ThreePidsSettingsUiState.AddingEmail(getString(CommonStrings.auth_invalid_email)))) return } @@ -150,14 +150,16 @@ class ThreePidsSettingsFragment : // Check that phone number is valid if (!msisdn.startsWith("+")) { viewModel.handle( - ThreePidsSettingsAction.ChangeUiState(ThreePidsSettingsUiState.AddingPhoneNumber(getString(R.string.login_msisdn_error_not_international))) + ThreePidsSettingsAction.ChangeUiState(ThreePidsSettingsUiState.AddingPhoneNumber( + getString(CommonStrings.login_msisdn_error_not_international)) + ) ) return } if (!msisdn.isMsisdn()) { viewModel.handle( - ThreePidsSettingsAction.ChangeUiState(ThreePidsSettingsUiState.AddingPhoneNumber(getString(R.string.login_msisdn_error_other))) + ThreePidsSettingsAction.ChangeUiState(ThreePidsSettingsUiState.AddingPhoneNumber(getString(CommonStrings.login_msisdn_error_other))) ) return } @@ -186,12 +188,12 @@ class ThreePidsSettingsFragment : } override fun deleteThreePid(threePid: ThreePid) { - MaterialAlertDialogBuilder(requireActivity(), R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) - .setMessage(getString(R.string.settings_remove_three_pid_confirmation_content, threePid.getFormattedValue())) - .setPositiveButton(R.string.action_remove) { _, _ -> + MaterialAlertDialogBuilder(requireActivity(), im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) + .setMessage(getString(CommonStrings.settings_remove_three_pid_confirmation_content, threePid.getFormattedValue())) + .setPositiveButton(CommonStrings.action_remove) { _, _ -> viewModel.handle(ThreePidsSettingsAction.DeleteThreePid(threePid)) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } diff --git a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt index 249df0007f..64a5d5f216 100644 --- a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt @@ -22,13 +22,13 @@ import com.airbnb.mvrx.MavericksViewModelFactory import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.ReadOnceTrue import im.vector.app.features.auth.PendingAuthHandler +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import org.matrix.android.sdk.api.auth.UIABaseAuth import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor @@ -185,8 +185,8 @@ class ThreePidsSettingsViewModel @AssistedInject constructor( IllegalArgumentException( stringProvider.getString( when (action.threePid) { - is ThreePid.Email -> R.string.auth_email_already_defined - is ThreePid.Msisdn -> R.string.auth_msisdn_already_defined + is ThreePid.Email -> CommonStrings.auth_email_already_defined + is ThreePid.Msisdn -> CommonStrings.auth_msisdn_already_defined } ) ) diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootRecyclerViewAdapter.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootRecyclerViewAdapter.kt index 1bd0cb3988..97ce528ade 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootRecyclerViewAdapter.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootRecyclerViewAdapter.kt @@ -47,12 +47,12 @@ class NotificationTroubleshootRecyclerViewAdapter(val tests: ArrayList { - views.troubleshootTestTitle.setTextColor(ThemeUtils.getColor(context, R.attr.vctr_content_secondary)) + views.troubleshootTestTitle.setTextColor(ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary)) views.troubleshootProgressBar.visibility = View.INVISIBLE views.troubleshootStatusIcon.visibility = View.VISIBLE @@ -61,7 +61,7 @@ class NotificationTroubleshootRecyclerViewAdapter(val tests: ArrayList { views.troubleshootProgressBar.visibility = View.INVISIBLE views.troubleshootStatusIcon.visibility = View.VISIBLE - val infoColor = ContextCompat.getColor(context, R.color.vector_info_color) + val infoColor = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.vector_info_color) val drawable = ContextCompat.getDrawable(itemView.context, R.drawable.ic_notification_privacy_warning)?.apply { ThemeUtils.tintDrawableWithColor(this, infoColor) } @@ -77,7 +77,7 @@ class NotificationTroubleshootRecyclerViewAdapter(val tests: ArrayList { views.troubleshootProgressBar.visibility = View.INVISIBLE diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestAccountSettings.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestAccountSettings.kt index 5032c97935..7b0f46f366 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestAccountSettings.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestAccountSettings.kt @@ -15,10 +15,10 @@ */ package im.vector.app.features.settings.troubleshoot -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.resources.StringProvider import im.vector.app.features.session.coroutineScope +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -34,7 +34,7 @@ class TestAccountSettings @Inject constructor( private val stringProvider: StringProvider, private val activeSessionHolder: ActiveSessionHolder ) : - TroubleshootTest(R.string.settings_troubleshoot_test_account_settings_title) { + TroubleshootTest(CommonStrings.settings_troubleshoot_test_account_settings_title) { override fun perform(testParameters: TestParameters) { val session = activeSessionHolder.getSafeActiveSession() ?: return @@ -43,12 +43,12 @@ class TestAccountSettings @Inject constructor( if (defaultRule != null) { if (!defaultRule.enabled) { - description = stringProvider.getString(R.string.settings_troubleshoot_test_account_settings_success) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_account_settings_success) quickFix = null status = TestStatus.SUCCESS } else { - description = stringProvider.getString(R.string.settings_troubleshoot_test_account_settings_failed) - quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_account_settings_quickfix) { + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_account_settings_failed) + quickFix = object : TroubleshootQuickFix(CommonStrings.settings_troubleshoot_test_account_settings_quickfix) { override fun doFix() { if (manager?.diagStatus == TestStatus.RUNNING) return // wait before all is finished 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 e6fa59f597..55368c974f 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 @@ -16,31 +16,32 @@ package im.vector.app.features.settings.troubleshoot -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.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class TestAvailableUnifiedPushDistributors @Inject constructor( private val unifiedPushHelper: UnifiedPushHelper, private val stringProvider: StringProvider, private val fcmHelper: FcmHelper, -) : TroubleshootTest(R.string.settings_troubleshoot_test_distributors_title) { +) : TroubleshootTest(CommonStrings.settings_troubleshoot_test_distributors_title) { override fun perform(testParameters: TestParameters) { val distributors = unifiedPushHelper.getExternalDistributors() description = if (distributors.isEmpty()) { stringProvider.getString( if (fcmHelper.isFirebaseAvailable()) { - R.string.settings_troubleshoot_test_distributors_gplay + CommonStrings.settings_troubleshoot_test_distributors_gplay } else { - R.string.settings_troubleshoot_test_distributors_fdroid + CommonStrings.settings_troubleshoot_test_distributors_fdroid } ) } else { val quantity = distributors.size + 1 - stringProvider.getQuantityString(R.plurals.settings_troubleshoot_test_distributors_many, quantity, quantity) + stringProvider.getQuantityString(CommonPlurals.settings_troubleshoot_test_distributors_many, quantity, quantity) } status = TestStatus.SUCCESS } diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestCurrentUnifiedPushDistributor.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestCurrentUnifiedPushDistributor.kt index bc291725fd..bf737f7b4d 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestCurrentUnifiedPushDistributor.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestCurrentUnifiedPushDistributor.kt @@ -16,19 +16,19 @@ package im.vector.app.features.settings.troubleshoot -import im.vector.app.R import im.vector.app.core.pushers.UnifiedPushHelper import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class TestCurrentUnifiedPushDistributor @Inject constructor( private val unifiedPushHelper: UnifiedPushHelper, private val stringProvider: StringProvider, -) : TroubleshootTest(R.string.settings_troubleshoot_test_current_distributor_title) { +) : TroubleshootTest(CommonStrings.settings_troubleshoot_test_current_distributor_title) { override fun perform(testParameters: TestParameters) { description = stringProvider.getString( - R.string.settings_troubleshoot_test_current_distributor, + CommonStrings.settings_troubleshoot_test_current_distributor, unifiedPushHelper.getCurrentDistributorName() ) status = TestStatus.SUCCESS diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestDeviceSettings.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestDeviceSettings.kt index a0be2a7077..620c1ea526 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestDeviceSettings.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestDeviceSettings.kt @@ -15,9 +15,9 @@ */ package im.vector.app.features.settings.troubleshoot -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings import javax.inject.Inject /** @@ -27,21 +27,21 @@ class TestDeviceSettings @Inject constructor( private val vectorPreferences: VectorPreferences, private val stringProvider: StringProvider ) : - TroubleshootTest(R.string.settings_troubleshoot_test_device_settings_title) { + TroubleshootTest(CommonStrings.settings_troubleshoot_test_device_settings_title) { override fun perform(testParameters: TestParameters) { if (vectorPreferences.areNotificationEnabledForDevice()) { - description = stringProvider.getString(R.string.settings_troubleshoot_test_device_settings_success) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_device_settings_success) quickFix = null status = TestStatus.SUCCESS } else { - quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_device_settings_quickfix) { + quickFix = object : TroubleshootQuickFix(CommonStrings.settings_troubleshoot_test_device_settings_quickfix) { override fun doFix() { vectorPreferences.setNotificationEnabledForDevice(true) manager?.retry(testParameters) } } - description = stringProvider.getString(R.string.settings_troubleshoot_test_device_settings_failed) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_device_settings_failed) status = TestStatus.FAILED } } diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestEndpointAsTokenRegistration.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestEndpointAsTokenRegistration.kt index 6489fe537d..7c9bf23de7 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestEndpointAsTokenRegistration.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestEndpointAsTokenRegistration.kt @@ -20,7 +20,6 @@ import androidx.fragment.app.FragmentActivity import androidx.lifecycle.lifecycleScope 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.PushersManager import im.vector.app.core.pushers.RegisterUnifiedPushUseCase @@ -28,6 +27,7 @@ import im.vector.app.core.pushers.UnifiedPushHelper import im.vector.app.core.pushers.UnregisterUnifiedPushUseCase import im.vector.app.core.resources.StringProvider import im.vector.app.features.session.coroutineScope +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.pushers.PusherState import javax.inject.Inject @@ -40,7 +40,7 @@ class TestEndpointAsTokenRegistration @Inject constructor( private val unifiedPushHelper: UnifiedPushHelper, private val registerUnifiedPushUseCase: RegisterUnifiedPushUseCase, private val unregisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase, -) : TroubleshootTest(R.string.settings_troubleshoot_test_endpoint_registration_title) { +) : TroubleshootTest(CommonStrings.settings_troubleshoot_test_endpoint_registration_title) { override fun perform(testParameters: TestParameters) { // Check if we have a registered pusher for this token @@ -57,17 +57,17 @@ class TestEndpointAsTokenRegistration @Inject constructor( } if (pushers.isEmpty()) { description = stringProvider.getString( - R.string.settings_troubleshoot_test_endpoint_registration_failed, - stringProvider.getString(R.string.sas_error_unknown) + CommonStrings.settings_troubleshoot_test_endpoint_registration_failed, + stringProvider.getString(CommonStrings.sas_error_unknown) ) - quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_endpoint_registration_quick_fix) { + quickFix = object : TroubleshootQuickFix(CommonStrings.settings_troubleshoot_test_endpoint_registration_quick_fix) { override fun doFix() { unregisterThenRegister(testParameters, endpoint) } } status = TestStatus.FAILED } else { - description = stringProvider.getString(R.string.settings_troubleshoot_test_endpoint_registration_success) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_endpoint_registration_success) status = TestStatus.SUCCESS } } diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNotification.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNotification.kt index 403c4a02c9..1a35ae4a5e 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNotification.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNotification.kt @@ -16,10 +16,10 @@ package im.vector.app.features.settings.troubleshoot import android.content.Context -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.startNotificationSettingsIntent import im.vector.app.features.notifications.NotificationUtils +import im.vector.lib.strings.CommonStrings import javax.inject.Inject /** @@ -30,14 +30,14 @@ class TestNotification @Inject constructor( private val notificationUtils: NotificationUtils, private val stringProvider: StringProvider ) : - TroubleshootTest(R.string.settings_troubleshoot_test_notification_title) { + TroubleshootTest(CommonStrings.settings_troubleshoot_test_notification_title) { override fun perform(testParameters: TestParameters) { // Display the notification right now notificationUtils.displayDiagnosticNotification() - description = stringProvider.getString(R.string.settings_troubleshoot_test_notification_notice) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_notification_notice) - quickFix = object : TroubleshootQuickFix(R.string.open_settings) { + quickFix = object : TroubleshootQuickFix(CommonStrings.open_settings) { override fun doFix() { startNotificationSettingsIntent(context, testParameters.activityResultLauncher) } @@ -47,7 +47,7 @@ class TestNotification @Inject constructor( } override fun onNotificationClicked() { - description = stringProvider.getString(R.string.settings_troubleshoot_test_notification_notification_clicked) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_notification_notification_clicked) quickFix = null status = TestStatus.SUCCESS } diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushFromPushGateway.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushFromPushGateway.kt index 1fec8691d7..7ae0e1cd8a 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushFromPushGateway.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushFromPushGateway.kt @@ -15,12 +15,12 @@ */ package im.vector.app.features.settings.troubleshoot -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.pushers.PushersManager import im.vector.app.core.resources.StringProvider import im.vector.app.features.session.coroutineScope +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch @@ -36,7 +36,7 @@ class TestPushFromPushGateway @Inject constructor( private val errorFormatter: ErrorFormatter, private val pushersManager: PushersManager, private val activeSessionHolder: ActiveSessionHolder, -) : TroubleshootTest(R.string.settings_troubleshoot_test_push_loop_title) { +) : TroubleshootTest(CommonStrings.settings_troubleshoot_test_push_loop_title) { private var action: Job? = null private var pushReceived: Boolean = false @@ -52,17 +52,17 @@ class TestPushFromPushGateway @Inject constructor( { if (pushReceived) { // Push already received (race condition) - description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_success) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_push_loop_success) TestStatus.SUCCESS } else { // Wait for the push to be received - description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_waiting_for_push) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_push_loop_waiting_for_push) TestStatus.RUNNING } }, { description = if (it is PushGatewayFailure.PusherRejected) { - stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_failed) + stringProvider.getString(CommonStrings.settings_troubleshoot_test_push_loop_failed) } else { errorFormatter.toHumanReadable(it) } @@ -75,7 +75,7 @@ class TestPushFromPushGateway @Inject constructor( override fun onPushReceived() { pushReceived = true - description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_success) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_push_loop_success) status = TestStatus.SUCCESS } diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushRulesSettings.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushRulesSettings.kt index 0fe6ed3ad0..c5d9650cfb 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushRulesSettings.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushRulesSettings.kt @@ -15,10 +15,10 @@ */ package im.vector.app.features.settings.troubleshoot -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.resources.StringProvider import im.vector.app.features.notifications.toNotificationAction +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.pushrules.RuleIds import org.matrix.android.sdk.api.session.pushrules.getActions import javax.inject.Inject @@ -27,7 +27,7 @@ class TestPushRulesSettings @Inject constructor( private val activeSessionHolder: ActiveSessionHolder, private val stringProvider: StringProvider ) : - TroubleshootTest(R.string.settings_troubleshoot_test_bing_settings_title) { + TroubleshootTest(CommonStrings.settings_troubleshoot_test_bing_settings_title) { private val testedRules = listOf( @@ -59,9 +59,9 @@ class TestPushRulesSettings @Inject constructor( } if (oneOrMoreRuleIsOff) { - description = stringProvider.getString(R.string.settings_troubleshoot_test_bing_settings_failed) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_bing_settings_failed) // TODO -// quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_bing_settings_quickfix) { +// quickFix = object : TroubleshootQuickFix(CommonStrings.settings_troubleshoot_test_bing_settings_quickfix) { // override fun doFix() { // val activity = fragment.activity // if (activity is VectorSettingsFragmentInteractionListener) { @@ -73,7 +73,7 @@ class TestPushRulesSettings @Inject constructor( status = TestStatus.FAILED } else { description = if (oneOrMoreRuleAreSilent) { - stringProvider.getString(R.string.settings_troubleshoot_test_bing_settings_success_with_warn) + stringProvider.getString(CommonStrings.settings_troubleshoot_test_bing_settings_success_with_warn) } else { null } diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestSystemSettings.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestSystemSettings.kt index 589edecad9..135bc372c8 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestSystemSettings.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestSystemSettings.kt @@ -18,10 +18,10 @@ package im.vector.app.features.settings.troubleshoot import android.os.Build import androidx.core.app.NotificationManagerCompat import androidx.fragment.app.FragmentActivity -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.startNotificationSettingsIntent import im.vector.app.features.home.NotificationPermissionManager +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.util.BuildVersionSdkIntProvider import javax.inject.Inject @@ -34,25 +34,25 @@ class TestSystemSettings @Inject constructor( private val stringProvider: StringProvider, private val sdkIntProvider: BuildVersionSdkIntProvider, private val notificationPermissionManager: NotificationPermissionManager, -) : TroubleshootTest(R.string.settings_troubleshoot_test_system_settings_title) { +) : TroubleshootTest(CommonStrings.settings_troubleshoot_test_system_settings_title) { override fun perform(testParameters: TestParameters) { if (NotificationManagerCompat.from(context).areNotificationsEnabled()) { - description = stringProvider.getString(R.string.settings_troubleshoot_test_system_settings_success) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_system_settings_success) quickFix = null status = TestStatus.SUCCESS } else { if (sdkIntProvider.isAtLeast(Build.VERSION_CODES.TIRAMISU) && notificationPermissionManager.isPermissionGranted(context).not()) { // In this case, we can ask for user permission - description = stringProvider.getString(R.string.settings_troubleshoot_test_system_settings_permission_failed) - quickFix = object : TroubleshootQuickFix(R.string.grant_permission) { + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_system_settings_permission_failed) + quickFix = object : TroubleshootQuickFix(CommonStrings.grant_permission) { override fun doFix() { notificationPermissionManager.askPermission(testParameters.permissionResultLauncher) } } } else { - description = stringProvider.getString(R.string.settings_troubleshoot_test_system_settings_failed) - quickFix = object : TroubleshootQuickFix(R.string.open_settings) { + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_system_settings_failed) + quickFix = object : TroubleshootQuickFix(CommonStrings.open_settings) { override fun doFix() { startNotificationSettingsIntent(context, testParameters.activityResultLauncher) } diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestUnifiedPushEndpoint.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestUnifiedPushEndpoint.kt index 632f145c01..f4fd5623df 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestUnifiedPushEndpoint.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestUnifiedPushEndpoint.kt @@ -16,23 +16,23 @@ package im.vector.app.features.settings.troubleshoot -import im.vector.app.R import im.vector.app.core.pushers.UnifiedPushHelper import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class TestUnifiedPushEndpoint @Inject constructor( private val stringProvider: StringProvider, private val unifiedPushHelper: UnifiedPushHelper, -) : TroubleshootTest(R.string.settings_troubleshoot_test_current_endpoint_title) { +) : TroubleshootTest(CommonStrings.settings_troubleshoot_test_current_endpoint_title) { override fun perform(testParameters: TestParameters) { val endpoint = unifiedPushHelper.getPrivacyFriendlyUpEndpoint() if (endpoint != null) { - description = stringProvider.getString(R.string.settings_troubleshoot_test_current_endpoint_success, endpoint) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_current_endpoint_success, endpoint) status = TestStatus.SUCCESS } else { - description = stringProvider.getString(R.string.settings_troubleshoot_test_current_endpoint_failed) + description = stringProvider.getString(CommonStrings.settings_troubleshoot_test_current_endpoint_failed) status = TestStatus.FAILED } } diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestUnifiedPushGateway.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestUnifiedPushGateway.kt index 52d5ad35a3..8e12d68ae6 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestUnifiedPushGateway.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestUnifiedPushGateway.kt @@ -16,19 +16,19 @@ package im.vector.app.features.settings.troubleshoot -import im.vector.app.R import im.vector.app.core.pushers.UnifiedPushHelper import im.vector.app.core.resources.StringProvider +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class TestUnifiedPushGateway @Inject constructor( private val unifiedPushHelper: UnifiedPushHelper, private val stringProvider: StringProvider -) : TroubleshootTest(R.string.settings_troubleshoot_test_current_gateway_title) { +) : TroubleshootTest(CommonStrings.settings_troubleshoot_test_current_gateway_title) { override fun perform(testParameters: TestParameters) { description = stringProvider.getString( - R.string.settings_troubleshoot_test_current_gateway, + CommonStrings.settings_troubleshoot_test_current_gateway, unifiedPushHelper.getPushGateway() ) status = TestStatus.SUCCESS diff --git a/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt b/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt index 0c556192ac..459fac23f2 100644 --- a/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt +++ b/vector/src/main/java/im/vector/app/features/share/IncomingShareController.kt @@ -18,12 +18,12 @@ package im.vector.app.features.share import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.mvrx.Incomplete -import im.vector.app.R import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.RoomListDisplayMode import im.vector.app.features.home.room.list.RoomSummaryItemFactory +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject @@ -51,7 +51,7 @@ class IncomingShareController @Inject constructor( if (roomSummaries.isNullOrEmpty()) { noResultItem { id("no_result") - text(host.stringProvider.getString(R.string.no_result_placeholder)) + text(host.stringProvider.getString(CommonStrings.no_result_placeholder)) } } else { roomSummaries.forEach { roomSummary -> diff --git a/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt b/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt index a80d058197..35a5ee126f 100644 --- a/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt +++ b/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt @@ -30,7 +30,6 @@ import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.registerStartForActivityResult @@ -40,6 +39,7 @@ import im.vector.app.features.analytics.plan.ViewRoom import im.vector.app.features.attachments.ShareIntentHandler import im.vector.app.features.attachments.preview.AttachmentsPreviewActivity import im.vector.app.features.attachments.preview.AttachmentsPreviewArgs +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject @@ -90,7 +90,7 @@ class IncomingShareFragment : } if (!isShareManaged) { - cannotManageShare(R.string.error_handling_incoming_share) + cannotManageShare(CommonStrings.error_handling_incoming_share) } views.incomingShareSearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { @@ -176,12 +176,12 @@ class IncomingShareFragment : private fun showConfirmationDialog(roomSummary: RoomSummary, sharedData: SharedData) { MaterialAlertDialogBuilder(requireActivity()) - .setTitle(R.string.send_attachment) - .setMessage(getString(R.string.share_confirm_room, roomSummary.displayName)) - .setPositiveButton(R.string.action_send) { _, _ -> + .setTitle(CommonStrings.send_attachment) + .setMessage(getString(CommonStrings.share_confirm_room, roomSummary.displayName)) + .setPositiveButton(CommonStrings.action_send) { _, _ -> navigator.openRoomForSharingAndFinish(requireActivity(), roomSummary.roomId, sharedData) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } diff --git a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutActivity.kt b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutActivity.kt index a90d4205b2..d56936b070 100644 --- a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutActivity.kt +++ b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutActivity.kt @@ -24,11 +24,11 @@ import com.airbnb.mvrx.Success import com.airbnb.mvrx.viewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.replaceFragment import im.vector.app.features.MainActivity import im.vector.app.features.MainActivityArgs import im.vector.app.features.login.LoginActivity +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.failure.GlobalError import org.matrix.android.sdk.api.session.Session import timber.log.Timber @@ -66,7 +66,7 @@ class SoftLogoutActivity : LoginActivity() { // And inform the user showError( getString( - R.string.soft_logout_sso_not_same_user_error, + CommonStrings.soft_logout_sso_not_same_user_error, softLogoutViewEvents.currentUserId, softLogoutViewEvents.newUserId ) @@ -80,9 +80,9 @@ class SoftLogoutActivity : LoginActivity() { private fun showError(message: String) { MaterialAlertDialogBuilder(this) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(message) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(CommonStrings.ok, null) .show() } diff --git a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutController.kt b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutController.kt index 9281fc6c8e..83b2457551 100644 --- a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutController.kt +++ b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutController.kt @@ -22,7 +22,6 @@ import com.airbnb.mvrx.Incomplete import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized -import im.vector.app.R import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.extensions.toReducedUrl @@ -36,6 +35,7 @@ import im.vector.app.features.signout.soft.epoxy.loginRedButtonItem import im.vector.app.features.signout.soft.epoxy.loginTextItem import im.vector.app.features.signout.soft.epoxy.loginTitleItem import im.vector.app.features.signout.soft.epoxy.loginTitleSmallItem +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.auth.LoginType import org.matrix.android.sdk.api.extensions.orFalse import javax.inject.Inject @@ -70,17 +70,17 @@ class SoftLogoutController @Inject constructor( } loginTitleItem { id("title") - text(host.stringProvider.getString(R.string.soft_logout_title)) + text(host.stringProvider.getString(CommonStrings.soft_logout_title)) } loginTitleSmallItem { id("signTitle") - text(host.stringProvider.getString(R.string.soft_logout_signin_title)) + text(host.stringProvider.getString(CommonStrings.soft_logout_signin_title)) } loginTextItem { id("signText1") text( host.stringProvider.getString( - R.string.soft_logout_signin_notice, + CommonStrings.soft_logout_signin_notice, state.homeServerUrl.toReducedUrl(), state.userDisplayName, state.userId @@ -90,7 +90,7 @@ class SoftLogoutController @Inject constructor( if (state.hasUnsavedKeys().orFalse()) { loginTextItem { id("signText2") - text(host.stringProvider.getString(R.string.soft_logout_signin_e2e_warning_notice)) + text(host.stringProvider.getString(CommonStrings.soft_logout_signin_e2e_warning_notice)) } } } @@ -143,7 +143,7 @@ class SoftLogoutController @Inject constructor( val host = this loginCenterButtonItem { id("sso") - text(host.stringProvider.getString(R.string.login_signin_sso)) + text(host.stringProvider.getString(CommonStrings.login_signin_sso)) listener { host.listener?.signinFallbackSubmit() } } } @@ -164,7 +164,7 @@ class SoftLogoutController @Inject constructor( val host = this loginCenterButtonItem { id("fallback") - text(host.stringProvider.getString(R.string.login_signin)) + text(host.stringProvider.getString(CommonStrings.login_signin)) listener { host.listener?.signinFallbackSubmit() } } } @@ -173,15 +173,15 @@ class SoftLogoutController @Inject constructor( val host = this loginTitleSmallItem { id("clearDataTitle") - text(host.stringProvider.getString(R.string.soft_logout_clear_data_title)) + text(host.stringProvider.getString(CommonStrings.soft_logout_clear_data_title)) } loginTextItem { id("clearDataText") - text(host.stringProvider.getString(R.string.soft_logout_clear_data_notice)) + text(host.stringProvider.getString(CommonStrings.soft_logout_clear_data_notice)) } loginRedButtonItem { id("clearDataSubmit") - text(host.stringProvider.getString(R.string.soft_logout_clear_data_submit)) + text(host.stringProvider.getString(CommonStrings.soft_logout_clear_data_submit)) listener { host.listener?.clearData() } } } diff --git a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutFragment.kt b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutFragment.kt index 60b4a7403e..b8a99ded02 100644 --- a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutFragment.kt +++ b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutFragment.kt @@ -24,7 +24,6 @@ import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.hideKeyboard @@ -33,6 +32,7 @@ import im.vector.app.features.login.AbstractLoginFragment import im.vector.app.features.login.LoginAction import im.vector.app.features.login.LoginMode import im.vector.app.features.login.LoginViewEvents +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orFalse import javax.inject.Inject @@ -132,16 +132,16 @@ class SoftLogoutFragment : cleanupUi() val messageResId = if (state.hasUnsavedKeys().orFalse()) { - R.string.soft_logout_clear_data_dialog_e2e_warning_content + CommonStrings.soft_logout_clear_data_dialog_e2e_warning_content } else { - R.string.soft_logout_clear_data_dialog_content + CommonStrings.soft_logout_clear_data_dialog_content } - MaterialAlertDialogBuilder(requireActivity(), R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) - .setTitle(R.string.soft_logout_clear_data_dialog_title) + MaterialAlertDialogBuilder(requireActivity(), im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) + .setTitle(CommonStrings.soft_logout_clear_data_dialog_title) .setMessage(messageResId) - .setNegativeButton(R.string.action_cancel, null) - .setPositiveButton(R.string.soft_logout_clear_data_submit) { _, _ -> + .setNegativeButton(CommonStrings.action_cancel, null) + .setPositiveButton(CommonStrings.soft_logout_clear_data_submit) { _, _ -> softLogoutViewModel.handle(SoftLogoutAction.ClearData) } .show() diff --git a/vector/src/main/java/im/vector/app/features/spaces/InviteRoomSpaceChooserBottomSheet.kt b/vector/src/main/java/im/vector/app/features/spaces/InviteRoomSpaceChooserBottomSheet.kt index 702bdc2a8f..060be0fca5 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/InviteRoomSpaceChooserBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/InviteRoomSpaceChooserBottomSheet.kt @@ -25,10 +25,10 @@ import androidx.core.view.isVisible import androidx.fragment.app.FragmentManager import com.airbnb.mvrx.args import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.databinding.BottomSheetSpaceInviteChooserBinding +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import javax.inject.Inject @@ -64,16 +64,16 @@ class InviteRoomSpaceChooserBottomSheet : VectorBaseBottomSheetDialogFragment(R.layo super.bind(holder) holder.view.onClick(listener) - holder.plus.imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_primary)) + holder.plus.imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(holder.view.context, im.vector.lib.ui.styles.R.attr.vctr_content_primary)) } class Holder : VectorEpoxyHolder() { diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt index 199169484c..bc0b1bfdf1 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt @@ -17,11 +17,11 @@ package im.vector.app.features.spaces import com.airbnb.epoxy.EpoxyController -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.grouplist.newHomeSpaceSummaryItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.list.UnreadCounterBadgeView +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -69,7 +69,7 @@ class NewSpaceSummaryController @Inject constructor( val host = this newHomeSpaceSummaryItem { id("space_home") - text(host.stringProvider.getString(R.string.all_chats)) + text(host.stringProvider.getString(CommonStrings.all_chats)) selected(selected) countState(UnreadCounterBadgeView.State.Count(homeCount.totalCount, homeCount.isHighlight)) listener { host.callback?.onSpaceSelected(null, isSubSpace = false) } diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryItem.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryItem.kt index d59de6ac99..f1acf97b44 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryItem.kt @@ -29,6 +29,7 @@ import im.vector.app.core.epoxy.onClick import im.vector.app.core.platform.CheckableConstraintLayout import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.list.UnreadCounterBadgeView +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.util.MatrixItem @EpoxyModelClass @@ -59,7 +60,7 @@ abstract class NewSpaceSummaryItem : VectorEpoxyModel { @@ -120,7 +122,7 @@ class SpaceCreationActivity : SimpleFragmentActivity() { } private fun navigateToFragment(fragmentClass: Class) { - val frag = supportFragmentManager.findFragmentByTag(fragmentClass.name) ?: fragmentClass.newInstance() + val frag = supportFragmentManager.findFragmentByTag(fragmentClass.name) ?: fragmentClass.getDeclaredConstructor().newInstance() supportFragmentManager.beginTransaction() .setCustomAnimations(R.anim.fade_in, R.anim.fade_out, R.anim.fade_in, R.anim.fade_out) .replace( @@ -131,20 +133,22 @@ class SpaceCreationActivity : SimpleFragmentActivity() { .commit() } + @Suppress("OVERRIDE_DEPRECATION") + @SuppressLint("MissingSuperCall") override fun onBackPressed() { viewModel.handle(CreateSpaceAction.OnBackPressed) } private fun renderState(state: CreateSpaceState) { val titleRes = when (state.step) { - CreateSpaceState.Step.ChooseType -> R.string.activity_create_space_title + CreateSpaceState.Step.ChooseType -> CommonStrings.activity_create_space_title CreateSpaceState.Step.SetDetails, CreateSpaceState.Step.AddRooms -> { - if (state.spaceType == SpaceType.Public) R.string.your_public_space - else R.string.your_private_space + if (state.spaceType == SpaceType.Public) CommonStrings.your_public_space + else CommonStrings.your_private_space } CreateSpaceState.Step.AddEmailsOrInvites, - CreateSpaceState.Step.ChoosePrivateType -> R.string.your_private_space + CreateSpaceState.Step.ChoosePrivateType -> CommonStrings.your_private_space } supportActionBar?.let { it.title = getString(titleRes) @@ -153,7 +157,7 @@ class SpaceCreationActivity : SimpleFragmentActivity() { } if (state.creationResult is Loading) { - showWaitingView(getString(R.string.create_spaces_loading_message)) + showWaitingView(getString(CommonStrings.create_spaces_loading_message)) } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceExploreActivity.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceExploreActivity.kt index b36dd2df4d..e8f60948c6 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceExploreActivity.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceExploreActivity.kt @@ -25,7 +25,6 @@ import androidx.fragment.app.FragmentManager import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.viewModel import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.platform.VectorBaseActivity @@ -41,13 +40,14 @@ import im.vector.app.features.spaces.explore.SpaceDirectoryViewAction import im.vector.app.features.spaces.explore.SpaceDirectoryViewEvents import im.vector.app.features.spaces.explore.SpaceDirectoryViewModel import im.vector.lib.core.utils.compat.getParcelableExtraCompat +import im.vector.lib.strings.CommonStrings @AndroidEntryPoint class SpaceExploreActivity : VectorBaseActivity(), MatrixToBottomSheet.InteractionListener { override fun getBinding(): ActivitySimpleBinding = ActivitySimpleBinding.inflate(layoutInflater) - override fun getTitleRes(): Int = R.string.space_explore_activity_title + override fun getTitleRes(): Int = CommonStrings.space_explore_activity_title val sharedViewModel: SpaceDirectoryViewModel by viewModel() diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceInviteItem.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceInviteItem.kt index 59095a8dd1..00cf0974c4 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceInviteItem.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceInviteItem.kt @@ -28,6 +28,7 @@ import im.vector.app.core.epoxy.onClick import im.vector.app.core.platform.CheckableConstraintLayout import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.list.UnreadCounterBadgeView +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.util.MatrixItem @EpoxyModelClass @@ -47,7 +48,7 @@ abstract class SpaceInviteItem : VectorEpoxyModel(R.layo holder.root.onClick(onInviteSelectedListener) holder.root.setOnLongClickListener { onLongClickListener?.invoke(holder.root).let { true } } holder.name.text = matrixItem.displayName - holder.invitedBy.text = context.getString(R.string.invited_by, inviter) + holder.invitedBy.text = context.getString(CommonStrings.invited_by, inviter) avatarRenderer.render(matrixItem, holder.avatar) holder.notificationBadge.render(UnreadCounterBadgeView.State.Text("!", true)) diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt index acc1df5405..751af40e67 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt @@ -17,11 +17,11 @@ package im.vector.app.features.spaces import com.airbnb.epoxy.EpoxyController -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.grouplist.homeSpaceSummaryItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.list.UnreadCounterBadgeView +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -78,7 +78,7 @@ class SpaceSummaryController @Inject constructor( matrixItem(roomSummary.toMatrixItem()) countState(UnreadCounterBadgeView.State.Count(1, true)) selected(false) - description(host.stringProvider.getString(R.string.you_are_invited)) + description(host.stringProvider.getString(CommonStrings.you_are_invited)) canDrag(false) listener { host.callback?.onSpaceInviteSelected(roomSummary) } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/ChoosePrivateSpaceTypeFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/create/ChoosePrivateSpaceTypeFragment.kt index 02ffb7ff6a..53d7ff76ba 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/ChoosePrivateSpaceTypeFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/ChoosePrivateSpaceTypeFragment.kt @@ -22,12 +22,12 @@ import android.view.View import android.view.ViewGroup import com.airbnb.mvrx.activityViewModel import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.epoxy.onClick import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.resources.StringProvider import im.vector.app.databinding.FragmentSpaceCreateChoosePrivateModelBinding +import im.vector.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint @@ -54,7 +54,7 @@ class ChoosePrivateSpaceTypeFragment : } sharedViewModel.onEach { state -> - views.accessInfoHelpText.text = stringProvider.getString(R.string.create_spaces_make_sure_access, state.name ?: "") + views.accessInfoHelpText.text = stringProvider.getString(CommonStrings.create_spaces_make_sure_access, state.name ?: "") } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceAdd3pidInvitesFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceAdd3pidInvitesFragment.kt index a46991caa3..3d0082014b 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceAdd3pidInvitesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceAdd3pidInvitesFragment.kt @@ -22,7 +22,6 @@ import android.view.View import android.view.ViewGroup import com.airbnb.mvrx.activityViewModel import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.hideKeyboard @@ -30,6 +29,7 @@ import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentSpaceCreateGenericEpoxyFormBinding import im.vector.app.features.settings.VectorSettingsActivity +import im.vector.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint @@ -57,7 +57,7 @@ class CreateSpaceAdd3pidInvitesFragment : invalidateState(it) } - views.nextButton.setText(R.string.action_next) + views.nextButton.setText(CommonStrings.action_next) views.nextButton.debouncedClicks { view.hideKeyboard() sharedViewModel.handle(CreateSpaceAction.NextFromAdd3pid) @@ -68,9 +68,9 @@ class CreateSpaceAdd3pidInvitesFragment : epoxyController.setData(it) val noEmails = it.default3pidInvite?.all { it.value.isNullOrBlank() } ?: true views.nextButton.text = if (noEmails) { - getString(R.string.skip_for_now) + getString(CommonStrings.skip_for_now) } else { - getString(R.string.action_next) + getString(CommonStrings.action_next) } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceDefaultRoomsFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceDefaultRoomsFragment.kt index 68e9522282..95e15b9778 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceDefaultRoomsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceDefaultRoomsFragment.kt @@ -22,12 +22,12 @@ import android.view.View import android.view.ViewGroup import com.airbnb.mvrx.activityViewModel import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentSpaceCreateGenericEpoxyFormBinding +import im.vector.lib.strings.CommonStrings import javax.inject.Inject @AndroidEntryPoint @@ -53,7 +53,7 @@ class CreateSpaceDefaultRoomsFragment : epoxyController.setData(it) } - views.nextButton.setText(R.string.create_space) + views.nextButton.setText(CommonStrings.create_space) views.nextButton.debouncedClicks { view.hideKeyboard() sharedViewModel.handle(CreateSpaceAction.NextFromDefaultRooms) diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt index 2d72999a03..d4a9fc510e 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt @@ -25,7 +25,6 @@ import com.airbnb.mvrx.ViewModelContext import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.error.ErrorFormatter @@ -33,6 +32,7 @@ import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.features.analytics.AnalyticsTracker import im.vector.app.features.analytics.plan.Interaction +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.matrix.android.sdk.api.MatrixPatterns @@ -99,8 +99,8 @@ class CreateSpaceViewModel @AssistedInject constructor( override fun initialState(viewModelContext: ViewModelContext): CreateSpaceState { return CreateSpaceState( defaultRooms = mapOf( - 0 to viewModelContext.activity.getString(R.string.create_spaces_default_public_room_name), - 1 to viewModelContext.activity.getString(R.string.create_spaces_default_public_random_room_name) + 0 to viewModelContext.activity.getString(CommonStrings.create_spaces_default_public_room_name), + 1 to viewModelContext.activity.getString(CommonStrings.create_spaces_default_public_random_room_name) ) ) } @@ -298,7 +298,7 @@ class CreateSpaceViewModel @AssistedInject constructor( if (state.name.isNullOrBlank()) { setState { copy( - nameInlineError = stringProvider.getString(R.string.create_space_error_empty_field_space_name) + nameInlineError = stringProvider.getString(CommonStrings.create_space_error_empty_field_space_name) ) } } else { diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/SpaceAdd3pidEpoxyController.kt b/vector/src/main/java/im/vector/app/features/spaces/create/SpaceAdd3pidEpoxyController.kt index 1193ecb496..e92e615739 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/SpaceAdd3pidEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/SpaceAdd3pidEpoxyController.kt @@ -19,7 +19,6 @@ package im.vector.app.features.spaces.create import android.text.InputType import com.airbnb.epoxy.TypedEpoxyController import com.google.android.material.textfield.TextInputLayout -import im.vector.app.R import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.ItemStyle @@ -28,6 +27,7 @@ import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.core.ui.list.genericPillItem import im.vector.app.features.form.formEditTextItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class SpaceAdd3pidEpoxyController @Inject constructor( @@ -43,13 +43,13 @@ class SpaceAdd3pidEpoxyController @Inject constructor( genericFooterItem { id("info_help_header") style(ItemStyle.TITLE) - text(host.stringProvider.getString(R.string.create_spaces_invite_public_header).toEpoxyCharSequence()) - textColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + text(host.stringProvider.getString(CommonStrings.create_spaces_invite_public_header).toEpoxyCharSequence()) + textColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) } genericFooterItem { id("info_help_desc") - text(host.stringProvider.getString(R.string.create_spaces_invite_public_header_desc, data.name ?: "").toEpoxyCharSequence()) - textColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary)) + text(host.stringProvider.getString(CommonStrings.create_spaces_invite_public_header_desc, data.name ?: "").toEpoxyCharSequence()) + textColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary)) } if (data.canInviteByMail) { @@ -57,13 +57,13 @@ class SpaceAdd3pidEpoxyController @Inject constructor( } else { genericPillItem { id("no_IDS") - imageRes(R.drawable.ic_baseline_perm_contact_calendar_24) - text(host.stringProvider.getString(R.string.create_space_identity_server_info_none).toEpoxyCharSequence()) + imageRes(im.vector.app.R.drawable.ic_baseline_perm_contact_calendar_24) + text(host.stringProvider.getString(CommonStrings.create_space_identity_server_info_none).toEpoxyCharSequence()) } genericButtonItem { id("Discover_Settings") - text(host.stringProvider.getString(R.string.open_discovery_settings)) - textColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + text(host.stringProvider.getString(CommonStrings.open_discovery_settings)) + textColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary)) buttonClickAction { host.listener?.onNoIdentityServer() } @@ -78,12 +78,12 @@ class SpaceAdd3pidEpoxyController @Inject constructor( id("3pid$index") enabled(true) value(mail) - hint(host.stringProvider.getString(R.string.medium_email)) + hint(host.stringProvider.getString(CommonStrings.medium_email)) inputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS) endIconMode(TextInputLayout.END_ICON_CLEAR_TEXT) errorMessage( if (data.emailValidationResult?.get(index) == false) { - host.stringProvider.getString(R.string.does_not_look_like_valid_email) + host.stringProvider.getString(CommonStrings.does_not_look_like_valid_email) } else null ) onTextChange { text -> diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDefaultRoomEpoxyController.kt b/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDefaultRoomEpoxyController.kt index 4ef469500b..731868ccea 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDefaultRoomEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDefaultRoomEpoxyController.kt @@ -18,13 +18,13 @@ package im.vector.app.features.spaces.create import com.airbnb.epoxy.TypedEpoxyController import com.google.android.material.textfield.TextInputLayout -import im.vector.app.R import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.ItemStyle import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.form.formEditTextItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class SpaceDefaultRoomEpoxyController @Inject constructor( @@ -43,12 +43,12 @@ class SpaceDefaultRoomEpoxyController @Inject constructor( style(ItemStyle.TITLE) text( if (data?.spaceType == SpaceType.Public) { - host.stringProvider.getString(R.string.create_spaces_room_public_header, data.name) + host.stringProvider.getString(CommonStrings.create_spaces_room_public_header, data.name) } else { - host.stringProvider.getString(R.string.create_spaces_room_private_header) + host.stringProvider.getString(CommonStrings.create_spaces_room_private_header) }.toEpoxyCharSequence() ) - textColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + textColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary)) } genericFooterItem { @@ -56,13 +56,13 @@ class SpaceDefaultRoomEpoxyController @Inject constructor( text( host.stringProvider.getString( if (data?.spaceType == SpaceType.Public) { - R.string.create_spaces_room_public_header_desc + CommonStrings.create_spaces_room_public_header_desc } else { - R.string.create_spaces_room_private_header_desc + CommonStrings.create_spaces_room_private_header_desc } ).toEpoxyCharSequence() ) - textColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary)) + textColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary)) } val firstRoomName = data?.defaultRooms?.get(0) @@ -70,7 +70,7 @@ class SpaceDefaultRoomEpoxyController @Inject constructor( id("roomName1") enabled(true) value(firstRoomName) - hint(host.stringProvider.getString(R.string.create_room_name_section)) + hint(host.stringProvider.getString(CommonStrings.create_room_name_section)) endIconMode(TextInputLayout.END_ICON_CLEAR_TEXT) onTextChange { text -> host.listener?.onNameChange(0, text) @@ -82,7 +82,7 @@ class SpaceDefaultRoomEpoxyController @Inject constructor( id("roomName2") enabled(true) value(secondRoomName) - hint(host.stringProvider.getString(R.string.create_room_name_section)) + hint(host.stringProvider.getString(CommonStrings.create_room_name_section)) endIconMode(TextInputLayout.END_ICON_CLEAR_TEXT) onTextChange { text -> host.listener?.onNameChange(1, text) @@ -94,7 +94,7 @@ class SpaceDefaultRoomEpoxyController @Inject constructor( id("roomName3") enabled(true) value(thirdRoomName) - hint(host.stringProvider.getString(R.string.create_room_name_section)) + hint(host.stringProvider.getString(CommonStrings.create_room_name_section)) endIconMode(TextInputLayout.END_ICON_CLEAR_TEXT) onTextChange { text -> host.listener?.onNameChange(2, text) diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDetailEpoxyController.kt b/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDetailEpoxyController.kt index aee405388b..bf095ff751 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDetailEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDetailEpoxyController.kt @@ -18,7 +18,6 @@ package im.vector.app.features.spaces.create import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.mvrx.Fail -import im.vector.app.R import im.vector.app.core.epoxy.TextListener import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem @@ -28,6 +27,7 @@ import im.vector.app.features.form.formMultiLineEditTextItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roomdirectory.createroom.RoomAliasErrorFormatter import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.MatrixConstants import org.matrix.android.sdk.api.session.room.alias.RoomAliasError import org.matrix.android.sdk.api.util.MatrixItem @@ -59,9 +59,9 @@ class SpaceDetailEpoxyController @Inject constructor( id("info_help") text( if (data?.spaceType == SpaceType.Public) { - host.stringProvider.getString(R.string.create_spaces_details_public_header) + host.stringProvider.getString(CommonStrings.create_spaces_details_public_header) } else { - host.stringProvider.getString(R.string.create_spaces_details_private_header) + host.stringProvider.getString(CommonStrings.create_spaces_details_private_header) }.toEpoxyCharSequence() ) } @@ -80,7 +80,7 @@ class SpaceDetailEpoxyController @Inject constructor( id("name") enabled(true) value(data?.name) - hint(host.stringProvider.getString(R.string.create_room_name_hint)) + hint(host.stringProvider.getString(CommonStrings.create_room_name_hint)) errorMessage(data?.nameInlineError) onTextChange { text -> host.listener?.onNameChange(text) @@ -93,7 +93,7 @@ class SpaceDetailEpoxyController @Inject constructor( enabled(true) forceUpdateValue(!data.aliasManuallyModified) value(data.aliasLocalPart) - hint(host.stringProvider.getString(R.string.create_space_alias_hint)) + hint(host.stringProvider.getString(CommonStrings.create_space_alias_hint)) suffixText(":" + data.homeServerName) prefixText("#") maxLength(MatrixConstants.maxAliasLocalPartLength(data.homeServerName)) @@ -113,7 +113,7 @@ class SpaceDetailEpoxyController @Inject constructor( id("topic") enabled(true) value(data?.topic) - hint(host.stringProvider.getString(R.string.create_space_topic_hint)) + hint(host.stringProvider.getString(CommonStrings.create_space_topic_hint)) textSizeSp(16) onTextChange { text -> host.listener?.onTopicChange(text) diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/WizardButtonView.kt b/vector/src/main/java/im/vector/app/features/spaces/create/WizardButtonView.kt index c1bfba7205..c051402039 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/WizardButtonView.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/WizardButtonView.kt @@ -79,11 +79,11 @@ class WizardButtonView @JvmOverloads constructor(context: Context, attrs: Attrib subTitle = "This is doing something" } - context.withStyledAttributes(attrs, R.styleable.WizardButtonView) { - title = getString(R.styleable.WizardButtonView_title) - subTitle = getString(R.styleable.WizardButtonView_subTitle) - icon = getDrawable(R.styleable.WizardButtonView_icon) - tint = getColor(R.styleable.WizardButtonView_iconTint, -1) + context.withStyledAttributes(attrs, im.vector.lib.ui.styles.R.styleable.WizardButtonView) { + title = getString(im.vector.lib.ui.styles.R.styleable.WizardButtonView_title) + subTitle = getString(im.vector.lib.ui.styles.R.styleable.WizardButtonView_subTitle) + icon = getDrawable(im.vector.lib.ui.styles.R.styleable.WizardButtonView_icon) + tint = getColor(im.vector.lib.ui.styles.R.styleable.WizardButtonView_iconTint, -1) .takeIf { it != -1 } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt index e2fde4d45b..e1cc0911ff 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt @@ -37,6 +37,7 @@ import im.vector.app.features.home.room.list.spaceChildInfoItem import im.vector.app.features.home.room.list.spaceDirectoryFilterNoResultsItem import im.vector.app.features.spaces.manage.SpaceChildInfoMatchFilter import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.failure.Failure @@ -85,13 +86,13 @@ class SpaceDirectoryController @Inject constructor( tintIcon(false) text( span { - span(host.stringProvider.getString(R.string.spaces_no_server_support_title)) { + span(host.stringProvider.getString(CommonStrings.spaces_no_server_support_title)) { textStyle = "bold" - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary) + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary) } +"\n\n" - span(host.stringProvider.getString(R.string.spaces_no_server_support_description)) { - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + span(host.stringProvider.getString(CommonStrings.spaces_no_server_support_description)) { + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) } }.toEpoxyCharSequence() ) @@ -116,15 +117,15 @@ class SpaceDirectoryController @Inject constructor( if (flattenChildInfo.isEmpty()) { genericEmptyWithActionItem { id("empty_res") - title(host.stringProvider.getString(R.string.this_space_has_no_rooms)) + title(host.stringProvider.getString(CommonStrings.this_space_has_no_rooms)) iconRes(R.drawable.ic_empty_icon_room) - iconTint(host.colorProvider.getColorFromAttribute(R.attr.vctr_reaction_background_on)) + iconTint(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_reaction_background_on)) apply { if (data?.canAddRooms == true) { - description(host.stringProvider.getString(R.string.this_space_has_no_rooms_admin)) + description(host.stringProvider.getString(CommonStrings.this_space_has_no_rooms_admin)) buttonAction( Action( - title = host.stringProvider.getString(R.string.space_add_existing_rooms), + title = host.stringProvider.getString(CommonStrings.space_add_existing_rooms), listener = object : ClickListener { override fun invoke(p1: View) { host.listener?.addExistingRooms(data.spaceId) @@ -132,7 +133,7 @@ class SpaceDirectoryController @Inject constructor( } )) } else { - description(host.stringProvider.getString(R.string.this_space_has_no_rooms_not_admin)) + description(host.stringProvider.getString(CommonStrings.this_space_has_no_rooms_not_admin)) } } } @@ -162,16 +163,16 @@ class SpaceDirectoryController @Inject constructor( suggested(info.suggested.orFalse()) errorLabel( error?.let { - host.stringProvider.getString(R.string.error_failed_to_join_room, host.errorFormatter.toHumanReadable(it)) + host.stringProvider.getString(CommonStrings.error_failed_to_join_room, host.errorFormatter.toHumanReadable(it)) } ) memberCount(info.activeMemberCount ?: 0) loading(isLoading) buttonLabel( when { - error != null -> host.stringProvider.getString(R.string.global_retry) - isJoined -> host.stringProvider.getString(R.string.action_open) - else -> host.stringProvider.getString(R.string.action_join) + error != null -> host.stringProvider.getString(CommonStrings.global_retry) + isJoined -> host.stringProvider.getString(CommonStrings.action_open) + else -> host.stringProvider.getString(CommonStrings.action_join) } ) apply { diff --git a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryFragment.kt index b6c49e5d41..b5447bca97 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryFragment.kt @@ -51,6 +51,7 @@ import im.vector.app.features.permalink.PermalinkHandler import im.vector.app.features.spaces.manage.ManageType import im.vector.app.features.spaces.manage.SpaceAddRoomSpaceChooserBottomSheet import im.vector.app.features.spaces.manage.SpaceManageActivity +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo @@ -166,16 +167,16 @@ class SpaceDirectoryFragment : if (currentParentId == null) { // it's the root - toolbar?.setTitle(R.string.space_explore_activity_title) + toolbar?.setTitle(CommonStrings.space_explore_activity_title) } else { val spaceName = state.currentRootSummary?.name ?: state.currentRootSummary?.canonicalAlias if (spaceName != null) { toolbar?.title = spaceName - toolbar?.subtitle = getString(R.string.space_explore_activity_title) + toolbar?.subtitle = getString(CommonStrings.space_explore_activity_title) } else { - toolbar?.title = getString(R.string.space_explore_activity_title) + toolbar?.title = getString(CommonStrings.space_explore_activity_title) } } @@ -261,18 +262,24 @@ class SpaceDirectoryFragment : val isHandled = permalinkHandler.launch(requireActivity(), url, null) if (!isHandled) { if (title.isValidUrl() && url.isValidUrl() && URL(title).host != URL(url).host) { - MaterialAlertDialogBuilder(requireActivity(), R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) - .setTitle(R.string.external_link_confirmation_title) + MaterialAlertDialogBuilder(requireActivity(), im.vector.lib.ui.styles.R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive) + .setTitle(CommonStrings.external_link_confirmation_title) .setMessage( - getString(R.string.external_link_confirmation_message, title, url) + getString(CommonStrings.external_link_confirmation_message, title, url) .toSpannable() - .colorizeMatchingText(url, colorProvider.getColorFromAttribute(R.attr.vctr_content_tertiary)) - .colorizeMatchingText(title, colorProvider.getColorFromAttribute(R.attr.vctr_content_tertiary)) + .colorizeMatchingText( + url, + colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_tertiary) + ) + .colorizeMatchingText( + title, + colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_tertiary) + ) ) - .setPositiveButton(R.string._continue) { _, _ -> + .setPositiveButton(CommonStrings._continue) { _, _ -> openUrlInExternalBrowser(requireContext(), url) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } else { // Open in external browser, in a new Tab diff --git a/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheet.kt b/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheet.kt index cff59c175d..fe6e8c6cc0 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheet.kt @@ -31,7 +31,6 @@ import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.ButtonStateView import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.core.utils.toast @@ -39,6 +38,7 @@ import im.vector.app.databinding.BottomSheetInvitedToSpaceBinding import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.matrixto.SpaceCardRenderer +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject @@ -110,7 +110,7 @@ class SpaceInviteBottomSheet : VectorBaseBottomSheetDialogFragment { diff --git a/vector/src/main/java/im/vector/app/features/spaces/leave/SelectChildrenController.kt b/vector/src/main/java/im/vector/app/features/spaces/leave/SelectChildrenController.kt index 079bdf838c..b5a18c5813 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/leave/SelectChildrenController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/leave/SelectChildrenController.kt @@ -22,12 +22,12 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized -import im.vector.app.R import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.spaces.manage.roomSelectionItem +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.util.toMatrixItem @@ -61,7 +61,7 @@ class SelectChildrenController @Inject constructor( if (roomList.isEmpty()) { noResultItem { id("empty") - text(host.stringProvider.getString(R.string.no_result_placeholder)) + text(host.stringProvider.getString(CommonStrings.no_result_placeholder)) } } else { roomList.forEach { item -> diff --git a/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedActivity.kt b/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedActivity.kt index 6f9aef401d..3df4a67b88 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedActivity.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedActivity.kt @@ -28,7 +28,6 @@ import com.airbnb.mvrx.Success import com.airbnb.mvrx.viewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.extensions.setTextOrHide @@ -36,6 +35,7 @@ import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.databinding.ActivitySimpleLoadingBinding import im.vector.app.features.spaces.SpaceBottomSheetSettingsArgs import im.vector.lib.core.utils.compat.getParcelableExtraCompat +import im.vector.lib.strings.CommonStrings @AndroidEntryPoint class SpaceLeaveAdvancedActivity : VectorBaseActivity() { @@ -86,9 +86,9 @@ class SpaceLeaveAdvancedActivity : VectorBaseActivity { hideWaitingView() MaterialAlertDialogBuilder(this) - .setTitle(R.string.dialog_title_error) + .setTitle(CommonStrings.dialog_title_error) .setMessage(errorFormatter.toHumanReadable(state.leaveState.error)) - .setPositiveButton(R.string.ok) { _, _ -> + .setPositiveButton(CommonStrings.ok) { _, _ -> leaveViewModel.handle(SpaceLeaveAdvanceViewAction.ClearError) } .show() diff --git a/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedFragment.kt index da6b43aede..d173ad178e 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedFragment.kt @@ -36,6 +36,7 @@ import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.utils.ToggleableAppBarLayoutBehavior import im.vector.app.databinding.FragmentSpaceLeaveAdvancedBinding +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject @@ -68,9 +69,9 @@ class SpaceLeaveAdvancedFragment : state.spaceSummary?.let { summary -> val warningMessage: CharSequence? = when { - summary.otherMemberIds.isEmpty() -> getString(R.string.space_leave_prompt_msg_only_you) - state.isLastAdmin -> getString(R.string.space_leave_prompt_msg_as_admin) - !summary.isPublic -> getString(R.string.space_leave_prompt_msg_private) + summary.otherMemberIds.isEmpty() -> getString(CommonStrings.space_leave_prompt_msg_only_you) + state.isLastAdmin -> getString(CommonStrings.space_leave_prompt_msg_as_admin) + !summary.isPublic -> getString(CommonStrings.space_leave_prompt_msg_private) else -> null } @@ -78,7 +79,7 @@ class SpaceLeaveAdvancedFragment : views.spaceLeavePromptDescription.text = warningMessage } - views.spaceLeavePromptTitle.text = getString(R.string.space_leave_prompt_msg_with_name, state.spaceSummary?.name ?: "") + views.spaceLeavePromptTitle.text = getString(CommonStrings.space_leave_prompt_msg_with_name, state.spaceSummary?.name ?: "") } views.roomList.configureWith(controller) diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/RoomManageSelectionItem.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/RoomManageSelectionItem.kt index b1ccc1aa59..430acf344c 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/RoomManageSelectionItem.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/RoomManageSelectionItem.kt @@ -29,6 +29,7 @@ import im.vector.app.core.epoxy.VectorEpoxyModel import im.vector.app.core.epoxy.onClick import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.util.MatrixItem @EpoxyModelClass @@ -48,10 +49,10 @@ abstract class RoomManageSelectionItem : VectorEpoxyModel(R. if (selected) { holder.checkboxImage.setImageDrawable(ContextCompat.getDrawable(holder.view.context, R.drawable.ic_checkbox_on)) - holder.checkboxImage.contentDescription = holder.view.context.getString(R.string.a11y_checked) + holder.checkboxImage.contentDescription = holder.view.context.getString(CommonStrings.a11y_checked) } else { holder.checkboxImage.setImageDrawable(ContextCompat.getDrawable(holder.view.context, R.drawable.ic_checkbox_off)) - holder.checkboxImage.contentDescription = holder.view.context.getString(R.string.a11y_unchecked) + holder.checkboxImage.contentDescription = holder.view.context.getString(CommonStrings.a11y_unchecked) } holder.view.onClick(itemClickListener) diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt index edc18a8816..2a4057ba45 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt @@ -39,6 +39,7 @@ import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.databinding.FragmentSpaceAddRoomsBinding +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.launchIn @@ -86,7 +87,7 @@ class SpaceAddRoomFragment : } .launchIn(viewLifecycleOwner.lifecycleScope) - spaceEpoxyController.subHeaderText = getString(R.string.spaces_feeling_experimental_subspace) + spaceEpoxyController.subHeaderText = getString(CommonStrings.spaces_feeling_experimental_subspace) viewModel.selectionListLiveData.observe(viewLifecycleOwner) { spaceEpoxyController.selectedItems = it roomEpoxyController.selectedItems = it @@ -120,8 +121,8 @@ class SpaceAddRoomFragment : viewModel.onEach(SpaceAddRoomsState::onlyShowSpaces) { spaceEpoxyController.disabled = !it roomEpoxyController.disabled = it - views.createNewRoom.text = if (it) getString(R.string.create_space) else getString(R.string.create_new_room) - toolbar?.setTitle(if (it) R.string.space_add_existing_spaces else R.string.space_add_existing_rooms_only) + views.createNewRoom.text = if (it) getString(CommonStrings.create_space) else getString(CommonStrings.create_new_room) + toolbar?.setTitle(if (it) CommonStrings.space_add_existing_spaces else CommonStrings.space_add_existing_rooms_only) } views.createNewRoom.debouncedClicks { @@ -138,12 +139,12 @@ class SpaceAddRoomFragment : when (it) { SpaceAddRoomsViewEvents.WarnUnsavedChanged -> { MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.dialog_title_warning) - .setMessage(R.string.warning_unsaved_change) - .setPositiveButton(R.string.warning_unsaved_change_discard) { _, _ -> + .setTitle(CommonStrings.dialog_title_warning) + .setMessage(CommonStrings.warning_unsaved_change) + .setPositiveButton(CommonStrings.warning_unsaved_change_discard) { _, _ -> sharedViewModel.handle(SpaceManagedSharedAction.HandleBack) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } is SpaceAddRoomsViewEvents.SaveFailed -> { @@ -192,7 +193,7 @@ class SpaceAddRoomFragment : } private fun setupSpaceSection() { - spaceEpoxyController.sectionName = getString(R.string.spaces_header) + spaceEpoxyController.sectionName = getString(CommonStrings.spaces_header) spaceEpoxyController.listener = this viewModel.spaceUpdatableLivePageResult.liveBoundaries.observe(viewLifecycleOwner) { spaceEpoxyController.boundaryChange(it) @@ -204,7 +205,7 @@ class SpaceAddRoomFragment : } private fun setupRoomSection() { - roomEpoxyController.sectionName = getString(R.string.rooms_header) + roomEpoxyController.sectionName = getString(CommonStrings.rooms_header) roomEpoxyController.listener = this viewModel.roomUpdatableLivePageResult.liveBoundaries.observe(viewLifecycleOwner) { @@ -220,7 +221,7 @@ class SpaceAddRoomFragment : private fun setupDmSection() { // This controller can be disabled depending on the space type (public or not) - dmEpoxyController.sectionName = getString(R.string.direct_chats_header) + dmEpoxyController.sectionName = getString(CommonStrings.direct_chats_header) dmEpoxyController.listener = this viewModel.dmUpdatableLivePageResult.liveBoundaries.observe(viewLifecycleOwner) { dmEpoxyController.boundaryChange(it) diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageActivity.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageActivity.kt index a246bd29aa..94fb91d751 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageActivity.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageActivity.kt @@ -27,7 +27,6 @@ import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.addFragmentToBackstack import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.replaceFragment @@ -41,6 +40,7 @@ import im.vector.app.features.roomprofile.RoomProfileArgs import im.vector.app.features.roomprofile.alias.RoomAliasFragment import im.vector.app.features.roomprofile.permissions.RoomPermissionsFragment import im.vector.lib.core.utils.compat.getParcelableExtraCompat +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.parcelize.Parcelize @@ -58,7 +58,7 @@ class SpaceManageActivity : VectorBaseActivity() { override fun getBinding(): ActivitySimpleLoadingBinding = ActivitySimpleLoadingBinding.inflate(layoutInflater) - override fun getTitleRes(): Int = R.string.space_add_existing_rooms + override fun getTitleRes(): Int = CommonStrings.space_add_existing_rooms val sharedViewModel: SpaceManageSharedViewModel by viewModel() diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageRoomsController.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageRoomsController.kt index 54f19ce297..d25cb42a1e 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageRoomsController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageRoomsController.kt @@ -20,7 +20,6 @@ import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.epoxy.VisibilityState import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Incomplete -import im.vector.app.R import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.error.ErrorFormatter @@ -28,6 +27,7 @@ import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.home.AvatarRenderer import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject @@ -75,7 +75,7 @@ class SpaceManageRoomsController @Inject constructor( if (filteredResult.isEmpty()) { genericFooterItem { id("empty_result") - text(host.stringProvider.getString(R.string.no_result_placeholder).toEpoxyCharSequence()) + text(host.stringProvider.getString(CommonStrings.no_result_placeholder).toEpoxyCharSequence()) } } else { filteredResult.forEach { childInfo -> diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageRoomsFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageRoomsFragment.kt index 4580119070..920a0c55fd 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageRoomsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageRoomsFragment.kt @@ -40,6 +40,8 @@ import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.toast import im.vector.app.databinding.FragmentSpaceAddRoomsBinding +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -71,7 +73,7 @@ class SpaceManageRoomsFragment : super.onViewCreated(view, savedInstanceState) setupToolbar(views.addRoomToSpaceToolbar) - .setTitle(R.string.space_manage_rooms_and_spaces) + .setTitle(CommonStrings.space_manage_rooms_and_spaces) .allowBack() views.createNewRoom.isVisible = false @@ -125,7 +127,7 @@ class SpaceManageRoomsFragment : views.addRoomToSpaceToolbar.isVisible = true vectorBaseActivity.startSupportActionMode(this) } else { - toolbar?.title = resources.getQuantityString(R.plurals.room_details_selected, state.selectedRooms.size, state.selectedRooms.size) + toolbar?.title = resources.getQuantityString(CommonPlurals.room_details_selected, state.selectedRooms.size, state.selectedRooms.size) } // views.addRoomToSpaceToolbar.isVisible = false // views.addRoomToSpaceToolbar.startActionMode(this) @@ -153,7 +155,7 @@ class SpaceManageRoomsFragment : val inflater = mode?.menuInflater inflater?.inflate(R.menu.menu_manage_space, menu) withState(viewModel) { - mode?.title = resources.getQuantityString(R.plurals.room_details_selected, it.selectedRooms.size, it.selectedRooms.size) + mode?.title = resources.getQuantityString(CommonPlurals.room_details_selected, it.selectedRooms.size, it.selectedRooms.size) } currentActionMode = mode views.addRoomToSpaceToolbar.isVisible = false diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsController.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsController.kt index 7cd5a70279..f24348a058 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsController.kt @@ -17,7 +17,6 @@ package im.vector.app.features.spaces.manage import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.epoxy.dividerItem import im.vector.app.core.epoxy.profiles.buildProfileAction import im.vector.app.core.epoxy.profiles.buildProfileSection @@ -28,6 +27,7 @@ import im.vector.app.features.form.formMultiLineEditTextItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roomprofile.settings.RoomSettingsViewState import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.room.model.RoomJoinRules import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject @@ -81,14 +81,14 @@ class SpaceSettingsController @Inject constructor( } buildProfileSection( - stringProvider.getString(R.string.settings) + stringProvider.getString(CommonStrings.settings) ) formEditTextItem { id("name") enabled(data.actionPermissions.canChangeName) value(data.newName ?: roomSummary.displayName) - hint(host.stringProvider.getString(R.string.create_room_name_hint)) + hint(host.stringProvider.getString(CommonStrings.create_room_name_hint)) onTextChange { text -> host.callback?.onNameChanged(text) } @@ -98,7 +98,7 @@ class SpaceSettingsController @Inject constructor( id("topic") enabled(data.actionPermissions.canChangeTopic) value(data.newTopic ?: roomSummary.topic) - hint(host.stringProvider.getString(R.string.create_space_topic_hint)) + hint(host.stringProvider.getString(CommonStrings.create_space_topic_hint)) onTextChange { text -> host.callback?.onTopicChanged(text) } @@ -107,7 +107,7 @@ class SpaceSettingsController @Inject constructor( val isPublic = (data.newRoomJoinRules.newJoinRules ?: data.currentRoomJoinRules) == RoomJoinRules.PUBLIC buildProfileAction( id = "joinRule", - title = stringProvider.getString(R.string.room_settings_space_access_title), + title = stringProvider.getString(CommonStrings.room_settings_space_access_title), subtitle = data.getJoinRuleWording(stringProvider), divider = true, editable = data.actionPermissions.canChangeJoinRule, @@ -116,7 +116,7 @@ class SpaceSettingsController @Inject constructor( // if (vectorPreferences.labsUseExperimentalRestricted()) { // buildProfileAction( // id = "joinRule", -// title = stringProvider.getString(R.string.room_settings_room_access_title), +// title = stringProvider.getString(CommonStrings.room_settings_room_access_title), // subtitle = data.getJoinRuleWording(stringProvider), // divider = false, // editable = data.actionPermissions.canChangeJoinRule, @@ -126,7 +126,7 @@ class SpaceSettingsController @Inject constructor( // formSwitchItem { // id("isPublic") // enabled(data.actionPermissions.canChangeJoinRule) -// title(host.stringProvider.getString(R.string.make_this_space_public)) +// title(host.stringProvider.getString(CommonStrings.make_this_space_public)) // switchChecked(isPublic) // // listener { value -> @@ -140,7 +140,7 @@ class SpaceSettingsController @Inject constructor( buildProfileAction( id = "manage_rooms", - title = stringProvider.getString(R.string.space_settings_manage_rooms), + title = stringProvider.getString(CommonStrings.space_settings_manage_rooms), // subtitle = data.getJoinRuleWording(stringProvider), divider = true, editable = data.actionPermissions.canAddChildren, @@ -152,8 +152,8 @@ class SpaceSettingsController @Inject constructor( if (isPublic) { buildProfileAction( id = "alias", - title = stringProvider.getString(R.string.space_settings_alias_title), - subtitle = stringProvider.getString(R.string.space_settings_alias_subtitle), + title = stringProvider.getString(CommonStrings.space_settings_alias_title), + subtitle = stringProvider.getString(CommonStrings.space_settings_alias_subtitle), divider = true, editable = true, action = { callback?.onRoomAliasesClicked() } @@ -162,8 +162,8 @@ class SpaceSettingsController @Inject constructor( buildProfileAction( id = "permissions", - title = stringProvider.getString(R.string.space_settings_permissions_title), - subtitle = stringProvider.getString(R.string.space_settings_permissions_subtitle), + title = stringProvider.getString(CommonStrings.space_settings_permissions_title), + subtitle = stringProvider.getString(CommonStrings.space_settings_permissions_subtitle), divider = vectorPreferences.developerMode(), editable = true, action = { callback?.onRoomPermissionsClicked() } @@ -172,8 +172,8 @@ class SpaceSettingsController @Inject constructor( if (vectorPreferences.developerMode()) { buildProfileAction( id = "dev_tools", - title = stringProvider.getString(R.string.settings_dev_tools), - icon = R.drawable.ic_verification_glasses, + title = stringProvider.getString(CommonStrings.settings_dev_tools), + icon = org.matrix.android.sdk.R.drawable.ic_verification_glasses, tintIcon = false, divider = true, action = { @@ -183,8 +183,8 @@ class SpaceSettingsController @Inject constructor( buildProfileAction( id = "room_tools", - title = stringProvider.getString(R.string.room_list_quick_actions_room_settings), - icon = R.drawable.ic_verification_glasses, + title = stringProvider.getString(CommonStrings.room_list_quick_actions_room_settings), + icon = org.matrix.android.sdk.R.drawable.ic_verification_glasses, tintIcon = false, divider = false, action = { diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt index 98c81b19bc..dc6e16f110 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt @@ -50,6 +50,7 @@ import im.vector.app.features.roomprofile.settings.RoomSettingsViewModel import im.vector.app.features.roomprofile.settings.RoomSettingsViewState import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleActivity import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleSharedActionViewModel +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.session.room.model.GuestAccess @@ -98,7 +99,7 @@ class SpaceSettingsFragment : setupRoomJoinRuleSharedActionViewModel() epoxyController.callback = this views.roomSettingsRecyclerView.configureWith(epoxyController, hasFixedSize = true) - views.waitingView.waitingStatusText.setText(R.string.please_wait) + views.waitingView.waitingStatusText.setText(CommonStrings.please_wait) views.waitingView.waitingStatusText.isVisible = true viewModel.observeViewEvents { @@ -171,12 +172,12 @@ class SpaceSettingsFragment : return withState(viewModel) { return@withState if (it.showSaveAction) { MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.dialog_title_warning) - .setMessage(R.string.warning_unsaved_change) - .setPositiveButton(R.string.warning_unsaved_change_discard) { _, _ -> + .setTitle(CommonStrings.dialog_title_warning) + .setMessage(CommonStrings.warning_unsaved_change) + .setPositiveButton(CommonStrings.warning_unsaved_change_discard) { _, _ -> viewModel.handle(RoomSettingsAction.Cancel) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() true } else { @@ -186,7 +187,7 @@ class SpaceSettingsFragment : } private fun showSuccess() { - activity?.toast(R.string.room_settings_save_success) + activity?.toast(CommonStrings.room_settings_save_success) } override fun onNameChanged(name: String) { diff --git a/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleActivity.kt b/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleActivity.kt index 0e7a9e4edf..f3a2234266 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleActivity.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleActivity.kt @@ -24,7 +24,6 @@ import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.Mavericks import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.platform.GenericIdArgs @@ -33,6 +32,7 @@ import im.vector.app.databinding.ActivitySimpleLoadingBinding import im.vector.app.features.analytics.plan.ViewRoom import im.vector.app.features.spaces.share.ShareSpaceBottomSheet import im.vector.lib.core.utils.compat.getParcelableExtraCompat +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -82,7 +82,7 @@ class SpacePeopleActivity : VectorBaseActivity() { is SpacePeopleSharedAction.NavigateToRoom -> navigateToRooms(sharedAction) SpacePeopleSharedAction.HideModalLoading -> hideWaitingView() SpacePeopleSharedAction.ShowModalLoading -> { - showWaitingView(getString(R.string.please_wait)) + showWaitingView(getString(CommonStrings.please_wait)) } is SpacePeopleSharedAction.NavigateToInvite -> { ShareSpaceBottomSheet.show(supportFragmentManager, sharedAction.spaceId) diff --git a/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleFragment.kt index 239b0ccb53..64f85040e0 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleFragment.kt @@ -29,7 +29,6 @@ import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.OnBackPressed @@ -37,6 +36,8 @@ import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentRecyclerviewWithSearchBinding import im.vector.app.features.roomprofile.members.RoomMemberListAction import im.vector.app.features.roomprofile.members.RoomMemberListViewModel +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -68,7 +69,7 @@ class SpacePeopleFragment : views.progressBar.isGone = memberListState.areAllMembersLoaded val memberCount = (memberListState.roomSummary.invoke()?.otherMemberIds?.size ?: 0) + 1 - toolbar?.subtitle = resources.getQuantityString(R.plurals.room_title_members, memberCount, memberCount) + toolbar?.subtitle = resources.getQuantityString(CommonPlurals.room_title_members, memberCount, memberCount) // views.listBuildingProgress.isVisible = true epoxyController.setData(memberListState) } @@ -114,7 +115,7 @@ class SpacePeopleFragment : } private fun setupSearchView() { - views.memberNameFilter.queryHint = getString(R.string.search_members_hint) + views.memberNameFilter.queryHint = getString(CommonStrings.search_members_hint) views.memberNameFilter.queryTextChanges() .debounce(100) .onEach { diff --git a/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleListController.kt b/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleListController.kt index 3b74b4b38b..9ccf76f157 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleListController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleListController.kt @@ -17,7 +17,6 @@ package im.vector.app.features.spaces.people import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.R import im.vector.app.core.epoxy.dividerItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.profiles.profileMatrixItemWithPowerLevel @@ -31,6 +30,7 @@ import im.vector.app.features.roomprofile.members.RoomMemberListCategories import im.vector.app.features.roomprofile.members.RoomMemberListViewState import im.vector.app.features.roomprofile.members.RoomMemberSummaryFilter import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +import im.vector.lib.strings.CommonStrings import me.gujun.android.span.span import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.util.toMatrixItem @@ -83,8 +83,10 @@ class SpacePeopleListController @Inject constructor( if (memberEntry.first == RoomMemberListCategories.INVITE) { powerLevelLabel( span { - span(host.stringProvider.getString(R.string.invited)) { - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + span(host.stringProvider.getString(CommonStrings.invited)) { + textColor = host.colorProvider.getColorFromAttribute( + im.vector.lib.ui.styles.R.attr.vctr_content_secondary + ) textStyle = "bold" // fontFamily = "monospace" } @@ -94,10 +96,14 @@ class SpacePeopleListController @Inject constructor( powerLevelLabel( span { span(" $pl ") { - backgroundColor = host.colorProvider.getColor(R.color.notification_accent_color) + backgroundColor = host.colorProvider.getColor( + im.vector.lib.ui.styles.R.color.notification_accent_color + ) paddingTop = host.dimensionConverter.dpToPx(2) paddingBottom = host.dimensionConverter.dpToPx(2) - textColor = host.colorProvider.getColorFromAttribute(R.attr.colorOnPrimary) + textColor = host.colorProvider.getColorFromAttribute( + com.google.android.material.R.attr.colorOnPrimary + ) textStyle = "bold" // fontFamily = "monospace" } @@ -128,15 +134,15 @@ class SpacePeopleListController @Inject constructor( title( span { +"\n" - +host.stringProvider.getString(R.string.no_result_placeholder) + +host.stringProvider.getString(CommonStrings.no_result_placeholder) }.toEpoxyCharSequence() ) description( span { - +host.stringProvider.getString(R.string.looking_for_someone_not_in_space, data.roomSummary.invoke()?.displayName ?: "") + +host.stringProvider.getString(CommonStrings.looking_for_someone_not_in_space, data.roomSummary.invoke()?.displayName ?: "") +"\n" span("Invite them") { - textColor = host.colorProvider.getColorFromAttribute(R.attr.colorPrimary) + textColor = host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary) textStyle = "bold" } }.toEpoxyCharSequence() @@ -150,8 +156,8 @@ class SpacePeopleListController @Inject constructor( private fun toPowerLevelLabel(categories: RoomMemberListCategories): String? { return when (categories) { - RoomMemberListCategories.ADMIN -> stringProvider.getString(R.string.power_level_admin) - RoomMemberListCategories.MODERATOR -> stringProvider.getString(R.string.power_level_moderator) + RoomMemberListCategories.ADMIN -> stringProvider.getString(CommonStrings.power_level_admin) + RoomMemberListCategories.MODERATOR -> stringProvider.getString(CommonStrings.power_level_moderator) else -> null } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewController.kt b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewController.kt index d149a3521d..e9f3556b17 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewController.kt @@ -19,12 +19,13 @@ package im.vector.app.features.spaces.preview import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success -import im.vector.app.R import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericHeaderItem import im.vector.app.core.utils.TextUtils import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.strings.CommonPlurals +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class SpacePreviewController @Inject constructor( @@ -42,7 +43,7 @@ class SpacePreviewController @Inject constructor( spaceTopSummaryItem { id("info") - formattedMemberCount(host.stringProvider.getQuantityString(R.plurals.room_title_members, memberCount, memberCount)) + formattedMemberCount(host.stringProvider.getQuantityString(CommonPlurals.room_title_members, memberCount, memberCount)) topic(data?.spaceInfo?.invoke()?.topic ?: data?.topic ?: "") } @@ -50,7 +51,7 @@ class SpacePreviewController @Inject constructor( if (result.isNotEmpty()) { genericHeaderItem { id("header_rooms") - text(host.stringProvider.getString(R.string.rooms)) + text(host.stringProvider.getString(CommonStrings.rooms)) } buildChildren(result, 0) diff --git a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewFragment.kt index df15d3001c..00c860e71e 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewFragment.kt @@ -30,7 +30,6 @@ import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment @@ -39,6 +38,7 @@ import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.spaces.SpacePreviewSharedAction import im.vector.app.features.spaces.SpacePreviewSharedActionViewModel import im.vector.lib.core.utils.flow.throttleFirst +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.parcelize.Parcelize @@ -139,7 +139,7 @@ class SpacePreviewFragment : } is SpacePreviewViewEvents.JoinFailure -> { sharedActionViewModel.post(SpacePreviewSharedAction.HideModalLoading) - sharedActionViewModel.post(SpacePreviewSharedAction.ShowErrorMessage(viewEvents.message ?: getString(R.string.matrix_error))) + sharedActionViewModel.post(SpacePreviewSharedAction.ShowErrorMessage(viewEvents.message ?: getString(CommonStrings.matrix_error))) } } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/share/ShareSpaceBottomSheet.kt b/vector/src/main/java/im/vector/app/features/spaces/share/ShareSpaceBottomSheet.kt index 3b0bc7f0fe..09d04b82db 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/share/ShareSpaceBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/share/ShareSpaceBottomSheet.kt @@ -26,12 +26,12 @@ import androidx.fragment.app.FragmentManager import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.core.utils.startSharePlainTextIntent import im.vector.app.databinding.BottomSheetSpaceInviteBinding import im.vector.app.features.invite.InviteUsersToRoomActivity +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize @AndroidEntryPoint @@ -58,10 +58,10 @@ class ShareSpaceBottomSheet : VectorBaseBottomSheetDialogFragment { MaterialAlertDialogBuilder(this) .setMessage(errorFormatter.toHumanReadable(it.throwable)) - .setPositiveButton(R.string.ok) { _, _ -> + .setPositiveButton(CommonStrings.ok) { _, _ -> if (it.finish) { finish() } diff --git a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt index 2e8e2c3c14..10c6dbec77 100644 --- a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt @@ -26,13 +26,13 @@ import com.airbnb.mvrx.Success import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.openUrlInChromeCustomTab import im.vector.app.databinding.FragmentReviewTermsBinding +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.terms.TermsService import javax.inject.Inject @@ -53,8 +53,8 @@ class ReviewTermsFragment : super.onViewCreated(view, savedInstanceState) termsController.description = when (reviewTermsViewModel.termsArgs.type) { - TermsService.ServiceType.IdentityService -> getString(R.string.terms_description_for_identity_server) - TermsService.ServiceType.IntegrationManager -> getString(R.string.terms_description_for_integration_manager) + TermsService.ServiceType.IdentityService -> getString(CommonStrings.terms_description_for_identity_server) + TermsService.ServiceType.IntegrationManager -> getString(CommonStrings.terms_description_for_integration_manager) } termsController.listener = this @@ -75,7 +75,7 @@ class ReviewTermsFragment : } } - reviewTermsViewModel.handle(ReviewTermsAction.LoadTerms(getString(R.string.resources_language))) + reviewTermsViewModel.handle(ReviewTermsAction.LoadTerms(getString(CommonStrings.resources_language))) } override fun onDestroyView() { @@ -86,7 +86,7 @@ class ReviewTermsFragment : override fun onResume() { super.onResume() - (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.terms_of_service) + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(CommonStrings.terms_of_service) } override fun invalidate() = withState(reviewTermsViewModel) { state -> @@ -105,7 +105,7 @@ class ReviewTermsFragment : } override fun retry() { - reviewTermsViewModel.handle(ReviewTermsAction.LoadTerms(getString(R.string.resources_language))) + reviewTermsViewModel.handle(ReviewTermsAction.LoadTerms(getString(CommonStrings.resources_language))) } override fun setChecked(term: Term, isChecked: Boolean) { diff --git a/vector/src/main/java/im/vector/app/features/terms/TermsController.kt b/vector/src/main/java/im/vector/app/features/terms/TermsController.kt index 2e01f18769..8bbdad5184 100644 --- a/vector/src/main/java/im/vector/app/features/terms/TermsController.kt +++ b/vector/src/main/java/im/vector/app/features/terms/TermsController.kt @@ -20,11 +20,11 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized -import im.vector.app.R import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.error.ErrorFormatter import im.vector.app.features.discovery.settingsSectionTitleItem +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class TermsController @Inject constructor( @@ -60,7 +60,7 @@ class TermsController @Inject constructor( val host = this settingsSectionTitleItem { id("header") - titleResId(R.string.widget_integration_review_terms) + titleResId(CommonStrings.widget_integration_review_terms) } termsList.forEach { term -> termItem { diff --git a/vector/src/main/java/im/vector/app/features/themes/ActivityOtherThemes.kt b/vector/src/main/java/im/vector/app/features/themes/ActivityOtherThemes.kt index 656110c43d..71c1694154 100644 --- a/vector/src/main/java/im/vector/app/features/themes/ActivityOtherThemes.kt +++ b/vector/src/main/java/im/vector/app/features/themes/ActivityOtherThemes.kt @@ -17,7 +17,7 @@ package im.vector.app.features.themes import androidx.annotation.StyleRes -import im.vector.app.R +import im.vector.lib.ui.styles.R /** * Class to manage Activity other possible themes. diff --git a/vector/src/main/java/im/vector/app/features/themes/ThemeUtils.kt b/vector/src/main/java/im/vector/app/features/themes/ThemeUtils.kt index 3c902d162e..ae98ee2eaf 100644 --- a/vector/src/main/java/im/vector/app/features/themes/ThemeUtils.kt +++ b/vector/src/main/java/im/vector/app/features/themes/ThemeUtils.kt @@ -29,7 +29,7 @@ import androidx.core.content.ContextCompat import androidx.core.content.edit import androidx.core.graphics.drawable.DrawableCompat import androidx.preference.PreferenceManager -import im.vector.app.R +import im.vector.lib.ui.styles.R import timber.log.Timber import java.util.concurrent.atomic.AtomicReference diff --git a/vector/src/main/java/im/vector/app/features/usercode/UserCodeActivity.kt b/vector/src/main/java/im/vector/app/features/usercode/UserCodeActivity.kt index 4fd8305f29..25a880cd64 100644 --- a/vector/src/main/java/im/vector/app/features/usercode/UserCodeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/usercode/UserCodeActivity.kt @@ -29,7 +29,6 @@ import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.utils.onPermissionDeniedSnackbar @@ -41,6 +40,7 @@ import im.vector.app.features.qrcode.QrCodeScannerEvents import im.vector.app.features.qrcode.QrCodeScannerFragment import im.vector.app.features.qrcode.QrCodeScannerViewModel import im.vector.app.features.qrcode.QrScannerArgs +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import kotlin.reflect.KClass @@ -89,7 +89,7 @@ class UserCodeActivity : VectorBaseActivity(), when (mode) { UserCodeState.Mode.SHOW -> showFragment(ShowUserCodeFragment::class) UserCodeState.Mode.SCAN -> { - val args = QrScannerArgs(showExtraButtons = true, R.string.user_code_scan) + val args = QrScannerArgs(showExtraButtons = true, CommonStrings.user_code_scan) showFragment(QrCodeScannerFragment::class, args) } is UserCodeState.Mode.RESULT -> { @@ -108,7 +108,7 @@ class UserCodeActivity : VectorBaseActivity(), is UserCodeShareViewEvents.NavigateToRoom -> navigator.openRoom(this, it.roomId) is UserCodeShareViewEvents.CameraPermissionNotGranted -> { if (it.deniedPermanently) { - onPermissionDeniedSnackbar(R.string.permissions_denied_qr_code) + onPermissionDeniedSnackbar(CommonStrings.permissions_denied_qr_code) } } else -> { @@ -125,7 +125,7 @@ class UserCodeActivity : VectorBaseActivity(), sharedViewModel.handle(UserCodeActions.SwitchMode(UserCodeState.Mode.SHOW)) } is QrCodeScannerEvents.ParseFailed -> { - Toast.makeText(this, R.string.qr_code_not_scanned, Toast.LENGTH_SHORT).show() + Toast.makeText(this, CommonStrings.qr_code_not_scanned, Toast.LENGTH_SHORT).show() finish() } } @@ -149,6 +149,7 @@ class UserCodeActivity : VectorBaseActivity(), override fun mxToBottomSheetSwitchToSpace(spaceId: String) {} + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() = withState(sharedViewModel) { when (it.mode) { UserCodeState.Mode.SHOW -> { diff --git a/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt index e76837f182..6d5627538f 100644 --- a/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt @@ -20,12 +20,12 @@ import com.airbnb.mvrx.MavericksViewModelFactory import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.features.createdirect.DirectRoomHelper +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.matrix.android.sdk.api.extensions.tryOrNull @@ -73,12 +73,12 @@ class UserCodeSharedViewModel @AssistedInject constructor( private fun handleShareByText() { session.permalinkService().createPermalink(session.myUserId)?.let { permalink -> - val text = stringProvider.getString(R.string.invite_friends_text, permalink) + val text = stringProvider.getString(CommonStrings.invite_friends_text, permalink) _viewEvents.post( UserCodeShareViewEvents.SharePlainText( text, - stringProvider.getString(R.string.invite_friends), - stringProvider.getString(R.string.invite_friends_rich_title) + stringProvider.getString(CommonStrings.invite_friends), + stringProvider.getString(CommonStrings.invite_friends_rich_title) ) ) } @@ -94,7 +94,7 @@ class UserCodeSharedViewModel @AssistedInject constructor( val roomId = try { directRoomHelper.ensureDMExists(mxId) } catch (failure: Throwable) { - _viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(R.string.invite_users_to_room_failure))) + _viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(CommonStrings.invite_users_to_room_failure))) return@launch } finally { _viewEvents.post(UserCodeShareViewEvents.HideWaitingScreen) @@ -106,7 +106,7 @@ class UserCodeSharedViewModel @AssistedInject constructor( private fun handleQrCodeDecoded(action: UserCodeActions.DecodedQRCode) { val linkedId = PermalinkParser.parse(action.code) if (linkedId is PermalinkData.FallbackLink) { - _viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(R.string.not_a_valid_qr_code))) + _viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(CommonStrings.not_a_valid_qr_code))) return } _viewEvents.post(UserCodeShareViewEvents.ShowWaitingScreen) @@ -114,7 +114,7 @@ class UserCodeSharedViewModel @AssistedInject constructor( when (linkedId) { is PermalinkData.RoomLink -> { // not yet supported - _viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(R.string.not_implemented))) + _viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(CommonStrings.not_implemented))) } is PermalinkData.UserLink -> { val user = tryOrNull { session.userService().resolveUser(linkedId.userId) } @@ -130,7 +130,7 @@ class UserCodeSharedViewModel @AssistedInject constructor( is PermalinkData.RoomEmailInviteLink, is PermalinkData.FallbackLink -> { // not yet supported - _viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(R.string.not_implemented))) + _viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(CommonStrings.not_implemented))) } } _viewEvents.post(UserCodeShareViewEvents.HideWaitingScreen) diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryUserItem.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryUserItem.kt index 5dac059efc..c2c4880a16 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryUserItem.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserDirectoryUserItem.kt @@ -57,7 +57,7 @@ abstract class UserDirectoryUserItem : VectorEpoxyModel userListHeaderItem { id("identity_server_result_header") - header(host.stringProvider.getString(R.string.discovery_section, currentState.configuredIdentityServer ?: "")) + header(host.stringProvider.getString(CommonStrings.discovery_section, currentState.configuredIdentityServer ?: "")) } val isSelected = currentState.pendingSelections.any { pendingSelection -> when (pendingSelection) { @@ -157,13 +158,13 @@ class UserListController @Inject constructor( text( span { span { - text = host.stringProvider.getString(R.string.settings_discovery_consent_notice_off_2) + text = host.stringProvider.getString(CommonStrings.settings_discovery_consent_notice_off_2) } +"\n" span { - text = host.stringProvider.getString(R.string.settings_discovery_consent_action_give_consent) + text = host.stringProvider.getString(CommonStrings.settings_discovery_consent_action_give_consent) textStyle = "bold" - textColor = host.colorProvider.getColorFromAttribute(R.attr.colorPrimary) + textColor = host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary) } }.toEpoxyCharSequence() ) @@ -179,19 +180,19 @@ class UserListController @Inject constructor( text( span { span { - text = host.stringProvider.getString(R.string.finish_setting_up_discovery) - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary) + text = host.stringProvider.getString(CommonStrings.finish_setting_up_discovery) + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_primary) } +"\n" span { - text = host.stringProvider.getString(R.string.discovery_invite) - textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) + text = host.stringProvider.getString(CommonStrings.discovery_invite) + textColor = host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary) } +"\n" span { - text = host.stringProvider.getString(R.string.finish_setup) + text = host.stringProvider.getString(CommonStrings.finish_setup) textStyle = "bold" - textColor = host.colorProvider.getColorFromAttribute(R.attr.colorPrimary) + textColor = host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary) } }.toEpoxyCharSequence() ) @@ -205,7 +206,7 @@ class UserListController @Inject constructor( is Loading -> { userListHeaderItem { id("identity_server_result_header_loading") - header(host.stringProvider.getString(R.string.discovery_section, currentState.configuredIdentityServer ?: "")) + header(host.stringProvider.getString(CommonStrings.discovery_section, currentState.configuredIdentityServer ?: "")) } loadingItem { id("is_loading") @@ -245,7 +246,7 @@ class UserListController @Inject constructor( ?.let { userList -> userListHeaderItem { id("known_header") - header(host.stringProvider.getString(R.string.direct_room_user_list_known_title)) + header(host.stringProvider.getString(CommonStrings.direct_room_user_list_known_title)) } if (userList.isEmpty()) { @@ -277,7 +278,7 @@ class UserListController @Inject constructor( } userListHeaderItem { id("suggestions") - header(host.stringProvider.getString(R.string.direct_room_user_list_suggestions_title)) + header(host.stringProvider.getString(CommonStrings.direct_room_user_list_suggestions_title)) } if (toDisplay.isEmpty()) { renderEmptyState() @@ -307,7 +308,7 @@ class UserListController @Inject constructor( val host = this noResultItem { id("noResult") - text(host.stringProvider.getString(R.string.no_result_placeholder)) + text(host.stringProvider.getString(CommonStrings.no_result_placeholder)) } } diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt index 6904bf735b..6b92324f68 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt @@ -43,6 +43,7 @@ import im.vector.app.core.utils.showIdentityServerConsentDialog import im.vector.app.core.utils.startSharePlainTextIntent import im.vector.app.databinding.FragmentUserListBinding import im.vector.app.features.settings.VectorSettingsActivity +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart @@ -96,13 +97,13 @@ class UserListFragment : viewModel.observeViewEvents { when (it) { is UserListViewEvents.OpenShareMatrixToLink -> { - val text = getString(R.string.invite_friends_text, it.link) + val text = getString(CommonStrings.invite_friends_text, it.link) startSharePlainTextIntent( context = requireContext(), activityResultLauncher = null, - chooserTitle = getString(R.string.invite_friends), + chooserTitle = getString(CommonStrings.invite_friends), text = text, - extraTitle = getString(R.string.invite_friends_rich_title) + extraTitle = getString(CommonStrings.invite_friends_rich_title) ) } is UserListViewEvents.Failure -> showFailure(it.throwable) diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt index 729790f071..597fbca1b3 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt @@ -23,7 +23,6 @@ import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.extensions.toggle @@ -32,6 +31,7 @@ import im.vector.app.core.resources.StringProvider import im.vector.app.features.discovery.fetchIdentityServerWithTerms import im.vector.app.features.raw.wellknown.getElementWellknown import im.vector.app.features.raw.wellknown.isE2EByDefault +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.debounce @@ -140,7 +140,7 @@ class UserListViewModel @AssistedInject constructor( private fun handleUserConsentRequest() { viewModelScope.launch { val event = try { - val result = session.fetchIdentityServerWithTerms(stringProvider.getString(R.string.resources_language)) + val result = session.fetchIdentityServerWithTerms(stringProvider.getString(CommonStrings.resources_language)) UserListViewEvents.OnPoliciesRetrieved(result) } catch (throwable: Throwable) { UserListViewEvents.Failure(throwable) diff --git a/vector/src/main/java/im/vector/app/features/voice/AudioWaveformView.kt b/vector/src/main/java/im/vector/app/features/voice/AudioWaveformView.kt index 0af0488090..1af36ffc67 100644 --- a/vector/src/main/java/im/vector/app/features/voice/AudioWaveformView.kt +++ b/vector/src/main/java/im/vector/app/features/voice/AudioWaveformView.kt @@ -22,7 +22,6 @@ import android.graphics.Canvas import android.graphics.Paint import android.util.AttributeSet import android.view.View -import im.vector.app.R import kotlin.math.max import kotlin.random.Random @@ -66,19 +65,21 @@ class AudioWaveformView @JvmOverloads constructor( .theme .obtainStyledAttributes( attrs, - R.styleable.AudioWaveformView, + im.vector.lib.ui.styles.R.styleable.AudioWaveformView, 0, 0 ) .apply { - alignment = Alignment.values().find { it.value == getInt(R.styleable.AudioWaveformView_alignment, alignment.value) }!! - flow = Flow.values().find { it.value == getInt(R.styleable.AudioWaveformView_flow, alignment.value) }!! - verticalPadding = getDimension(R.styleable.AudioWaveformView_verticalPadding, verticalPadding) - horizontalPadding = getDimension(R.styleable.AudioWaveformView_horizontalPadding, horizontalPadding) - barWidth = getDimension(R.styleable.AudioWaveformView_barWidth, barWidth) - barSpace = getDimension(R.styleable.AudioWaveformView_barSpace, barSpace) - barMinHeight = getDimension(R.styleable.AudioWaveformView_barMinHeight, barMinHeight) - isBarRounded = getBoolean(R.styleable.AudioWaveformView_isBarRounded, isBarRounded) + alignment = Alignment.values().find { + it.value == getInt(im.vector.lib.ui.styles.R.styleable.AudioWaveformView_alignment, alignment.value) + }!! + flow = Flow.values().find { it.value == getInt(im.vector.lib.ui.styles.R.styleable.AudioWaveformView_flow, alignment.value) }!! + verticalPadding = getDimension(im.vector.lib.ui.styles.R.styleable.AudioWaveformView_verticalPadding, verticalPadding) + horizontalPadding = getDimension(im.vector.lib.ui.styles.R.styleable.AudioWaveformView_horizontalPadding, horizontalPadding) + barWidth = getDimension(im.vector.lib.ui.styles.R.styleable.AudioWaveformView_barWidth, barWidth) + barSpace = getDimension(im.vector.lib.ui.styles.R.styleable.AudioWaveformView_barSpace, barSpace) + barMinHeight = getDimension(im.vector.lib.ui.styles.R.styleable.AudioWaveformView_barMinHeight, barMinHeight) + isBarRounded = getBoolean(im.vector.lib.ui.styles.R.styleable.AudioWaveformView_isBarRounded, isBarRounded) setWillNotDraw(false) barPaint.isAntiAlias = true } diff --git a/vector/src/main/java/im/vector/app/features/voicebroadcast/views/VoiceBroadcastMetadataView.kt b/vector/src/main/java/im/vector/app/features/voicebroadcast/views/VoiceBroadcastMetadataView.kt index c743d8a542..de477b9851 100644 --- a/vector/src/main/java/im/vector/app/features/voicebroadcast/views/VoiceBroadcastMetadataView.kt +++ b/vector/src/main/java/im/vector/app/features/voicebroadcast/views/VoiceBroadcastMetadataView.kt @@ -45,7 +45,7 @@ class VoiceBroadcastMetadataView @JvmOverloads constructor( init { context.obtainStyledAttributes( attrs, - R.styleable.VoiceBroadcastMetadataView, + im.vector.lib.ui.styles.R.styleable.VoiceBroadcastMetadataView, 0, 0 ).use { @@ -55,12 +55,12 @@ class VoiceBroadcastMetadataView @JvmOverloads constructor( } private fun setIcon(typedArray: TypedArray) { - val icon = typedArray.getDrawable(R.styleable.VoiceBroadcastMetadataView_metadataIcon) + val icon = typedArray.getDrawable(im.vector.lib.ui.styles.R.styleable.VoiceBroadcastMetadataView_metadataIcon) views.metadataIcon.setImageDrawable(icon) } private fun setValue(typedArray: TypedArray) { - val value = typedArray.getString(R.styleable.VoiceBroadcastMetadataView_metadataValue) + val value = typedArray.getString(im.vector.lib.ui.styles.R.styleable.VoiceBroadcastMetadataView_metadataValue) views.metadataText.text = value } } diff --git a/vector/src/main/java/im/vector/app/features/webview/VectorWebViewActivity.kt b/vector/src/main/java/im/vector/app/features/webview/VectorWebViewActivity.kt index 6f60ed9958..913e4dce87 100644 --- a/vector/src/main/java/im/vector/app/features/webview/VectorWebViewActivity.kt +++ b/vector/src/main/java/im/vector/app/features/webview/VectorWebViewActivity.kt @@ -94,11 +94,11 @@ class VectorWebViewActivity : VectorBaseActivity() * UI event * ========================================================================================== */ + @Suppress("OVERRIDE_DEPRECATION") override fun onBackPressed() { if (views.simpleWebview.canGoBack()) { views.simpleWebview.goBack() } else { - @Suppress("DEPRECATION") super.onBackPressed() } } diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt index eeb3959ef8..8eb2b66453 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt @@ -16,6 +16,7 @@ package im.vector.app.features.widgets +import android.annotation.SuppressLint import android.app.Activity import android.app.PendingIntent import android.app.PendingIntent.FLAG_IMMUTABLE @@ -35,7 +36,6 @@ import androidx.core.view.isVisible import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.viewModel import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.extensions.addFragment import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.databinding.ActivityWidgetBinding @@ -44,6 +44,8 @@ import im.vector.app.features.widgets.permissions.RoomWidgetPermissionViewEvents import im.vector.app.features.widgets.permissions.RoomWidgetPermissionViewModel import im.vector.lib.core.utils.compat.getParcelableCompat import im.vector.lib.core.utils.compat.getSerializableCompat +import im.vector.lib.strings.CommonStrings +import im.vector.lib.ui.styles.R import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.events.model.Content import java.io.Serializable @@ -83,7 +85,7 @@ class WidgetActivity : VectorBaseActivity() { override fun getBinding() = ActivityWidgetBinding.inflate(layoutInflater) - override fun getTitleRes() = R.string.room_widget_activity_title + override fun getTitleRes() = CommonStrings.room_widget_activity_title override fun initUiAndData() { val widgetArgs: WidgetArgs? = intent?.extras?.getParcelableCompat(Mavericks.KEY_ARG) @@ -172,8 +174,8 @@ class WidgetActivity : VectorBaseActivity() { val actions = mutableListOf() val intent = Intent(ACTION_MEDIA_CONTROL).putExtra(EXTRA_CONTROL_TYPE, CONTROL_TYPE_HANGUP) val pendingIntent = PendingIntent.getBroadcast(this, REQUEST_CODE_HANGUP, intent, FLAG_IMMUTABLE) - val icon = Icon.createWithResource(this, R.drawable.ic_call_hangup) - actions.add(RemoteAction(icon, getString(R.string.call_notification_hangup), getString(R.string.call_notification_hangup), pendingIntent)) + val icon = Icon.createWithResource(this, im.vector.app.R.drawable.ic_call_hangup) + actions.add(RemoteAction(icon, getString(CommonStrings.call_notification_hangup), getString(CommonStrings.call_notification_hangup), pendingIntent)) val aspectRatio = Rational(resources.getDimensionPixelSize(R.dimen.call_pip_width), resources.getDimensionPixelSize(R.dimen.call_pip_height)) return PictureInPictureParams.Builder() @@ -184,6 +186,7 @@ class WidgetActivity : VectorBaseActivity() { private var hangupBroadcastReceiver: BroadcastReceiver? = null + @SuppressLint("UnspecifiedRegisterReceiverFlag") private val pictureInPictureModeChangedInfoConsumer = Consumer { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return@Consumer @@ -198,7 +201,11 @@ class WidgetActivity : VectorBaseActivity() { } } } - registerReceiver(hangupBroadcastReceiver, IntentFilter(ACTION_MEDIA_CONTROL)) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + registerReceiver(hangupBroadcastReceiver, IntentFilter(ACTION_MEDIA_CONTROL), RECEIVER_NOT_EXPORTED) + } else { + registerReceiver(hangupBroadcastReceiver, IntentFilter(ACTION_MEDIA_CONTROL)) + } } else { unregisterReceiver(hangupBroadcastReceiver) } diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt index ee234e313c..a5a54b47b1 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt @@ -53,6 +53,7 @@ import im.vector.app.features.widgets.webview.WebviewPermissionUtils import im.vector.app.features.widgets.webview.clearAfterWidget import im.vector.app.features.widgets.webview.setupForWidget import im.vector.lib.core.utils.compat.resolveActivityCompat +import im.vector.lib.strings.CommonStrings import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.session.terms.TermsService import timber.log.Timber @@ -306,7 +307,7 @@ class WidgetFragment : override fun onPermissionRequest(request: PermissionRequest) { permissionUtils.promptForPermissions( - title = R.string.room_widget_resource_permission_title, + title = CommonStrings.room_widget_resource_permission_title, request = request, context = requireContext(), activity = requireActivity(), @@ -342,7 +343,7 @@ class WidgetFragment : views.widgetProgressBar.isVisible = false views.widgetErrorLayout.isVisible = true views.widgetWebView.isInvisible = true - views.widgetErrorText.text = getString(R.string.room_widget_failed_to_load, message) + views.widgetErrorText.text = getString(CommonStrings.room_widget_failed_to_load, message) } } @@ -358,11 +359,11 @@ class WidgetFragment : private fun deleteWidget() { MaterialAlertDialogBuilder(requireContext()) - .setMessage(R.string.widget_delete_message_confirmation) - .setPositiveButton(R.string.action_remove) { _, _ -> + .setMessage(CommonStrings.widget_delete_message_confirmation) + .setPositiveButton(CommonStrings.action_remove) { _, _ -> viewModel.handle(WidgetAction.DeleteWidget) } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetPostAPIHandler.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetPostAPIHandler.kt index fc1defd20f..e664ef1745 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/WidgetPostAPIHandler.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetPostAPIHandler.kt @@ -20,9 +20,9 @@ import android.text.TextUtils import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.session.coroutineScope +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.Job import kotlinx.coroutines.launch import org.matrix.android.sdk.api.query.QueryStringValue @@ -146,7 +146,7 @@ class WidgetPostAPIHandler @AssistedInject constructor( } Timber.d("Received request canSendEvent in room $roomId") if (room.roomSummary()?.membership != Membership.JOIN) { - widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_must_be_in_room), eventData) + widgetPostAPIMediator.sendError(stringProvider.getString(CommonStrings.widget_integration_must_be_in_room), eventData) return } @@ -167,7 +167,7 @@ class WidgetPostAPIHandler @AssistedInject constructor( widgetPostAPIMediator.sendBoolResponse(true, eventData) } else { Timber.d("## canSendEvent() returns widget_integration_no_permission_in_room") - widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_no_permission_in_room), eventData) + widgetPostAPIMediator.sendError(stringProvider.getString(CommonStrings.widget_integration_no_permission_in_room), eventData) } } @@ -187,7 +187,7 @@ class WidgetPostAPIHandler @AssistedInject constructor( if (roomMemberStateEvent != null) { widgetPostAPIMediator.sendObjectResponse(Map::class.java, roomMemberStateEvent.content, eventData) } else { - widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_failed_to_send_request), eventData) + widgetPostAPIMediator.sendError(stringProvider.getString(CommonStrings.widget_integration_failed_to_send_request), eventData) } } @@ -206,7 +206,7 @@ class WidgetPostAPIHandler @AssistedInject constructor( if (joinedEvents.isNotEmpty()) { widgetPostAPIMediator.sendObjectResponse(Event::class.java, joinedEvents.last(), eventData) } else { - widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_failed_to_send_request), eventData) + widgetPostAPIMediator.sendError(stringProvider.getString(CommonStrings.widget_integration_failed_to_send_request), eventData) } } @@ -256,7 +256,7 @@ class WidgetPostAPIHandler @AssistedInject constructor( // optional val widgetData = eventData["data"] if (widgetId == null) { - widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_unable_to_create), eventData) + widgetPostAPIMediator.sendError(stringProvider.getString(CommonStrings.widget_integration_unable_to_create), eventData) return } @@ -264,7 +264,7 @@ class WidgetPostAPIHandler @AssistedInject constructor( if (null != widgetUrl) { if (null == widgetType) { - widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_unable_to_create), eventData) + widgetPostAPIMediator.sendError(stringProvider.getString(CommonStrings.widget_integration_unable_to_create), eventData) return } @@ -378,7 +378,7 @@ class WidgetPostAPIHandler @AssistedInject constructor( // room.updateUserPowerLevels(userId, level, WidgetApiCallback(eventData, description)) } else { Timber.e("## setBotPower() : Power level must be positive integer.") - widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_positive_power_level), eventData) + widgetPostAPIMediator.sendError(stringProvider.getString(CommonStrings.widget_integration_positive_power_level), eventData) } } @@ -424,12 +424,12 @@ class WidgetPostAPIHandler @AssistedInject constructor( Timber.d("Received request send sticker") val data = eventData["data"] if (data == null) { - widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_missing_parameter), eventData) + widgetPostAPIMediator.sendError(stringProvider.getString(CommonStrings.widget_integration_missing_parameter), eventData) return } val content = (data as? JsonDict)?.get("content") as? Content if (content == null) { - widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_missing_parameter), eventData) + widgetPostAPIMediator.sendError(stringProvider.getString(CommonStrings.widget_integration_missing_parameter), eventData) return } widgetPostAPIMediator.sendSuccess(eventData) @@ -446,12 +446,12 @@ class WidgetPostAPIHandler @AssistedInject constructor( val roomIdInEvent = eventData["room_id"] as String? // Check if param is present if (null == roomIdInEvent) { - widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_missing_room_id), eventData) + widgetPostAPIMediator.sendError(stringProvider.getString(CommonStrings.widget_integration_missing_room_id), eventData) return true } if (!TextUtils.equals(roomIdInEvent, roomId)) { - widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_room_not_visible), eventData) + widgetPostAPIMediator.sendError(stringProvider.getString(CommonStrings.widget_integration_room_not_visible), eventData) return true } @@ -469,7 +469,7 @@ class WidgetPostAPIHandler @AssistedInject constructor( val userIdInEvent = eventData["user_id"] as String? // Check if param is present if (null == userIdInEvent) { - widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_missing_user_id), eventData) + widgetPostAPIMediator.sendError(stringProvider.getString(CommonStrings.widget_integration_missing_user_id), eventData) return true } // OK @@ -486,7 +486,7 @@ class WidgetPostAPIHandler @AssistedInject constructor( widgetPostAPIMediator.sendSuccess(eventData) }, onFailure = { - widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_failed_to_send_request), eventData) + widgetPostAPIMediator.sendError(stringProvider.getString(CommonStrings.widget_integration_failed_to_send_request), eventData) } ) } diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetViewState.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetViewState.kt index cd2ed23980..c5b2952ef5 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/WidgetViewState.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetViewState.kt @@ -20,7 +20,7 @@ import androidx.annotation.StringRes import com.airbnb.mvrx.Async import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.Uninitialized -import im.vector.app.R +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.widgets.model.Widget import org.matrix.android.sdk.api.session.widgets.model.WidgetType @@ -31,8 +31,8 @@ enum class WidgetStatus { } enum class WidgetKind(@StringRes val nameRes: Int, val screenId: String?) { - ROOM(R.string.room_widget_activity_title, null), - STICKER_PICKER(R.string.title_activity_choose_sticker, WidgetType.StickerPicker.preferred), + ROOM(CommonStrings.room_widget_activity_title, null), + STICKER_PICKER(CommonStrings.title_activity_choose_sticker, WidgetType.StickerPicker.preferred), INTEGRATION_MANAGER(0, null), ELEMENT_CALL(0, null); diff --git a/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionBottomSheet.kt b/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionBottomSheet.kt index a917b6699d..b92ca0b13e 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionBottomSheet.kt @@ -26,11 +26,11 @@ import android.view.ViewGroup import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.databinding.BottomSheetRoomWidgetPermissionBinding import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.widgets.WidgetArgs +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject @@ -73,15 +73,19 @@ class RoomWidgetPermissionBottomSheet : val domain = permissionData.widgetDomain ?: "" val infoBuilder = SpannableStringBuilder() .append(getString( - R.string.room_widget_permission_webview_shared_info_title + CommonStrings.room_widget_permission_webview_shared_info_title .takeIf { permissionData.isWebviewWidget } - ?: R.string.room_widget_permission_shared_info_title, + ?: CommonStrings.room_widget_permission_shared_info_title, "'$domain'")) infoBuilder.append("\n") permissionData.permissionsList.forEach { infoBuilder.append("\n") val bulletPoint = getString(it) - infoBuilder.append(bulletPoint, BulletSpan(resources.getDimension(R.dimen.quote_gap).toInt()), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) + infoBuilder.append( + bulletPoint, + BulletSpan(resources.getDimension(im.vector.lib.ui.styles.R.dimen.quote_gap).toInt()), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ) } infoBuilder.append("\n") views.widgetPermissionSharedInfo.text = infoBuilder diff --git a/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionViewModel.kt b/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionViewModel.kt index e9f16baf9d..b75431e32c 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionViewModel.kt @@ -19,10 +19,10 @@ import com.airbnb.mvrx.MavericksViewModelFactory import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch @@ -60,8 +60,8 @@ class RoomWidgetPermissionViewModel @AssistedInject constructor( // For now put all if (widget.type == WidgetType.Jitsi) { val infoShared = listOf( - R.string.room_widget_permission_display_name, - R.string.room_widget_permission_avatar_url + CommonStrings.room_widget_permission_display_name, + CommonStrings.room_widget_permission_avatar_url ) RoomWidgetPermissionViewState.WidgetPermissionData( widget = widget, @@ -71,12 +71,12 @@ class RoomWidgetPermissionViewModel @AssistedInject constructor( ) } else { val infoShared = listOf( - R.string.room_widget_permission_display_name, - R.string.room_widget_permission_avatar_url, - R.string.room_widget_permission_user_id, - R.string.room_widget_permission_theme, - R.string.room_widget_permission_widget_id, - R.string.room_widget_permission_room_id + CommonStrings.room_widget_permission_display_name, + CommonStrings.room_widget_permission_avatar_url, + CommonStrings.room_widget_permission_user_id, + CommonStrings.room_widget_permission_theme, + CommonStrings.room_widget_permission_widget_id, + CommonStrings.room_widget_permission_room_id ) RoomWidgetPermissionViewState.WidgetPermissionData( widget = widget, diff --git a/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt b/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt index 44af4ec335..43d43d2f55 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/webview/WebviewPermissionUtils.kt @@ -23,10 +23,10 @@ import androidx.annotation.StringRes import androidx.annotation.VisibleForTesting import androidx.fragment.app.FragmentActivity import com.google.android.material.dialog.MaterialAlertDialogBuilder -import im.vector.app.R import im.vector.app.core.error.fatalError import im.vector.app.core.utils.checkPermissions import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.strings.CommonStrings import javax.inject.Inject class WebviewPermissionUtils @Inject constructor( @@ -64,13 +64,13 @@ class WebviewPermissionUtils @Inject constructor( ) { _, which, isChecked -> allowedPermissions[which] = allowedPermissions[which].first to isChecked } - .setPositiveButton(R.string.room_widget_resource_grant_permission) { _, _ -> + .setPositiveButton(CommonStrings.room_widget_resource_grant_permission) { _, _ -> val permissions = allowedPermissions.mapNotNull { perm -> perm.first.takeIf { perm.second } } onPermissionsSelected(permissions, request, activity, activityResultLauncher) } - .setNegativeButton(R.string.room_widget_resource_decline_permission) { _, _ -> + .setNegativeButton(CommonStrings.room_widget_resource_decline_permission) { _, _ -> request.deny() } .show() @@ -131,9 +131,9 @@ class WebviewPermissionUtils @Inject constructor( private fun webPermissionToHumanReadable(permission: String, context: Context): String { return when (permission) { - PermissionRequest.RESOURCE_AUDIO_CAPTURE -> context.getString(R.string.room_widget_webview_access_microphone) - PermissionRequest.RESOURCE_VIDEO_CAPTURE -> context.getString(R.string.room_widget_webview_access_camera) - PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID -> context.getString(R.string.room_widget_webview_read_protected_media) + PermissionRequest.RESOURCE_AUDIO_CAPTURE -> context.getString(CommonStrings.room_widget_webview_access_microphone) + PermissionRequest.RESOURCE_VIDEO_CAPTURE -> context.getString(CommonStrings.room_widget_webview_access_camera) + PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID -> context.getString(CommonStrings.room_widget_webview_read_protected_media) else -> permission } } diff --git a/vector/src/main/java/im/vector/app/features/widgets/webview/WidgetWebView.kt b/vector/src/main/java/im/vector/app/features/widgets/webview/WidgetWebView.kt index 254a7f97f5..5e79353781 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/webview/WidgetWebView.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/webview/WidgetWebView.kt @@ -22,7 +22,6 @@ import android.webkit.CookieManager import android.webkit.PermissionRequest import android.webkit.WebChromeClient import android.webkit.WebView -import im.vector.app.R import im.vector.app.core.utils.CheckWebViewPermissionsUseCase import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.webview.VectorWebViewClient @@ -33,7 +32,7 @@ fun WebView.setupForWidget(activity: Activity, eventListener: WebEventListener, ) { // xml value seems ignored - setBackgroundColor(ThemeUtils.getColor(context, R.attr.colorSurface)) + setBackgroundColor(ThemeUtils.getColor(context, com.google.android.material.R.attr.colorSurface)) // clear caches clearHistory() diff --git a/vector/src/main/java/im/vector/app/features/workers/signout/SignOutBottomSheetActionButton.kt b/vector/src/main/java/im/vector/app/features/workers/signout/SignOutBottomSheetActionButton.kt index 7dd40cc165..1b97dbaebb 100644 --- a/vector/src/main/java/im/vector/app/features/workers/signout/SignOutBottomSheetActionButton.kt +++ b/vector/src/main/java/im/vector/app/features/workers/signout/SignOutBottomSheetActionButton.kt @@ -23,10 +23,10 @@ import android.util.AttributeSet import android.widget.FrameLayout import androidx.core.content.withStyledAttributes import androidx.core.view.isVisible -import im.vector.app.R import im.vector.app.core.extensions.setTextOrHide import im.vector.app.databinding.ViewSignOutBottomSheetActionButtonBinding import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.ui.styles.R class SignOutBottomSheetActionButton @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 @@ -67,7 +67,7 @@ class SignOutBottomSheetActionButton @JvmOverloads constructor( } init { - inflate(context, R.layout.view_sign_out_bottom_sheet_action_button, this) + inflate(context, im.vector.app.R.layout.view_sign_out_bottom_sheet_action_button, this) views = ViewSignOutBottomSheetActionButtonBinding.bind(this) context.withStyledAttributes(attrs, R.styleable.SignOutBottomSheetActionButton) { diff --git a/vector/src/main/java/im/vector/app/features/workers/signout/SignOutBottomSheetDialogFragment.kt b/vector/src/main/java/im/vector/app/features/workers/signout/SignOutBottomSheetDialogFragment.kt index ffdd074a8a..04f40dccc2 100644 --- a/vector/src/main/java/im/vector/app/features/workers/signout/SignOutBottomSheetDialogFragment.kt +++ b/vector/src/main/java/im/vector/app/features/workers/signout/SignOutBottomSheetDialogFragment.kt @@ -32,22 +32,26 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.dialogs.ExportKeysDialog import im.vector.app.core.extensions.queryExportKeys import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment +import im.vector.app.core.resources.BuildMeta import im.vector.app.databinding.BottomSheetLogoutAndBackupBinding import im.vector.app.features.crypto.keysbackup.setup.KeysBackupSetupActivity import im.vector.app.features.crypto.recover.BootstrapBottomSheet import im.vector.app.features.crypto.recover.SetupMode +import im.vector.lib.strings.CommonStrings import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState +import javax.inject.Inject // TODO this needs to be refactored to current standard and remove legacy @AndroidEntryPoint class SignOutBottomSheetDialogFragment : VectorBaseBottomSheetDialogFragment() { + @Inject lateinit var buildMeta: BuildMeta + var onSignOut: Runnable? = null companion object { @@ -75,10 +79,10 @@ class SignOutBottomSheetDialogFragment : views.exitAnywayButton.action = { context?.let { MaterialAlertDialogBuilder(it) - .setTitle(R.string.are_you_sure) - .setMessage(R.string.sign_out_bottom_sheet_will_lose_secure_messages) - .setPositiveButton(R.string.backup, null) - .setNegativeButton(R.string.action_sign_out) { _, _ -> + .setTitle(CommonStrings.are_you_sure) + .setMessage(CommonStrings.sign_out_bottom_sheet_will_lose_secure_messages) + .setPositiveButton(CommonStrings.backup, null) + .setNegativeButton(CommonStrings.action_sign_out) { _, _ -> onSignOut?.run() } .show() @@ -91,7 +95,11 @@ class SignOutBottomSheetDialogFragment : views.exportManuallyButton.action = { withState(viewModel) { state -> - queryExportKeys(state.userId, manualExportKeysActivityResultLauncher) + queryExportKeys( + userId = state.userId, + applicationName = buildMeta.applicationName, + activityResultLauncher = manualExportKeysActivityResultLauncher, + ) } } @@ -103,7 +111,7 @@ class SignOutBottomSheetDialogFragment : override fun invalidate() = withState(viewModel) { state -> views.signoutExportingLoading.isVisible = false if (state.crossSigningSetupAllKeysKnown && !state.backupIsSetup) { - views.bottomSheetSignoutWarningText.text = getString(R.string.sign_out_bottom_sheet_warning_no_backup) + views.bottomSheetSignoutWarningText.text = getString(CommonStrings.sign_out_bottom_sheet_warning_no_backup) views.backingUpStatusGroup.isVisible = false // we should show option to setup 4S views.setupRecoveryButton.isVisible = true @@ -113,7 +121,7 @@ class SignOutBottomSheetDialogFragment : views.exitAnywayButton.isVisible = true views.signOutButton.isVisible = false } else if (state.keysBackupState == KeysBackupState.Unknown || state.keysBackupState == KeysBackupState.Disabled) { - views.bottomSheetSignoutWarningText.text = getString(R.string.sign_out_bottom_sheet_warning_no_backup) + views.bottomSheetSignoutWarningText.text = getString(CommonStrings.sign_out_bottom_sheet_warning_no_backup) views.backingUpStatusGroup.isVisible = false // no key backup and cannot setup full 4S // we propose to setup @@ -131,13 +139,13 @@ class SignOutBottomSheetDialogFragment : when (state.keysBackupState) { KeysBackupState.ReadyToBackUp -> { - views.bottomSheetSignoutWarningText.text = getString(R.string.action_sign_out_confirmation_simple) + views.bottomSheetSignoutWarningText.text = getString(CommonStrings.action_sign_out_confirmation_simple) // Ok all keys are backedUp views.backingUpStatusGroup.isVisible = true views.backupProgress.isVisible = false views.backupCompleteImage.isVisible = true - views.backupStatusText.text = getString(R.string.keys_backup_info_keys_all_backup_up) + views.backupStatusText.text = getString(CommonStrings.keys_backup_info_keys_all_backup_up) views.setupMegolmBackupButton.isVisible = false views.exportManuallyButton.isVisible = false @@ -147,13 +155,13 @@ class SignOutBottomSheetDialogFragment : } KeysBackupState.WillBackUp, KeysBackupState.BackingUp -> { - views.bottomSheetSignoutWarningText.text = getString(R.string.sign_out_bottom_sheet_warning_backing_up) + views.bottomSheetSignoutWarningText.text = getString(CommonStrings.sign_out_bottom_sheet_warning_backing_up) // save in progress views.backingUpStatusGroup.isVisible = true views.backupProgress.isVisible = true views.backupCompleteImage.isVisible = false - views.backupStatusText.text = getString(R.string.sign_out_bottom_sheet_backing_up_keys) + views.backupStatusText.text = getString(CommonStrings.sign_out_bottom_sheet_backing_up_keys) views.setupMegolmBackupButton.isVisible = false views.exportManuallyButton.isVisible = false @@ -161,7 +169,7 @@ class SignOutBottomSheetDialogFragment : views.signOutButton.isVisible = false } KeysBackupState.NotTrusted -> { - views.bottomSheetSignoutWarningText.text = getString(R.string.sign_out_bottom_sheet_warning_backup_not_active) + views.bottomSheetSignoutWarningText.text = getString(CommonStrings.sign_out_bottom_sheet_warning_backup_not_active) // It's not trusted and we know there are unsaved keys.. views.backingUpStatusGroup.isVisible = false @@ -193,7 +201,7 @@ class SignOutBottomSheetDialogFragment : } is Success -> { if (state.hasBeenExportedToFile.invoke()) { - views.bottomSheetSignoutWarningText.text = getString(R.string.action_sign_out_confirmation_simple) + views.bottomSheetSignoutWarningText.text = getString(CommonStrings.action_sign_out_confirmation_simple) views.backingUpStatusGroup.isVisible = false views.setupRecoveryButton.isVisible = false diff --git a/vector/src/main/java/im/vector/app/features/workers/signout/SignOutUiWorker.kt b/vector/src/main/java/im/vector/app/features/workers/signout/SignOutUiWorker.kt index 66b69fd53c..4595edcef3 100644 --- a/vector/src/main/java/im/vector/app/features/workers/signout/SignOutUiWorker.kt +++ b/vector/src/main/java/im/vector/app/features/workers/signout/SignOutUiWorker.kt @@ -19,11 +19,11 @@ package im.vector.app.features.workers.signout import androidx.fragment.app.FragmentActivity import androidx.lifecycle.lifecycleScope import com.google.android.material.dialog.MaterialAlertDialogBuilder -import im.vector.app.R import im.vector.app.core.extensions.cannotLogoutSafely import im.vector.app.core.extensions.singletonEntryPoint import im.vector.app.features.MainActivity import im.vector.app.features.MainActivityArgs +import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.Session @@ -46,12 +46,12 @@ class SignOutUiWorker(private val activity: FragmentActivity) { } else { // Display a simple confirmation dialog MaterialAlertDialogBuilder(activity) - .setTitle(R.string.action_sign_out) - .setMessage(R.string.action_sign_out_confirmation_simple) - .setPositiveButton(R.string.action_sign_out) { _, _ -> + .setTitle(CommonStrings.action_sign_out) + .setMessage(CommonStrings.action_sign_out_confirmation_simple) + .setPositiveButton(CommonStrings.action_sign_out) { _, _ -> doSignOut() } - .setNegativeButton(R.string.action_cancel, null) + .setNegativeButton(CommonStrings.action_cancel, null) .show() } } diff --git a/vector/src/main/res/drawable/ic_presence_away.xml b/vector/src/main/res/drawable/ic_presence_away.xml index 617fe735b6..8863447471 100644 --- a/vector/src/main/res/drawable/ic_presence_away.xml +++ b/vector/src/main/res/drawable/ic_presence_away.xml @@ -1,12 +1,9 @@ - + android:viewportHeight="12"> diff --git a/vector/src/main/res/drawable/ic_presence_busy.xml b/vector/src/main/res/drawable/ic_presence_busy.xml index 9155a6b4a5..1301998136 100644 --- a/vector/src/main/res/drawable/ic_presence_busy.xml +++ b/vector/src/main/res/drawable/ic_presence_busy.xml @@ -1,12 +1,9 @@ - + android:viewportHeight="12"> diff --git a/vector/src/main/res/drawable/ic_presence_offline.xml b/vector/src/main/res/drawable/ic_presence_offline.xml index 3f0dc251ce..45150c52af 100644 --- a/vector/src/main/res/drawable/ic_presence_offline.xml +++ b/vector/src/main/res/drawable/ic_presence_offline.xml @@ -1,12 +1,9 @@ - + android:viewportHeight="12"> @@ -21,4 +18,4 @@ - \ No newline at end of file + diff --git a/vector/src/main/res/drawable/ic_presence_online.xml b/vector/src/main/res/drawable/ic_presence_online.xml index e5229de3fd..e9f899eb6c 100644 --- a/vector/src/main/res/drawable/ic_presence_online.xml +++ b/vector/src/main/res/drawable/ic_presence_online.xml @@ -1,12 +1,9 @@ - + android:viewportHeight="12"> diff --git a/vector/src/main/res/layout/activity_threads.xml b/vector/src/main/res/layout/activity_threads.xml index c34be9687d..64d4583489 100644 --- a/vector/src/main/res/layout/activity_threads.xml +++ b/vector/src/main/res/layout/activity_threads.xml @@ -1,7 +1,6 @@ @@ -21,4 +20,4 @@ - \ No newline at end of file + diff --git a/vector/src/main/res/layout/fragment_composer.xml b/vector/src/main/res/layout/fragment_composer.xml index 5038a9e179..6a18e91ebb 100644 --- a/vector/src/main/res/layout/fragment_composer.xml +++ b/vector/src/main/res/layout/fragment_composer.xml @@ -1,7 +1,5 @@ - (R.layout.item_radio) - view.findViewById(R.id.actionTitle).text = paparazzi.resources.getString(R.string.room_settings_all_messages) + view.findViewById(R.id.actionTitle).text = paparazzi.resources.getString(CommonStrings.room_settings_all_messages) view.findViewById(R.id.radioIcon).setImageResource(R.drawable.ic_radio_on) paparazzi.snapshot(view) diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeFontScalePreferences.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeFontScalePreferences.kt index 4e8abce74a..ff578779e0 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeFontScalePreferences.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeFontScalePreferences.kt @@ -16,9 +16,9 @@ package im.vector.app.test.fakes -import im.vector.app.R import im.vector.app.features.settings.FontScalePreferences import im.vector.app.features.settings.FontScaleValue +import im.vector.lib.strings.CommonStrings import io.mockk.every import io.mockk.mockk import io.mockk.verify @@ -26,13 +26,13 @@ import io.mockk.verify class FakeFontScalePreferences : FontScalePreferences by mockk(relaxUnitFun = true) { private val fontScaleValues = listOf( - FontScaleValue(0, "FONT_SCALE_TINY", 0.70f, R.string.tiny), - FontScaleValue(1, "FONT_SCALE_SMALL", 0.85f, R.string.small), - FontScaleValue(2, "FONT_SCALE_NORMAL", 1.00f, R.string.normal), - FontScaleValue(3, "FONT_SCALE_LARGE", 1.15f, R.string.large), - FontScaleValue(4, "FONT_SCALE_LARGER", 1.30f, R.string.larger), - FontScaleValue(5, "FONT_SCALE_LARGEST", 1.45f, R.string.largest), - FontScaleValue(6, "FONT_SCALE_HUGE", 1.60f, R.string.huge) + FontScaleValue(0, "FONT_SCALE_TINY", 0.70f, CommonStrings.tiny), + FontScaleValue(1, "FONT_SCALE_SMALL", 0.85f, CommonStrings.small), + FontScaleValue(2, "FONT_SCALE_NORMAL", 1.00f, CommonStrings.normal), + FontScaleValue(3, "FONT_SCALE_LARGE", 1.15f, CommonStrings.large), + FontScaleValue(4, "FONT_SCALE_LARGER", 1.30f, CommonStrings.larger), + FontScaleValue(5, "FONT_SCALE_LARGEST", 1.45f, CommonStrings.largest), + FontScaleValue(6, "FONT_SCALE_HUGE", 1.60f, CommonStrings.huge) ) init { diff --git a/vector/src/test/java/im/vector/app/test/fixtures/BuildMetaFixture.kt b/vector/src/test/java/im/vector/app/test/fixtures/BuildMetaFixture.kt index e4dee0e474..1050de7e3d 100644 --- a/vector/src/test/java/im/vector/app/test/fixtures/BuildMetaFixture.kt +++ b/vector/src/test/java/im/vector/app/test/fixtures/BuildMetaFixture.kt @@ -21,6 +21,7 @@ import im.vector.app.core.resources.BuildMeta fun aBuildMeta() = BuildMeta( isDebug = false, applicationId = "im.vector", + applicationName = "Element", lowPrivacyLoggingEnabled = false, versionName = "app-version-name", gitRevision = "abcdef", From 6671a3f925085cc7a54b26317842a1b7f885011b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Jul 2024 10:01:22 +0200 Subject: [PATCH 09/26] try API 29 --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 36a0365f84..b589217175 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,7 +19,7 @@ jobs: timeout-minutes: 90 # We might need to increase it if the time for tests grows strategy: matrix: - api-level: [34] + api-level: [29] # Allow all jobs on main and develop. Just one per PR. concurrency: group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('unit-tests-{0}', github.ref) }} From 5203dd86b47b2dde73045269d5dc1a30c5caec65 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Jul 2024 11:06:44 +0200 Subject: [PATCH 10/26] Add packaging pickFirst to fix tests. --- vector-app/build.gradle | 6 ++++++ vector/build.gradle | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/vector-app/build.gradle b/vector-app/build.gradle index 342930c44f..b22dae7710 100644 --- a/vector-app/build.gradle +++ b/vector-app/build.gradle @@ -372,6 +372,12 @@ android { viewBinding true buildConfig true } + + packaging { + pickFirsts.add("META-INF/LICENSE.md") + pickFirsts.add("META-INF/LICENSE-notice.md") + pickFirsts.add("MANIFEST.MF") + } } dependencies { diff --git a/vector/build.gradle b/vector/build.gradle index 57effb23fa..1374b236f9 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -106,6 +106,12 @@ android { viewBinding true buildConfig true } + + packaging { + pickFirsts.add("META-INF/LICENSE.md") + pickFirsts.add("META-INF/LICENSE-notice.md") + pickFirsts.add("MANIFEST.MF") + } } dependencies { From b3bd361a088859be3ab4c5045e7cdc2a88b92e5a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Jul 2024 14:57:24 +0200 Subject: [PATCH 11/26] Add Realm migrations due to upgrade of Kotlin version. See https://github.com/realm/realm-java/issues/7810 for more details. --- .../RealmSessionStoreMigration43Test.kt | 2 +- .../store/db/RealmCryptoStoreMigration.kt | 4 +- .../store/db/migration/MigrateCryptoTo023.kt | 30 ++++++++++ .../database/RealmSessionStoreMigration.kt | 4 +- .../database/migration/MigrateSessionTo055.kt | 57 +++++++++++++++++++ 5 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo023.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo055.kt diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration43Test.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration43Test.kt index e74aa52495..af8d2fdd3b 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration43Test.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration43Test.kt @@ -56,7 +56,7 @@ class RealmSessionStoreMigration43Test { } @Test - fun migrationShouldBeNeeed() { + fun migrationShouldBeNeeded() { val realmName = "session_42.realm" val realmConfiguration = configurationFactory.createConfiguration( realmName, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt index 99734f654f..1b0143f4fa 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt @@ -39,6 +39,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo020 import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo021 import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo022 +import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo023 import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration import org.matrix.android.sdk.internal.util.time.Clock import javax.inject.Inject @@ -54,7 +55,7 @@ internal class RealmCryptoStoreMigration @Inject constructor( private val rustMigrationInfoProvider: RustMigrationInfoProvider, ) : MatrixRealmMigration( dbName = "Crypto", - schemaVersion = 22L, + schemaVersion = 23L, ) { /** * Forces all RealmCryptoStoreMigration instances to be equal. @@ -91,5 +92,6 @@ internal class RealmCryptoStoreMigration @Inject constructor( rustMigrationInfoProvider.rustEncryptionConfiguration, rustMigrationInfoProvider.migrateMegolmGroupSessions ).perform() + if (oldVersion < 23) MigrateCryptoTo023(realm).perform() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo023.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo023.kt new file mode 100644 index 0000000000..1302b452bd --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo023.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.internal.crypto.store.db.migration + +import io.realm.DynamicRealm +import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingKeyRequestEntityFields +import org.matrix.android.sdk.internal.util.database.RealmMigrator + +// Some fields are now required due to upgrade of Kotlin version. +// See https://github.com/realm/realm-java/issues/7810 for more details. +internal class MigrateCryptoTo023(realm: DynamicRealm) : RealmMigrator(realm, 23) { + override fun doMigrate(realm: DynamicRealm) { + realm.schema.get("OutgoingKeyRequestEntity") + ?.setRequired(OutgoingKeyRequestEntityFields.REQUEST_STATE_STR, true) + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt index 4a7064ebf5..e02ffc36c5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt @@ -71,6 +71,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo051 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo052 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo053 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo054 +import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo055 import org.matrix.android.sdk.internal.util.Normalizer import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration import javax.inject.Inject @@ -79,7 +80,7 @@ internal class RealmSessionStoreMigration @Inject constructor( private val normalizer: Normalizer ) : MatrixRealmMigration( dbName = "Session", - schemaVersion = 54L, + schemaVersion = 55L, ) { /** * Forces all RealmSessionStoreMigration instances to be equal. @@ -143,5 +144,6 @@ internal class RealmSessionStoreMigration @Inject constructor( if (oldVersion < 52) MigrateSessionTo052(realm).perform() if (oldVersion < 53) MigrateSessionTo053(realm).perform() if (oldVersion < 54) MigrateSessionTo054(realm).perform() + if (oldVersion < 55) MigrateSessionTo055(realm).perform() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo055.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo055.kt new file mode 100644 index 0000000000..3a0e79d3e7 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo055.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.internal.database.migration + +import io.realm.DynamicRealm +import org.matrix.android.sdk.internal.database.model.EventEntityFields +import org.matrix.android.sdk.internal.database.model.EventInsertEntityFields +import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields +import org.matrix.android.sdk.internal.database.model.PushRulesEntityFields +import org.matrix.android.sdk.internal.database.model.PusherEntityFields +import org.matrix.android.sdk.internal.database.model.RoomEntityFields +import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFields +import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields +import org.matrix.android.sdk.internal.database.model.presence.UserPresenceEntityFields +import org.matrix.android.sdk.internal.util.database.RealmMigrator + +// Some fields are now required due to upgrade of Kotlin version. +// See https://github.com/realm/realm-java/issues/7810 for more details. +internal class MigrateSessionTo055(realm: DynamicRealm) : RealmMigrator(realm, 55) { + override fun doMigrate(realm: DynamicRealm) { + realm.schema.get("EventEntity") + ?.setRequired(EventEntityFields.SEND_STATE_STR, true) + ?.setRequired(EventEntityFields.THREAD_NOTIFICATION_STATE_STR, true) + realm.schema.get("EventInsertEntity") + ?.setRequired(EventInsertEntityFields.INSERT_TYPE_STR, true) + realm.schema.get("LocalRoomSummaryEntity") + ?.setRequired(LocalRoomSummaryEntityFields.STATE_STR, true) + realm.schema.get("PushRulesEntity") + ?.setRequired(PushRulesEntityFields.KIND_STR, true) + realm.schema.get("PusherEntity") + ?.setRequired(PusherEntityFields.STATE_STR, true) + realm.schema.get("RoomEntity") + ?.setRequired(RoomEntityFields.MEMBERSHIP_STR, true) + ?.setRequired(RoomEntityFields.MEMBERS_LOAD_STATUS_STR, true) + realm.schema.get("RoomMemberSummaryEntity") + ?.setRequired(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, true) + realm.schema.get("RoomSummaryEntity") + ?.setRequired(RoomSummaryEntityFields.MEMBERSHIP_STR, true) + ?.setRequired(RoomSummaryEntityFields.VERSIONING_STATE_STR, true) + realm.schema.get("UserPresenceEntity") + ?.setRequired(UserPresenceEntityFields.PRESENCE_STR, true) + } +} From cf464af6ef350c43e6711f7a2ba6d3d2c00aac0a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 16 Jul 2024 15:15:12 +0200 Subject: [PATCH 12/26] Revert to API 28 --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b589217175..ffe703c606 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,7 +19,7 @@ jobs: timeout-minutes: 90 # We might need to increase it if the time for tests grows strategy: matrix: - api-level: [29] + api-level: [28] # Allow all jobs on main and develop. Just one per PR. concurrency: group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('unit-tests-{0}', github.ref) }} From 224243aca5df60525d0b5204f8f68998ec3b7d16 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Jul 2024 10:48:11 +0200 Subject: [PATCH 13/26] Increase available memory for nightly builds and use G1GC Copy settings from EXA. They are failing with OutOfMemoryError. --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 3a9465c1e9..67a165a107 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -7,7 +7,7 @@ on: - cron: "0 4 * * *" env: - GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError -XX:MaxMetaspaceSize=1g" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false + GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx6g -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError -XX:MaxMetaspaceSize=1g" -Dkotlin.incremental=false -XX:+UseG1GC CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon jobs: From 10e79849a5b35fb69bc41f03205e06cdd43c2164 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Jul 2024 11:36:37 +0200 Subject: [PATCH 14/26] Fix Weblate conflicts --- library/ui-strings/src/main/res/values-fa/strings.xml | 2 +- library/ui-strings/src/main/res/values-zh-rCN/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/ui-strings/src/main/res/values-fa/strings.xml b/library/ui-strings/src/main/res/values-fa/strings.xml index d9e0e67c0a..e28afadaa8 100644 --- a/library/ui-strings/src/main/res/values-fa/strings.xml +++ b/library/ui-strings/src/main/res/values-fa/strings.xml @@ -1,5 +1,5 @@ - + دعوت %s ‫%1$s، %2$s را دعوت کرد %1$s دعوتتان کرد diff --git a/library/ui-strings/src/main/res/values-zh-rCN/strings.xml b/library/ui-strings/src/main/res/values-zh-rCN/strings.xml index 58000353b0..970bee794c 100644 --- a/library/ui-strings/src/main/res/values-zh-rCN/strings.xml +++ b/library/ui-strings/src/main/res/values-zh-rCN/strings.xml @@ -1,5 +1,5 @@ - + %s 的邀请 %1$s 邀请了 %2$s %1$s 邀请了你 From 1e32ebde41e5dc944c07f23d122cef2d411e3243 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Jul 2024 16:59:05 +0200 Subject: [PATCH 15/26] Use ContextCompat.registerReceiver with explicit RECEIVER_EXPORTED to fix crash on API 34. java.lang.SecurityException: im.vector.app.debug: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts --- .../network/NetworkCallbackStrategy.kt | 8 +++++++- .../app/receivers/VectorDebugReceiver.kt | 8 +++++++- .../java/im/vector/app/VectorApplication.kt | 18 +++++++++++------- .../core/services/BluetoothHeadsetReceiver.kt | 8 +++++++- .../core/services/WiredHeadsetStateReceiver.kt | 8 +++++++- .../app/features/mdm/DefaultMdmService.kt | 8 +++++++- .../app/features/widgets/WidgetActivity.kt | 12 +++++++----- 7 files changed, 53 insertions(+), 17 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkCallbackStrategy.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkCallbackStrategy.kt index 90d2719e25..540fc845c9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkCallbackStrategy.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkCallbackStrategy.kt @@ -22,6 +22,7 @@ import android.content.IntentFilter import android.net.ConnectivityManager import android.net.Network import android.os.Build +import androidx.core.content.ContextCompat import androidx.core.content.getSystemService import timber.log.Timber import javax.inject.Inject @@ -43,7 +44,12 @@ internal class FallbackNetworkCallbackStrategy @Inject constructor( networkInfoReceiver.isConnectedCallback = { hasChanged() } - context.registerReceiver(networkInfoReceiver, filter) + ContextCompat.registerReceiver( + context, + networkInfoReceiver, + filter, + ContextCompat.RECEIVER_NOT_EXPORTED, + ) } override fun unregister() { diff --git a/vector-app/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt b/vector-app/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt index 4edbdd0591..8c317fc935 100644 --- a/vector-app/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt +++ b/vector-app/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt @@ -21,6 +21,7 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.SharedPreferences +import androidx.core.content.ContextCompat import androidx.core.content.edit import im.vector.app.core.debug.DebugReceiver import im.vector.app.core.di.DefaultPreferences @@ -37,7 +38,12 @@ class VectorDebugReceiver @Inject constructor( ) : BroadcastReceiver(), DebugReceiver { override fun register(context: Context) { - context.registerReceiver(this, getIntentFilter(context)) + ContextCompat.registerReceiver( + context, + this, + getIntentFilter(context), + ContextCompat.RECEIVER_NOT_EXPORTED, + ) } override fun unregister(context: Context) { diff --git a/vector-app/src/main/java/im/vector/app/VectorApplication.kt b/vector-app/src/main/java/im/vector/app/VectorApplication.kt index df1c584b3a..18ea1b91bb 100644 --- a/vector-app/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector-app/src/main/java/im/vector/app/VectorApplication.kt @@ -27,6 +27,7 @@ import android.os.HandlerThread import android.os.StrictMode import android.util.Log import android.view.Gravity +import androidx.core.content.ContextCompat import androidx.core.provider.FontRequest import androidx.core.provider.FontsContractCompat import androidx.lifecycle.DefaultLifecycleObserver @@ -217,13 +218,16 @@ class VectorApplication : ProcessLifecycleOwner.get().lifecycle.addObserver(callManager) // This should be done as early as possible // initKnownEmojiHashSet(appContext) - - applicationContext.registerReceiver(powerKeyReceiver, IntentFilter().apply { - // Looks like i cannot receive OFF, if i don't have both ON and OFF - addAction(Intent.ACTION_SCREEN_OFF) - addAction(Intent.ACTION_SCREEN_ON) - }) - + ContextCompat.registerReceiver( + applicationContext, + powerKeyReceiver, + IntentFilter().apply { + // Looks like i cannot receive OFF, if i don't have both ON and OFF + addAction(Intent.ACTION_SCREEN_OFF) + addAction(Intent.ACTION_SCREEN_ON) + }, + ContextCompat.RECEIVER_NOT_EXPORTED, + ) EmojiManager.install(GoogleEmojiProvider()) // Initialize Mapbox before inflating mapViews diff --git a/vector/src/main/java/im/vector/app/core/services/BluetoothHeadsetReceiver.kt b/vector/src/main/java/im/vector/app/core/services/BluetoothHeadsetReceiver.kt index 4925adf69d..be32bc4c66 100644 --- a/vector/src/main/java/im/vector/app/core/services/BluetoothHeadsetReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/services/BluetoothHeadsetReceiver.kt @@ -23,6 +23,7 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import androidx.core.content.ContextCompat import im.vector.lib.core.utils.compat.getParcelableExtraCompat import java.lang.ref.WeakReference @@ -83,7 +84,12 @@ class BluetoothHeadsetReceiver : BroadcastReceiver() { fun createAndRegister(context: Context, listener: EventListener): BluetoothHeadsetReceiver { val receiver = BluetoothHeadsetReceiver() receiver.delegate = WeakReference(listener) - context.registerReceiver(receiver, IntentFilter(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) + ContextCompat.registerReceiver( + context, + receiver, + IntentFilter(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED), + ContextCompat.RECEIVER_NOT_EXPORTED, + ) return receiver } diff --git a/vector/src/main/java/im/vector/app/core/services/WiredHeadsetStateReceiver.kt b/vector/src/main/java/im/vector/app/core/services/WiredHeadsetStateReceiver.kt index a223352095..416cb43be6 100644 --- a/vector/src/main/java/im/vector/app/core/services/WiredHeadsetStateReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/services/WiredHeadsetStateReceiver.kt @@ -21,6 +21,7 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.media.AudioManager +import androidx.core.content.ContextCompat import timber.log.Timber import java.lang.ref.WeakReference @@ -69,7 +70,12 @@ class WiredHeadsetStateReceiver : BroadcastReceiver() { val receiver = WiredHeadsetStateReceiver() receiver.delegate = WeakReference(listener) val action = AudioManager.ACTION_HEADSET_PLUG - context.registerReceiver(receiver, IntentFilter(action)) + ContextCompat.registerReceiver( + context, + receiver, + IntentFilter(action), + ContextCompat.RECEIVER_NOT_EXPORTED, + ) return receiver } diff --git a/vector/src/main/java/im/vector/app/features/mdm/DefaultMdmService.kt b/vector/src/main/java/im/vector/app/features/mdm/DefaultMdmService.kt index 6633f3ce06..4786341a05 100644 --- a/vector/src/main/java/im/vector/app/features/mdm/DefaultMdmService.kt +++ b/vector/src/main/java/im/vector/app/features/mdm/DefaultMdmService.kt @@ -21,6 +21,7 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.RestrictionsManager +import androidx.core.content.ContextCompat import androidx.core.content.getSystemService import dagger.hilt.android.qualifiers.ApplicationContext import timber.log.Timber @@ -44,7 +45,12 @@ class DefaultMdmService @Inject constructor( override fun registerListener(context: Context, onChangedListener: () -> Unit) { val restrictionsFilter = IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED) this.onChangedListener = onChangedListener - context.registerReceiver(restrictionsReceiver, restrictionsFilter) + ContextCompat.registerReceiver( + context, + restrictionsReceiver, + restrictionsFilter, + ContextCompat.RECEIVER_NOT_EXPORTED + ) } override fun unregisterListener(context: Context) { diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt index 8eb2b66453..32bf92881b 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt @@ -31,6 +31,7 @@ import android.os.Build import android.util.Rational import androidx.annotation.RequiresApi import androidx.core.app.PictureInPictureModeChangedInfo +import androidx.core.content.ContextCompat import androidx.core.util.Consumer import androidx.core.view.isVisible import com.airbnb.mvrx.Mavericks @@ -201,11 +202,12 @@ class WidgetActivity : VectorBaseActivity() { } } } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - registerReceiver(hangupBroadcastReceiver, IntentFilter(ACTION_MEDIA_CONTROL), RECEIVER_NOT_EXPORTED) - } else { - registerReceiver(hangupBroadcastReceiver, IntentFilter(ACTION_MEDIA_CONTROL)) - } + ContextCompat.registerReceiver( + this, + hangupBroadcastReceiver, + IntentFilter(ACTION_MEDIA_CONTROL), + ContextCompat.RECEIVER_NOT_EXPORTED, + ) } else { unregisterReceiver(hangupBroadcastReceiver) } From fa0860ac0f44a45c137e6d1039267c0c2170a5b6 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 18 Jul 2024 17:52:53 +0200 Subject: [PATCH 16/26] Authenticated media : listen db. --- .../sdk/internal/session/SessionModule.kt | 5 +++ .../DefaultIsAuthenticatedMediaSupported.kt | 34 ++++++++++++++----- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt index 54834f4263..d6e1d36b54 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt @@ -83,6 +83,7 @@ import org.matrix.android.sdk.internal.session.events.DefaultEventService import org.matrix.android.sdk.internal.session.homeserver.DefaultHomeServerCapabilitiesService import org.matrix.android.sdk.internal.session.identity.DefaultIdentityService import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationManager +import org.matrix.android.sdk.internal.session.media.DefaultIsAuthenticatedMediaSupported import org.matrix.android.sdk.internal.session.openid.DefaultOpenIdService import org.matrix.android.sdk.internal.session.permalinks.DefaultPermalinkService import org.matrix.android.sdk.internal.session.room.EventRelationsAggregationProcessor @@ -365,6 +366,10 @@ internal abstract class SessionModule { @IntoSet abstract fun bindEventInsertObserver(observer: EventInsertLiveObserver): SessionLifecycleObserver + @Binds + @IntoSet + abstract fun bindIsMediaAuthenticated(observer: DefaultIsAuthenticatedMediaSupported): SessionLifecycleObserver + @Binds @IntoSet abstract fun bindIntegrationManager(manager: IntegrationManager): SessionLifecycleObserver diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/DefaultIsAuthenticatedMediaSupported.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/DefaultIsAuthenticatedMediaSupported.kt index f2884c5cf7..e6f09c9353 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/DefaultIsAuthenticatedMediaSupported.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/DefaultIsAuthenticatedMediaSupported.kt @@ -18,28 +18,44 @@ package org.matrix.android.sdk.internal.session.media import com.zhuinden.monarchy.Monarchy import io.realm.Realm +import io.realm.RealmResults +import org.matrix.android.sdk.internal.database.RealmLiveEntityObserver import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntity -import org.matrix.android.sdk.internal.database.query.get import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.session.SessionScope +import timber.log.Timber import javax.inject.Inject @SessionScope -class DefaultIsAuthenticatedMediaSupported @Inject constructor( +internal class DefaultIsAuthenticatedMediaSupported @Inject constructor( @SessionDatabase private val monarchy: Monarchy, -) : IsAuthenticatedMediaSupported { - - private val canUseAuthenticatedMedia: Boolean by lazy { - canUseAuthenticatedMedia() - } +) : + IsAuthenticatedMediaSupported, + RealmLiveEntityObserver(monarchy.realmConfiguration) { override fun invoke(): Boolean { return canUseAuthenticatedMedia } - private fun canUseAuthenticatedMedia(): Boolean { + override val query = Monarchy.Query { + it.where(HomeServerCapabilitiesEntity::class.java) + } + + override fun onChange(results: RealmResults) { + Timber.d("HomeServerCapabilitiesEntity updated.") + canUseAuthenticatedMedia = results.canUseAuthenticatedMedia() + Timber.d("canUseAuthenticatedMedia: $canUseAuthenticatedMedia") + } + + private var canUseAuthenticatedMedia = getInitialValue() + + private fun getInitialValue(): Boolean { return Realm.getInstance(monarchy.realmConfiguration).use { realm -> - HomeServerCapabilitiesEntity.get(realm)?.canUseAuthenticatedMedia ?: false + query.createQuery(realm).findAll().canUseAuthenticatedMedia() } } + + private fun RealmResults.canUseAuthenticatedMedia(): Boolean { + return firstOrNull()?.canUseAuthenticatedMedia ?: false + } } From d10e83bb486eaf030ab89431a8e968f7ac858639 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 19 Jul 2024 10:25:45 +0200 Subject: [PATCH 17/26] Authenticated media : fix formatting. --- .../internal/session/homeserver/GetHomeServerCapabilitiesTask.kt | 1 - .../src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt | 1 - .../java/im/vector/app/core/glide/AuthenticatedGlideUrlLoader.kt | 1 - .../im/vector/app/core/glide/ImageContentRendererDataLoader.kt | 1 - 4 files changed, 4 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt index 5e58443516..2a74cdf198 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt @@ -41,7 +41,6 @@ import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationManagerConfigExtractor import org.matrix.android.sdk.internal.session.media.GetMediaConfigResult import org.matrix.android.sdk.internal.session.media.MediaAPIProvider -import org.matrix.android.sdk.internal.session.media.UnauthenticatedMediaAPI import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction import org.matrix.android.sdk.internal.wellknown.GetWellknownTask diff --git a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt index 77135eed23..ca839dff42 100644 --- a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt +++ b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt @@ -16,7 +16,6 @@ package im.vector.app.core.di -import android.content.Context import im.vector.app.ActiveSessionDataSource import im.vector.app.core.dispatchers.CoroutineDispatchers import im.vector.app.core.pushers.UnregisterUnifiedPushUseCase diff --git a/vector/src/main/java/im/vector/app/core/glide/AuthenticatedGlideUrlLoader.kt b/vector/src/main/java/im/vector/app/core/glide/AuthenticatedGlideUrlLoader.kt index f56d6e0b60..4b1300b062 100644 --- a/vector/src/main/java/im/vector/app/core/glide/AuthenticatedGlideUrlLoader.kt +++ b/vector/src/main/java/im/vector/app/core/glide/AuthenticatedGlideUrlLoader.kt @@ -65,4 +65,3 @@ class AuthenticatedGlideUrlLoader( return ModelLoader.LoadData(model, fetcher) } } - diff --git a/vector/src/main/java/im/vector/app/core/glide/ImageContentRendererDataLoader.kt b/vector/src/main/java/im/vector/app/core/glide/ImageContentRendererDataLoader.kt index 6936a46d57..521eb08385 100644 --- a/vector/src/main/java/im/vector/app/core/glide/ImageContentRendererDataLoader.kt +++ b/vector/src/main/java/im/vector/app/core/glide/ImageContentRendererDataLoader.kt @@ -32,7 +32,6 @@ import im.vector.app.features.session.coroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import okhttp3.OkHttpClient import timber.log.Timber import java.io.IOException import java.io.InputStream From 669a80e8e4d0a3e470bbb21ef36ab7339f563146 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 19 Jul 2024 12:35:47 +0200 Subject: [PATCH 18/26] Update Realm gradle plugin and Flipper dependencies. --- dependencies.gradle | 2 +- matrix-sdk-android/build.gradle | 2 +- vector-app/build.gradle | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 14077987b2..0f18443f22 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -19,7 +19,7 @@ def markwon = "4.6.2" def moshi = "1.15.1" def lifecycle = "2.8.3" def flowBinding = "1.2.0" -def flipper = "0.190.0" +def flipper = "0.259.0" def epoxy = "5.0.0" def mavericks = "3.0.9" def glide = "4.16.0" diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 5d1a9f1497..78f4a6d179 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.16.0" + classpath "io.realm:realm-gradle-plugin:10.18.0" } } diff --git a/vector-app/build.gradle b/vector-app/build.gradle index b22dae7710..157e8eb0ff 100644 --- a/vector-app/build.gradle +++ b/vector-app/build.gradle @@ -399,7 +399,7 @@ dependencies { exclude group: 'com.facebook.fbjni', module: 'fbjni' } debugImplementation 'com.facebook.soloader:soloader:0.10.5' - debugImplementation "com.kgurgul.flipper:flipper-realm-android:2.2.0" + debugImplementation "com.kgurgul.flipper:flipper-realm-android:2.3.0" gplayImplementation "com.google.android.gms:play-services-location:21.3.0" // UnifiedPush gplay flavor only From 497f422b2b6c0ebc62d87115a6691c5956491890 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 19 Jul 2024 12:56:58 +0200 Subject: [PATCH 19/26] Authenticated media : fix pr remarks --- .../GetHomeServerCapabilitiesTask.kt | 23 ++++++++++++------- .../DefaultIsAuthenticatedMediaSupported.kt | 1 - .../session/media/GetRawPreviewUrlTask.kt | 4 ++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt index 2a74cdf198..5314237c3c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt @@ -20,6 +20,7 @@ import com.zhuinden.monarchy.Monarchy import org.matrix.android.sdk.api.MatrixPatterns.getServerName import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig import org.matrix.android.sdk.api.auth.wellknown.WellknownResult +import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.orTrue import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities import org.matrix.android.sdk.internal.auth.version.Versions @@ -39,8 +40,9 @@ import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationManagerConfigExtractor +import org.matrix.android.sdk.internal.session.media.AuthenticatedMediaAPI import org.matrix.android.sdk.internal.session.media.GetMediaConfigResult -import org.matrix.android.sdk.internal.session.media.MediaAPIProvider +import org.matrix.android.sdk.internal.session.media.UnauthenticatedMediaAPI import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction import org.matrix.android.sdk.internal.wellknown.GetWellknownTask @@ -56,7 +58,8 @@ internal interface GetHomeServerCapabilitiesTask : Task) { - Timber.d("HomeServerCapabilitiesEntity updated.") canUseAuthenticatedMedia = results.canUseAuthenticatedMedia() Timber.d("canUseAuthenticatedMedia: $canUseAuthenticatedMedia") } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetRawPreviewUrlTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetRawPreviewUrlTask.kt index 631d2fe6aa..bf0953522b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetRawPreviewUrlTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetRawPreviewUrlTask.kt @@ -30,13 +30,13 @@ internal interface GetRawPreviewUrlTask : Task Date: Fri, 19 Jul 2024 14:08:23 +0200 Subject: [PATCH 20/26] Fix copyrights. --- .../sdk/internal/database/migration/MigrateSessionTo056.kt | 2 +- .../android/sdk/internal/session/media/AuthenticatedMediaAPI.kt | 2 +- .../session/media/DefaultIsAuthenticatedMediaSupported.kt | 2 +- .../sdk/internal/session/media/IsAuthenticatedMediaSupported.kt | 2 +- .../org/matrix/android/sdk/internal/session/media/MediaAPI.kt | 2 +- .../android/sdk/internal/session/media/MediaAPIProvider.kt | 2 +- .../sdk/internal/session/media/UnauthenticatedMediaAPI.kt | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo056.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo056.kt index 258649bf85..dd345b7183 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo056.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo056.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 New Vector Ltd + * Copyright (c) 2024 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/AuthenticatedMediaAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/AuthenticatedMediaAPI.kt index baeb309cff..417d97abba 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/AuthenticatedMediaAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/AuthenticatedMediaAPI.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 New Vector Ltd + * Copyright (C) 2024 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/DefaultIsAuthenticatedMediaSupported.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/DefaultIsAuthenticatedMediaSupported.kt index c4ea7fabaf..90b9d1ff88 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/DefaultIsAuthenticatedMediaSupported.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/DefaultIsAuthenticatedMediaSupported.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 New Vector Ltd + * Copyright (C) 2024 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/IsAuthenticatedMediaSupported.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/IsAuthenticatedMediaSupported.kt index 825f6577fb..f1dad68fe5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/IsAuthenticatedMediaSupported.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/IsAuthenticatedMediaSupported.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 New Vector Ltd + * Copyright (C) 2024 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/MediaAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/MediaAPI.kt index abc251797d..7b2e71aee3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/MediaAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/MediaAPI.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 New Vector Ltd + * Copyright (C) 2024 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/MediaAPIProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/MediaAPIProvider.kt index 45b20165f7..8f8a5e6a5e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/MediaAPIProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/MediaAPIProvider.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 New Vector Ltd + * Copyright (C) 2024 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/UnauthenticatedMediaAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/UnauthenticatedMediaAPI.kt index 73dfdcb9c9..66bf784551 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/UnauthenticatedMediaAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/UnauthenticatedMediaAPI.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (C) 2024 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 91897d6bb674128211786bd9ee061be1f0da49b9 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 25 Jul 2024 11:36:16 +0200 Subject: [PATCH 21/26] Changelog for version 1.6.20 --- CHANGES.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index e3e7f46744..587f2d61c2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,11 @@ +Changes in Element v1.6.20 (2024-07-25) +======================================= + +Other changes +------------- +- Bump compile and target SDK to 34 ([#8860](https://github.com/element-hq/element-android/pull/8860) +- Supports Authenticated media apis ([#8868](https://github.com/element-hq/element-android/pull/8868) + Changes in Element v1.6.18 (2024-06-25) ======================================= From d0d05d543e5b80a23eef0214ce0e946796a334bd Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 25 Jul 2024 11:36:54 +0200 Subject: [PATCH 22/26] Adding fastlane file for version 1.6.20 --- fastlane/metadata/android/en-US/changelogs/40106200.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/40106200.txt diff --git a/fastlane/metadata/android/en-US/changelogs/40106200.txt b/fastlane/metadata/android/en-US/changelogs/40106200.txt new file mode 100644 index 0000000000..94ce8581ca --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40106200.txt @@ -0,0 +1,2 @@ +Main changes in this version: support authenticated media. +Full changelog: https://github.com/element-hq/element-android/releases \ No newline at end of file From 986f817964a2f05f8c6355982b45aca979dcf064 Mon Sep 17 00:00:00 2001 From: Yoan Pintas Date: Tue, 30 Jul 2024 15:26:29 +0200 Subject: [PATCH 23/26] Fix avatar size in pill (#1084) --- changelog.d/1082.bugfix | 1 + .../src/main/res/values-fr/strings.xml | 2 +- .../internal/session/content/FileUploader.kt | 34 +++++++++++++++++++ .../app/features/home/AvatarRenderer.kt | 10 +++--- .../vector/app/features/html/PillImageSpan.kt | 5 +-- 5 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 changelog.d/1082.bugfix diff --git a/changelog.d/1082.bugfix b/changelog.d/1082.bugfix new file mode 100644 index 0000000000..bd979c8c86 --- /dev/null +++ b/changelog.d/1082.bugfix @@ -0,0 +1 @@ +Correction du crash lorsque l'image de l'avatar d'un membre est trop grande. \ No newline at end of file diff --git a/library/ui-strings/src/main/res/values-fr/strings.xml b/library/ui-strings/src/main/res/values-fr/strings.xml index 7c88b18119..f361a2ed95 100644 --- a/library/ui-strings/src/main/res/values-fr/strings.xml +++ b/library/ui-strings/src/main/res/values-fr/strings.xml @@ -2013,7 +2013,7 @@ Assurez-vous que les bonnes personnes ont accès à %s. Avec qui travaillez-vous \? Pour rejoindre un espace existant, il vous faut une invitation. - Le fichier est trop volumineux pour être envoyé. + Le fichier est trop volumineux ou l’image est trop grande pour être envoyée. Compression de la vidéo %d %% Compression de l’image… Utiliser par défaut et ne plus demander diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt index eee55735e0..f14d4914ee 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt @@ -17,6 +17,8 @@ package org.matrix.android.sdk.internal.session.content import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory import android.net.Uri import com.squareup.moshi.Moshi import kotlinx.coroutines.Dispatchers @@ -37,12 +39,14 @@ import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.api.session.content.ContentUrlResolver import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService +import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeImage import org.matrix.android.sdk.internal.di.Authenticated import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.ProgressRequestBody import org.matrix.android.sdk.internal.network.awaitResponse import org.matrix.android.sdk.internal.network.toFailure import org.matrix.android.sdk.internal.util.TemporaryFileCreator +import timber.log.Timber import java.io.File import java.io.FileNotFoundException import java.io.IOException @@ -70,6 +74,7 @@ internal class FileUploader @Inject constructor( ): ContentUploadResponse { // Check size limit val maxUploadFileSize = homeServerCapabilitiesService.getHomeServerCapabilities().maxUploadFileSize + val maxImageSize = 32_000_000 if (maxUploadFileSize != HomeServerCapabilities.MAX_UPLOAD_FILE_SIZE_UNKNOWN && file.length() > maxUploadFileSize) { @@ -83,6 +88,24 @@ internal class FileUploader @Inject constructor( ) } + // TCHAP Check image size limit + if (mimeType.isMimeTypeImage()) { + BitmapFactory.Options().run { + inJustDecodeBounds = true + decodeBitmap(file, this) + if (outHeight * outWidth > maxImageSize) { + // Known limitation and image size too big for the server, save the pain to upload it + throw Failure.ServerError( + error = MatrixError( + code = MatrixError.M_TOO_LARGE, + message = "Cannot upload images larger than ${maxImageSize / 1_000_000} Megapixels" + ), + httpCode = 413 + ) + } + } + } + val uploadBody = object : RequestBody() { override fun contentLength() = file.length() @@ -135,6 +158,17 @@ internal class FileUploader @Inject constructor( } } + private fun decodeBitmap(file: File, options: BitmapFactory.Options = BitmapFactory.Options()): Bitmap? { + return try { + file.inputStream().use { inputStream -> + BitmapFactory.decodeStream(inputStream, null, options) + } + } catch (e: Exception) { + Timber.e(e, "Cannot decode Bitmap") + null + } + } + private suspend fun upload( uploadBody: RequestBody, filename: String?, diff --git a/vector/src/main/java/im/vector/app/features/home/AvatarRenderer.kt b/vector/src/main/java/im/vector/app/features/home/AvatarRenderer.kt index 7f142cf117..ffd5a4849c 100644 --- a/vector/src/main/java/im/vector/app/features/home/AvatarRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/home/AvatarRenderer.kt @@ -162,7 +162,8 @@ class AvatarRenderer @Inject constructor( fun render( glideRequests: GlideRequests, matrixItem: MatrixItem, - target: Target + target: Target, + maxPxSize: Int = 0 ) { val placeholder = getPlaceholderDrawable(matrixItem) glideRequests.loadResolvedUrl(matrixItem.avatarUrl) @@ -172,7 +173,8 @@ class AvatarRenderer @Inject constructor( it.transform(MultiTransformation(CenterCrop(), RoundedCorners(dimensionConverter.dpToPx(8)))) } else -> { - it.apply(RequestOptions.circleCropTransform()) + // TCHAP Fix avatar sizing + it.apply(RequestOptions.circleCropTransform().override(maxPxSize, maxPxSize)) } } } @@ -264,10 +266,10 @@ class AvatarRenderer @Inject constructor( } @AnyThread - fun getCachedDrawable(glideRequests: GlideRequests, matrixItem: MatrixItem): Drawable { + fun getCachedDrawable(glideRequests: GlideRequests, matrixItem: MatrixItem, maxPxSize: Int = 0): Drawable { return glideRequests.loadResolvedUrl(matrixItem.avatarUrl) .onlyRetrieveFromCache(true) - .apply(RequestOptions.circleCropTransform()) + .apply(RequestOptions.circleCropTransform().override(maxPxSize, maxPxSize)) // TCHAP Fix avatar sizing .submit() .get() } diff --git a/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt b/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt index 95592e564f..390804ba81 100644 --- a/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt +++ b/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt @@ -57,6 +57,7 @@ class PillImageSpan( override val matrixItem: MatrixItem ) : ReplacementSpan(), MatrixItemSpan { + private val maxPxSize = context.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.pill_avatar_size) private val pillDrawable = createChipDrawable() private val target = PillImageSpanTarget(this) private var tv: WeakReference? = null @@ -64,7 +65,7 @@ class PillImageSpan( @UiThread fun bind(textView: TextView) { tv = WeakReference(textView) - avatarRenderer.render(glideRequests, matrixItem, target) + avatarRenderer.render(glideRequests, matrixItem, target, maxPxSize) // TCHAP Fix avatar sizing } // ReplacementSpan ***************************************************************************** @@ -144,7 +145,7 @@ class PillImageSpan( } else -> { try { - avatarRenderer.getCachedDrawable(glideRequests, matrixItem) + avatarRenderer.getCachedDrawable(glideRequests, matrixItem, maxPxSize) // TCHAP Fix avatar sizing } catch (exception: Exception) { avatarRenderer.getPlaceholderDrawable(matrixItem) } From 91338545e3046371148fd3db84397f507631c44d Mon Sep 17 00:00:00 2001 From: Yoan Pintas Date: Wed, 31 Jul 2024 12:00:57 +0200 Subject: [PATCH 24/26] Restore code from Element to fix the crash on Android 5 and 6 (#1089) --- changelog.d/1088.bugfix | 1 + .../app/features/analytics/DecryptionFailureTracker.kt | 9 +++++---- .../analytics/ReportedDecryptionFailurePersistence.kt | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 changelog.d/1088.bugfix diff --git a/changelog.d/1088.bugfix b/changelog.d/1088.bugfix new file mode 100644 index 0000000000..c9f6423cad --- /dev/null +++ b/changelog.d/1088.bugfix @@ -0,0 +1 @@ +Correction du crash au lancement de l'application sur Android 5 et 6. \ No newline at end of file diff --git a/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt b/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt index 5ec7b6a63c..ed77690d1b 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt @@ -104,7 +104,7 @@ class DecryptionFailureTracker @Inject constructor( fun stop() { Timber.v("Stop DecryptionFailureTracker") post { - decryptionFailurePersistence.persist() + decryptionFailurePersistence.persist() } activeSessionSourceDisposable.cancel(CancellationException("Closing DecryptionFailureTracker")) @@ -136,8 +136,9 @@ class DecryptionFailureTracker @Inject constructor( } } } + private fun observeActiveSession() { - activeSessionSourceDisposable = sessionDataSource.stream() + activeSessionSourceDisposable = sessionDataSource.stream() .distinctUntilChanged() .onEach { Timber.v("Active session changed ${it.getOrNull()?.myUserId}") @@ -213,7 +214,7 @@ class DecryptionFailureTracker @Inject constructor( } val isOwnIdentityTrusted = session.cryptoService().crossSigningService().isCrossSigningVerified() val userHS = MatrixPatterns.extractServerNameFromId(session.myUserId) - val messageSenderHs = event.senderId?.let { MatrixPatterns.extractServerNameFromId(it) } + val messageSenderHs = event.senderId?.let { MatrixPatterns.extractServerNameFromId(it) } Timber.v("senderHs: $messageSenderHs, userHS: $userHS, isOwnIdentityTrusted: $isOwnIdentityTrusted") val deviceCreationTs = session.cryptoService().getMyCryptoDevice().firstTimeSeenLocalTs @@ -264,7 +265,7 @@ class DecryptionFailureTracker @Inject constructor( } } - fun utdDisplayedInTimeline(event: TimelineEvent) { + fun utdDisplayedInTimeline(event: TimelineEvent) { post { // should be tracked (unless already reported) val eventId = event.root.eventId ?: return@post diff --git a/vector/src/main/java/im/vector/app/features/analytics/ReportedDecryptionFailurePersistence.kt b/vector/src/main/java/im/vector/app/features/analytics/ReportedDecryptionFailurePersistence.kt index 8516e3621c..731c6f33d2 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/ReportedDecryptionFailurePersistence.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/ReportedDecryptionFailurePersistence.kt @@ -18,10 +18,10 @@ package im.vector.app.features.analytics import android.content.Context import android.util.LruCache +import com.google.common.hash.BloomFilter +import com.google.common.hash.Funnels import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import org.checkerframework.com.google.common.hash.BloomFilter -import org.checkerframework.com.google.common.hash.Funnels import timber.log.Timber import java.io.File import java.io.FileOutputStream From 91ffd8b1f161bf70eb221968e36dcbd4393aeddf Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 30 Jul 2024 15:21:42 +0200 Subject: [PATCH 25/26] Hide visio item --- .../vector/app/features/home/room/detail/TimelineViewModel.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt index 349ddebccf..2072f4f847 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt @@ -865,8 +865,7 @@ class TimelineViewModel @AssistedInject constructor( R.id.open_matrix_apps -> false // TCHAP there are no matrix apps R.id.voice_call -> state.isCallOptionAvailable() || state.hasActiveElementCallWidget() // TCHAP check if visio is enabled - R.id.video_call -> vectorFeatures.tchapIsVisioSupported(session.sessionParams.homeServerUrl) && - (state.isCallOptionAvailable() || state.jitsiState.confId == null || state.jitsiState.hasJoined) + R.id.video_call -> vectorFeatures.tchapIsVisioSupported(session.sessionParams.homeServerUrl) && state.isCallOptionAvailable() // Show Join conference button only if there is an active conf id not joined. Otherwise fallback to default video disabled. ^ R.id.join_conference -> vectorFeatures.tchapIsVisioSupported(session.sessionParams.homeServerUrl) && !state.isCallOptionAvailable() && state.jitsiState.confId != null && !state.jitsiState.hasJoined From 843b4139a0c2bf7b9ffc930e3411affee8d69f47 Mon Sep 17 00:00:00 2001 From: yostyle Date: Wed, 31 Jul 2024 20:02:34 +0200 Subject: [PATCH 26/26] Update changelog --- TCHAP_CHANGES.md | 12 ++++++++++++ changelog.d/1081.improvements | 1 - changelog.d/1082.bugfix | 1 - changelog.d/1088.bugfix | 1 - towncrier.toml | 2 +- 5 files changed, 13 insertions(+), 4 deletions(-) delete mode 100644 changelog.d/1081.improvements delete mode 100644 changelog.d/1082.bugfix delete mode 100644 changelog.d/1088.bugfix diff --git a/TCHAP_CHANGES.md b/TCHAP_CHANGES.md index e6741a9641..37038e3b05 100644 --- a/TCHAP_CHANGES.md +++ b/TCHAP_CHANGES.md @@ -1,3 +1,15 @@ +Changes in Tchap 2.13.1 (2024-07-31) +==================================== + +Improvements 🙌 +-------------- + - Rebase against Element-Android v1.6.20 ([#1081](https://github.com/tchapgouv/tchap-android/issues/1081)) + +Bugfixes 🐛 +---------- + - Correction du crash lorsque l'image de l'avatar d'un membre est trop grande. ([#1082](https://github.com/tchapgouv/tchap-android/issues/1082)) + - Correction du crash au lancement de l'application sur Android 5 et 6. ([#1088](https://github.com/tchapgouv/tchap-android/issues/1088)) + Changes in Tchap 2.13.0 (2024-07-25) ==================================== diff --git a/changelog.d/1081.improvements b/changelog.d/1081.improvements deleted file mode 100644 index 730d7232b6..0000000000 --- a/changelog.d/1081.improvements +++ /dev/null @@ -1 +0,0 @@ -Rebase against Element-Android v1.6.20 \ No newline at end of file diff --git a/changelog.d/1082.bugfix b/changelog.d/1082.bugfix deleted file mode 100644 index bd979c8c86..0000000000 --- a/changelog.d/1082.bugfix +++ /dev/null @@ -1 +0,0 @@ -Correction du crash lorsque l'image de l'avatar d'un membre est trop grande. \ No newline at end of file diff --git a/changelog.d/1088.bugfix b/changelog.d/1088.bugfix deleted file mode 100644 index c9f6423cad..0000000000 --- a/changelog.d/1088.bugfix +++ /dev/null @@ -1 +0,0 @@ -Correction du crash au lancement de l'application sur Android 5 et 6. \ No newline at end of file diff --git a/towncrier.toml b/towncrier.toml index 77802943a1..dda34dc633 100644 --- a/towncrier.toml +++ b/towncrier.toml @@ -1,5 +1,5 @@ [tool.towncrier] - version = "2.13.0" + version = "2.13.1" directory = "changelog.d" filename = "TCHAP_CHANGES.md" name = "Changes in Tchap"