diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 1c0491fda4..933c442501 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -7,10 +7,8 @@ on:
# Enrich gradle.properties for CI/CD
env:
- CI_GRADLE_ARG_PROPERTIES: >
- -Porg.gradle.jvmargs=-Xmx4g
- -Porg.gradle.parallel=false
- --no-daemon
+ GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
+ CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
jobs:
debug:
@@ -36,7 +34,7 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-
- name: Assemble ${{ matrix.target }} debug apk
- run: ./gradlew assemble${{ matrix.target }}Debug $CI_GRADLE_ARG_PROPERTIES --stacktrace
+ run: ./gradlew assemble${{ matrix.target }}Debug $CI_GRADLE_ARG_PROPERTIES
- name: Upload ${{ matrix.target }} debug APKs
uses: actions/upload-artifact@v3
with:
@@ -61,7 +59,7 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-
- name: Assemble GPlay unsigned apk
- run: ./gradlew clean assembleGplayRelease $CI_GRADLE_ARG_PROPERTIES --stacktrace
+ run: ./gradlew clean assembleGplayRelease $CI_GRADLE_ARG_PROPERTIES
- name: Upload Gplay unsigned APKs
uses: actions/upload-artifact@v3
with:
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index 36fd225674..51c1b32e82 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -6,10 +6,8 @@ on:
- cron: "0 4 * * *"
env:
- CI_GRADLE_ARG_PROPERTIES: >
- -Porg.gradle.jvmargs=-Xmx4g
- -Porg.gradle.parallel=false
- --no-daemon
+ GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
+ CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
jobs:
nightly:
@@ -40,7 +38,7 @@ jobs:
yes n | towncrier build --version nightly
- name: Build and upload Gplay Nightly APK
run: |
- ./gradlew assembleGplayNightly appDistributionUploadGplayNightly $CI_GRADLE_ARG_PROPERTIES --stacktrace
+ ./gradlew assembleGplayNightly appDistributionUploadGplayNightly $CI_GRADLE_ARG_PROPERTIES
env:
ELEMENT_ANDROID_NIGHTLY_KEYID: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_KEYID }}
ELEMENT_ANDROID_NIGHTLY_KEYPASSWORD: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_KEYPASSWORD }}
diff --git a/.github/workflows/post-pr.yml b/.github/workflows/post-pr.yml
index a7f1d6f204..5cde95e625 100644
--- a/.github/workflows/post-pr.yml
+++ b/.github/workflows/post-pr.yml
@@ -10,10 +10,8 @@ on:
# Enrich gradle.properties for CI/CD
env:
- CI_GRADLE_ARG_PROPERTIES: >
- -Porg.gradle.jvmargs=-Xmx4g
- -Porg.gradle.parallel=false
- --no-daemon
+ GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
+ CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
jobs:
diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml
index 56a7c8b97b..6e5e2e4d67 100644
--- a/.github/workflows/quality.yml
+++ b/.github/workflows/quality.yml
@@ -7,10 +7,8 @@ on:
# Enrich gradle.properties for CI/CD
env:
- CI_GRADLE_ARG_PROPERTIES: >
- -Porg.gradle.jvmargs=-Xmx4g
- -Porg.gradle.parallel=false
- --no-daemon
+ GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
+ CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
jobs:
check:
@@ -51,8 +49,8 @@ jobs:
- name: Run lint
# Not always, if ktlint or detekt fail, avoid running the long lint check.
run: |
- ./gradlew lintGplayRelease --stacktrace $CI_GRADLE_ARG_PROPERTIES
- ./gradlew lintFdroidRelease --stacktrace $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew lintGplayRelease $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew lintFdroidRelease $CI_GRADLE_ARG_PROPERTIES
- name: Upload reports
if: always()
uses: actions/upload-artifact@v3
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 2b9aa1a851..2a89ed3040 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -7,10 +7,8 @@ on:
# Enrich gradle.properties for CI/CD
env:
- CI_GRADLE_ARG_PROPERTIES: >
- -Porg.gradle.jvmargs=-Xmx4g
- -Porg.gradle.parallel=false
- --no-daemon
+ GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
+ CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
jobs:
tests:
@@ -51,9 +49,9 @@ jobs:
disable-animations: true
emulator-build: 7425822
script: |
- ./gradlew unitTestsWithCoverage --stacktrace $CI_GRADLE_ARG_PROPERTIES
- ./gradlew instrumentationTestsWithCoverage --stacktrace $CI_GRADLE_ARG_PROPERTIES
- ./gradlew generateCoverageReport --stacktrace $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES
# NB: continue-on-error marks steps.tests.conclusion = 'success' but leaves stes.tests.outcome = 'failure'
- name: Run all the codecoverage tests at once (retry if emulator failed)
uses: reactivecircus/android-emulator-runner@v2
@@ -67,9 +65,9 @@ jobs:
disable-animations: true
emulator-build: 7425822
script: |
- ./gradlew unitTestsWithCoverage --stacktrace $CI_GRADLE_ARG_PROPERTIES
- ./gradlew instrumentationTestsWithCoverage --stacktrace $CI_GRADLE_ARG_PROPERTIES
- ./gradlew generateCoverageReport --stacktrace $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
+ ./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES
- run: ./gradlew sonarqube $CI_GRADLE_ARG_PROPERTIES
if: always() # we may have failed a previous step and retried, that's OK
env:
@@ -114,5 +112,5 @@ jobs:
# restore-keys: |
# ${{ runner.os }}-gradle-
# - name: Build Android Tests
-# run: ./gradlew clean assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES --stacktrace
+# run: ./gradlew clean assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES
diff --git a/changelog.d/6406.misc b/changelog.d/6406.misc
new file mode 100644
index 0000000000..27cf3c6493
--- /dev/null
+++ b/changelog.d/6406.misc
@@ -0,0 +1 @@
+[Modularization] Provides abstraction to avoids direct usages of BuildConfig
diff --git a/changelog.d/6653.misc b/changelog.d/6653.misc
new file mode 100644
index 0000000000..1b5be1b83f
--- /dev/null
+++ b/changelog.d/6653.misc
@@ -0,0 +1 @@
+[Location share] Update minimum sending period to 5 seconds for a live
diff --git a/changelog.d/6678.misc b/changelog.d/6678.misc
new file mode 100644
index 0000000000..a7a53257d8
--- /dev/null
+++ b/changelog.d/6678.misc
@@ -0,0 +1 @@
+[Timeline] Memory leak in audio message playback tracker
diff --git a/changelog.d/6680.misc b/changelog.d/6680.misc
new file mode 100644
index 0000000000..f42160fbba
--- /dev/null
+++ b/changelog.d/6680.misc
@@ -0,0 +1 @@
+[FTUE] Memory leak on FtueAuthSplashCarouselFragment
diff --git a/changelog.d/6711.feature b/changelog.d/6711.feature
new file mode 100644
index 0000000000..cff718affd
--- /dev/null
+++ b/changelog.d/6711.feature
@@ -0,0 +1 @@
+[Location Share] Render fallback UI when map fails to load
diff --git a/changelog.d/6737.bugfix b/changelog.d/6737.bugfix
new file mode 100644
index 0000000000..6568e9ff31
--- /dev/null
+++ b/changelog.d/6737.bugfix
@@ -0,0 +1 @@
+Fixes onboarding login/account creation errors showing after navigation
diff --git a/changelog.d/6739.misc b/changelog.d/6739.misc
new file mode 100644
index 0000000000..5e5de00831
--- /dev/null
+++ b/changelog.d/6739.misc
@@ -0,0 +1 @@
+Link directly to DCO docs from danger message.
diff --git a/docs/nightly_build.md b/docs/nightly_build.md
index 91f18214c4..7750e0466a 100644
--- a/docs/nightly_build.md
+++ b/docs/nightly_build.md
@@ -48,7 +48,7 @@ mv towncrier.toml towncrier.toml.bak
sed 's/CHANGES\.md/CHANGES_NIGHTLY\.md/' towncrier.toml.bak > towncrier.toml
rm towncrier.toml.bak
yes n | towncrier --version nightly
-./gradlew assembleGplayNightly appDistributionUploadGplayNightly $CI_GRADLE_ARG_PROPERTIES --stacktrace
+./gradlew assembleGplayNightly appDistributionUploadGplayNightly $CI_GRADLE_ARG_PROPERTIES
```
Then you can reset the change on the codebase.
diff --git a/library/ui-styles/src/main/res/values/stylable_map_loading_error_view.xml b/library/ui-styles/src/main/res/values/stylable_map_loading_error_view.xml
new file mode 100644
index 0000000000..911167e52a
--- /dev/null
+++ b/library/ui-styles/src/main/res/values/stylable_map_loading_error_view.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle
index fdc6a3ed5e..45a962f12c 100644
--- a/matrix-sdk-android/build.gradle
+++ b/matrix-sdk-android/build.gradle
@@ -199,7 +199,7 @@ dependencies {
implementation libs.apache.commonsImaging
// Phone number https://github.com/google/libphonenumber
- implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.52'
+ implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.53'
testImplementation libs.tests.junit
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
diff --git a/tools/danger/dangerfile.js b/tools/danger/dangerfile.js
index 59a616db4a..4efd236419 100644
--- a/tools/danger/dangerfile.js
+++ b/tools/danger/dangerfile.js
@@ -83,7 +83,7 @@ if (requiresSignOff) {
const hasPRBodySignOff = pr.body.includes(signOff)
const hasCommitSignOff = danger.git.commits.every(commit => commit.message.includes(signOff))
if (!hasPRBodySignOff && !hasCommitSignOff) {
- fail("Please add a sign-off to either the PR description or to the commits themselves.")
+ fail("Please add a sign-off to either the PR description or to the commits themselves. See instructions [here](https://matrix-org.github.io/synapse/latest/development/contributing_guide.html#sign-off).")
}
}
diff --git a/vector-config/src/main/java/im/vector/app/config/Analytics.kt b/vector-config/src/main/java/im/vector/app/config/Analytics.kt
new file mode 100644
index 0000000000..7fdc78dc8a
--- /dev/null
+++ b/vector-config/src/main/java/im/vector/app/config/Analytics.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.config
+
+/**
+ * The types of analytics Element currently supports.
+ */
+sealed interface Analytics {
+
+ /**
+ * Disables the analytics integrations.
+ */
+ object Disabled : Analytics
+
+ /**
+ * Analytics integration via PostHog.
+ */
+ data class PostHog(
+ /**
+ * The PostHog instance url.
+ */
+ val postHogHost: String,
+
+ /**
+ * The PostHog instance API key.
+ */
+ val postHogApiKey: String,
+
+ /**
+ * A URL to more information about the analytics collection.
+ */
+ val policyLink: String,
+ ) : Analytics
+}
diff --git a/vector-config/src/main/java/im/vector/app/config/Config.kt b/vector-config/src/main/java/im/vector/app/config/Config.kt
index 7577e6dba5..f660799d06 100644
--- a/vector-config/src/main/java/im/vector/app/config/Config.kt
+++ b/vector-config/src/main/java/im/vector/app/config/Config.kt
@@ -36,4 +36,57 @@ object Config {
* - Changing the value from `true` to `false` will force the app to return to the background sync / Firebase Push.
*/
const val ALLOW_EXTERNAL_UNIFIED_PUSH_DISTRIBUTORS = true
+
+ const val ENABLE_LOCATION_SHARING = true
+ const val LOCATION_MAP_TILER_KEY = "fU3vlMsMn4Jb6dnEIFsx"
+
+ /**
+ * The maximum length of voice messages in milliseconds.
+ */
+ const val VOICE_MESSAGE_LIMIT_MS = 120_000L
+
+ /**
+ * The strategy for sharing device keys.
+ */
+ val KEY_SHARING_STRATEGY = KeySharingStrategy.WhenTyping
+
+ /**
+ * The onboarding flow.
+ */
+ val ONBOARDING_VARIANT = OnboardingVariant.FTUE_AUTH
+
+ /**
+ * If set, MSC3086 asserted identity messages sent on VoIP calls will cause the call to appear in the room corresponding to the asserted identity.
+ * This *must* only be set in trusted environments.
+ */
+ const val HANDLE_CALL_ASSERTED_IDENTITY_EVENTS = false
+
+ const val LOW_PRIVACY_LOG_ENABLE = false
+ const val ENABLE_STRICT_MODE_LOGS = false
+
+ /**
+ * The analytics configuration to use for the Debug build type.
+ * Can be disabled by providing Analytics.Disabled
+ */
+ val DEBUG_ANALYTICS_CONFIG = Analytics.PostHog(
+ postHogHost = "https://posthog.element.dev",
+ postHogApiKey = "phc_VtA1L35nw3aeAtHIx1ayrGdzGkss7k1xINeXcoIQzXN",
+ policyLink = "https://element.io/cookie-policy",
+ )
+
+ /**
+ * The analytics configuration to use for the Release build type.
+ * Can be disabled by providing Analytics.Disabled
+ */
+ val RELEASE_ANALYTICS_CONFIG = Analytics.PostHog(
+ postHogHost = "https://posthog.hss.element.io",
+ postHogApiKey = "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO",
+ policyLink = "https://element.io/cookie-policy",
+ )
+
+ /**
+ * The analytics configuration to use for the Nightly build type.
+ * Can be disabled by providing Analytics.Disabled
+ */
+ val NIGHTLY_ANALYTICS_CONFIG = RELEASE_ANALYTICS_CONFIG
}
diff --git a/vector/src/release/java/im/vector/app/config/AnalyticsConfig.kt b/vector-config/src/main/java/im/vector/app/config/KeySharingStrategy.kt
similarity index 50%
rename from vector/src/release/java/im/vector/app/config/AnalyticsConfig.kt
rename to vector-config/src/main/java/im/vector/app/config/KeySharingStrategy.kt
index e1427338b2..51f3d81151 100644
--- a/vector/src/release/java/im/vector/app/config/AnalyticsConfig.kt
+++ b/vector-config/src/main/java/im/vector/app/config/KeySharingStrategy.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 New Vector Ltd
+ * Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,17 +16,20 @@
package im.vector.app.config
-import im.vector.app.BuildConfig
-import im.vector.app.features.analytics.AnalyticsConfig
+enum class KeySharingStrategy {
+ /**
+ * Keys will be sent for the first time when the first message is sent.
+ * This is handled by the Matrix SDK so there's no need to do it in Vector.
+ */
+ WhenSendingEvent,
-private val allowedPackageList = listOf(
- "im.vector.app",
- "im.vector.app.nightly",
-)
+ /**
+ * Keys will be sent for the first time when the timeline displayed.
+ */
+ WhenEnteringRoom,
-val analyticsConfig: AnalyticsConfig = object : AnalyticsConfig {
- override val isEnabled = BuildConfig.APPLICATION_ID in allowedPackageList
- override val postHogHost = "https://posthog.hss.element.io"
- override val postHogApiKey = "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO"
- override val policyLink = "https://element.io/cookie-policy"
+ /**
+ * Keys will be sent for the first time when a typing started.
+ */
+ WhenTyping
}
diff --git a/vector-config/src/main/java/im/vector/app/config/OnboardingVariant.kt b/vector-config/src/main/java/im/vector/app/config/OnboardingVariant.kt
new file mode 100644
index 0000000000..ae8cfd1172
--- /dev/null
+++ b/vector-config/src/main/java/im/vector/app/config/OnboardingVariant.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.config
+
+enum class OnboardingVariant {
+ LEGACY,
+ LOGIN_2,
+ FTUE_AUTH
+}
diff --git a/vector/build.gradle b/vector/build.gradle
index 0b7973a148..dc0a2da35d 100644
--- a/vector/build.gradle
+++ b/vector/build.gradle
@@ -156,19 +156,6 @@ android {
buildConfigField "String", "GIT_BRANCH_NAME", "\"${gitBranchName()}\""
buildConfigField "String", "BUILD_NUMBER", "\"${buildNumber}\""
- buildConfigField "im.vector.app.features.VectorFeatures.OnboardingVariant", "ONBOARDING_VARIANT", "im.vector.app.features.VectorFeatures.OnboardingVariant.FTUE_AUTH"
-
- buildConfigField "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy", "outboundSessionKeySharingStrategy", "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy.WhenTyping"
-
- buildConfigField "Long", "VOICE_MESSAGE_DURATION_LIMIT_MS", "120_000L"
-
- // If set, MSC3086 asserted identity messages sent on VoIP calls will cause the call to appear in the room corresponding to the asserted identity.
- // This *must* only be set in trusted environments.
- buildConfigField "Boolean", "handleCallAssertedIdentityEvents", "false"
-
- buildConfigField "Boolean", "enableLocationSharing", "true"
- buildConfigField "String", "mapTilerKey", "\"fU3vlMsMn4Jb6dnEIFsx\""
-
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// Keep abiFilter for the universalApk
@@ -250,10 +237,6 @@ android {
resValue "string", "app_name", "Element dbg"
resValue "color", "launcher_background", "#0DBD8B"
- buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false"
- // Set to true if you want to enable strict mode in debug
- buildConfigField "boolean", "ENABLE_STRICT_MODE_LOGS", "false"
-
signingConfig signingConfigs.debug
if (project.hasProperty("coverage")) {
@@ -265,10 +248,6 @@ android {
resValue "string", "app_name", "Element"
resValue "color", "launcher_background", "#0DBD8B"
- buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false"
- buildConfigField "boolean", "ENABLE_STRICT_MODE_LOGS", "false"
-
- // When updating this block, please also update the same block in the `nightly` buildType below
postprocessing {
removeUnusedCode true
removeUnusedResources true
@@ -329,7 +308,6 @@ android {
versionName "${versionMajor}.${versionMinor}.${versionPatch}${getGplayVersionSuffix()}"
resValue "bool", "isGplay", "true"
- buildConfigField "boolean", "ALLOW_FCM_USE", "true"
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\""
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\""
}
@@ -340,7 +318,6 @@ android {
versionName "${versionMajor}.${versionMinor}.${versionPatch}${getFdroidVersionSuffix()}"
resValue "bool", "isGplay", "false"
- buildConfigField "boolean", "ALLOW_FCM_USE", "false"
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\""
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\""
}
@@ -438,7 +415,7 @@ dependencies {
implementation 'com.facebook.stetho:stetho:1.6.0'
// Phone number https://github.com/google/libphonenumber
- implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.52'
+ implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.53'
// FlowBinding
implementation libs.github.flowBinding
diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt b/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt
index 8fe65bd387..d7e402c4dc 100644
--- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt
+++ b/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt
@@ -70,6 +70,11 @@ class DebugFeaturesStateFactory @Inject constructor(
key = DebugFeatureKeys.allowExternalUnifiedPushDistributors,
factory = VectorFeatures::allowExternalUnifiedPushDistributors
),
+ createBooleanFeature(
+ label = "Enable Live Location Sharing",
+ key = DebugFeatureKeys.liveLocationSharing,
+ factory = VectorFeatures::isLocationSharingEnabled
+ ),
createBooleanFeature(
label = "Force usage of OpusEncoder library",
key = DebugFeatureKeys.forceUsageOfOpusEncoder,
diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt b/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt
index 23aad65653..031ff11d59 100644
--- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt
+++ b/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt
@@ -24,6 +24,7 @@ import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
+import im.vector.app.config.OnboardingVariant
import im.vector.app.features.DefaultVectorFeatures
import im.vector.app.features.VectorFeatures
import kotlinx.coroutines.flow.first
@@ -39,8 +40,8 @@ class DebugVectorFeatures(
private val dataStore = context.dataStore
- override fun onboardingVariant(): VectorFeatures.OnboardingVariant {
- return readPreferences().getEnum() ?: vectorFeatures.onboardingVariant()
+ override fun onboardingVariant(): OnboardingVariant {
+ return readPreferences().getEnum() ?: vectorFeatures.onboardingVariant()
}
override fun isOnboardingAlreadyHaveAccountSplashEnabled(): Boolean = read(DebugFeatureKeys.onboardingAlreadyHaveAnAccount)
@@ -66,6 +67,9 @@ class DebugVectorFeatures(
override fun isScreenSharingEnabled(): Boolean = read(DebugFeatureKeys.screenSharing)
?: vectorFeatures.isScreenSharingEnabled()
+ override fun isLocationSharingEnabled(): Boolean = read(DebugFeatureKeys.liveLocationSharing)
+ ?: vectorFeatures.isLocationSharingEnabled()
+
override fun forceUsageOfOpusEncoder(): Boolean = read(DebugFeatureKeys.forceUsageOfOpusEncoder)
?: vectorFeatures.forceUsageOfOpusEncoder()
diff --git a/vector/src/main/java/im/vector/app/VectorApplication.kt b/vector/src/main/java/im/vector/app/VectorApplication.kt
index d3dfbf8c4f..b1bd0fc308 100644
--- a/vector/src/main/java/im/vector/app/VectorApplication.kt
+++ b/vector/src/main/java/im/vector/app/VectorApplication.kt
@@ -40,7 +40,9 @@ import com.mapbox.mapboxsdk.Mapbox
import com.vanniktech.emoji.EmojiManager
import com.vanniktech.emoji.google.GoogleEmojiProvider
import dagger.hilt.android.HiltAndroidApp
+import im.vector.app.config.Config
import im.vector.app.core.di.ActiveSessionHolder
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.features.analytics.VectorAnalytics
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.configuration.VectorConfiguration
@@ -99,6 +101,7 @@ class VectorApplication :
@Inject lateinit var flipperProxy: FlipperProxy
@Inject lateinit var matrix: Matrix
@Inject lateinit var fcmHelper: FcmHelper
+ @Inject lateinit var buildMeta: BuildMeta
// font thread handler
private var fontThreadHandler: Handler? = null
@@ -127,12 +130,12 @@ class VectorApplication :
.filterIsInstance(JitsiMeetDefaultLogHandler::class.java)
.forEach { Timber.uproot(it) }
- if (BuildConfig.DEBUG) {
+ if (buildMeta.isDebug) {
Timber.plant(Timber.DebugTree())
}
Timber.plant(vectorFileLogger)
- if (BuildConfig.DEBUG) {
+ if (buildMeta.isDebug) {
Stetho.initializeWithDefaults(this)
}
logInfo()
@@ -148,7 +151,7 @@ class VectorApplication :
R.array.com_google_android_gms_fonts_certs
)
FontsContractCompat.requestFont(this, fontRequest, emojiCompatFontProvider, getFontThreadHandler())
- VectorLocale.init(this)
+ VectorLocale.init(this, buildMeta)
ThemeUtils.init(this)
vectorConfiguration.applyToApplicationContext()
@@ -196,7 +199,7 @@ class VectorApplication :
}
private fun enableStrictModeIfNeeded() {
- if (BuildConfig.ENABLE_STRICT_MODE_LOGS) {
+ if (Config.ENABLE_STRICT_MODE_LOGS) {
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectAll()
diff --git a/vector/src/main/java/im/vector/app/core/di/ConfigurationModule.kt b/vector/src/main/java/im/vector/app/core/di/ConfigurationModule.kt
new file mode 100644
index 0000000000..a75b3fa46b
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/di/ConfigurationModule.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.core.di
+
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import im.vector.app.BuildConfig
+import im.vector.app.config.Analytics
+import im.vector.app.config.Config
+import im.vector.app.config.KeySharingStrategy
+import im.vector.app.features.analytics.AnalyticsConfig
+import im.vector.app.features.call.webrtc.VoipConfig
+import im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy
+import im.vector.app.features.home.room.detail.composer.voice.VoiceMessageConfig
+import im.vector.app.features.location.LocationSharingConfig
+import im.vector.app.features.raw.wellknown.CryptoConfig
+
+@InstallIn(SingletonComponent::class)
+@Module
+object ConfigurationModule {
+
+ @Provides
+ fun providesAnalyticsConfig(): AnalyticsConfig {
+ val config: Analytics = when (BuildConfig.BUILD_TYPE) {
+ "debug" -> Config.DEBUG_ANALYTICS_CONFIG
+ "nightly" -> Config.NIGHTLY_ANALYTICS_CONFIG
+ "release" -> Config.RELEASE_ANALYTICS_CONFIG
+ else -> throw IllegalStateException("Unhandled build type: ${BuildConfig.BUILD_TYPE}")
+ }
+ return when (config) {
+ Analytics.Disabled -> AnalyticsConfig(isEnabled = false, "", "", "")
+ is Analytics.PostHog -> AnalyticsConfig(
+ isEnabled = true,
+ postHogHost = config.postHogHost,
+ postHogApiKey = config.postHogApiKey,
+ policyLink = config.policyLink
+ )
+ }
+ }
+
+ @Provides
+ fun providesVoiceMessageConfig() = VoiceMessageConfig(
+ lengthLimitMs = Config.VOICE_MESSAGE_LIMIT_MS
+ )
+
+ @Provides
+ fun providesCryptoConfig() = CryptoConfig(
+ fallbackKeySharingStrategy = when (Config.KEY_SHARING_STRATEGY) {
+ KeySharingStrategy.WhenSendingEvent -> OutboundSessionKeySharingStrategy.WhenSendingEvent
+ KeySharingStrategy.WhenEnteringRoom -> OutboundSessionKeySharingStrategy.WhenSendingEvent
+ KeySharingStrategy.WhenTyping -> OutboundSessionKeySharingStrategy.WhenSendingEvent
+ }
+ )
+
+ @Provides
+ fun providesLocationSharingConfig() = LocationSharingConfig(
+ mapTilerKey = Config.LOCATION_MAP_TILER_KEY,
+ )
+
+ @Provides
+ fun providesVoipConfig() = VoipConfig(
+ handleCallAssertedIdentityEvents = Config.HANDLE_CALL_ASSERTED_IDENTITY_EVENTS
+ )
+}
diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
index 3cdc8a1afe..e86b350534 100644
--- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
@@ -64,8 +64,8 @@ import im.vector.app.features.home.room.detail.search.SearchFragment
import im.vector.app.features.home.room.list.RoomListFragment
import im.vector.app.features.home.room.list.home.HomeRoomListFragment
import im.vector.app.features.home.room.threads.list.views.ThreadListFragment
-import im.vector.app.features.location.LocationPreviewFragment
import im.vector.app.features.location.LocationSharingFragment
+import im.vector.app.features.location.preview.LocationPreviewFragment
import im.vector.app.features.login.LoginCaptchaFragment
import im.vector.app.features.login.LoginFragment
import im.vector.app.features.login.LoginGenericTextInputFormFragment
diff --git a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt
index 9b511a1bfd..331b4afa18 100644
--- a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt
@@ -56,6 +56,7 @@ import im.vector.app.features.homeserver.HomeServerCapabilitiesViewModel
import im.vector.app.features.invite.InviteUsersToRoomViewModel
import im.vector.app.features.location.LocationSharingViewModel
import im.vector.app.features.location.live.map.LiveLocationMapViewModel
+import im.vector.app.features.location.preview.LocationPreviewViewModel
import im.vector.app.features.login.LoginViewModel
import im.vector.app.features.login2.LoginViewModel2
import im.vector.app.features.login2.created.AccountCreatedViewModel
@@ -605,6 +606,11 @@ interface MavericksViewModelModule {
@MavericksViewModelKey(LocationSharingViewModel::class)
fun createLocationSharingViewModelFactory(factory: LocationSharingViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(LocationPreviewViewModel::class)
+ fun createLocationPreviewViewModelFactory(factory: LocationPreviewViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
@Binds
@IntoMap
@MavericksViewModelKey(VectorAttachmentViewerViewModel::class)
diff --git a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt
index c969df74e4..6959f17586 100644
--- a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt
@@ -33,7 +33,7 @@ import im.vector.app.EmojiCompatWrapper
import im.vector.app.EmojiSpanify
import im.vector.app.SpaceStateHandler
import im.vector.app.SpaceStateHandlerImpl
-import im.vector.app.config.analyticsConfig
+import im.vector.app.config.Config
import im.vector.app.core.dispatchers.CoroutineDispatchers
import im.vector.app.core.error.DefaultErrorFormatter
import im.vector.app.core.error.ErrorFormatter
@@ -42,7 +42,6 @@ import im.vector.app.core.time.Clock
import im.vector.app.core.time.DefaultClock
import im.vector.app.core.utils.AndroidSystemSettingsProvider
import im.vector.app.core.utils.SystemSettingsProvider
-import im.vector.app.features.analytics.AnalyticsConfig
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.VectorAnalytics
import im.vector.app.features.analytics.impl.DefaultVectorAnalytics
@@ -205,17 +204,23 @@ object VectorStaticModule {
return GlobalScope
}
- @Provides
- fun providesAnalyticsConfig(): AnalyticsConfig {
- return analyticsConfig
- }
-
@Provides
fun providesPhoneNumberUtil(): PhoneNumberUtil = PhoneNumberUtil.getInstance()
@Provides
@Singleton
- fun providesBuildMeta() = BuildMeta()
+ fun providesBuildMeta() = BuildMeta(
+ isDebug = BuildConfig.DEBUG,
+ applicationId = BuildConfig.APPLICATION_ID,
+ lowPrivacyLoggingEnabled = Config.LOW_PRIVACY_LOG_ENABLE,
+ versionName = BuildConfig.VERSION_NAME,
+ gitRevision = BuildConfig.GIT_REVISION,
+ gitRevisionDate = BuildConfig.GIT_REVISION_DATE,
+ gitBranchName = BuildConfig.GIT_BRANCH_NAME,
+ buildNumber = BuildConfig.BUILD_NUMBER,
+ flavorDescription = BuildConfig.FLAVOR_DESCRIPTION,
+ flavorShortDescription = BuildConfig.SHORT_FLAVOR_DESCRIPTION,
+ )
@Provides
@Singleton
diff --git a/vector/src/main/java/im/vector/app/core/extensions/Context.kt b/vector/src/main/java/im/vector/app/core/extensions/Context.kt
index 509dd6a862..14e639bf32 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/Context.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/Context.kt
@@ -37,7 +37,7 @@ import androidx.datastore.preferences.core.Preferences
import dagger.hilt.EntryPoints
import im.vector.app.core.datastore.dataStoreProvider
import im.vector.app.core.di.SingletonEntryPoint
-import im.vector.app.core.resources.BuildMeta
+import org.matrix.android.sdk.api.util.BuildVersionSdkIntProvider
import java.io.OutputStream
import kotlin.math.roundToInt
@@ -93,9 +93,9 @@ fun Context.safeOpenOutputStream(uri: Uri): OutputStream? {
*/
@Suppress("deprecation")
@SuppressLint("NewApi") // false positive
-fun Context.inferNoConnectivity(buildMeta: BuildMeta): Boolean {
+fun Context.inferNoConnectivity(sdkIntProvider: BuildVersionSdkIntProvider): Boolean {
val connectivityManager = getSystemService()!!
- return if (buildMeta.sdkInt > Build.VERSION_CODES.M) {
+ return if (sdkIntProvider.get() > Build.VERSION_CODES.M) {
val networkCapabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
when {
networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == true -> false
diff --git a/vector/src/main/java/im/vector/app/core/extensions/TextInputLayout.kt b/vector/src/main/java/im/vector/app/core/extensions/TextInputLayout.kt
index 4739840f01..909c343a45 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/TextInputLayout.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/TextInputLayout.kt
@@ -78,10 +78,14 @@ fun TextInputLayout.setOnImeDoneListener(action: () -> Unit) {
}
}
-fun TextInputLayout.setOnFocusLostListener(action: () -> Unit) {
+/**
+ * Set a listener for when the input has lost focus, such as moving to the another input field.
+ * The listener is only called when the view is in a resumed state to avoid triggers when exiting a screen.
+ */
+fun TextInputLayout.setOnFocusLostListener(lifecycleOwner: LifecycleOwner, action: () -> Unit) {
editText().setOnFocusChangeListener { _, hasFocus ->
when (hasFocus) {
- false -> action()
+ false -> lifecycleOwner.lifecycleScope.launchWhenResumed { action() }
else -> {
// do nothing
}
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 e7d130a6d5..8a09b6bd46 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
@@ -54,7 +54,6 @@ import com.google.android.material.color.MaterialColors
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.EntryPointAccessors
-import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.ActivityEntryPoint
@@ -68,6 +67,7 @@ import im.vector.app.core.extensions.restart
import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.core.extensions.toMvRxBundle
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.utils.AndroidSystemSettingsProvider
import im.vector.app.core.utils.ToolbarConfig
import im.vector.app.core.utils.toast
@@ -157,11 +157,9 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver
protected lateinit var bugReporter: BugReporter
private lateinit var pinLocker: PinLocker
- @Inject
- lateinit var rageShake: RageShake
-
- @Inject
- lateinit var fontScalePreferences: FontScalePreferences
+ @Inject lateinit var rageShake: RageShake
+ @Inject lateinit var buildMeta: BuildMeta
+ @Inject lateinit var fontScalePreferences: FontScalePreferences
@Inject
lateinit var vectorFeatures: VectorFeatures
@@ -422,7 +420,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver
}
DebugReceiver
.getIntentFilter(this)
- .takeIf { BuildConfig.DEBUG }
+ .takeIf { buildMeta.isDebug }
?.let {
debugReceiver = DebugReceiver()
registerReceiver(debugReceiver, it)
diff --git a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt
index 0d6828f569..8e88e44627 100644
--- a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt
+++ b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt
@@ -25,14 +25,14 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import dagger.hilt.android.AndroidEntryPoint
-import im.vector.app.BuildConfig
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.network.WifiDetector
import im.vector.app.core.pushers.model.PushData
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.services.GuardServiceStarter
import im.vector.app.features.notifications.NotifiableEventResolver
+import im.vector.app.features.notifications.NotificationActionIds
import im.vector.app.features.notifications.NotificationDrawerManager
-import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.settings.BackgroundSyncMode
import im.vector.app.features.settings.VectorDataStore
import im.vector.app.features.settings.VectorPreferences
@@ -68,6 +68,8 @@ class VectorMessagingReceiver : MessagingReceiver() {
@Inject lateinit var unifiedPushHelper: UnifiedPushHelper
@Inject lateinit var unifiedPushStore: UnifiedPushStore
@Inject lateinit var pushParser: PushParser
+ @Inject lateinit var actionIds: NotificationActionIds
+ @Inject lateinit var buildMeta: BuildMeta
private val coroutineScope = CoroutineScope(SupervisorJob())
@@ -87,7 +89,7 @@ class VectorMessagingReceiver : MessagingReceiver() {
Timber.tag(loggerTag.value).d("## onMessage() received")
val sMessage = String(message)
- if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
+ if (buildMeta.lowPrivacyLoggingEnabled) {
Timber.tag(loggerTag.value).d("## onMessage() $sMessage")
}
@@ -100,7 +102,7 @@ class VectorMessagingReceiver : MessagingReceiver() {
// Diagnostic Push
if (pushData.eventId == PushersManager.TEST_EVENT_ID) {
- val intent = Intent(NotificationUtils.PUSH_ACTION)
+ val intent = Intent(actionIds.push)
LocalBroadcastManager.getInstance(context).sendBroadcast(intent)
return
}
@@ -171,7 +173,7 @@ class VectorMessagingReceiver : MessagingReceiver() {
*/
private suspend fun onMessageReceivedInternal(pushData: PushData) {
try {
- if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
+ if (buildMeta.lowPrivacyLoggingEnabled) {
Timber.tag(loggerTag.value).d("## onMessageReceivedInternal() : $pushData")
} else {
Timber.tag(loggerTag.value).d("## onMessageReceivedInternal()")
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 14d97e4c8f..6c25348ea1 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
@@ -16,8 +16,15 @@
package im.vector.app.core.resources
-import android.os.Build
-
data class BuildMeta(
- val sdkInt: Int = Build.VERSION.SDK_INT
+ val isDebug: Boolean,
+ val applicationId: String,
+ val lowPrivacyLoggingEnabled: Boolean,
+ val versionName: String,
+ val gitRevision: String,
+ val gitRevisionDate: String,
+ val gitBranchName: String,
+ val buildNumber: String,
+ val flavorDescription: String,
+ val flavorShortDescription: String,
)
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 3a8ffac543..d52b7088ff 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
@@ -39,7 +39,6 @@ import androidx.browser.customtabs.CustomTabsSession
import androidx.core.app.ShareCompat
import androidx.core.content.FileProvider
import androidx.core.content.getSystemService
-import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.themes.ThemeUtils
@@ -182,7 +181,7 @@ fun openUri(activity: Activity, uri: String) {
*/
fun openMedia(activity: Activity, savedMediaPath: String, mimeType: String) {
val file = File(savedMediaPath)
- val uri = FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".fileProvider", file)
+ val uri = FileProvider.getUriForFile(activity, activity.packageName + ".fileProvider", file)
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri, mimeType)
@@ -214,7 +213,7 @@ fun openLocation(activity: Activity, latitude: Double, longitude: Double) {
fun shareMedia(context: Context, file: File, mediaMimeType: String?) {
val mediaUri = try {
- FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", file)
+ FileProvider.getUriForFile(context, context.packageName + ".fileProvider", file)
} catch (e: Exception) {
Timber.e(e, "onMediaAction Selected File cannot be shared")
return
@@ -376,7 +375,7 @@ private fun addToGallery(savedFile: File, mediaMimeType: String?, context: Conte
/**
* Open the play store to the provided application Id, default to this app.
*/
-fun openPlayStore(activity: Activity, appId: String = BuildConfig.APPLICATION_ID) {
+fun openPlayStore(activity: Activity, appId: String) {
try {
activity.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=$appId")))
} catch (activityNotFoundException: ActivityNotFoundException) {
diff --git a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt
index 3a56f31b72..290d21879d 100644
--- a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt
+++ b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt
@@ -16,8 +16,8 @@
package im.vector.app.features
-import im.vector.app.BuildConfig
import im.vector.app.config.Config
+import im.vector.app.config.OnboardingVariant
interface VectorFeatures {
@@ -30,19 +30,14 @@ interface VectorFeatures {
fun isOnboardingCombinedLoginEnabled(): Boolean
fun allowExternalUnifiedPushDistributors(): Boolean
fun isScreenSharingEnabled(): Boolean
+ fun isLocationSharingEnabled(): Boolean
fun forceUsageOfOpusEncoder(): Boolean
fun shouldStartDmOnFirstMessage(): Boolean
fun isNewAppLayoutEnabled(): Boolean
-
- enum class OnboardingVariant {
- LEGACY,
- LOGIN_2,
- FTUE_AUTH
- }
}
class DefaultVectorFeatures : VectorFeatures {
- override fun onboardingVariant(): VectorFeatures.OnboardingVariant = BuildConfig.ONBOARDING_VARIANT
+ override fun onboardingVariant() = Config.ONBOARDING_VARIANT
override fun isOnboardingAlreadyHaveAccountSplashEnabled() = true
override fun isOnboardingSplashCarouselEnabled() = true
override fun isOnboardingUseCaseEnabled() = true
@@ -51,6 +46,7 @@ class DefaultVectorFeatures : VectorFeatures {
override fun isOnboardingCombinedLoginEnabled() = true
override fun allowExternalUnifiedPushDistributors(): Boolean = Config.ALLOW_EXTERNAL_UNIFIED_PUSH_DISTRIBUTORS
override fun isScreenSharingEnabled(): Boolean = true
+ override fun isLocationSharingEnabled() = Config.ENABLE_LOCATION_SHARING
override fun forceUsageOfOpusEncoder(): Boolean = false
override fun shouldStartDmOnFirstMessage(): Boolean = false
override fun isNewAppLayoutEnabled(): Boolean = false
diff --git a/vector/src/main/java/im/vector/app/features/analytics/AnalyticsConfig.kt b/vector/src/main/java/im/vector/app/features/analytics/AnalyticsConfig.kt
index 46119f5563..bffba6fa9c 100644
--- a/vector/src/main/java/im/vector/app/features/analytics/AnalyticsConfig.kt
+++ b/vector/src/main/java/im/vector/app/features/analytics/AnalyticsConfig.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 New Vector Ltd
+ * Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,9 +16,9 @@
package im.vector.app.features.analytics
-interface AnalyticsConfig {
- val isEnabled: Boolean
- val postHogHost: String
- val postHogApiKey: String
- val policyLink: String
-}
+data class AnalyticsConfig(
+ val isEnabled: Boolean,
+ val postHogHost: String,
+ val postHogApiKey: String,
+ val policyLink: String,
+)
diff --git a/vector/src/main/java/im/vector/app/features/analytics/impl/PostHogFactory.kt b/vector/src/main/java/im/vector/app/features/analytics/impl/PostHogFactory.kt
index 029732f76c..7442989352 100644
--- a/vector/src/main/java/im/vector/app/features/analytics/impl/PostHogFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/analytics/impl/PostHogFactory.kt
@@ -18,11 +18,15 @@ package im.vector.app.features.analytics.impl
import android.content.Context
import com.posthog.android.PostHog
-import im.vector.app.BuildConfig
-import im.vector.app.config.analyticsConfig
+import im.vector.app.core.resources.BuildMeta
+import im.vector.app.features.analytics.AnalyticsConfig
import javax.inject.Inject
-class PostHogFactory @Inject constructor(private val context: Context) {
+class PostHogFactory @Inject constructor(
+ private val context: Context,
+ private val analyticsConfig: AnalyticsConfig,
+ private val buildMeta: BuildMeta,
+) {
fun createPosthog(): PostHog {
return PostHog.Builder(context, analyticsConfig.postHogApiKey, analyticsConfig.postHogHost)
@@ -43,7 +47,7 @@ class PostHogFactory @Inject constructor(private val context: Context) {
}
private fun getLogLevel(): PostHog.LogLevel {
- return if (BuildConfig.DEBUG) {
+ return if (buildMeta.isDebug) {
PostHog.LogLevel.DEBUG
} else {
PostHog.LogLevel.INFO
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 320386aebd..a5bafa2ee6 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,17 +22,17 @@ import android.view.View
import android.view.ViewGroup
import com.airbnb.mvrx.activityViewModel
import im.vector.app.R
-import im.vector.app.config.analyticsConfig
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 javax.inject.Inject
-class AnalyticsOptInFragment @Inject constructor() :
- VectorBaseFragment(),
- OnBackPressed {
+class AnalyticsOptInFragment @Inject constructor(
+ private val analyticsConfig: AnalyticsConfig,
+) : VectorBaseFragment(), OnBackPressed {
// Share the view model with the Activity so that the Activity
// can decide what to do when the data has been saved
diff --git a/vector/src/main/java/im/vector/app/features/attachments/AttachmentsHelper.kt b/vector/src/main/java/im/vector/app/features/attachments/AttachmentsHelper.kt
index d0843b3b64..f8aa22f418 100644
--- a/vector/src/main/java/im/vector/app/features/attachments/AttachmentsHelper.kt
+++ b/vector/src/main/java/im/vector/app/features/attachments/AttachmentsHelper.kt
@@ -23,9 +23,9 @@ import android.os.Bundle
import androidx.activity.result.ActivityResultLauncher
import im.vector.app.core.dialogs.PhotoOrVideoDialog
import im.vector.app.core.platform.Restorable
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.features.settings.VectorPreferences
import im.vector.lib.multipicker.MultiPicker
-import org.matrix.android.sdk.BuildConfig
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
import timber.log.Timber
@@ -35,15 +35,14 @@ private const val PENDING_TYPE_KEY = "PENDING_TYPE_KEY"
/**
* This class helps to handle attachments by providing simple methods.
*/
-class AttachmentsHelper(val context: Context, val callback: Callback) : Restorable {
+class AttachmentsHelper(
+ val context: Context,
+ val callback: Callback,
+ private val buildMeta: BuildMeta,
+) : Restorable {
interface Callback {
- fun onContactAttachmentReady(contactAttachment: ContactAttachment) {
- if (BuildConfig.LOG_PRIVATE_DATA) {
- Timber.v("On contact attachment ready: $contactAttachment")
- }
- }
-
+ fun onContactAttachmentReady(contactAttachment: ContactAttachment)
fun onContentAttachmentsReady(attachments: List)
}
@@ -144,6 +143,9 @@ class AttachmentsHelper(val context: Context, val callback: Callback) : Restorab
.firstOrNull()
?.toContactAttachment()
?.let {
+ if (buildMeta.lowPrivacyLoggingEnabled) {
+ Timber.v("On contact attachment ready: $it")
+ }
callback.onContactAttachmentReady(it)
}
}
diff --git a/vector/src/main/java/im/vector/app/features/call/webrtc/VoipConfig.kt b/vector/src/main/java/im/vector/app/features/call/webrtc/VoipConfig.kt
new file mode 100644
index 0000000000..03a9312999
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/call/webrtc/VoipConfig.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.call.webrtc
+
+data class VoipConfig(
+ val handleCallAssertedIdentityEvents: Boolean
+)
diff --git a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt
index b35ab774be..074779c6cc 100644
--- a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt
+++ b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt
@@ -20,7 +20,6 @@ import android.content.Context
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import im.vector.app.ActiveSessionDataSource
-import im.vector.app.BuildConfig
import im.vector.app.core.pushers.UnifiedPushHelper
import im.vector.app.core.services.CallAndroidService
import im.vector.app.features.analytics.AnalyticsTracker
@@ -74,6 +73,7 @@ class WebRtcCallManager @Inject constructor(
private val activeSessionDataSource: ActiveSessionDataSource,
private val analyticsTracker: AnalyticsTracker,
private val unifiedPushHelper: UnifiedPushHelper,
+ private val voipConfig: VoipConfig,
) : CallListener,
DefaultLifecycleObserver {
@@ -444,7 +444,7 @@ class WebRtcCallManager @Inject constructor(
}
override fun onCallAssertedIdentityReceived(callAssertedIdentityContent: CallAssertedIdentityContent) {
- if (!BuildConfig.handleCallAssertedIdentityEvents) {
+ if (!voipConfig.handleCallAssertedIdentityEvents) {
return
}
val call = callsByCallId[callAssertedIdentityContent.callId]
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt
index eb24a1ba86..cfe76706a5 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt
@@ -22,11 +22,11 @@ import com.airbnb.mvrx.ViewModelContext
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
-import im.vector.app.config.analyticsConfig
import im.vector.app.core.di.ActiveSessionHolder
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.features.analytics.AnalyticsConfig
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toAnalyticsType
import im.vector.app.features.analytics.plan.Signup
@@ -80,7 +80,8 @@ class HomeActivityViewModel @AssistedInject constructor(
private val analyticsStore: AnalyticsStore,
private val lightweightSettingsStorage: LightweightSettingsStorage,
private val vectorPreferences: VectorPreferences,
- private val analyticsTracker: AnalyticsTracker
+ private val analyticsTracker: AnalyticsTracker,
+ private val analyticsConfig: AnalyticsConfig,
) : VectorViewModel(initialState) {
@AssistedFactory
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 d96b44b705..d4c89c1bca 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
@@ -41,7 +41,6 @@ import im.vector.app.core.ui.views.CurrentCallsView
import im.vector.app.core.ui.views.CurrentCallsViewPresenter
import im.vector.app.core.ui.views.KeysBackupBanner
import im.vector.app.databinding.FragmentHomeDetailBinding
-import im.vector.app.features.VectorFeatures
import im.vector.app.features.call.SharedKnownCallsViewModel
import im.vector.app.features.call.VectorCallActivity
import im.vector.app.features.call.dialpad.DialPadFragment
@@ -49,7 +48,6 @@ import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.home.room.list.RoomListFragment
import im.vector.app.features.home.room.list.RoomListParams
import im.vector.app.features.home.room.list.UnreadCounterBadgeView
-import im.vector.app.features.home.room.list.home.HomeRoomListFragment
import im.vector.app.features.popup.PopupAlertManager
import im.vector.app.features.popup.VerificationVectorAlert
import im.vector.app.features.settings.VectorLocale
@@ -69,7 +67,6 @@ class HomeDetailFragment @Inject constructor(
private val callManager: WebRtcCallManager,
private val vectorPreferences: VectorPreferences,
private val spaceStateHandler: SpaceStateHandler,
- private val vectorFeatures: VectorFeatures,
) : VectorBaseFragment(),
KeysBackupBanner.Delegate,
CurrentCallsView.Callback,
@@ -355,12 +352,8 @@ class HomeDetailFragment @Inject constructor(
if (fragmentToShow == null) {
when (tab) {
is HomeTab.RoomList -> {
- if (vectorFeatures.isNewAppLayoutEnabled()) {
- add(R.id.roomListContainer, HomeRoomListFragment::class.java, null, fragmentTag)
- } else {
- val params = RoomListParams(tab.displayMode)
- add(R.id.roomListContainer, RoomListFragment::class.java, params.toMvRxBundle(), fragmentTag)
- }
+ val params = RoomListParams(tab.displayMode)
+ add(R.id.roomListContainer, RoomListFragment::class.java, params.toMvRxBundle(), fragmentTag)
}
is HomeTab.DialPad -> {
add(R.id.roomListContainer, createDialPadFragment(), fragmentTag)
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 e79387c66d..535f38e68e 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
@@ -23,11 +23,11 @@ import android.view.ViewGroup
import androidx.core.app.ActivityOptionsCompat
import androidx.core.view.ViewCompat
import androidx.core.view.isVisible
-import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.extensions.observeK
import im.vector.app.core.extensions.replaceChildFragment
import im.vector.app.core.platform.VectorBaseFragment
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.utils.startSharePlainTextIntent
import im.vector.app.databinding.FragmentHomeDrawerBinding
import im.vector.app.features.analytics.plan.MobileScreen
@@ -43,7 +43,8 @@ import javax.inject.Inject
class HomeDrawerFragment @Inject constructor(
private val session: Session,
private val vectorPreferences: VectorPreferences,
- private val avatarRenderer: AvatarRenderer
+ private val avatarRenderer: AvatarRenderer,
+ private val buildMeta: BuildMeta,
) : VectorBaseFragment() {
private lateinit var sharedActionViewModel: HomeSharedActionViewModel
@@ -112,7 +113,7 @@ class HomeDrawerFragment @Inject constructor(
}
// Debug menu
- views.homeDrawerHeaderDebugView.isVisible = BuildConfig.DEBUG && vectorPreferences.developerMode()
+ views.homeDrawerHeaderDebugView.isVisible = buildMeta.isDebug && vectorPreferences.developerMode()
views.homeDrawerHeaderDebugView.debouncedClicks {
sharedActionViewModel.post(HomeActivitySharedAction.CloseDrawer)
navigator.openDebug(requireActivity())
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 55fb3daafa..c0f6c673f4 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
@@ -31,7 +31,6 @@ import com.google.android.material.badge.BadgeDrawable
import im.vector.app.R
import im.vector.app.SpaceStateHandler
import im.vector.app.core.extensions.commitTransaction
-import im.vector.app.core.extensions.toMvRxBundle
import im.vector.app.core.platform.OnBackPressed
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.platform.VectorBaseFragment
diff --git a/vector/src/main/java/im/vector/app/features/home/ShortcutCreator.kt b/vector/src/main/java/im/vector/app/features/home/ShortcutCreator.kt
index a51b8eff63..861fdc64b2 100644
--- a/vector/src/main/java/im/vector/app/features/home/ShortcutCreator.kt
+++ b/vector/src/main/java/im/vector/app/features/home/ShortcutCreator.kt
@@ -24,8 +24,8 @@ import androidx.annotation.WorkerThread
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.IconCompat
-import im.vector.app.BuildConfig
import im.vector.app.core.glide.GlideApp
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.features.MainActivity
import org.matrix.android.sdk.api.session.room.model.RoomSummary
@@ -35,13 +35,15 @@ import javax.inject.Inject
private val useAdaptiveIcon = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
private const val adaptiveIconSizeDp = 108
private const val adaptiveIconOuterSidesDp = 18
-private const val directShareCategory = BuildConfig.APPLICATION_ID + ".SHORTCUT_SHARE"
class ShortcutCreator @Inject constructor(
private val context: Context,
private val avatarRenderer: AvatarRenderer,
- private val dimensionConverter: DimensionConverter
+ private val dimensionConverter: DimensionConverter,
+ buildMeta: BuildMeta,
) {
+
+ private val directShareCategory = buildMeta.applicationId + ".SHORTCUT_SHARE"
private val adaptiveIconSize = dimensionConverter.dpToPx(adaptiveIconSizeDp)
private val adaptiveIconOuterSides = dimensionConverter.dpToPx(adaptiveIconOuterSidesDp)
private val iconSize by lazy {
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 7acc77a686..f164183914 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
@@ -67,7 +67,6 @@ import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.vanniktech.emoji.EmojiPopup
-import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.animations.play
import im.vector.app.core.dialogs.ConfirmationDialogBuilder
@@ -92,6 +91,7 @@ import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.platform.VectorMenuProvider
import im.vector.app.core.platform.lifecycleAwareLazy
import im.vector.app.core.platform.showOptimizedSnackbar
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.UserPreferencesProvider
import im.vector.app.core.time.Clock
@@ -125,6 +125,7 @@ import im.vector.app.core.utils.startInstallFromSourceIntent
import im.vector.app.core.utils.toast
import im.vector.app.databinding.DialogReportContentBinding
import im.vector.app.databinding.FragmentTimelineBinding
+import im.vector.app.features.VectorFeatures
import im.vector.app.features.analytics.extensions.toAnalyticsInteraction
import im.vector.app.features.analytics.plan.Interaction
import im.vector.app.features.analytics.plan.MobileScreen
@@ -275,7 +276,9 @@ class TimelineFragment @Inject constructor(
private val callManager: WebRtcCallManager,
private val audioMessagePlaybackTracker: AudioMessagePlaybackTracker,
private val shareIntentHandler: ShareIntentHandler,
- private val clock: Clock
+ private val clock: Clock,
+ private val vectorFeatures: VectorFeatures,
+ private val buildMeta: BuildMeta,
) :
VectorBaseFragment(),
TimelineEventController.Callback,
@@ -372,7 +375,7 @@ class TimelineFragment @Inject constructor(
sharedActionViewModel = activityViewModelProvider.get(MessageSharedActionViewModel::class.java)
sharedActivityActionViewModel = activityViewModelProvider.get(RoomDetailSharedActionViewModel::class.java)
knownCallsViewModel = activityViewModelProvider.get(SharedKnownCallsViewModel::class.java)
- attachmentsHelper = AttachmentsHelper(requireContext(), this).register()
+ attachmentsHelper = AttachmentsHelper(requireContext(), this, buildMeta).register()
callActionsHandler = StartCallActionsHandler(
roomId = timelineArgs.roomId,
fragment = this,
@@ -962,7 +965,7 @@ class TimelineFragment @Inject constructor(
}
override fun onDestroyView() {
- audioMessagePlaybackTracker.makeAllPlaybacksIdle()
+ messageComposerViewModel.endAllVoiceActions()
lazyLoadedViews.unBind()
timelineEventController.callback = null
timelineEventController.removeModelBuildListener(modelBuildListener)
@@ -1095,7 +1098,7 @@ class TimelineFragment @Inject constructor(
else -> state.isAllowedToManageWidgets
}
menu.findItem(R.id.video_call).icon?.alpha = if (callButtonsEnabled) 0xFF else 0x40
- menu.findItem(R.id.voice_call).icon?.alpha = if (callButtonsEnabled || state.hasActiveElementCallWidget()) 0xFF else 0x40
+ menu.findItem(R.id.voice_call).icon?.alpha = if (callButtonsEnabled || state.hasActiveElementCallWidget()) 0xFF else 0x40
val matrixAppsMenuItem = menu.findItem(R.id.open_matrix_apps)
val widgetsCount = state.activeRoomWidgets.invoke()?.size ?: 0
@@ -1559,7 +1562,7 @@ class TimelineFragment @Inject constructor(
attachmentTypeSelector = AttachmentTypeSelectorView(vectorBaseActivity, vectorBaseActivity.layoutInflater, this@TimelineFragment)
attachmentTypeSelector.setAttachmentVisibility(
AttachmentTypeSelectorView.Type.LOCATION,
- BuildConfig.enableLocationSharing
+ vectorFeatures.isLocationSharingEnabled(),
)
attachmentTypeSelector.setAttachmentVisibility(
AttachmentTypeSelectorView.Type.POLL, !isThreadTimeLine()
@@ -2646,7 +2649,6 @@ class TimelineFragment @Inject constructor(
}
override fun onContactAttachmentReady(contactAttachment: ContactAttachment) {
- super.onContactAttachmentReady(contactAttachment)
val formattedContact = contactAttachment.toHumanReadable()
messageComposerViewModel.handle(MessageComposerAction.SendMessage(formattedContact, false))
}
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 9e31c737bf..c0f90aba7a 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
@@ -33,6 +33,7 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.mvrx.runCatchingToAsync
import im.vector.app.core.platform.VectorViewModel
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.BehaviorDataSource
import im.vector.app.features.analytics.AnalyticsTracker
@@ -56,6 +57,7 @@ import im.vector.app.features.location.live.StopLiveLocationShareUseCase
import im.vector.app.features.location.live.tracking.LocationSharingServiceConnection
import im.vector.app.features.notifications.NotificationDrawerManager
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
+import im.vector.app.features.raw.wellknown.CryptoConfig
import im.vector.app.features.raw.wellknown.getOutboundSessionKeySharingStrategyOrDefault
import im.vector.app.features.raw.wellknown.withElementWellKnown
import im.vector.app.features.session.coroutineScope
@@ -137,6 +139,8 @@ class TimelineViewModel @AssistedInject constructor(
private val locationSharingServiceConnection: LocationSharingServiceConnection,
private val stopLiveLocationShareUseCase: StopLiveLocationShareUseCase,
private val redactLiveLocationShareEventUseCase: RedactLiveLocationShareEventUseCase,
+ private val cryptoConfig: CryptoConfig,
+ buildMeta: BuildMeta,
timelineFactory: TimelineFactory,
spaceStateHandler: SpaceStateHandler,
) : VectorViewModel(initialState),
@@ -150,7 +154,7 @@ class TimelineViewModel @AssistedInject constructor(
val timeline = timelineFactory.createTimeline(viewModelScope, room, eventId, initialState.rootThreadEventId)
// Same lifecycle than the ViewModel (survive to screen rotation)
- val previewUrlRetriever = PreviewUrlRetriever(session, viewModelScope)
+ val previewUrlRetriever = PreviewUrlRetriever(session, viewModelScope, buildMeta)
// Slot to keep a pending action during permission request
var pendingAction: RoomDetailAction? = null
@@ -205,7 +209,7 @@ class TimelineViewModel @AssistedInject constructor(
// Ensure to share the outbound session keys with all members
if (room.roomCryptoService().isEncrypted()) {
rawService.withElementWellKnown(viewModelScope, session.sessionParams) {
- val strategy = it.getOutboundSessionKeySharingStrategyOrDefault()
+ val strategy = it.getOutboundSessionKeySharingStrategyOrDefault(cryptoConfig.fallbackKeySharingStrategy)
if (strategy == OutboundSessionKeySharingStrategy.WhenEnteringRoom) {
prepareForEncryption()
}
@@ -688,7 +692,7 @@ class TimelineViewModel @AssistedInject constructor(
// Ensure outbound session keys
if (room.roomCryptoService().isEncrypted()) {
rawService.withElementWellKnown(viewModelScope, session.sessionParams) {
- val strategy = it.getOutboundSessionKeySharingStrategyOrDefault()
+ val strategy = it.getOutboundSessionKeySharingStrategyOrDefault(cryptoConfig.fallbackKeySharingStrategy)
if (strategy == OutboundSessionKeySharingStrategy.WhenTyping && action.focused) {
// Should we add some rate limit here, or do it only once per model lifecycle?
prepareForEncryption()
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/AudioMessageHelper.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/AudioMessageHelper.kt
index 9374d51228..2e150daee6 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/AudioMessageHelper.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/AudioMessageHelper.kt
@@ -20,7 +20,7 @@ import android.content.Context
import android.media.AudioAttributes
import android.media.MediaPlayer
import androidx.core.content.FileProvider
-import im.vector.app.BuildConfig
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
import im.vector.app.features.voice.VoiceFailure
import im.vector.app.features.voice.VoiceRecorder
@@ -43,6 +43,7 @@ import javax.inject.Inject
class AudioMessageHelper @Inject constructor(
private val context: Context,
private val playbackTracker: AudioMessagePlaybackTracker,
+ private val buildMeta: BuildMeta,
voiceRecorderProvider: VoiceRecorderProvider
) {
private var mediaPlayer: MediaPlayer? = null
@@ -88,7 +89,7 @@ class AudioMessageHelper @Inject constructor(
try {
voiceMessageFile?.let {
- val outputFileUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", it, "Voice message.${it.extension}")
+ val outputFileUri = FileProvider.getUriForFile(context, buildMeta.applicationId + ".fileProvider", it, "Voice message.${it.extension}")
return outputFileUri
.toMultiPickerAudioType(context)
?.apply {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerAction.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerAction.kt
index 0da324ffc2..527f42a67a 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerAction.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerAction.kt
@@ -41,7 +41,6 @@ sealed class MessageComposerAction : VectorViewModelAction {
object PauseRecordingVoiceMessage : MessageComposerAction()
data class PlayOrPauseVoicePlayback(val eventId: String, val messageAudioContent: MessageAudioContent) : MessageComposerAction()
object PlayOrPauseRecordingPlayback : MessageComposerAction()
- data class EndAllVoiceActions(val deleteRecord: Boolean = true) : MessageComposerAction()
data class VoiceWaveformTouchedUp(val eventId: String, val duration: Int, val percentage: Float) : MessageComposerAction()
data class VoiceWaveformMovedTo(val eventId: String, val duration: Int, val percentage: Float) : MessageComposerAction()
data class AudioSeekBarMovedTo(val eventId: String, val duration: Int, val percentage: Float) : MessageComposerAction()
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 ce4235a825..ca86010915 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
@@ -107,7 +107,6 @@ class MessageComposerViewModel @AssistedInject constructor(
is MessageComposerAction.PlayOrPauseVoicePlayback -> handlePlayOrPauseVoicePlayback(action)
MessageComposerAction.PauseRecordingVoiceMessage -> handlePauseRecordingVoiceMessage()
MessageComposerAction.PlayOrPauseRecordingPlayback -> handlePlayOrPauseRecordingPlayback()
- is MessageComposerAction.EndAllVoiceActions -> handleEndAllVoiceActions(action.deleteRecord)
is MessageComposerAction.InitializeVoiceRecorder -> handleInitializeVoiceRecorder(action.attachmentData)
is MessageComposerAction.OnEntersBackground -> handleEntersBackground(action.composerText)
is MessageComposerAction.VoiceWaveformTouchedUp -> handleVoiceWaveformTouchedUp(action)
@@ -887,7 +886,7 @@ class MessageComposerViewModel @AssistedInject constructor(
audioMessageHelper.startOrPauseRecordingPlayback()
}
- private fun handleEndAllVoiceActions(deleteRecord: Boolean) {
+ fun endAllVoiceActions(deleteRecord: Boolean = true) {
audioMessageHelper.clearTracker()
audioMessageHelper.stopAllVoiceActions(deleteRecord)
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageConfig.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageConfig.kt
new file mode 100644
index 0000000000..5ba5e40ca8
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageConfig.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.home.room.detail.composer.voice
+
+data class VoiceMessageConfig(
+ val lengthLimitMs: Long
+)
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 536a582ec1..13e0477ab6 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
@@ -21,7 +21,6 @@ import android.util.AttributeSet
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import dagger.hilt.android.AndroidEntryPoint
-import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.hardware.vibrate
import im.vector.app.core.time.Clock
@@ -57,6 +56,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
}
@Inject lateinit var clock: Clock
+ @Inject lateinit var voiceMessageConfig: VoiceMessageConfig
// We need to define views as lateinit var to be able to check if initialized for the bug fix on api 21 and 22.
@Suppress("UNNECESSARY_LATEINIT")
@@ -202,7 +202,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
private fun onRecordingTick(isLocked: Boolean, milliseconds: Long) {
voiceMessageViews.renderRecordingTimer(isLocked, milliseconds / 1_000)
- val timeDiffToRecordingLimit = BuildConfig.VOICE_MESSAGE_DURATION_LIMIT_MS - milliseconds
+ val timeDiffToRecordingLimit = voiceMessageConfig.lengthLimitMs - milliseconds
if (timeDiffToRecordingLimit <= 0) {
post {
callback.onRecordingLimitReached()
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 b7790b8a30..4903b8c8cf 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
@@ -36,6 +36,8 @@ import im.vector.app.core.utils.DimensionConverter
import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout
import im.vector.app.features.home.room.detail.timeline.style.granularRoundedCorners
+import im.vector.app.features.location.MapLoadingErrorView
+import im.vector.app.features.location.MapLoadingErrorViewState
abstract class AbsMessageLocationItem(
@LayoutRes layoutId: Int = R.layout.item_timeline_event_base
@@ -86,8 +88,10 @@ abstract class AbsMessageLocationItem(
target: Target?,
isFirstResource: Boolean
): Boolean {
- holder.staticMapPinImageView.setImageResource(R.drawable.ic_location_pin_failed)
- holder.staticMapErrorTextView.isVisible = true
+ holder.staticMapPinImageView.setImageDrawable(null)
+ holder.staticMapLoadingErrorView.isVisible = true
+ val mapErrorViewState = MapLoadingErrorViewState(imageCornerTransformation)
+ holder.staticMapLoadingErrorView.render(mapErrorViewState)
holder.staticMapCopyrightTextView.isVisible = false
return false
}
@@ -103,7 +107,7 @@ abstract class AbsMessageLocationItem(
// we are not using Glide since it does not display it correctly when there is no user photo
holder.staticMapPinImageView.setImageDrawable(pinDrawable)
}
- holder.staticMapErrorTextView.isVisible = false
+ holder.staticMapLoadingErrorView.isVisible = false
holder.staticMapCopyrightTextView.isVisible = true
return false
}
@@ -115,7 +119,7 @@ abstract class AbsMessageLocationItem(
abstract class Holder(@IdRes stubId: Int) : AbsMessageItem.Holder(stubId) {
val staticMapImageView by bind(R.id.staticMapImageView)
val staticMapPinImageView by bind(R.id.staticMapPinImageView)
- val staticMapErrorTextView by bind(R.id.staticMapErrorTextView)
+ val staticMapLoadingErrorView by bind(R.id.staticMapLoadingError)
val staticMapCopyrightTextView by bind(R.id.staticMapCopyrightTextView)
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlRetriever.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlRetriever.kt
index eef649dbc0..1c5cdd2562 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlRetriever.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlRetriever.kt
@@ -16,7 +16,7 @@
package im.vector.app.features.home.room.detail.timeline.url
-import im.vector.app.BuildConfig
+import im.vector.app.core.resources.BuildMeta
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -27,7 +27,8 @@ import org.matrix.android.sdk.api.session.room.timeline.getLatestEventId
class PreviewUrlRetriever(
session: Session,
- private val coroutineScope: CoroutineScope
+ private val coroutineScope: CoroutineScope,
+ private val buildMeta: BuildMeta,
) {
private val mediaService = session.mediaService()
@@ -77,7 +78,7 @@ class PreviewUrlRetriever(
mediaService.getPreviewUrl(
url = urlToRetrieve,
timestamp = null,
- cacheStrategy = if (BuildConfig.DEBUG) CacheStrategy.NoCache else CacheStrategy.TtlCache(CACHE_VALIDITY, false)
+ cacheStrategy = if (buildMeta.isDebug) CacheStrategy.NoCache else CacheStrategy.TtlCache(CACHE_VALIDITY, false)
)
}.fold(
{
diff --git a/vector/src/main/java/im/vector/app/features/location/Config.kt b/vector/src/main/java/im/vector/app/features/location/Config.kt
index c29e2e911a..b65b5517d1 100644
--- a/vector/src/main/java/im/vector/app/features/location/Config.kt
+++ b/vector/src/main/java/im/vector/app/features/location/Config.kt
@@ -22,5 +22,3 @@ const val DEFAULT_PIN_ID = "DEFAULT_PIN_ID"
const val INITIAL_MAP_ZOOM_IN_PREVIEW = 15.0
const val INITIAL_MAP_ZOOM_IN_TIMELINE = 17.0
-const val MIN_TIME_TO_UPDATE_LOCATION_MILLIS = 2 * 1_000L // every 2 seconds
-const val MIN_DISTANCE_TO_UPDATE_LOCATION_METERS = 10f
diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt
index 264b1f0e0b..5a1edbf8a1 100644
--- a/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt
+++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt
@@ -25,4 +25,5 @@ sealed class LocationSharingAction : VectorViewModelAction {
object ZoomToUserLocation : LocationSharingAction()
object LiveLocationSharingRequested : LocationSharingAction()
data class StartLiveLocationSharing(val durationMillis: Long) : LocationSharingAction()
+ object ShowMapLoadingError : LocationSharingAction()
}
diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt
index 169af4a5a2..9eddcad649 100644
--- a/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt
@@ -23,6 +23,7 @@ import dagger.hilt.android.AndroidEntryPoint
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.location.preview.LocationPreviewFragment
import kotlinx.parcelize.Parcelize
@Parcelize
diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingConfig.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingConfig.kt
new file mode 100644
index 0000000000..4615564e41
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingConfig.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.location
+
+data class LocationSharingConfig(
+ val mapTilerKey: String,
+)
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 ca524a0126..d96410010e 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
@@ -24,6 +24,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.core.view.isGone
+import androidx.core.view.isVisible
import androidx.fragment.app.setFragmentResultListener
import androidx.lifecycle.lifecycleScope
import com.airbnb.mvrx.fragmentViewModel
@@ -69,6 +70,7 @@ class LocationSharingFragment @Inject constructor(
private var mapView: WeakReference? = null
private var hasRenderedUserAvatar = false
+ private var mapLoadingErrorListener: MapView.OnDidFailLoadingMapListener? = null
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationSharingBinding {
return FragmentLocationSharingBinding.inflate(inflater, container, false)
@@ -87,6 +89,9 @@ class LocationSharingFragment @Inject constructor(
super.onViewCreated(view, savedInstanceState)
mapView = WeakReference(views.mapView)
+ mapLoadingErrorListener = MapView.OnDidFailLoadingMapListener {
+ viewModel.handle(LocationSharingAction.ShowMapLoadingError)
+ }.also { views.mapView.addOnDidFailLoadingMapListener(it) }
views.mapView.onCreate(savedInstanceState)
lifecycleScope.launchWhenCreated {
@@ -112,6 +117,12 @@ class LocationSharingFragment @Inject constructor(
}
}
+ override fun onDestroyView() {
+ mapLoadingErrorListener?.let { mapView?.get()?.removeOnDidFailLoadingMapListener(it) }
+ mapLoadingErrorListener = null
+ super.onDestroyView()
+ }
+
override fun onResume() {
super.onResume()
views.mapView.onResume()
@@ -256,20 +267,27 @@ class LocationSharingFragment @Inject constructor(
}
private fun updateMap(state: LocationSharingViewState) {
- // first, update the options view
- val options: Set = when (state.areTargetAndUserLocationEqual) {
- true -> setOf(LocationSharingOption.USER_CURRENT, LocationSharingOption.USER_LIVE)
- false -> setOf(LocationSharingOption.PINNED)
- else -> emptySet()
- }
- views.shareLocationOptionsPicker.render(options)
+ if (state.loadingMapHasFailed) {
+ views.shareLocationOptionsPicker.render(emptySet())
+ views.shareLocationMapLoadingError.isVisible = true
+ } else {
+ // first, update the options view
+ val options: Set = when (state.areTargetAndUserLocationEqual) {
+ true -> setOf(LocationSharingOption.USER_CURRENT, LocationSharingOption.USER_LIVE)
+ false -> setOf(LocationSharingOption.PINNED)
+ else -> emptySet()
+ }
+ views.shareLocationOptionsPicker.render(options)
- // then, update the map using the height of the options view after it has been rendered
- views.shareLocationOptionsPicker.post {
- val mapState = state
- .toMapState()
- .copy(logoMarginBottom = views.shareLocationOptionsPicker.height)
- views.mapView.render(mapState)
+ // then, update the map using the height of the options view after it has been rendered
+ views.shareLocationOptionsPicker.post {
+ val mapState = state
+ .toMapState()
+ .copy(logoMarginBottom = views.shareLocationOptionsPicker.height)
+ views.mapView.render(mapState)
+ }
+
+ views.shareLocationMapLoadingError.isGone = true
}
}
diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt
index 8056b72d57..28e37a38eb 100644
--- a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt
@@ -152,6 +152,7 @@ class LocationSharingViewModel @AssistedInject constructor(
LocationSharingAction.ZoomToUserLocation -> handleZoomToUserLocationAction()
LocationSharingAction.LiveLocationSharingRequested -> handleLiveLocationSharingRequestedAction()
is LocationSharingAction.StartLiveLocationSharing -> handleStartLiveLocationSharingAction(action.durationMillis)
+ LocationSharingAction.ShowMapLoadingError -> handleShowMapLoadingError()
}
}
@@ -211,6 +212,10 @@ class LocationSharingViewModel @AssistedInject constructor(
)
}
+ private fun handleShowMapLoadingError() {
+ setState { copy(loadingMapHasFailed = true) }
+ }
+
private fun onLocationUpdate(locationData: LocationData) {
Timber.d("onLocationUpdate()")
setState {
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 d5226eacfb..c7a2349afa 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
@@ -36,6 +36,7 @@ data class LocationSharingViewState(
val lastKnownUserLocation: LocationData? = null,
val locationTargetDrawable: Drawable? = null,
val canShareLiveLocation: Boolean = false,
+ val loadingMapHasFailed: Boolean = false
) : MavericksState {
constructor(locationSharingArgs: LocationSharingArgs) : this(
diff --git a/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt b/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt
index aa05fe764b..c617277f3f 100644
--- a/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt
+++ b/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt
@@ -24,8 +24,8 @@ import androidx.annotation.RequiresPermission
import androidx.annotation.VisibleForTesting
import androidx.core.content.getSystemService
import androidx.core.location.LocationListenerCompat
-import im.vector.app.BuildConfig
import im.vector.app.core.di.ActiveSessionHolder
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.features.session.coroutineScope
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
@@ -36,11 +36,16 @@ import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton
+import kotlin.time.Duration.Companion.seconds
+
+@VisibleForTesting
+const val MIN_DISTANCE_TO_UPDATE_LOCATION_METERS = 10f
@Singleton
class LocationTracker @Inject constructor(
context: Context,
- private val activeSessionHolder: ActiveSessionHolder
+ private val activeSessionHolder: ActiveSessionHolder,
+ private val buildMeta: BuildMeta,
) : LocationListenerCompat {
private val locationManager = context.getSystemService()
@@ -61,14 +66,25 @@ class LocationTracker @Inject constructor(
@VisibleForTesting
var hasLocationFromGPSProvider = false
+ private var firstLocationHandled = false
private val _locations = MutableSharedFlow(replay = 1)
+ @VisibleForTesting
+ val minDurationToUpdateLocationMillis = 5.seconds.inWholeMilliseconds
+
/**
* SharedFlow to collect location updates.
*/
val locations = _locations.asSharedFlow()
.onEach { Timber.d("new location emitted") }
- .debounce(MIN_TIME_TO_UPDATE_LOCATION_MILLIS)
+ .debounce {
+ if (firstLocationHandled) {
+ minDurationToUpdateLocationMillis
+ } else {
+ firstLocationHandled = true
+ 0
+ }
+ }
.onEach { Timber.d("new location emitted after debounce") }
.map { it.toLocationData() }
@@ -95,7 +111,7 @@ class LocationTracker @Inject constructor(
locationManager.requestLocationUpdates(
provider,
- MIN_TIME_TO_UPDATE_LOCATION_MILLIS,
+ minDurationToUpdateLocationMillis,
MIN_DISTANCE_TO_UPDATE_LOCATION_METERS,
this
)
@@ -104,7 +120,7 @@ class LocationTracker @Inject constructor(
}
.maxByOrNull { location -> location.time }
?.let { latestKnownLocation ->
- if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
+ if (buildMeta.lowPrivacyLoggingEnabled) {
Timber.d("lastKnownLocation: $latestKnownLocation")
} else {
Timber.d("lastKnownLocation: ${latestKnownLocation.provider}")
@@ -162,7 +178,7 @@ class LocationTracker @Inject constructor(
}
override fun onLocationChanged(location: Location) {
- if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
+ if (buildMeta.lowPrivacyLoggingEnabled) {
Timber.d("onLocationChanged: $location")
} else {
Timber.d("onLocationChanged: ${location.provider}")
@@ -196,7 +212,7 @@ class LocationTracker @Inject constructor(
private fun notifyLocation(location: Location) {
activeSessionHolder.getSafeActiveSession()?.coroutineScope?.launch {
- if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
+ if (buildMeta.lowPrivacyLoggingEnabled) {
Timber.d("notify location: $location")
} else {
Timber.d("notify location: ${location.provider}")
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
new file mode 100644
index 0000000000..8ea4fcac54
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/location/MapLoadingErrorView.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.location
+
+import android.content.Context
+import android.content.res.TypedArray
+import android.graphics.drawable.ColorDrawable
+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
+
+/**
+ * Custom view to display an error when map fails to load.
+ */
+class MapLoadingErrorView @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
+) : ConstraintLayout(context, attrs, defStyleAttr) {
+
+ private val binding = ViewMapLoadingErrorBinding.inflate(
+ LayoutInflater.from(context),
+ this
+ )
+
+ init {
+ context.obtainStyledAttributes(
+ attrs,
+ R.styleable.MapLoadingErrorView,
+ 0,
+ 0
+ ).use {
+ setErrorDescription(it)
+ }
+ }
+
+ private fun setErrorDescription(typedArray: TypedArray) {
+ val description = typedArray.getString(R.styleable.MapLoadingErrorView_mapErrorDescription)
+ if (description.isNullOrEmpty()) {
+ binding.mapLoadingErrorDescription.setText(R.string.location_share_loading_map_error)
+ } else {
+ binding.mapLoadingErrorDescription.text = description
+ }
+ }
+
+ fun render(mapLoadingErrorViewState: MapLoadingErrorViewState) {
+ GlideApp.with(binding.mapLoadingErrorBackground)
+ .load(ColorDrawable(ThemeUtils.getColor(context, R.attr.vctr_system)))
+ .transform(mapLoadingErrorViewState.backgroundTransformation)
+ .into(binding.mapLoadingErrorBackground)
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/features/location/MapLoadingErrorViewState.kt b/vector/src/main/java/im/vector/app/features/location/MapLoadingErrorViewState.kt
new file mode 100644
index 0000000000..8098d26a12
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/location/MapLoadingErrorViewState.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.location
+
+import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
+
+data class MapLoadingErrorViewState(val backgroundTransformation: BitmapTransformation)
diff --git a/vector/src/main/java/im/vector/app/features/location/UrlMapProvider.kt b/vector/src/main/java/im/vector/app/features/location/UrlMapProvider.kt
index f043006d70..3748b1b19e 100644
--- a/vector/src/main/java/im/vector/app/features/location/UrlMapProvider.kt
+++ b/vector/src/main/java/im/vector/app/features/location/UrlMapProvider.kt
@@ -16,7 +16,6 @@
package im.vector.app.features.location
-import im.vector.app.BuildConfig
import im.vector.app.features.raw.wellknown.getElementWellknown
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.raw.RawService
@@ -25,9 +24,10 @@ import javax.inject.Inject
class UrlMapProvider @Inject constructor(
private val session: Session,
- private val rawService: RawService
+ private val rawService: RawService,
+ locationSharingConfig: LocationSharingConfig,
) {
- private val keyParam = "?key=${BuildConfig.mapTilerKey}"
+ private val keyParam = "?key=${locationSharingConfig.mapTilerKey}"
private val fallbackMapUrl = buildString {
append(MAP_BASE_URL)
diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapAction.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapAction.kt
index 2a07934146..295d6b5d41 100644
--- a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapAction.kt
+++ b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapAction.kt
@@ -22,4 +22,5 @@ sealed class LiveLocationMapAction : VectorViewModelAction {
data class AddMapSymbol(val key: String, val value: Long) : LiveLocationMapAction()
data class RemoveMapSymbol(val key: String) : LiveLocationMapAction()
object StopSharing : LiveLocationMapAction()
+ object ShowMapLoadingError : LiveLocationMapAction()
}
diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewFragment.kt
index 283774dbc6..85095e7c9f 100644
--- a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewFragment.kt
@@ -71,11 +71,13 @@ class LiveLocationMapViewFragment @Inject constructor() : VectorBaseFragment? = null
+ private var mapView: MapView? = null
private var symbolManager: SymbolManager? = null
private var mapStyle: Style? = null
private val pendingLiveLocations = mutableListOf()
private var isMapFirstUpdate = true
private var onSymbolClickListener: OnSymbolClickListener? = null
+ private var mapLoadingErrorListener: MapView.OnDidFailLoadingMapListener? = null
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLiveLocationMapViewBinding {
return FragmentLiveLocationMapViewBinding.inflate(layoutInflater, container, false)
@@ -84,6 +86,7 @@ class LiveLocationMapViewFragment @Inject constructor() : VectorBaseFragment
+ (mapFragment.view as? MapView)?.let {
+ mapView = it
+ listenMapLoadingError(it)
+ }
lifecycleScope.launch {
mapboxMap.setStyle(urlMapProvider.getMapUrl()) { style ->
mapStyle = style
@@ -141,6 +146,12 @@ class LiveLocationMapViewFragment @Inject constructor() : VectorBaseFragment
- updateMap(viewState.userLocations)
+ if (viewState.loadingMapHasFailed) {
+ views.mapPreviewLoadingError.isVisible = true
+ } else {
+ views.mapPreviewLoadingError.isGone = true
+ updateMap(viewState.userLocations)
+ }
updateUserListBottomSheet(viewState.userLocations)
}
diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewModel.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewModel.kt
index 280789e4c6..33c584ff85 100644
--- a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewModel.kt
@@ -61,6 +61,7 @@ class LiveLocationMapViewModel @AssistedInject constructor(
is LiveLocationMapAction.AddMapSymbol -> handleAddMapSymbol(action)
is LiveLocationMapAction.RemoveMapSymbol -> handleRemoveMapSymbol(action)
LiveLocationMapAction.StopSharing -> handleStopSharing()
+ LiveLocationMapAction.ShowMapLoadingError -> handleShowMapLoadingError()
}
}
@@ -87,6 +88,10 @@ class LiveLocationMapViewModel @AssistedInject constructor(
}
}
+ private fun handleShowMapLoadingError() {
+ setState { copy(loadingMapHasFailed = true) }
+ }
+
override fun onLocationServiceRunning(roomIds: Set) {
// NOOP
}
diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewState.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewState.kt
index 615b4381e2..ddd1cd2369 100644
--- a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewState.kt
+++ b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewState.kt
@@ -27,7 +27,8 @@ data class LiveLocationMapViewState(
/**
* Map to keep track of symbol ids associated to each user Id.
*/
- val mapSymbolIds: Map = emptyMap()
+ val mapSymbolIds: Map = emptyMap(),
+ val loadingMapHasFailed: Boolean = false,
) : MavericksState {
constructor(liveLocationMapViewArgs: LiveLocationMapViewArgs) : this(
roomId = liveLocationMapViewArgs.roomId
diff --git a/vector/src/main/java/im/vector/app/features/location/live/tracking/LiveLocationNotificationBuilder.kt b/vector/src/main/java/im/vector/app/features/location/live/tracking/LiveLocationNotificationBuilder.kt
index b8dd17e8fd..5bc730f3d7 100644
--- a/vector/src/main/java/im/vector/app/features/location/live/tracking/LiveLocationNotificationBuilder.kt
+++ b/vector/src/main/java/im/vector/app/features/location/live/tracking/LiveLocationNotificationBuilder.kt
@@ -31,6 +31,7 @@ import im.vector.app.features.home.room.detail.RoomDetailActivity
import im.vector.app.features.home.room.detail.arguments.TimelineArgs
import im.vector.app.features.location.live.map.LiveLocationMapViewActivity
import im.vector.app.features.location.live.map.LiveLocationMapViewArgs
+import im.vector.app.features.notifications.NotificationActionIds
import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.themes.ThemeUtils
import javax.inject.Inject
@@ -41,6 +42,7 @@ class LiveLocationNotificationBuilder @Inject constructor(
private val context: Context,
private val stringProvider: StringProvider,
private val clock: Clock,
+ private val actionIds: NotificationActionIds,
) {
/**
@@ -66,7 +68,7 @@ class LiveLocationNotificationBuilder @Inject constructor(
liveLocationMapViewArgs = LiveLocationMapViewArgs(roomId = roomId),
firstStartMainActivity = true
)
- mapIntent.action = NotificationUtils.TAP_TO_VIEW_ACTION
+ mapIntent.action = actionIds.tapToView
// pending intent get reused by system, this will mess up the extra params, so put unique info to avoid that
mapIntent.data = createIgnoredUri("openLiveLocationMap?$roomId")
diff --git a/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewAction.kt b/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewAction.kt
new file mode 100644
index 0000000000..38f6952f67
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewAction.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.location.preview
+
+import im.vector.app.core.platform.VectorViewModelAction
+
+sealed class LocationPreviewAction : VectorViewModelAction {
+ object ShowMapLoadingError : LocationPreviewAction()
+}
diff --git a/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt b/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewFragment.kt
similarity index 78%
rename from vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt
rename to vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewFragment.kt
index 131119a7aa..8285d0156b 100644
--- a/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewFragment.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 New Vector Ltd
+ * Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +14,18 @@
* limitations under the License.
*/
-package im.vector.app.features.location
+package im.vector.app.features.location.preview
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
+import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.airbnb.mvrx.args
+import com.airbnb.mvrx.fragmentViewModel
+import com.airbnb.mvrx.withState
import com.mapbox.mapboxsdk.maps.MapView
import im.vector.app.R
import im.vector.app.core.platform.VectorBaseFragment
@@ -30,6 +33,10 @@ import im.vector.app.core.platform.VectorMenuProvider
import im.vector.app.core.utils.openLocation
import im.vector.app.databinding.FragmentLocationPreviewBinding
import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
+import im.vector.app.features.location.DEFAULT_PIN_ID
+import im.vector.app.features.location.LocationSharingArgs
+import im.vector.app.features.location.MapState
+import im.vector.app.features.location.UrlMapProvider
import java.lang.ref.WeakReference
import javax.inject.Inject
@@ -44,9 +51,13 @@ class LocationPreviewFragment @Inject constructor(
private val args: LocationSharingArgs by args()
+ private val viewModel: LocationPreviewViewModel by fragmentViewModel()
+
// Keep a ref to handle properly the onDestroy callback
private var mapView: WeakReference? = null
+ private var mapLoadingErrorListener: MapView.OnDidFailLoadingMapListener? = null
+
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationPreviewBinding {
return FragmentLocationPreviewBinding.inflate(layoutInflater, container, false)
}
@@ -55,6 +66,9 @@ class LocationPreviewFragment @Inject constructor(
super.onViewCreated(view, savedInstanceState)
mapView = WeakReference(views.mapView)
+ mapLoadingErrorListener = MapView.OnDidFailLoadingMapListener {
+ viewModel.handle(LocationPreviewAction.ShowMapLoadingError)
+ }.also { views.mapView.addOnDidFailLoadingMapListener(it) }
views.mapView.onCreate(savedInstanceState)
lifecycleScope.launchWhenCreated {
@@ -63,6 +77,12 @@ class LocationPreviewFragment @Inject constructor(
}
}
+ override fun onDestroyView() {
+ mapLoadingErrorListener?.let { mapView?.get()?.removeOnDidFailLoadingMapListener(it) }
+ mapLoadingErrorListener = null
+ super.onDestroyView()
+ }
+
override fun onResume() {
super.onResume()
views.mapView.onResume()
@@ -99,6 +119,10 @@ class LocationPreviewFragment @Inject constructor(
super.onDestroy()
}
+ override fun invalidate() = withState(viewModel) { state ->
+ views.mapPreviewLoadingError.isVisible = state.loadingMapHasFailed
+ }
+
override fun getMenuRes() = R.menu.menu_location_preview
override fun handleMenuItemSelected(item: MenuItem): Boolean {
diff --git a/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewViewModel.kt b/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewViewModel.kt
new file mode 100644
index 0000000000..f0698249ce
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewViewModel.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.location.preview
+
+import com.airbnb.mvrx.MavericksViewModelFactory
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import im.vector.app.core.di.MavericksAssistedViewModelFactory
+import im.vector.app.core.di.hiltMavericksViewModelFactory
+import im.vector.app.core.platform.EmptyViewEvents
+import im.vector.app.core.platform.VectorViewModel
+
+class LocationPreviewViewModel @AssistedInject constructor(
+ @Assisted private val initialState: LocationPreviewViewState,
+) : VectorViewModel(initialState) {
+
+ @AssistedFactory
+ interface Factory : MavericksAssistedViewModelFactory {
+ override fun create(initialState: LocationPreviewViewState): LocationPreviewViewModel
+ }
+
+ companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory()
+
+ override fun handle(action: LocationPreviewAction) {
+ when (action) {
+ LocationPreviewAction.ShowMapLoadingError -> handleShowMapLoadingError()
+ }
+ }
+
+ private fun handleShowMapLoadingError() {
+ setState { copy(loadingMapHasFailed = true) }
+ }
+}
diff --git a/vector/src/debug/java/im/vector/app/config/AnalyticsConfig.kt b/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewViewState.kt
similarity index 55%
rename from vector/src/debug/java/im/vector/app/config/AnalyticsConfig.kt
rename to vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewViewState.kt
index 63f14f72f6..96e8316323 100644
--- a/vector/src/debug/java/im/vector/app/config/AnalyticsConfig.kt
+++ b/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewViewState.kt
@@ -14,14 +14,10 @@
* limitations under the License.
*/
-package im.vector.app.config
+package im.vector.app.features.location.preview
-import im.vector.app.BuildConfig
-import im.vector.app.features.analytics.AnalyticsConfig
+import com.airbnb.mvrx.MavericksState
-val analyticsConfig: AnalyticsConfig = object : AnalyticsConfig {
- override val isEnabled = BuildConfig.APPLICATION_ID == "im.vector.app.debug"
- override val postHogHost = "https://posthog.element.dev"
- override val postHogApiKey = "phc_VtA1L35nw3aeAtHIx1ayrGdzGkss7k1xINeXcoIQzXN"
- override val policyLink = "https://element.io/cookie-policy"
-}
+data class LocationPreviewViewState(
+ val loadingMapHasFailed: Boolean = false
+) : MavericksState
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 b0adeff04b..937e1bdf55 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
@@ -27,9 +27,9 @@ import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.google.android.material.textfield.TextInputLayout
-import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.extensions.hideKeyboard
+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
@@ -43,7 +43,9 @@ import javax.inject.Inject
/**
* In this screen, the user is prompted to enter a homeserver url.
*/
-class LoginServerUrlFormFragment @Inject constructor() : AbstractLoginFragment() {
+class LoginServerUrlFormFragment @Inject constructor(
+ private val buildMeta: BuildMeta,
+) : AbstractLoginFragment() {
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLoginServerUrlFormBinding {
return FragmentLoginServerUrlFormBinding.inflate(inflater, container, false)
@@ -99,7 +101,7 @@ class LoginServerUrlFormFragment @Inject constructor() : AbstractLoginFragment() {
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLoginSplashBinding {
@@ -57,12 +58,12 @@ class LoginSplashFragment @Inject constructor(
private fun setupViews() {
views.loginSplashSubmit.debouncedClicks { getStarted() }
- if (BuildConfig.DEBUG || vectorPreferences.developerMode()) {
+ if (buildMeta.isDebug || vectorPreferences.developerMode()) {
views.loginSplashVersion.isVisible = true
@SuppressLint("SetTextI18n")
- views.loginSplashVersion.text = "Version : ${BuildConfig.VERSION_NAME}\n" +
- "Branch: ${BuildConfig.GIT_BRANCH_NAME}\n" +
- "Build: ${BuildConfig.BUILD_NUMBER}"
+ views.loginSplashVersion.text = "Version : ${buildMeta.versionName}\n" +
+ "Branch: ${buildMeta.gitBranchName}\n" +
+ "Build: ${buildMeta.buildNumber}"
views.loginSplashVersion.debouncedClicks { navigator.openDebug(requireContext()) }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginServerUrlFormFragment2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginServerUrlFormFragment2.kt
index bcd2d84346..50f8f38634 100644
--- a/vector/src/main/java/im/vector/app/features/login2/LoginServerUrlFormFragment2.kt
+++ b/vector/src/main/java/im/vector/app/features/login2/LoginServerUrlFormFragment2.kt
@@ -26,9 +26,9 @@ import android.widget.ArrayAdapter
import androidx.core.view.isInvisible
import androidx.lifecycle.lifecycleScope
import com.google.android.material.textfield.TextInputLayout
-import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.extensions.hideKeyboard
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.utils.ensureProtocol
import im.vector.app.databinding.FragmentLoginServerUrlForm2Binding
import kotlinx.coroutines.flow.launchIn
@@ -43,7 +43,9 @@ import javax.net.ssl.HttpsURLConnection
/**
* In this screen, the user is prompted to enter a homeserver url.
*/
-class LoginServerUrlFormFragment2 @Inject constructor() : AbstractLoginFragment2() {
+class LoginServerUrlFormFragment2 @Inject constructor(
+ private val buildMeta: BuildMeta,
+) : AbstractLoginFragment2() {
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLoginServerUrlForm2Binding {
return FragmentLoginServerUrlForm2Binding.inflate(inflater, container, false)
@@ -80,7 +82,7 @@ class LoginServerUrlFormFragment2 @Inject constructor() : AbstractLoginFragment2
}
private fun setupUi(state: LoginViewState2) {
- val completions = state.knownCustomHomeServersUrls + if (BuildConfig.DEBUG) listOf("http://10.0.2.2:8080") else emptyList()
+ val completions = state.knownCustomHomeServersUrls + if (buildMeta.isDebug) listOf("http://10.0.2.2:8080") else emptyList()
views.loginServerUrlFormHomeServerUrl.setAdapter(
ArrayAdapter(
requireContext(),
diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginSplashSignUpSignInSelectionFragment2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginSplashSignUpSignInSelectionFragment2.kt
index 611b5f4cd2..84af28f75e 100644
--- a/vector/src/main/java/im/vector/app/features/login2/LoginSplashSignUpSignInSelectionFragment2.kt
+++ b/vector/src/main/java/im/vector/app/features/login2/LoginSplashSignUpSignInSelectionFragment2.kt
@@ -22,7 +22,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
-import im.vector.app.BuildConfig
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.databinding.FragmentLoginSplash2Binding
import im.vector.app.features.settings.VectorPreferences
import javax.inject.Inject
@@ -32,7 +32,8 @@ import javax.inject.Inject
* This is the new splash screen.
*/
class LoginSplashSignUpSignInSelectionFragment2 @Inject constructor(
- private val vectorPreferences: VectorPreferences
+ private val vectorPreferences: VectorPreferences,
+ private val buildMeta: BuildMeta,
) : AbstractLoginFragment2() {
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLoginSplash2Binding {
@@ -49,12 +50,12 @@ class LoginSplashSignUpSignInSelectionFragment2 @Inject constructor(
views.loginSignupSigninSignUp.setOnClickListener { signUp() }
views.loginSignupSigninSignIn.setOnClickListener { signIn() }
- if (BuildConfig.DEBUG || vectorPreferences.developerMode()) {
+ if (buildMeta.isDebug || vectorPreferences.developerMode()) {
views.loginSplashVersion.isVisible = true
@SuppressLint("SetTextI18n")
- views.loginSplashVersion.text = "Version : ${BuildConfig.VERSION_NAME}\n" +
- "Branch: ${BuildConfig.GIT_BRANCH_NAME}\n" +
- "Build: ${BuildConfig.BUILD_NUMBER}"
+ views.loginSplashVersion.text = "Version : ${buildMeta.versionName}\n" +
+ "Branch: ${buildMeta.gitBranchName}\n" +
+ "Build: ${buildMeta.buildNumber}"
views.loginSplashVersion.debouncedClicks { navigator.openDebug(requireContext()) }
}
}
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 d2404b5bb8..38db642287 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
@@ -33,10 +33,10 @@ import androidx.core.view.ViewCompat
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.di.ActiveSessionHolder
import im.vector.app.core.error.fatalError
import im.vector.app.features.VectorFeatures
-import im.vector.app.features.VectorFeatures.OnboardingVariant
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toAnalyticsViewRoom
import im.vector.app.features.analytics.plan.ViewRoom
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 1ca72b8399..1cf80de4ee 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,9 +16,9 @@
package im.vector.app.features.notifications
import android.net.Uri
-import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.extensions.takeAs
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.time.Clock
import im.vector.app.features.displayname.getBestName
@@ -62,6 +62,7 @@ class NotifiableEventResolver @Inject constructor(
private val noticeEventFormatter: NoticeEventFormatter,
private val displayableEventFormatter: DisplayableEventFormatter,
private val clock: Clock,
+ private val buildMeta: BuildMeta,
) {
// private val eventDisplay = RiotEventDisplay(context)
@@ -264,7 +265,7 @@ class NotifiableEventResolver @Inject constructor(
)
} else {
Timber.e("## unsupported notifiable event for eventId [${event.eventId}]")
- if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
+ if (buildMeta.lowPrivacyLoggingEnabled) {
Timber.e("## unsupported notifiable event for event [$event]")
}
// TODO generic handling?
diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationActionIds.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationActionIds.kt
new file mode 100644
index 0000000000..3bd7a635ae
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationActionIds.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.notifications
+
+import im.vector.app.core.resources.BuildMeta
+import javax.inject.Inject
+
+/**
+ * Util class for creating notifications.
+ * Note: Cannot inject ColorProvider in the constructor, because it requires an Activity
+ */
+
+data class NotificationActionIds @Inject constructor(
+ private val buildMeta: BuildMeta,
+) {
+
+ val join = "${buildMeta.applicationId}.NotificationActions.JOIN_ACTION"
+ val reject = "${buildMeta.applicationId}.NotificationActions.REJECT_ACTION"
+ val quickLaunch = "${buildMeta.applicationId}.NotificationActions.QUICK_LAUNCH_ACTION"
+ val markRoomRead = "${buildMeta.applicationId}.NotificationActions.MARK_ROOM_READ_ACTION"
+ val smartReply = "${buildMeta.applicationId}.NotificationActions.SMART_REPLY_ACTION"
+ val dismissSummary = "${buildMeta.applicationId}.NotificationActions.DISMISS_SUMMARY_ACTION"
+ val dismissRoom = "${buildMeta.applicationId}.NotificationActions.DISMISS_ROOM_NOTIF_ACTION"
+ val tapToView = "${buildMeta.applicationId}.NotificationActions.TAP_TO_VIEW_ACTION"
+ val diagnostic = "${buildMeta.applicationId}.NotificationActions.DIAGNOSTIC"
+ val push = "${buildMeta.applicationId}.PUSH"
+}
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 c01be9a44f..3fe0898eb4 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
@@ -48,31 +48,32 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
@Inject lateinit var analyticsTracker: AnalyticsTracker
@Inject lateinit var clock: Clock
+ @Inject lateinit var actionIds: NotificationActionIds
override fun onReceive(context: Context?, intent: Intent?) {
if (intent == null || context == null) return
Timber.v("NotificationBroadcastReceiver received : $intent")
when (intent.action) {
- NotificationUtils.SMART_REPLY_ACTION ->
+ actionIds.smartReply ->
handleSmartReply(intent, context)
- NotificationUtils.DISMISS_ROOM_NOTIF_ACTION ->
+ actionIds.dismissRoom ->
intent.getStringExtra(KEY_ROOM_ID)?.let { roomId ->
notificationDrawerManager.updateEvents { it.clearMessagesForRoom(roomId) }
}
- NotificationUtils.DISMISS_SUMMARY_ACTION ->
+ actionIds.dismissSummary ->
notificationDrawerManager.clearAllEvents()
- NotificationUtils.MARK_ROOM_READ_ACTION ->
+ actionIds.markRoomRead ->
intent.getStringExtra(KEY_ROOM_ID)?.let { roomId ->
notificationDrawerManager.updateEvents { it.clearMessagesForRoom(roomId) }
handleMarkAsRead(roomId)
}
- NotificationUtils.JOIN_ACTION -> {
+ actionIds.join -> {
intent.getStringExtra(KEY_ROOM_ID)?.let { roomId ->
notificationDrawerManager.updateEvents { it.clearMemberShipNotificationForRoom(roomId) }
handleJoinRoom(roomId)
}
}
- NotificationUtils.REJECT_ACTION -> {
+ actionIds.reject -> {
intent.getStringExtra(KEY_ROOM_ID)?.let { roomId ->
notificationDrawerManager.updateEvents { it.clearMemberShipNotificationForRoom(roomId) }
handleRejectRoom(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 686ed324dc..5f43ff6b90 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
@@ -20,8 +20,8 @@ import android.os.Handler
import android.os.HandlerThread
import androidx.annotation.WorkerThread
import im.vector.app.ActiveSessionDataSource
-import im.vector.app.BuildConfig
import im.vector.app.R
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.utils.FirstThrottler
import im.vector.app.features.displayname.getBestName
import im.vector.app.features.settings.VectorPreferences
@@ -46,7 +46,8 @@ class NotificationDrawerManager @Inject constructor(
private val activeSessionDataSource: ActiveSessionDataSource,
private val notifiableEventProcessor: NotifiableEventProcessor,
private val notificationRenderer: NotificationRenderer,
- private val notificationEventPersistence: NotificationEventPersistence
+ private val notificationEventPersistence: NotificationEventPersistence,
+ private val buildMeta: BuildMeta,
) {
private val handlerThread: HandlerThread = HandlerThread("NotificationDrawerManager", Thread.MIN_PRIORITY)
@@ -92,7 +93,7 @@ class NotificationDrawerManager @Inject constructor(
}
// If we support multi session, event list should be per userId
// Currently only manage single session
- if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
+ if (buildMeta.lowPrivacyLoggingEnabled) {
Timber.d("onNotifiableEventReceived(): $notifiableEvent")
} else {
Timber.d("onNotifiableEventReceived(): is push: ${notifiableEvent.canBeReplaced}")
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 b5bd02b9d5..8f05819fc4 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
@@ -45,7 +45,6 @@ import androidx.core.content.getSystemService
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.IconCompat
import androidx.fragment.app.Fragment
-import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.extensions.createIgnoredUri
import im.vector.app.core.platform.PendingIntentCompat
@@ -69,16 +68,13 @@ import javax.inject.Inject
import javax.inject.Singleton
import kotlin.random.Random
-/**
- * Util class for creating notifications.
- * Note: Cannot inject ColorProvider in the constructor, because it requires an Activity
- */
@Singleton
class NotificationUtils @Inject constructor(
private val context: Context,
private val stringProvider: StringProvider,
private val vectorPreferences: VectorPreferences,
private val clock: Clock,
+ private val actionIds: NotificationActionIds,
) {
companion object {
@@ -94,21 +90,6 @@ class NotificationUtils @Inject constructor(
*/
const val NOTIFICATION_ID_FOREGROUND_SERVICE = 61
- /* ==========================================================================================
- * IDs for actions
- * ========================================================================================== */
-
- const val JOIN_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationActions.JOIN_ACTION"
- const val REJECT_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationActions.REJECT_ACTION"
- private const val QUICK_LAUNCH_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationActions.QUICK_LAUNCH_ACTION"
- const val MARK_ROOM_READ_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationActions.MARK_ROOM_READ_ACTION"
- const val SMART_REPLY_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationActions.SMART_REPLY_ACTION"
- const val DISMISS_SUMMARY_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationActions.DISMISS_SUMMARY_ACTION"
- const val DISMISS_ROOM_NOTIF_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationActions.DISMISS_ROOM_NOTIF_ACTION"
- const val TAP_TO_VIEW_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationActions.TAP_TO_VIEW_ACTION"
- const val DIAGNOSTIC_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationActions.DIAGNOSTIC"
- const val PUSH_ACTION = "${BuildConfig.APPLICATION_ID}.PUSH"
-
/* ==========================================================================================
* IDs for channels
* ========================================================================================== */
@@ -651,7 +632,7 @@ class NotificationUtils @Inject constructor(
// Add actions and notification intents
// Mark room as read
val markRoomReadIntent = Intent(context, NotificationBroadcastReceiver::class.java)
- markRoomReadIntent.action = MARK_ROOM_READ_ACTION
+ markRoomReadIntent.action = actionIds.markRoomRead
markRoomReadIntent.data = createIgnoredUri(roomInfo.roomId)
markRoomReadIntent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomInfo.roomId)
val markRoomReadPendingIntent = PendingIntent.getBroadcast(
@@ -698,7 +679,7 @@ class NotificationUtils @Inject constructor(
val intent = Intent(context, NotificationBroadcastReceiver::class.java)
intent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomInfo.roomId)
- intent.action = DISMISS_ROOM_NOTIF_ACTION
+ intent.action = actionIds.dismissRoom
val pendingIntent = PendingIntent.getBroadcast(
context.applicationContext,
clock.epochMillis().toInt(),
@@ -733,7 +714,7 @@ class NotificationUtils @Inject constructor(
val roomId = inviteNotifiableEvent.roomId
// offer to type a quick reject button
val rejectIntent = Intent(context, NotificationBroadcastReceiver::class.java)
- rejectIntent.action = REJECT_ACTION
+ rejectIntent.action = actionIds.reject
rejectIntent.data = createIgnoredUri("$roomId&$matrixId")
rejectIntent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId)
val rejectIntentPendingIntent = PendingIntent.getBroadcast(
@@ -751,7 +732,7 @@ class NotificationUtils @Inject constructor(
// offer to type a quick accept button
val joinIntent = Intent(context, NotificationBroadcastReceiver::class.java)
- joinIntent.action = JOIN_ACTION
+ joinIntent.action = actionIds.join
joinIntent.data = createIgnoredUri("$roomId&$matrixId")
joinIntent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId)
val joinIntentPendingIntent = PendingIntent.getBroadcast(
@@ -834,7 +815,7 @@ class NotificationUtils @Inject constructor(
private fun buildOpenRoomIntent(roomId: String): PendingIntent? {
val roomIntentTap = RoomDetailActivity.newIntent(context, TimelineArgs(roomId = roomId, switchToParentSpace = true), true)
- roomIntentTap.action = TAP_TO_VIEW_ACTION
+ roomIntentTap.action = actionIds.tapToView
// pending intent get reused by system, this will mess up the extra params, so put unique info to avoid that
roomIntentTap.data = createIgnoredUri("openRoom?$roomId")
@@ -872,7 +853,7 @@ class NotificationUtils @Inject constructor(
val intent: Intent
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent = Intent(context, NotificationBroadcastReceiver::class.java)
- intent.action = SMART_REPLY_ACTION
+ intent.action = actionIds.smartReply
intent.data = createIgnoredUri(roomId)
intent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId)
return PendingIntent.getBroadcast(
@@ -948,7 +929,7 @@ class NotificationUtils @Inject constructor(
private fun getDismissSummaryPendingIntent(): PendingIntent {
val intent = Intent(context, NotificationBroadcastReceiver::class.java)
- intent.action = DISMISS_SUMMARY_ACTION
+ intent.action = actionIds.dismissSummary
intent.data = createIgnoredUri("deleteSummary")
return PendingIntent.getBroadcast(
context.applicationContext,
@@ -987,7 +968,7 @@ class NotificationUtils @Inject constructor(
fun displayDiagnosticNotification() {
val testActionIntent = Intent(context, TestNotificationReceiver::class.java)
- testActionIntent.action = DIAGNOSTIC_ACTION
+ testActionIntent.action = actionIds.diagnostic
val testPendingIntent = PendingIntent.getBroadcast(
context,
0,
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 8d9f372bdd..9837db8e91 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
@@ -16,6 +16,7 @@
package im.vector.app.features.onboarding
+import im.vector.app.config.OnboardingVariant
import im.vector.app.core.platform.ScreenOrientationLocker
import im.vector.app.databinding.ActivityLoginBinding
import im.vector.app.features.VectorFeatures
@@ -34,8 +35,8 @@ class OnboardingVariantFactory @Inject constructor(
onboardingViewModel: Lazy,
loginViewModel2: Lazy
) = when (vectorFeatures.onboardingVariant()) {
- VectorFeatures.OnboardingVariant.LEGACY -> error("Legacy is not supported by the FTUE")
- VectorFeatures.OnboardingVariant.FTUE_AUTH -> FtueAuthVariant(
+ OnboardingVariant.LEGACY -> error("Legacy is not supported by the FTUE")
+ OnboardingVariant.FTUE_AUTH -> FtueAuthVariant(
views = views,
onboardingViewModel = onboardingViewModel.value,
activity = activity,
@@ -43,7 +44,7 @@ class OnboardingVariantFactory @Inject constructor(
vectorFeatures = vectorFeatures,
orientationLocker = orientationLocker
)
- VectorFeatures.OnboardingVariant.LOGIN_2 -> Login2Variant(
+ OnboardingVariant.LOGIN_2 -> Login2Variant(
views = views,
loginViewModel = loginViewModel2.value,
activity = activity,
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 6cadb4308a..8136dc379b 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
@@ -32,7 +32,6 @@ import im.vector.app.core.extensions.isMatrixId
import im.vector.app.core.extensions.toReducedUrl
import im.vector.app.core.extensions.vectorStore
import im.vector.app.core.platform.VectorViewModel
-import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.ensureProtocol
import im.vector.app.core.utils.ensureTrailingSlash
@@ -63,6 +62,7 @@ import org.matrix.android.sdk.api.auth.registration.RegistrationAvailability
import org.matrix.android.sdk.api.auth.registration.RegistrationWizard
import org.matrix.android.sdk.api.failure.isHomeserverUnavailable
import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.util.BuildVersionSdkIntProvider
import timber.log.Timber
import java.util.UUID
import java.util.concurrent.CancellationException
@@ -86,7 +86,7 @@ class OnboardingViewModel @AssistedInject constructor(
private val startAuthenticationFlowUseCase: StartAuthenticationFlowUseCase,
private val vectorOverrides: VectorOverrides,
private val registrationActionHandler: RegistrationActionHandler,
- private val buildMeta: BuildMeta,
+ private val sdkIntProvider: BuildVersionSdkIntProvider,
) : VectorViewModel(initialState) {
@AssistedFactory
@@ -708,7 +708,7 @@ class OnboardingViewModel @AssistedInject constructor(
private fun onAuthenticationStartError(error: Throwable, trigger: OnboardingAction.HomeServerChange) {
when {
- error.isHomeserverUnavailable() && applicationContext.inferNoConnectivity(buildMeta) -> _viewEvents.post(
+ error.isHomeserverUnavailable() && applicationContext.inferNoConnectivity(sdkIntProvider) -> _viewEvents.post(
OnboardingViewEvents.Failure(error)
)
deeplinkUrlIsUnavailable(error, trigger) -> _viewEvents.post(
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 58b1edddf8..c2d2346765 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
@@ -63,7 +63,9 @@ class FtueAuthCombinedLoginFragment @Inject constructor(
views.loginRoot.realignPercentagesToParent()
views.editServerButton.debouncedClicks { viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.EditServerSelection)) }
views.loginPasswordInput.setOnImeDoneListener { submit() }
- views.loginInput.setOnFocusLostListener { viewModel.handle(OnboardingAction.UserNameEnteredAction.Login(views.loginInput.content())) }
+ views.loginInput.setOnFocusLostListener(viewLifecycleOwner) {
+ viewModel.handle(OnboardingAction.UserNameEnteredAction.Login(views.loginInput.content()))
+ }
views.loginForgotPassword.debouncedClicks { viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnForgetPasswordClicked)) }
}
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 c69706a17b..8340fb903a 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
@@ -86,7 +86,7 @@ class FtueAuthCombinedRegisterFragment @Inject constructor() : AbstractSSOFtueAu
views.createAccountEntryFooter.text = ""
}
- views.createAccountInput.setOnFocusLostListener {
+ views.createAccountInput.setOnFocusLostListener(viewLifecycleOwner) {
viewModel.handle(OnboardingAction.UserNameEnteredAction.Registration(views.createAccountInput.content()))
}
}
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 b2a99ffb7e..b16ad3ee93 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
@@ -27,9 +27,9 @@ import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.google.android.material.textfield.TextInputLayout
-import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.extensions.hideKeyboard
+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
@@ -47,7 +47,9 @@ import javax.inject.Inject
/**
* In this screen, the user is prompted to enter a homeserver url.
*/
-class FtueAuthServerUrlFormFragment @Inject constructor() : AbstractFtueAuthFragment() {
+class FtueAuthServerUrlFormFragment @Inject constructor(
+ private val buildMeta: BuildMeta,
+) : AbstractFtueAuthFragment() {
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLoginServerUrlFormBinding {
return FragmentLoginServerUrlFormBinding.inflate(inflater, container, false)
@@ -103,7 +105,7 @@ class FtueAuthServerUrlFormFragment @Inject constructor() : AbstractFtueAuthFrag
views.loginServerUrlFormNotice.text = getString(R.string.login_server_url_form_common_notice)
}
}
- val completions = state.knownCustomHomeServersUrls + if (BuildConfig.DEBUG) listOf("http://10.0.2.2:8080") else emptyList()
+ val completions = state.knownCustomHomeServersUrls + if (buildMeta.isDebug) listOf("http://10.0.2.2:8080") else emptyList()
views.loginServerUrlFormHomeServerUrl.setAdapter(
ArrayAdapter(
requireContext(),
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 0d86c4cd24..0333f6047b 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
@@ -27,10 +27,10 @@ import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.tabs.TabLayoutMediator
-import im.vector.app.BuildConfig
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
import im.vector.app.databinding.FragmentFtueSplashCarouselBinding
import im.vector.app.features.VectorFeatures
import im.vector.app.features.onboarding.OnboardingAction
@@ -48,9 +48,12 @@ class FtueAuthSplashCarouselFragment @Inject constructor(
private val vectorPreferences: VectorPreferences,
private val vectorFeatures: VectorFeatures,
private val carouselController: SplashCarouselController,
- private val carouselStateFactory: SplashCarouselStateFactory
+ private val carouselStateFactory: SplashCarouselStateFactory,
+ private val buildMeta: BuildMeta,
) : AbstractFtueAuthFragment() {
+ private var tabLayoutMediator: TabLayoutMediator? = null
+
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueSplashCarouselBinding {
return FragmentFtueSplashCarouselBinding.inflate(inflater, container, false)
}
@@ -60,10 +63,19 @@ class FtueAuthSplashCarouselFragment @Inject constructor(
setupViews()
}
+ override fun onDestroyView() {
+ tabLayoutMediator?.detach()
+ tabLayoutMediator = null
+ views.splashCarousel.adapter = null
+ super.onDestroyView()
+ }
+
private fun setupViews() {
val carouselAdapter = carouselController.adapter
views.splashCarousel.adapter = carouselAdapter
- TabLayoutMediator(views.carouselIndicator, views.splashCarousel) { _, _ -> }.attach()
+ tabLayoutMediator = TabLayoutMediator(views.carouselIndicator, views.splashCarousel) { _, _ -> }
+ .also { it.attach() }
+
carouselController.setData(carouselStateFactory.create())
val isAlreadyHaveAccountEnabled = vectorFeatures.isOnboardingAlreadyHaveAccountSplashEnabled()
@@ -76,11 +88,11 @@ class FtueAuthSplashCarouselFragment @Inject constructor(
debouncedClicks { alreadyHaveAnAccount() }
}
- if (BuildConfig.DEBUG || vectorPreferences.developerMode()) {
+ if (buildMeta.isDebug || vectorPreferences.developerMode()) {
views.loginSplashVersion.isVisible = true
@SuppressLint("SetTextI18n")
- views.loginSplashVersion.text = "Version : ${BuildConfig.VERSION_NAME}#${BuildConfig.BUILD_NUMBER}\n" +
- "Branch: ${BuildConfig.GIT_BRANCH_NAME}"
+ views.loginSplashVersion.text = "Version : ${buildMeta.versionName}#${buildMeta.buildNumber}\n" +
+ "Branch: ${buildMeta.gitBranchName}"
views.loginSplashVersion.debouncedClicks { navigator.openDebug(requireContext()) }
}
views.splashCarousel.registerAutomaticUntilInteractionTransitions()
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 cd1e4b2714..a04e8a5c01 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
@@ -22,8 +22,8 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
-import im.vector.app.BuildConfig
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
@@ -36,7 +36,8 @@ import javax.inject.Inject
*/
class FtueAuthSplashFragment @Inject constructor(
private val vectorPreferences: VectorPreferences,
- private val vectorFeatures: VectorFeatures
+ private val vectorFeatures: VectorFeatures,
+ private val buildMeta: BuildMeta,
) : AbstractFtueAuthFragment() {
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueAuthSplashBinding {
@@ -59,12 +60,12 @@ class FtueAuthSplashFragment @Inject constructor(
debouncedClicks { alreadyHaveAnAccount() }
}
- if (BuildConfig.DEBUG || vectorPreferences.developerMode()) {
+ if (buildMeta.isDebug || vectorPreferences.developerMode()) {
views.loginSplashVersion.isVisible = true
@SuppressLint("SetTextI18n")
- views.loginSplashVersion.text = "Version : ${BuildConfig.VERSION_NAME}\n" +
- "Branch: ${BuildConfig.GIT_BRANCH_NAME}\n" +
- "Build: ${BuildConfig.BUILD_NUMBER}"
+ views.loginSplashVersion.text = "Version : ${buildMeta.versionName}\n" +
+ "Branch: ${buildMeta.gitBranchName}\n" +
+ "Build: ${buildMeta.buildNumber}"
views.loginSplashVersion.debouncedClicks { navigator.openDebug(requireContext()) }
}
}
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 e2e5ee2c6e..ad09593ebd 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
@@ -30,6 +30,7 @@ import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.extensions.getAllChildFragments
import im.vector.app.core.extensions.toOnOff
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.features.settings.VectorLocale
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.settings.devtools.GossipingEventsSerializer
@@ -50,6 +51,7 @@ import okhttp3.Response
import org.json.JSONException
import org.json.JSONObject
import org.matrix.android.sdk.api.Matrix
+import org.matrix.android.sdk.api.util.BuildVersionSdkIntProvider
import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.api.util.MatrixJsonParser
import org.matrix.android.sdk.api.util.MimeTypes
@@ -74,7 +76,9 @@ class BugReporter @Inject constructor(
private val vectorPreferences: VectorPreferences,
private val vectorFileLogger: VectorFileLogger,
private val systemLocaleProvider: SystemLocaleProvider,
- private val matrix: Matrix
+ private val matrix: Matrix,
+ private val buildMeta: BuildMeta,
+ private val sdkIntProvider: BuildVersionSdkIntProvider,
) {
var inMultiWindowMode = false
@@ -278,14 +282,14 @@ class BugReporter @Inject constructor(
.addFormDataPart("can_contact", canContact.toString())
.addFormDataPart("device_id", deviceId)
.addFormDataPart("version", versionProvider.getVersion(longFormat = true, useBuildNumber = false))
- .addFormDataPart("branch_name", BuildConfig.GIT_BRANCH_NAME)
+ .addFormDataPart("branch_name", buildMeta.gitBranchName)
.addFormDataPart("matrix_sdk_version", Matrix.getSdkVersion())
.addFormDataPart("olm_version", olmVersion)
.addFormDataPart("device", Build.MODEL.trim())
.addFormDataPart("verbose_log", vectorPreferences.labAllowedExtendedLogging().toOnOff())
.addFormDataPart("multi_window", inMultiWindowMode.toOnOff())
.addFormDataPart(
- "os", Build.VERSION.RELEASE + " (API " + Build.VERSION.SDK_INT + ") " +
+ "os", Build.VERSION.RELEASE + " (API " + sdkIntProvider.get() + ") " +
Build.VERSION.INCREMENTAL + "-" + Build.VERSION.CODENAME
)
.addFormDataPart("locale", Locale.getDefault().toString())
@@ -299,7 +303,7 @@ class BugReporter @Inject constructor(
}
}
- val buildNumber = BuildConfig.BUILD_NUMBER
+ val buildNumber = buildMeta.buildNumber
if (buildNumber.isNotEmpty() && buildNumber != "0") {
builder.addFormDataPart("build_number", buildNumber)
}
@@ -339,9 +343,9 @@ class BugReporter @Inject constructor(
screenshot = null
// add some github labels
- builder.addFormDataPart("label", BuildConfig.VERSION_NAME)
- builder.addFormDataPart("label", BuildConfig.FLAVOR_DESCRIPTION)
- builder.addFormDataPart("label", BuildConfig.GIT_BRANCH_NAME)
+ builder.addFormDataPart("label", buildMeta.versionName)
+ builder.addFormDataPart("label", buildMeta.flavorDescription)
+ builder.addFormDataPart("label", buildMeta.gitBranchName)
// Special for Element
builder.addFormDataPart("label", "[Element]")
diff --git a/vector/src/main/java/im/vector/app/features/raw/wellknown/CryptoConfig.kt b/vector/src/main/java/im/vector/app/features/raw/wellknown/CryptoConfig.kt
new file mode 100644
index 0000000000..130fa0078a
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/raw/wellknown/CryptoConfig.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.raw.wellknown
+
+import im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy
+
+data class CryptoConfig(
+ val fallbackKeySharingStrategy: OutboundSessionKeySharingStrategy
+)
diff --git a/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnown.kt b/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnown.kt
index 0df5f0e9cf..78329350d3 100644
--- a/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnown.kt
+++ b/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnown.kt
@@ -68,7 +68,7 @@ data class E2EWellKnownConfig(
val secureBackupSetupMethods: List? = null,
/**
- * Configuration for sharing keys strategy which should be used instead of [im.vector.app.BuildConfig.outboundSessionKeySharingStrategy].
+ * Configuration for sharing keys strategy which should be used instead of [im.vector.app.config.Config.KEY_SHARING_STRATEGY].
* One of on_room_opening, on_typing or disabled.
*/
@Json(name = "outbound_keys_pre_sharing_mode")
diff --git a/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnownExt.kt b/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnownExt.kt
index 73662613f7..28c7fecf0b 100644
--- a/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnownExt.kt
+++ b/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnownExt.kt
@@ -16,7 +16,6 @@
package im.vector.app.features.raw.wellknown
-import im.vector.app.BuildConfig
import im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -35,12 +34,12 @@ suspend fun RawService.getElementWellknown(sessionParams: SessionParams): Elemen
fun ElementWellKnown.isE2EByDefault() = elementE2E?.e2eDefault ?: riotE2E?.e2eDefault ?: true
-fun ElementWellKnown?.getOutboundSessionKeySharingStrategyOrDefault(): OutboundSessionKeySharingStrategy {
+fun ElementWellKnown?.getOutboundSessionKeySharingStrategyOrDefault(fallback: OutboundSessionKeySharingStrategy): OutboundSessionKeySharingStrategy {
return when (this?.elementE2E?.outboundsKeyPreSharingMode) {
"on_room_opening" -> OutboundSessionKeySharingStrategy.WhenEnteringRoom
"on_typing" -> OutboundSessionKeySharingStrategy.WhenTyping
"disabled" -> OutboundSessionKeySharingStrategy.WhenSendingEvent
- else -> BuildConfig.outboundSessionKeySharingStrategy
+ else -> fallback
}
}
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 326f20845f..4666d586d3 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
@@ -19,9 +19,9 @@ package im.vector.app.features.settings
import android.content.Context
import android.content.res.Configuration
import androidx.core.content.edit
-import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.di.DefaultSharedPreferences
+import im.vector.app.core.resources.BuildMeta
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import timber.log.Timber
@@ -53,12 +53,14 @@ object VectorLocale {
private set
private lateinit var context: Context
+ private lateinit var buildMeta: BuildMeta
/**
* Init this object.
*/
- fun init(context: Context) {
+ fun init(context: Context, buildMeta: BuildMeta) {
this.context = context
+ this.buildMeta = buildMeta
val preferences = DefaultSharedPreferences.getInstance(context)
if (preferences.contains(APPLICATION_LOCALE_LANGUAGE_KEY)) {
@@ -174,7 +176,7 @@ object VectorLocale {
.setScript(script)
.build()
} catch (exception: IllformedLocaleException) {
- if (BuildConfig.DEBUG) {
+ if (buildMeta.isDebug) {
throw exception
}
// Ignore this locale in production
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 3b202969e5..ac14bfc3c7 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,9 +23,9 @@ import android.provider.MediaStore
import androidx.annotation.BoolRes
import androidx.core.content.edit
import com.squareup.seismic.ShakeDetector
-import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.di.DefaultSharedPreferences
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.time.Clock
import im.vector.app.features.disclaimer.SHARED_PREF_KEY
import im.vector.app.features.home.ShortcutsHandler
@@ -38,6 +38,7 @@ import javax.inject.Inject
class VectorPreferences @Inject constructor(
private val context: Context,
private val clock: Clock,
+ private val buildMeta: BuildMeta,
) {
companion object {
@@ -364,7 +365,7 @@ class VectorPreferences @Inject constructor(
}
fun failFast(): Boolean {
- return BuildConfig.DEBUG || (developerMode() && defaultPrefs.getBoolean(SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY, false))
+ return buildMeta.isDebug || (developerMode() && defaultPrefs.getBoolean(SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY, false))
}
fun didAskUserToEnableSessionPush(): Boolean {
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 5844467a1f..df7baa7397 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
@@ -18,10 +18,10 @@ package im.vector.app.features.settings
import android.os.Bundle
import androidx.preference.Preference
-import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.extensions.orEmpty
import im.vector.app.core.preference.VectorPreference
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.utils.FirstThrottler
import im.vector.app.core.utils.copyToClipboard
import im.vector.app.core.utils.openAppSettingsPage
@@ -32,7 +32,8 @@ import org.matrix.android.sdk.api.Matrix
import javax.inject.Inject
class VectorSettingsHelpAboutFragment @Inject constructor(
- private val versionProvider: VersionProvider
+ private val versionProvider: VersionProvider,
+ private val buildMeta: BuildMeta,
) : VectorSettingsBaseFragment() {
override var titleRes = R.string.preference_root_help_about
@@ -66,9 +67,9 @@ class VectorSettingsHelpAboutFragment @Inject constructor(
findPreference(VectorPreferences.SETTINGS_VERSION_PREFERENCE_KEY)!!.let {
it.summary = buildString {
append(versionProvider.getVersion(longFormat = false, useBuildNumber = true))
- if (BuildConfig.DEBUG) {
+ if (buildMeta.isDebug) {
append(" ")
- append(BuildConfig.GIT_BRANCH_NAME)
+ append(buildMeta.gitBranchName)
}
}
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 f25ad0661a..ac8a47b81e 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
@@ -35,7 +35,6 @@ import androidx.recyclerview.widget.RecyclerView
import com.airbnb.mvrx.fragmentViewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
-import im.vector.app.config.analyticsConfig
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.dialogs.ExportKeysDialog
import im.vector.app.core.extensions.queryExportKeys
@@ -51,6 +50,7 @@ import im.vector.app.core.utils.copyToClipboard
import im.vector.app.core.utils.openFileSelection
import im.vector.app.core.utils.toast
import im.vector.app.databinding.DialogImportE2eKeysBinding
+import im.vector.app.features.analytics.AnalyticsConfig
import im.vector.app.features.analytics.plan.MobileScreen
import im.vector.app.features.analytics.ui.consent.AnalyticsConsentViewActions
import im.vector.app.features.analytics.ui.consent.AnalyticsConsentViewModel
@@ -84,7 +84,8 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
private val keysExporter: KeysExporter,
private val keysImporter: KeysImporter,
private val rawService: RawService,
- private val navigator: Navigator
+ private val navigator: Navigator,
+ private val analyticsConfig: AnalyticsConfig,
) : VectorSettingsBaseFragment() {
override var titleRes = R.string.settings_security_and_privacy
diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationsTroubleshootFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationsTroubleshootFragment.kt
index 0eb22bf24d..8a3407b428 100644
--- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationsTroubleshootFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationsTroubleshootFragment.kt
@@ -34,7 +34,7 @@ import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentSettingsNotificationsTroubleshootBinding
-import im.vector.app.features.notifications.NotificationUtils
+import im.vector.app.features.notifications.NotificationActionIds
import im.vector.app.features.rageshake.BugReporter
import im.vector.app.features.settings.VectorSettingsFragmentInteractionListener
import im.vector.app.features.settings.troubleshoot.NotificationTroubleshootTestManager
@@ -46,7 +46,8 @@ import javax.inject.Inject
class VectorSettingsNotificationsTroubleshootFragment @Inject constructor(
private val bugReporter: BugReporter,
- private val testManagerFactory: NotificationTroubleshootTestManagerFactory
+ private val testManagerFactory: NotificationTroubleshootTestManagerFactory,
+ private val actionIds: NotificationActionIds,
) : VectorBaseFragment() {
private var testManager: NotificationTroubleshootTestManager? = null
@@ -151,11 +152,11 @@ class VectorSettingsNotificationsTroubleshootFragment @Inject constructor(
tryOrNull("Unable to register the receiver") {
LocalBroadcastManager.getInstance(requireContext())
- .registerReceiver(broadcastReceiverPush, IntentFilter(NotificationUtils.PUSH_ACTION))
+ .registerReceiver(broadcastReceiverPush, IntentFilter(actionIds.push))
}
tryOrNull("Unable to register the receiver") {
LocalBroadcastManager.getInstance(requireContext())
- .registerReceiver(broadcastReceiverNotification, IntentFilter(NotificationUtils.DIAGNOSTIC_ACTION))
+ .registerReceiver(broadcastReceiverNotification, IntentFilter(actionIds.diagnostic))
}
}
diff --git a/vector/src/main/java/im/vector/app/features/version/VersionProvider.kt b/vector/src/main/java/im/vector/app/features/version/VersionProvider.kt
index 96a7d917e5..4c8188dc8b 100644
--- a/vector/src/main/java/im/vector/app/features/version/VersionProvider.kt
+++ b/vector/src/main/java/im/vector/app/features/version/VersionProvider.kt
@@ -16,24 +16,27 @@
package im.vector.app.features.version
-import im.vector.app.BuildConfig
+import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.resources.VersionCodeProvider
import javax.inject.Inject
-class VersionProvider @Inject constructor(private val versionCodeProvider: VersionCodeProvider) {
+class VersionProvider @Inject constructor(
+ private val versionCodeProvider: VersionCodeProvider,
+ private val buildMeta: BuildMeta,
+) {
fun getVersion(longFormat: Boolean, useBuildNumber: Boolean): String {
- var result = "${BuildConfig.VERSION_NAME} [${versionCodeProvider.getVersionCode()}]"
+ var result = "${buildMeta.versionName} [${versionCodeProvider.getVersionCode()}]"
- var flavor = BuildConfig.SHORT_FLAVOR_DESCRIPTION
+ var flavor = buildMeta.flavorShortDescription
if (flavor.isNotBlank()) {
flavor += "-"
}
- var gitVersion = BuildConfig.GIT_REVISION
- val gitRevisionDate = BuildConfig.GIT_REVISION_DATE
- val buildNumber = BuildConfig.BUILD_NUMBER
+ var gitVersion = buildMeta.gitRevision
+ val gitRevisionDate = buildMeta.gitRevisionDate
+ val buildNumber = buildMeta.buildNumber
var useLongFormat = longFormat
diff --git a/vector/src/main/res/drawable/ic_location_pin_failed.xml b/vector/src/main/res/drawable/ic_location_pin_failed.xml
deleted file mode 100644
index 250d048836..0000000000
--- a/vector/src/main/res/drawable/ic_location_pin_failed.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/vector/src/main/res/layout/fragment_ftue_combined_login.xml b/vector/src/main/res/layout/fragment_ftue_combined_login.xml
index 9533ab29fc..12943b4dc0 100644
--- a/vector/src/main/res/layout/fragment_ftue_combined_login.xml
+++ b/vector/src/main/res/layout/fragment_ftue_combined_login.xml
@@ -147,6 +147,7 @@
app:layout_constraintTop_toBottomOf="@id/serverSelectionSpacing">
+
+
+
+
diff --git a/vector/src/main/res/layout/fragment_location_sharing.xml b/vector/src/main/res/layout/fragment_location_sharing.xml
index cd15f418ea..4f0825b992 100644
--- a/vector/src/main/res/layout/fragment_location_sharing.xml
+++ b/vector/src/main/res/layout/fragment_location_sharing.xml
@@ -52,4 +52,14 @@
app:layout_constraintBottom_toBottomOf="@id/shareLocationOptionsPicker"
app:layout_constraintEnd_toEndOf="@id/shareLocationOptionsPicker" />
+
+
diff --git a/vector/src/main/res/layout/item_timeline_event_location_stub.xml b/vector/src/main/res/layout/item_timeline_event_location_stub.xml
index e4c87dab71..8de98b2260 100644
--- a/vector/src/main/res/layout/item_timeline_event_location_stub.xml
+++ b/vector/src/main/res/layout/item_timeline_event_location_stub.xml
@@ -29,21 +29,16 @@
app:layout_constraintTop_toTopOf="@id/staticMapImageView"
app:layout_constraintVertical_bias="1.0" />
-
+ app:layout_constraintBottom_toTopOf="@id/liveLocationRunningBanner"
+ app:layout_constraintEnd_toEndOf="@id/staticMapImageView"
+ app:layout_constraintStart_toStartOf="@id/staticMapImageView"
+ app:layout_constraintTop_toTopOf="@id/staticMapImageView"
+ app:mapErrorDescription="@string/location_timeline_failed_to_load_map" />
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml
index 859e4daffc..6de931dfe6 100644
--- a/vector/src/main/res/values/strings.xml
+++ b/vector/src/main/res/values/strings.xml
@@ -3116,6 +3116,7 @@
${app_name} could not access your location. Please try again later.
Open with
Failed to load map
+ Unable to load map\nThis home server may not be configured to display maps.
Live location enabled
Loading live location…
Live location ended
diff --git a/vector/src/test/java/im/vector/app/features/location/LocationTrackerTest.kt b/vector/src/test/java/im/vector/app/features/location/LocationTrackerTest.kt
index 454a73cd70..ebb7419ddc 100644
--- a/vector/src/test/java/im/vector/app/features/location/LocationTrackerTest.kt
+++ b/vector/src/test/java/im/vector/app/features/location/LocationTrackerTest.kt
@@ -23,6 +23,7 @@ import im.vector.app.features.session.coroutineScope
import im.vector.app.test.fakes.FakeActiveSessionHolder
import im.vector.app.test.fakes.FakeContext
import im.vector.app.test.fakes.FakeLocationManager
+import im.vector.app.test.fixtures.aBuildMeta
import im.vector.app.test.test
import io.mockk.every
import io.mockk.just
@@ -56,7 +57,7 @@ class LocationTrackerTest {
@Before
fun setUp() {
mockkStatic("im.vector.app.features.session.SessionCoroutineScopesKt")
- locationTracker = LocationTracker(fakeContext.instance, fakeActiveSessionHolder.instance)
+ locationTracker = LocationTracker(fakeContext.instance, fakeActiveSessionHolder.instance, aBuildMeta())
fakeLocationManager.givenRemoveUpdates(locationTracker)
}
@@ -75,19 +76,19 @@ class LocationTrackerTest {
verifyOrder {
fakeLocationManager.instance.requestLocationUpdates(
LocationManager.FUSED_PROVIDER,
- MIN_TIME_TO_UPDATE_LOCATION_MILLIS,
+ locationTracker.minDurationToUpdateLocationMillis,
MIN_DISTANCE_TO_UPDATE_LOCATION_METERS,
locationTracker
)
fakeLocationManager.instance.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
- MIN_TIME_TO_UPDATE_LOCATION_MILLIS,
+ locationTracker.minDurationToUpdateLocationMillis,
MIN_DISTANCE_TO_UPDATE_LOCATION_METERS,
locationTracker
)
fakeLocationManager.instance.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
- MIN_TIME_TO_UPDATE_LOCATION_MILLIS,
+ locationTracker.minDurationToUpdateLocationMillis,
MIN_DISTANCE_TO_UPDATE_LOCATION_METERS,
locationTracker
)
@@ -154,7 +155,7 @@ class LocationTrackerTest {
locationTracker.onLocationChanged(fusedLocation)
locationTracker.onLocationChanged(gpsLocation)
locationTracker.onLocationChanged(networkLocation)
- advanceTimeBy(MIN_TIME_TO_UPDATE_LOCATION_MILLIS + 1)
+ advanceTimeBy(locationTracker.minDurationToUpdateLocationMillis + 1)
val expectedLocationData = LocationData(
latitude = 1.0,
@@ -188,7 +189,7 @@ class LocationTrackerTest {
locationTracker.onLocationChanged(gpsLocation)
locationTracker.onLocationChanged(networkLocation)
- advanceTimeBy(MIN_TIME_TO_UPDATE_LOCATION_MILLIS + 1)
+ advanceTimeBy(locationTracker.minDurationToUpdateLocationMillis + 1)
val expectedLocationData = LocationData(
latitude = 1.0,
@@ -217,7 +218,7 @@ class LocationTrackerTest {
val resultUpdates = locationTracker.locations.test(this)
locationTracker.onLocationChanged(networkLocation)
- advanceTimeBy(MIN_TIME_TO_UPDATE_LOCATION_MILLIS + 1)
+ advanceTimeBy(locationTracker.minDurationToUpdateLocationMillis + 1)
val expectedLocationData = LocationData(
latitude = 1.0,
@@ -243,7 +244,7 @@ class LocationTrackerTest {
val resultUpdates = locationTracker.locations.test(this)
locationTracker.requestLastKnownLocation()
- advanceTimeBy(MIN_TIME_TO_UPDATE_LOCATION_MILLIS + 1)
+ advanceTimeBy(locationTracker.minDurationToUpdateLocationMillis + 1)
val expectedLocationData = LocationData(
latitude = A_LATITUDE,
diff --git a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt
index a9bbb3eb07..61d3101b64 100644
--- a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt
+++ b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt
@@ -17,6 +17,7 @@
package im.vector.app.features.onboarding
import android.net.Uri
+import android.os.Build
import com.airbnb.mvrx.test.MvRxTestRule
import im.vector.app.R
import im.vector.app.features.login.LoginConfig
@@ -24,6 +25,7 @@ import im.vector.app.features.login.LoginMode
import im.vector.app.features.login.ReAuthHelper
import im.vector.app.features.login.SignMode
import im.vector.app.features.onboarding.StartAuthenticationFlowUseCase.StartAuthenticationResult
+import im.vector.app.test.TestBuildVersionSdkIntProvider
import im.vector.app.test.fakes.FakeActiveSessionHolder
import im.vector.app.test.fakes.FakeAnalyticsTracker
import im.vector.app.test.fakes.FakeAuthenticationService
@@ -43,7 +45,6 @@ import im.vector.app.test.fakes.FakeVectorFeatures
import im.vector.app.test.fakes.FakeVectorOverrides
import im.vector.app.test.fakes.toTestString
import im.vector.app.test.fixtures.a401ServerError
-import im.vector.app.test.fixtures.aBuildMeta
import im.vector.app.test.fixtures.aHomeServerCapabilities
import im.vector.app.test.test
import kotlinx.coroutines.test.runTest
@@ -720,7 +721,7 @@ class OnboardingViewModelTest {
fakeStartAuthenticationFlowUseCase.instance,
FakeVectorOverrides(),
fakeRegistrationActionHandler.instance,
- aBuildMeta(),
+ TestBuildVersionSdkIntProvider().also { it.value = Build.VERSION_CODES.O },
).also {
viewModel = it
initialState = state
diff --git a/vector/src/test/java/im/vector/app/test/fixtures/AnalyticsConfigFixture.kt b/vector/src/test/java/im/vector/app/test/fixtures/AnalyticsConfigFixture.kt
index 5fbcdd98d1..ea1769ecb2 100644
--- a/vector/src/test/java/im/vector/app/test/fixtures/AnalyticsConfigFixture.kt
+++ b/vector/src/test/java/im/vector/app/test/fixtures/AnalyticsConfigFixture.kt
@@ -24,10 +24,5 @@ object AnalyticsConfigFixture {
postHogHost: String = "http://posthog.url",
postHogApiKey: String = "api-key",
policyLink: String = "http://policy.link"
- ) = object : AnalyticsConfig {
- override val isEnabled: Boolean = isEnabled
- override val postHogHost = postHogHost
- override val postHogApiKey = postHogApiKey
- override val policyLink = policyLink
- }
+ ) = AnalyticsConfig(isEnabled, postHogHost, postHogApiKey, policyLink)
}
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 b0e6b1dd51..4f4649106d 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
@@ -16,7 +16,17 @@
package im.vector.app.test.fixtures
-import android.os.Build
import im.vector.app.core.resources.BuildMeta
-fun aBuildMeta() = BuildMeta(Build.VERSION_CODES.O)
+fun aBuildMeta() = BuildMeta(
+ isDebug = false,
+ applicationId = "im.vector",
+ lowPrivacyLoggingEnabled = false,
+ versionName = "app-version-name",
+ gitRevision = "abcdef",
+ gitRevisionDate = "01-01-01",
+ gitBranchName = "a-branch-name",
+ buildNumber = "100",
+ flavorDescription = "Gplay",
+ flavorShortDescription = "",
+)