Compare commits
13 Commits
develop
...
feature/ad
Author | SHA1 | Date | |
---|---|---|---|
|
28c9b0cf4b | ||
|
bc6a0a842f | ||
|
51888e176c | ||
|
d403d16731 | ||
|
92c615af31 | ||
|
a8190cf9c1 | ||
|
c773eda3d6 | ||
|
0e633bad46 | ||
|
d689778470 | ||
|
59cb6a03c8 | ||
|
4e9618fd0d | ||
|
b1035a808e | ||
|
0193695aa3 |
@ -33,6 +33,7 @@ buildscript {
|
|||||||
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.10"
|
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.10"
|
||||||
classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0"
|
classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0"
|
||||||
classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3'
|
classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3'
|
||||||
|
classpath 'app.cash.paparazzi:paparazzi-gradle-plugin:1.0.0'
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ ext.groups = [
|
|||||||
regex: [
|
regex: [
|
||||||
],
|
],
|
||||||
group: [
|
group: [
|
||||||
|
'app.cash.paparazzi',
|
||||||
'ch.qos.logback',
|
'ch.qos.logback',
|
||||||
'com.adevinta.android',
|
'com.adevinta.android',
|
||||||
'com.airbnb.android',
|
'com.airbnb.android',
|
||||||
@ -145,11 +146,14 @@ ext.groups = [
|
|||||||
'it.unimi.dsi',
|
'it.unimi.dsi',
|
||||||
'jakarta.activation',
|
'jakarta.activation',
|
||||||
'jakarta.xml.bind',
|
'jakarta.xml.bind',
|
||||||
|
'javax.activation',
|
||||||
'javax.annotation',
|
'javax.annotation',
|
||||||
'javax.inject',
|
'javax.inject',
|
||||||
|
'javax.xml.bind',
|
||||||
'jline',
|
'jline',
|
||||||
'jp.wasabeef',
|
'jp.wasabeef',
|
||||||
'junit',
|
'junit',
|
||||||
|
'kxml2',
|
||||||
'me.saket',
|
'me.saket',
|
||||||
'net.bytebuddy',
|
'net.bytebuddy',
|
||||||
'net.java',
|
'net.java',
|
||||||
@ -178,11 +182,13 @@ ext.groups = [
|
|||||||
'org.hamcrest',
|
'org.hamcrest',
|
||||||
'org.jacoco',
|
'org.jacoco',
|
||||||
'org.java-websocket',
|
'org.java-websocket',
|
||||||
|
'org.jcodec',
|
||||||
'org.jetbrains',
|
'org.jetbrains',
|
||||||
'org.jetbrains.dokka',
|
'org.jetbrains.dokka',
|
||||||
'org.jetbrains.intellij.deps',
|
'org.jetbrains.intellij.deps',
|
||||||
'org.jetbrains.kotlin',
|
'org.jetbrains.kotlin',
|
||||||
'org.jetbrains.kotlinx',
|
'org.jetbrains.kotlinx',
|
||||||
|
'org.jetbrains.trove4j',
|
||||||
'org.json',
|
'org.json',
|
||||||
'org.jsoup',
|
'org.jsoup',
|
||||||
'org.junit',
|
'org.junit',
|
||||||
|
@ -12,10 +12,12 @@ org.gradle.jvmargs=-Xmx4g -Xms512M -XX:MaxPermSize=2048m -XX:MaxMetaspaceSize=1g
|
|||||||
org.gradle.configureondemand=true
|
org.gradle.configureondemand=true
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
org.gradle.vfs.watch=true
|
org.gradle.vfs.watch=true
|
||||||
|
org.gradle.caching=true
|
||||||
|
|
||||||
# Android Settings
|
# Android Settings
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
|
android.jetifier.ignorelist=android-base-common,common
|
||||||
|
|
||||||
#Project Settings
|
#Project Settings
|
||||||
# Change debugPrivateData to true for debugging
|
# Change debugPrivateData to true for debugging
|
||||||
|
@ -341,6 +341,13 @@ android {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
// Add sourceSets for `release` version when building `nightly`
|
||||||
|
nightly {
|
||||||
|
java.srcDirs += "src/release/java"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding true
|
viewBinding true
|
||||||
}
|
}
|
||||||
@ -349,11 +356,39 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':vector')
|
implementation project(':vector')
|
||||||
implementation project(':vector-config')
|
implementation project(':vector-config')
|
||||||
|
debugImplementation project(':library:ui-styles')
|
||||||
implementation libs.dagger.hilt
|
implementation libs.dagger.hilt
|
||||||
implementation 'androidx.multidex:multidex:2.0.1'
|
implementation 'androidx.multidex:multidex:2.0.1'
|
||||||
implementation "androidx.sharetarget:sharetarget:1.1.0"
|
implementation "androidx.sharetarget:sharetarget:1.1.0"
|
||||||
|
|
||||||
|
// Flipper, debug builds only
|
||||||
|
debugImplementation(libs.flipper.flipper) {
|
||||||
|
exclude group: 'com.facebook.fbjni', module: 'fbjni'
|
||||||
|
}
|
||||||
|
debugImplementation(libs.flipper.flipperNetworkPlugin) {
|
||||||
|
exclude group: 'com.facebook.fbjni', module: 'fbjni'
|
||||||
|
}
|
||||||
|
debugImplementation 'com.facebook.soloader:soloader:0.10.4'
|
||||||
|
debugImplementation "com.kgurgul.flipper:flipper-realm-android:2.2.0"
|
||||||
|
|
||||||
|
gplayImplementation "com.google.android.gms:play-services-location:16.0.0"
|
||||||
|
// UnifiedPush gplay flavor only
|
||||||
|
gplayImplementation('com.github.UnifiedPush:android-embedded_fcm_distributor:2.1.2') {
|
||||||
|
exclude group: 'com.google.firebase', module: 'firebase-core'
|
||||||
|
exclude group: 'com.google.firebase', module: 'firebase-analytics'
|
||||||
|
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nightly
|
||||||
|
// API-only library
|
||||||
|
gplayImplementation libs.google.appdistributionApi
|
||||||
|
// Full SDK implementation
|
||||||
|
gplayImplementation libs.google.appdistribution
|
||||||
|
|
||||||
|
// OSS License, gplay flavor only
|
||||||
|
gplayImplementation 'com.google.android.gms:play-services-oss-licenses:17.0.0'
|
||||||
kapt libs.dagger.hiltCompiler
|
kapt libs.dagger.hiltCompiler
|
||||||
|
kapt libs.airbnb.epoxyProcessor
|
||||||
|
|
||||||
androidTestImplementation libs.androidx.testCore
|
androidTestImplementation libs.androidx.testCore
|
||||||
androidTestImplementation libs.androidx.testRunner
|
androidTestImplementation libs.androidx.testRunner
|
||||||
@ -378,5 +413,6 @@ dependencies {
|
|||||||
androidTestImplementation libs.androidx.fragmentTesting
|
androidTestImplementation libs.androidx.fragmentTesting
|
||||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-reflect:1.7.10"
|
androidTestImplementation "org.jetbrains.kotlin:kotlin-reflect:1.7.10"
|
||||||
debugImplementation libs.androidx.fragmentTesting
|
debugImplementation libs.androidx.fragmentTesting
|
||||||
|
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
vector-app/src/debug/AndroidManifest.xml
Normal file
22
vector-app/src/debug/AndroidManifest.xml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<application>
|
||||||
|
<activity android:name="im.vector.app.features.debug.TestLinkifyActivity" />
|
||||||
|
<activity android:name="im.vector.app.features.debug.DebugPermissionActivity" />
|
||||||
|
<activity android:name="im.vector.app.features.debug.analytics.DebugAnalyticsActivity" />
|
||||||
|
<activity android:name="im.vector.app.features.debug.settings.DebugPrivateSettingsActivity" />
|
||||||
|
<activity android:name="im.vector.app.features.debug.sas.DebugSasEmojiActivity" />
|
||||||
|
<activity android:name="im.vector.app.features.debug.features.DebugFeaturesSettingsActivity" />
|
||||||
|
<activity android:name="im.vector.app.features.debug.DebugMenuActivity" />
|
||||||
|
<activity android:name="im.vector.app.features.debug.leak.DebugMemoryLeaksActivity" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity"
|
||||||
|
android:exported="true" />
|
||||||
|
|
||||||
|
<!-- Used for UI tests to display the BiometricPrompt. It's normal that it appears as an error. -->
|
||||||
|
<activity android:exported="false" android:name=".features.pin.lockscreen.tests.LockScreenTestActivity" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
@ -34,13 +34,13 @@ import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
|
|||||||
import im.vector.app.core.utils.checkPermissions
|
import im.vector.app.core.utils.checkPermissions
|
||||||
import im.vector.app.core.utils.registerForPermissionsResult
|
import im.vector.app.core.utils.registerForPermissionsResult
|
||||||
import im.vector.app.core.utils.toast
|
import im.vector.app.core.utils.toast
|
||||||
import im.vector.app.databinding.ActivityDebugMenuBinding
|
|
||||||
import im.vector.app.features.debug.analytics.DebugAnalyticsActivity
|
import im.vector.app.features.debug.analytics.DebugAnalyticsActivity
|
||||||
import im.vector.app.features.debug.features.DebugFeaturesSettingsActivity
|
import im.vector.app.features.debug.features.DebugFeaturesSettingsActivity
|
||||||
import im.vector.app.features.debug.leak.DebugMemoryLeaksActivity
|
import im.vector.app.features.debug.leak.DebugMemoryLeaksActivity
|
||||||
import im.vector.app.features.debug.sas.DebugSasEmojiActivity
|
import im.vector.app.features.debug.sas.DebugSasEmojiActivity
|
||||||
import im.vector.app.features.debug.settings.DebugPrivateSettingsActivity
|
import im.vector.app.features.debug.settings.DebugPrivateSettingsActivity
|
||||||
import im.vector.app.features.qrcode.QrCodeScannerActivity
|
import im.vector.app.features.qrcode.QrCodeScannerActivity
|
||||||
|
import im.vector.application.databinding.ActivityDebugMenuBinding
|
||||||
import im.vector.lib.ui.styles.debug.DebugMaterialThemeDarkDefaultActivity
|
import im.vector.lib.ui.styles.debug.DebugMaterialThemeDarkDefaultActivity
|
||||||
import im.vector.lib.ui.styles.debug.DebugMaterialThemeDarkTestActivity
|
import im.vector.lib.ui.styles.debug.DebugMaterialThemeDarkTestActivity
|
||||||
import im.vector.lib.ui.styles.debug.DebugMaterialThemeDarkVectorActivity
|
import im.vector.lib.ui.styles.debug.DebugMaterialThemeDarkVectorActivity
|
@ -23,13 +23,13 @@ import android.widget.Toast
|
|||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import im.vector.app.R
|
|
||||||
import im.vector.app.core.platform.VectorBaseActivity
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
import im.vector.app.core.utils.checkPermissions
|
import im.vector.app.core.utils.checkPermissions
|
||||||
import im.vector.app.core.utils.onPermissionDeniedDialog
|
import im.vector.app.core.utils.onPermissionDeniedDialog
|
||||||
import im.vector.app.core.utils.onPermissionDeniedSnackbar
|
import im.vector.app.core.utils.onPermissionDeniedSnackbar
|
||||||
import im.vector.app.core.utils.registerForPermissionsResult
|
import im.vector.app.core.utils.registerForPermissionsResult
|
||||||
import im.vector.app.databinding.ActivityDebugPermissionBinding
|
import im.vector.application.R
|
||||||
|
import im.vector.application.databinding.ActivityDebugPermissionBinding
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
@ -20,9 +20,9 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import im.vector.app.R
|
import im.vector.application.R
|
||||||
import im.vector.app.databinding.ActivityTestLinkifyBinding
|
import im.vector.application.databinding.ActivityTestLinkifyBinding
|
||||||
import im.vector.app.databinding.ItemTestLinkifyBinding
|
import im.vector.application.databinding.ItemTestLinkifyBinding
|
||||||
|
|
||||||
class TestLinkifyActivity : AppCompatActivity() {
|
class TestLinkifyActivity : AppCompatActivity() {
|
||||||
|
|
@ -25,7 +25,7 @@ import com.airbnb.mvrx.withState
|
|||||||
import im.vector.app.core.epoxy.onClick
|
import im.vector.app.core.epoxy.onClick
|
||||||
import im.vector.app.core.extensions.toOnOff
|
import im.vector.app.core.extensions.toOnOff
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
import im.vector.app.databinding.FragmentDebugAnalyticsBinding
|
import im.vector.application.databinding.FragmentDebugAnalyticsBinding
|
||||||
import me.gujun.android.span.span
|
import me.gujun.android.span.span
|
||||||
|
|
||||||
class DebugAnalyticsFragment : VectorBaseFragment<FragmentDebugAnalyticsBinding>() {
|
class DebugAnalyticsFragment : VectorBaseFragment<FragmentDebugAnalyticsBinding>() {
|
@ -23,9 +23,9 @@ import android.widget.Spinner
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.app.R
|
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||||
|
import im.vector.application.R
|
||||||
|
|
||||||
@EpoxyModelClass
|
@EpoxyModelClass
|
||||||
abstract class BooleanFeatureItem : VectorEpoxyModel<BooleanFeatureItem.Holder>(R.layout.item_feature) {
|
abstract class BooleanFeatureItem : VectorEpoxyModel<BooleanFeatureItem.Holder>(R.layout.item_feature) {
|
||||||
@ -70,8 +70,8 @@ abstract class BooleanFeatureItem : VectorEpoxyModel<BooleanFeatureItem.Holder>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Holder : VectorEpoxyHolder() {
|
class Holder : VectorEpoxyHolder() {
|
||||||
val label by bind<TextView>(im.vector.app.R.id.feature_label)
|
val label by bind<TextView>(R.id.feature_label)
|
||||||
val optionsSpinner by bind<Spinner>(im.vector.app.R.id.feature_options)
|
val optionsSpinner by bind<Spinner>(R.id.feature_options)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Listener {
|
interface Listener {
|
@ -66,13 +66,13 @@ class DebugVectorOverrides(private val context: Context) : VectorOverrides {
|
|||||||
suspend fun setHomeserverCapabilities(block: HomeserverCapabilitiesOverride.() -> HomeserverCapabilitiesOverride) {
|
suspend fun setHomeserverCapabilities(block: HomeserverCapabilitiesOverride.() -> HomeserverCapabilitiesOverride) {
|
||||||
val capabilitiesOverride = block(forceHomeserverCapabilities.firstOrNull() ?: HomeserverCapabilitiesOverride(null, null))
|
val capabilitiesOverride = block(forceHomeserverCapabilities.firstOrNull() ?: HomeserverCapabilitiesOverride(null, null))
|
||||||
context.dataStore.edit { settings ->
|
context.dataStore.edit { settings ->
|
||||||
when (capabilitiesOverride.canChangeDisplayName) {
|
when (val canChangeDisplayName = capabilitiesOverride.canChangeDisplayName) {
|
||||||
null -> settings.remove(forceCanChangeDisplayName)
|
null -> settings.remove(forceCanChangeDisplayName)
|
||||||
else -> settings[forceCanChangeDisplayName] = capabilitiesOverride.canChangeDisplayName
|
else -> settings[forceCanChangeDisplayName] = canChangeDisplayName
|
||||||
}
|
}
|
||||||
when (capabilitiesOverride.canChangeAvatar) {
|
when (val canChangeAvatar = capabilitiesOverride.canChangeAvatar) {
|
||||||
null -> settings.remove(forceCanChangeAvatar)
|
null -> settings.remove(forceCanChangeAvatar)
|
||||||
else -> settings[forceCanChangeAvatar] = capabilitiesOverride.canChangeAvatar
|
else -> settings[forceCanChangeAvatar] = canChangeAvatar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,9 +23,9 @@ import android.widget.Spinner
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.app.R
|
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||||
|
import im.vector.application.R
|
||||||
|
|
||||||
@EpoxyModelClass
|
@EpoxyModelClass
|
||||||
abstract class EnumFeatureItem : VectorEpoxyModel<EnumFeatureItem.Holder>(R.layout.item_feature) {
|
abstract class EnumFeatureItem : VectorEpoxyModel<EnumFeatureItem.Holder>(R.layout.item_feature) {
|
||||||
@ -70,8 +70,8 @@ abstract class EnumFeatureItem : VectorEpoxyModel<EnumFeatureItem.Holder>(R.layo
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Holder : VectorEpoxyHolder() {
|
class Holder : VectorEpoxyHolder() {
|
||||||
val label by bind<TextView>(im.vector.app.R.id.feature_label)
|
val label by bind<TextView>(R.id.feature_label)
|
||||||
val optionsSpinner by bind<Spinner>(im.vector.app.R.id.feature_options)
|
val optionsSpinner by bind<Spinner>(R.id.feature_options)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Listener {
|
interface Listener {
|
@ -25,7 +25,7 @@ import com.airbnb.mvrx.withState
|
|||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import im.vector.app.core.epoxy.onClick
|
import im.vector.app.core.epoxy.onClick
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
import im.vector.app.databinding.FragmentDebugMemoryLeaksBinding
|
import im.vector.application.databinding.FragmentDebugMemoryLeaksBinding
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class DebugMemoryLeaksFragment :
|
class DebugMemoryLeaksFragment :
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
@ -21,9 +21,9 @@ import android.widget.TextView
|
|||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.app.R
|
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||||
|
import im.vector.application.R
|
||||||
import me.gujun.android.span.image
|
import me.gujun.android.span.image
|
||||||
import me.gujun.android.span.span
|
import me.gujun.android.span.span
|
||||||
import org.matrix.android.sdk.api.session.crypto.verification.EmojiRepresentation
|
import org.matrix.android.sdk.api.session.crypto.verification.EmojiRepresentation
|
@ -23,7 +23,7 @@ import android.view.ViewGroup
|
|||||||
import com.airbnb.mvrx.fragmentViewModel
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
import im.vector.app.databinding.FragmentDebugPrivateSettingsBinding
|
import im.vector.application.databinding.FragmentDebugPrivateSettingsBinding
|
||||||
|
|
||||||
class DebugPrivateSettingsFragment : VectorBaseFragment<FragmentDebugPrivateSettingsBinding>() {
|
class DebugPrivateSettingsFragment : VectorBaseFragment<FragmentDebugPrivateSettingsBinding>() {
|
||||||
|
|
@ -24,7 +24,7 @@ import android.view.View
|
|||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import im.vector.app.databinding.ViewBooleanDropdownBinding
|
import im.vector.application.databinding.ViewBooleanDropdownBinding
|
||||||
|
|
||||||
class OverrideDropdownView @JvmOverloads constructor(
|
class OverrideDropdownView @JvmOverloads constructor(
|
||||||
context: Context,
|
context: Context,
|
@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
package="im.vector.app">
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
@ -15,7 +14,7 @@
|
|||||||
<application>
|
<application>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".fdroid.receiver.OnApplicationUpgradeOrRebootReceiver"
|
android:name="im.vector.app.fdroid.receiver.OnApplicationUpgradeOrRebootReceiver"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||||
@ -24,12 +23,12 @@
|
|||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".fdroid.receiver.AlarmSyncBroadcastReceiver"
|
android:name="im.vector.app.fdroid.receiver.AlarmSyncBroadcastReceiver"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".fdroid.receiver.KeepInternalDistributor"
|
android:name="im.vector.app.fdroid.receiver.KeepInternalDistributor"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@ -43,7 +42,7 @@
|
|||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".fdroid.service.GuardAndroidService"
|
android:name="im.vector.app.fdroid.service.GuardAndroidService"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
tools:ignore="Instantiatable" />
|
tools:ignore="Instantiatable" />
|
||||||
|
|
@ -3,6 +3,7 @@ apply plugin: 'kotlin-android'
|
|||||||
apply plugin: 'kotlin-parcelize'
|
apply plugin: 'kotlin-parcelize'
|
||||||
apply plugin: 'kotlin-kapt'
|
apply plugin: 'kotlin-kapt'
|
||||||
apply plugin: 'dagger.hilt.android.plugin'
|
apply plugin: 'dagger.hilt.android.plugin'
|
||||||
|
apply plugin: 'app.cash.paparazzi'
|
||||||
|
|
||||||
if (project.hasProperty("coverage")) {
|
if (project.hasProperty("coverage")) {
|
||||||
apply plugin: 'jacoco'
|
apply plugin: 'jacoco'
|
||||||
@ -66,30 +67,6 @@ android {
|
|||||||
testCoverageEnabled = coverage.enableTestCoverage
|
testCoverageEnabled = coverage.enableTestCoverage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nightly {
|
|
||||||
initWith release
|
|
||||||
matchingFallbacks = ['release']
|
|
||||||
}
|
|
||||||
release
|
|
||||||
}
|
|
||||||
|
|
||||||
flavorDimensions "store"
|
|
||||||
|
|
||||||
productFlavors {
|
|
||||||
gplay {
|
|
||||||
dimension "store"
|
|
||||||
isDefault = true
|
|
||||||
|
|
||||||
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\""
|
|
||||||
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\""
|
|
||||||
}
|
|
||||||
|
|
||||||
fdroid {
|
|
||||||
dimension "store"
|
|
||||||
|
|
||||||
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\""
|
|
||||||
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
@ -118,10 +95,6 @@ android {
|
|||||||
test {
|
test {
|
||||||
java.srcDirs += "src/sharedTest/java"
|
java.srcDirs += "src/sharedTest/java"
|
||||||
}
|
}
|
||||||
// Add sourceSets for `release` version when building `nightly`
|
|
||||||
nightly {
|
|
||||||
java.srcDirs += "src/release/java"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
@ -190,12 +163,6 @@ dependencies {
|
|||||||
// Snap Helper https://github.com/rubensousa/GravitySnapHelper
|
// Snap Helper https://github.com/rubensousa/GravitySnapHelper
|
||||||
api 'com.github.rubensousa:gravitysnaphelper:2.2.2'
|
api 'com.github.rubensousa:gravitysnaphelper:2.2.2'
|
||||||
|
|
||||||
// Nightly
|
|
||||||
// API-only library
|
|
||||||
gplayImplementation libs.google.appdistributionApi
|
|
||||||
// Full SDK implementation
|
|
||||||
gplayImplementation libs.google.appdistribution
|
|
||||||
|
|
||||||
// Work
|
// Work
|
||||||
api libs.androidx.work
|
api libs.androidx.work
|
||||||
|
|
||||||
@ -211,7 +178,7 @@ dependencies {
|
|||||||
// UI
|
// UI
|
||||||
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
||||||
implementation libs.google.material
|
implementation libs.google.material
|
||||||
implementation 'me.gujun.android:span:1.7'
|
api 'me.gujun.android:span:1.7'
|
||||||
implementation libs.markwon.core
|
implementation libs.markwon.core
|
||||||
implementation libs.markwon.extLatex
|
implementation libs.markwon.extLatex
|
||||||
implementation libs.markwon.inlineParser
|
implementation libs.markwon.inlineParser
|
||||||
@ -263,15 +230,6 @@ dependencies {
|
|||||||
|
|
||||||
// UnifiedPush
|
// UnifiedPush
|
||||||
implementation 'com.github.UnifiedPush:android-connector:2.0.1'
|
implementation 'com.github.UnifiedPush:android-connector:2.0.1'
|
||||||
// UnifiedPush gplay flavor only
|
|
||||||
gplayImplementation('com.github.UnifiedPush:android-embedded_fcm_distributor:2.1.2') {
|
|
||||||
exclude group: 'com.google.firebase', module: 'firebase-core'
|
|
||||||
exclude group: 'com.google.firebase', module: 'firebase-analytics'
|
|
||||||
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
|
|
||||||
}
|
|
||||||
|
|
||||||
// OSS License, gplay flavor only
|
|
||||||
gplayImplementation 'com.google.android.gms:play-services-oss-licenses:17.0.0'
|
|
||||||
|
|
||||||
implementation "androidx.emoji2:emoji2:1.1.0"
|
implementation "androidx.emoji2:emoji2:1.1.0"
|
||||||
|
|
||||||
@ -307,14 +265,12 @@ dependencies {
|
|||||||
implementation 'commons-codec:commons-codec:1.15'
|
implementation 'commons-codec:commons-codec:1.15'
|
||||||
|
|
||||||
// MapTiler
|
// MapTiler
|
||||||
fdroidApi(libs.maplibre.androidSdk) {
|
api(libs.maplibre.androidSdk) {
|
||||||
exclude group: 'com.google.android.gms', module: 'play-services-location'
|
exclude group: 'com.google.android.gms', module: 'play-services-location'
|
||||||
}
|
}
|
||||||
fdroidApi(libs.maplibre.pluginAnnotation) {
|
api(libs.maplibre.pluginAnnotation) {
|
||||||
exclude group: 'com.google.android.gms', module: 'play-services-location'
|
exclude group: 'com.google.android.gms', module: 'play-services-location'
|
||||||
}
|
}
|
||||||
gplayApi libs.maplibre.androidSdk
|
|
||||||
gplayApi libs.maplibre.pluginAnnotation
|
|
||||||
|
|
||||||
// TESTS
|
// TESTS
|
||||||
testImplementation libs.tests.junit
|
testImplementation libs.tests.junit
|
||||||
@ -327,19 +283,6 @@ dependencies {
|
|||||||
exclude group: "org.jetbrains.kotlinx", module: "kotlinx-coroutines-debug"
|
exclude group: "org.jetbrains.kotlinx", module: "kotlinx-coroutines-debug"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flipper, debug builds only
|
|
||||||
debugImplementation(libs.flipper.flipper) {
|
|
||||||
exclude group: 'com.facebook.fbjni', module: 'fbjni'
|
|
||||||
}
|
|
||||||
debugImplementation(libs.flipper.flipperNetworkPlugin) {
|
|
||||||
exclude group: 'com.facebook.fbjni', module: 'fbjni'
|
|
||||||
}
|
|
||||||
debugImplementation 'com.facebook.soloader:soloader:0.10.4'
|
|
||||||
debugImplementation "com.kgurgul.flipper:flipper-realm-android:2.2.0"
|
|
||||||
|
|
||||||
// Activate when you want to check for leaks, from time to time.
|
|
||||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
|
|
||||||
|
|
||||||
androidTestImplementation libs.androidx.testCore
|
androidTestImplementation libs.androidx.testCore
|
||||||
androidTestImplementation libs.androidx.testRunner
|
androidTestImplementation libs.androidx.testRunner
|
||||||
androidTestImplementation libs.androidx.testRules
|
androidTestImplementation libs.androidx.testRules
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="im.vector.app">
|
|
||||||
|
|
||||||
<application>
|
|
||||||
<activity android:name=".features.debug.TestLinkifyActivity" />
|
|
||||||
<activity android:name=".features.debug.DebugPermissionActivity" />
|
|
||||||
<activity android:name=".features.debug.analytics.DebugAnalyticsActivity" />
|
|
||||||
<activity android:name=".features.debug.settings.DebugPrivateSettingsActivity" />
|
|
||||||
<activity android:name=".features.debug.sas.DebugSasEmojiActivity" />
|
|
||||||
<activity android:name=".features.debug.features.DebugFeaturesSettingsActivity" />
|
|
||||||
<activity android:name=".features.debug.DebugMenuActivity" />
|
|
||||||
<activity android:name=".features.debug.leak.DebugMemoryLeaksActivity" />
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name="com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity"
|
|
||||||
android:exported="true" />
|
|
||||||
|
|
||||||
<!-- Used for UI tests to display the BiometricPrompt. It's normal that it appears as an error. -->
|
|
||||||
<activity android:exported="false" android:name=".features.pin.lockscreen.tests.LockScreenTestActivity" />
|
|
||||||
</application>
|
|
||||||
|
|
||||||
</manifest>
|
|
@ -20,8 +20,11 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.error.ErrorFormatter
|
||||||
import im.vector.app.core.extensions.associateContentStateWith
|
import im.vector.app.core.extensions.associateContentStateWith
|
||||||
import im.vector.app.core.extensions.clearErrorOnChange
|
import im.vector.app.core.extensions.clearErrorOnChange
|
||||||
import im.vector.app.core.extensions.content
|
import im.vector.app.core.extensions.content
|
||||||
@ -30,6 +33,7 @@ import im.vector.app.core.extensions.realignPercentagesToParent
|
|||||||
import im.vector.app.core.extensions.setOnImeDoneListener
|
import im.vector.app.core.extensions.setOnImeDoneListener
|
||||||
import im.vector.app.core.extensions.showKeyboard
|
import im.vector.app.core.extensions.showKeyboard
|
||||||
import im.vector.app.core.extensions.toReducedUrl
|
import im.vector.app.core.extensions.toReducedUrl
|
||||||
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.core.utils.ensureProtocol
|
import im.vector.app.core.utils.ensureProtocol
|
||||||
import im.vector.app.core.utils.ensureTrailingSlash
|
import im.vector.app.core.utils.ensureTrailingSlash
|
||||||
import im.vector.app.core.utils.openUrlInExternalBrowser
|
import im.vector.app.core.utils.openUrlInExternalBrowser
|
||||||
@ -37,49 +41,82 @@ import im.vector.app.databinding.FragmentFtueServerSelectionCombinedBinding
|
|||||||
import im.vector.app.features.onboarding.OnboardingAction
|
import im.vector.app.features.onboarding.OnboardingAction
|
||||||
import im.vector.app.features.onboarding.OnboardingFlow
|
import im.vector.app.features.onboarding.OnboardingFlow
|
||||||
import im.vector.app.features.onboarding.OnboardingViewEvents
|
import im.vector.app.features.onboarding.OnboardingViewEvents
|
||||||
|
import im.vector.app.features.onboarding.OnboardingViewModel
|
||||||
import im.vector.app.features.onboarding.OnboardingViewState
|
import im.vector.app.features.onboarding.OnboardingViewState
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import org.matrix.android.sdk.api.failure.isHomeserverUnavailable
|
import org.matrix.android.sdk.api.failure.isHomeserverUnavailable
|
||||||
|
import reactivecircus.flowbinding.android.view.clicks
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class FtueAuthCombinedServerSelectionFragment :
|
class FtueAuthCombinedServerSelectionFragment : AbstractFtueAuthFragment<FragmentFtueServerSelectionCombinedBinding>() {
|
||||||
AbstractFtueAuthFragment<FragmentFtueServerSelectionCombinedBinding>() {
|
|
||||||
|
@Inject lateinit var stringProvider: StringProvider
|
||||||
|
private lateinit var controller: Controller
|
||||||
|
|
||||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueServerSelectionCombinedBinding {
|
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueServerSelectionCombinedBinding {
|
||||||
return FragmentFtueServerSelectionCombinedBinding.inflate(inflater, container, false)
|
return FragmentFtueServerSelectionCombinedBinding.inflate(inflater, container, false).also {
|
||||||
|
controller = Controller(viewLifecycleOwner, it, stringProvider, errorFormatter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
setupViews()
|
controller.listener = object : Controller.Listener {
|
||||||
}
|
override fun onNavigationClicked() {
|
||||||
|
|
||||||
private fun setupViews() {
|
|
||||||
views.chooseServerRoot.realignPercentagesToParent()
|
|
||||||
views.chooseServerToolbar.setNavigationOnClickListener {
|
|
||||||
viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnBack))
|
viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnBack))
|
||||||
}
|
}
|
||||||
views.chooseServerInput.associateContentStateWith(button = views.chooseServerSubmit, enabledPredicate = { canSubmit(it) })
|
|
||||||
views.chooseServerInput.setOnImeDoneListener {
|
|
||||||
if (canSubmit(views.chooseServerInput.content())) {
|
|
||||||
updateServerUrl()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
views.chooseServerGetInTouch.debouncedClicks { openUrlInExternalBrowser(requireContext(), getString(R.string.ftue_ems_url)) }
|
|
||||||
views.chooseServerSubmit.debouncedClicks { updateServerUrl() }
|
|
||||||
views.chooseServerInput.clearErrorOnChange(viewLifecycleOwner)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun canSubmit(url: String) = url.isNotEmpty()
|
override fun updateServerUrl() {
|
||||||
|
|
||||||
private fun updateServerUrl() {
|
|
||||||
viewModel.handle(OnboardingAction.HomeServerChange.EditHomeServer(views.chooseServerInput.content().ensureProtocol().ensureTrailingSlash()))
|
viewModel.handle(OnboardingAction.HomeServerChange.EditHomeServer(views.chooseServerInput.content().ensureProtocol().ensureTrailingSlash()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getInTouchClicked() {
|
||||||
|
openUrlInExternalBrowser(requireContext(), getString(R.string.ftue_ems_url))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun resetViewModel() {
|
override fun resetViewModel() {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateWithState(state: OnboardingViewState) {
|
override fun updateWithState(state: OnboardingViewState) {
|
||||||
|
controller.setData(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(throwable: Throwable) {
|
||||||
|
controller.setError(throwable)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Controller(
|
||||||
|
lifecycleOwner: LifecycleOwner,
|
||||||
|
private val views: FragmentFtueServerSelectionCombinedBinding,
|
||||||
|
private val stringProvider: StringProvider,
|
||||||
|
private val errorFormatter: ErrorFormatter,
|
||||||
|
private val viewModel: OnboardingViewModel,
|
||||||
|
) {
|
||||||
|
|
||||||
|
var listener: Listener? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
views.chooseServerRoot.realignPercentagesToParent()
|
||||||
|
views.chooseServerToolbar.setNavigationOnClickListener { listener?.onNavigationClicked() }
|
||||||
|
views.chooseServerInput.associateContentStateWith(button = views.chooseServerSubmit, enabledPredicate = { canSubmit(it) })
|
||||||
|
views.chooseServerInput.setOnImeDoneListener {
|
||||||
|
if (canSubmit(views.chooseServerInput.content())) {
|
||||||
|
listener?.updateServerUrl()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
views.chooseServerGetInTouch.debouncedClicks(lifecycleOwner) { listener?.getInTouchClicked() }
|
||||||
|
views.chooseServerSubmit.debouncedClicks(lifecycleOwner) { listener?.updateServerUrl() }
|
||||||
|
views.chooseServerInput.clearErrorOnChange(lifecycleOwner)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun canSubmit(url: String) = url.isNotEmpty()
|
||||||
|
|
||||||
|
fun setData(state: OnboardingViewState) {
|
||||||
views.chooseServerHeaderSubtitle.setText(
|
views.chooseServerHeaderSubtitle.setText(
|
||||||
when (state.onboardingFlow) {
|
when (state.onboardingFlow) {
|
||||||
OnboardingFlow.SignIn -> R.string.ftue_auth_choose_server_sign_in_subtitle
|
OnboardingFlow.SignIn -> R.string.ftue_auth_choose_server_sign_in_subtitle
|
||||||
@ -97,12 +134,26 @@ class FtueAuthCombinedServerSelectionFragment :
|
|||||||
views.chooseServerInput.editText().showKeyboard(true)
|
views.chooseServerInput.editText().showKeyboard(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(throwable: Throwable) {
|
fun setError(throwable: Throwable) {
|
||||||
views.chooseServerInput.error = when {
|
views.chooseServerInput.error = when {
|
||||||
throwable.isHomeserverUnavailable() -> getString(R.string.login_error_homeserver_not_found)
|
throwable.isHomeserverUnavailable() -> stringProvider.getString(R.string.login_error_homeserver_not_found)
|
||||||
else -> errorFormatter.toHumanReadable(throwable)
|
else -> errorFormatter.toHumanReadable(throwable)
|
||||||
}
|
}
|
||||||
|
println(views.chooseServerInput.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.toReducedUrlKeepingSchemaIfInsecure() = toReducedUrl(keepSchema = this.startsWith("http://"))
|
private fun String.toReducedUrlKeepingSchemaIfInsecure() = toReducedUrl(keepSchema = this.startsWith("http://"))
|
||||||
|
|
||||||
|
interface Listener {
|
||||||
|
fun onNavigationClicked()
|
||||||
|
fun updateServerUrl()
|
||||||
|
fun getInTouchClicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun View.debouncedClicks(lifecycleOwner: LifecycleOwner, onClicked: () -> Unit) {
|
||||||
|
clicks()
|
||||||
|
.onEach { onClicked() }
|
||||||
|
.launchIn(lifecycleOwner.lifecycleScope)
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@
|
|||||||
app:layout_constraintHeight_percent="0.03"
|
app:layout_constraintHeight_percent="0.03"
|
||||||
app:layout_constraintTop_toBottomOf="@id/chooseServerInput" />
|
app:layout_constraintTop_toBottomOf="@id/chooseServerInput" />
|
||||||
|
|
||||||
<Button
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/chooseServerSubmit"
|
android:id="@+id/chooseServerSubmit"
|
||||||
style="@style/Widget.Vector.Button.Login"
|
style="@style/Widget.Vector.Button.Login"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
181
vector/src/test/java/im/vector/app/PaparazziScreenshotTest.kt
Normal file
181
vector/src/test/java/im/vector/app/PaparazziScreenshotTest.kt
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.lifecycle.LifecycleRegistry
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import app.cash.paparazzi.DeviceConfig.Companion.PIXEL_3
|
||||||
|
import app.cash.paparazzi.Paparazzi
|
||||||
|
import com.airbnb.epoxy.EpoxyController
|
||||||
|
import com.airbnb.mvrx.Success
|
||||||
|
import im.vector.app.core.error.DefaultErrorFormatter
|
||||||
|
import im.vector.app.core.extensions.configureWith
|
||||||
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
import im.vector.app.core.utils.DimensionConverter
|
||||||
|
import im.vector.app.databinding.FragmentFtueServerSelectionCombinedBinding
|
||||||
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
|
import im.vector.app.features.home.room.detail.timeline.format.RoomHistoryVisibilityFormatter
|
||||||
|
import im.vector.app.features.onboarding.OnboardingFlow
|
||||||
|
import im.vector.app.features.onboarding.OnboardingViewState
|
||||||
|
import im.vector.app.features.onboarding.SelectedHomeserverState
|
||||||
|
import im.vector.app.features.onboarding.ftueauth.FtueAuthCombinedServerSelectionFragment
|
||||||
|
import im.vector.app.features.roomprofile.settings.RoomSettingsController
|
||||||
|
import im.vector.app.features.roomprofile.settings.RoomSettingsViewState
|
||||||
|
import im.vector.app.test.fakes.FakeErrorFormatter
|
||||||
|
import im.vector.app.test.fakes.FakeVectorPreferences
|
||||||
|
import io.mockk.coJustRun
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
import java.lang.reflect.Modifier
|
||||||
|
|
||||||
|
class PaparazziScreenshotTest {
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
val paparazzi = Paparazzi(
|
||||||
|
deviceConfig = PIXEL_3,
|
||||||
|
theme = "Theme.Vector.Light",
|
||||||
|
)
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
setFinalStaticValue(Build::class.java.getDeclaredField("MANUFACTURER"), "GOOGLE")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `empty server selection`() {
|
||||||
|
val (view, binding) = paparazzi.inflate(R.layout.fragment_ftue_server_selection_combined, FragmentFtueServerSelectionCombinedBinding::bind)
|
||||||
|
val stringProvider = StringProvider(paparazzi.resources)
|
||||||
|
val lifecycleOwner = fakeLifecycleOwner()
|
||||||
|
|
||||||
|
FtueAuthCombinedServerSelectionFragment.Controller(lifecycleOwner, binding, stringProvider, FakeErrorFormatter())
|
||||||
|
.setData(
|
||||||
|
OnboardingViewState(
|
||||||
|
onboardingFlow = OnboardingFlow.SignIn,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
paparazzi.snapshot(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `server selection with content`() {
|
||||||
|
val (view, binding) = paparazzi.inflate(R.layout.fragment_ftue_server_selection_combined, FragmentFtueServerSelectionCombinedBinding::bind)
|
||||||
|
val stringProvider = StringProvider(paparazzi.resources)
|
||||||
|
val lifecycleOwner = fakeLifecycleOwner()
|
||||||
|
|
||||||
|
FtueAuthCombinedServerSelectionFragment.Controller(lifecycleOwner, binding, stringProvider, DefaultErrorFormatter(stringProvider))
|
||||||
|
.setData(
|
||||||
|
OnboardingViewState(
|
||||||
|
onboardingFlow = OnboardingFlow.SignIn,
|
||||||
|
selectedHomeserver = SelectedHomeserverState(userFacingUrl = "matrix.org")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
paparazzi.snapshot(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `room settings`() {
|
||||||
|
// Material components aren't fully supported yet https://github.com/cashapp/paparazzi/issues/223
|
||||||
|
val strings = StringProvider(paparazzi.resources)
|
||||||
|
val fakeAvatarRender = FakeAvatarRender()
|
||||||
|
val fakeDimensionConverter = FakeDimensionConverter()
|
||||||
|
val fakeVectorPreferences = FakeVectorPreferences().also { it.givenDeveloperMode(false) }
|
||||||
|
val controller = RoomSettingsController(
|
||||||
|
strings,
|
||||||
|
fakeAvatarRender.instance,
|
||||||
|
fakeDimensionConverter.instance,
|
||||||
|
RoomHistoryVisibilityFormatter(strings),
|
||||||
|
fakeVectorPreferences.instance,
|
||||||
|
)
|
||||||
|
|
||||||
|
val view = inflateRecyclerView(controller)
|
||||||
|
|
||||||
|
controller.setData(
|
||||||
|
RoomSettingsViewState(
|
||||||
|
roomId = "room-id",
|
||||||
|
roomSummary = Success(
|
||||||
|
RoomSummary(
|
||||||
|
roomId = "!room-id",
|
||||||
|
isEncrypted = true,
|
||||||
|
encryptionEventTs = null,
|
||||||
|
typingUsers = emptyList(),
|
||||||
|
displayName = "A room name",
|
||||||
|
topic = "A room topic",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
paparazzi.snapshot(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun inflateRecyclerView(controller: EpoxyController): View {
|
||||||
|
val view = paparazzi.inflate<FrameLayout>(R.layout.fragment_generic_recycler)
|
||||||
|
val recyclerView = view.findViewById<RecyclerView>(R.id.genericRecyclerView)
|
||||||
|
recyclerView.configureWith(controller)
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setFinalStaticValue(field: Field, value: Any) {
|
||||||
|
val modifiersField = Field::class.java.getDeclaredField("modifiers")
|
||||||
|
modifiersField.isAccessible = true
|
||||||
|
modifiersField.setInt(field, field.modifiers and Modifier.FINAL.inv())
|
||||||
|
field.isAccessible = true
|
||||||
|
|
||||||
|
field.set(null, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <B> Paparazzi.inflate(layoutId: Int, binder: (View) -> B): Pair<View, B> {
|
||||||
|
val view = inflate<View>(layoutId)
|
||||||
|
val binding = binder(view)
|
||||||
|
return view to binding
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fakeLifecycleOwner(): LifecycleOwner {
|
||||||
|
val lifecycleOwner = mockk<LifecycleOwner>()
|
||||||
|
every { lifecycleOwner.lifecycle } returns LifecycleRegistry(lifecycleOwner)
|
||||||
|
return lifecycleOwner
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeDimensionConverter {
|
||||||
|
|
||||||
|
val instance = mockk<DimensionConverter>().also {
|
||||||
|
every { it.dpToPx(any()) }.answers { arg ->
|
||||||
|
arg.invocation.args.first() as Int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeAvatarRender {
|
||||||
|
|
||||||
|
val instance = mockk<AvatarRenderer>().also {
|
||||||
|
coJustRun { it.render(any<MatrixItem>(), any()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -36,4 +36,8 @@ class FakeVectorPreferences {
|
|||||||
fun verifySetSpaceBackstack(value: List<String?>, inverse: Boolean = false) {
|
fun verifySetSpaceBackstack(value: List<String?>, inverse: Boolean = false) {
|
||||||
verify(inverse = inverse) { instance.setSpaceBackstack(value) }
|
verify(inverse = inverse) { instance.setSpaceBackstack(value) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun givenDeveloperMode(isDeveloperMode: Boolean) {
|
||||||
|
every { instance.developerMode() } returns isDeveloperMode
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
Loading…
Reference in New Issue
Block a user