Browse Source

[Architecture] split all feature modules to api/impl

misc/jme/add-logging-to-state-machine
ganfra 2 years ago
parent
commit
bc9f3b69cc
  1. 2
      app/build.gradle.kts
  2. 2
      app/src/main/kotlin/io/element/android/x/initializer/CrashInitializer.kt
  3. 2
      app/src/main/kotlin/io/element/android/x/initializer/TimberInitializer.kt
  4. 14
      appnav/build.gradle.kts
  5. 5
      appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt
  6. 4
      appnav/src/main/kotlin/io/element/android/appnav/root/RootPresenter.kt
  7. 9
      appnav/src/main/kotlin/io/element/android/appnav/root/RootState.kt
  8. 4
      appnav/src/main/kotlin/io/element/android/appnav/root/RootStateProvider.kt
  9. 8
      appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt
  10. 70
      appnav/src/test/kotlin/io/element/android/appnav/FakeBugReporter.kt
  11. 50
      appnav/src/test/kotlin/io/element/android/appnav/FakeCrashDataStore.kt
  12. 44
      appnav/src/test/kotlin/io/element/android/appnav/FakeRageShake.kt
  13. 46
      appnav/src/test/kotlin/io/element/android/appnav/FakeRageshakeDataStore.kt
  14. 16
      appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt
  15. 1
      features/login/.gitignore
  16. 27
      features/login/api/build.gradle.kts
  17. 0
      features/login/api/src/main/kotlin/io/element/android/features/login/api/LoginEntryPoint.kt
  18. 0
      features/login/consumer-rules.pro
  19. 3
      features/login/impl/build.gradle.kts
  20. 0
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPoint.kt
  21. 0
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt
  22. 0
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerEvents.kt
  23. 2
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerNode.kt
  24. 2
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenter.kt
  25. 0
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerState.kt
  26. 0
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerStateProvider.kt
  27. 2
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt
  28. 0
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/error/ErrorFormatter.kt
  29. 0
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootEvents.kt
  30. 0
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootNode.kt
  31. 5
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootPresenter.kt
  32. 0
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootScreen.kt
  33. 0
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootState.kt
  34. 0
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootStateProvider.kt
  35. 2
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/util/LoginConstants.kt
  36. 0
      features/login/impl/src/main/res/drawable/ic_homeserver.xml
  37. 2
      features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt
  38. 2
      features/login/impl/src/test/kotlin/io/element/android/features/login/impl/root/LoginRootPresenterTest.kt
  39. 21
      features/login/proguard-rules.pro
  40. 38
      features/login/src/androidTest/kotlin/io/element/android/features/login/ExampleInstrumentedTest.kt
  41. 20
      features/login/src/main/AndroidManifest.xml
  42. 32
      features/login/src/test/kotlin/io/element/android/features/login/ExampleUnitTest.kt
  43. 1
      features/logout/.gitignore
  44. 29
      features/logout/api/build.gradle.kts
  45. 2
      features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferenceEvents.kt
  46. 21
      features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferencePresenter.kt
  47. 2
      features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferenceScreen.kt
  48. 2
      features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferenceState.kt
  49. 2
      features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferenceStateProvider.kt
  50. 0
      features/logout/consumer-rules.pro
  51. 6
      features/logout/impl/build.gradle.kts
  52. 4
      features/logout/impl/src/main/AndroidManifest.xml
  53. 13
      features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/DefaultLogoutPreferencePresenter.kt
  54. 10
      features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPreferencePresenterTest.kt
  55. 21
      features/logout/proguard-rules.pro
  56. 38
      features/logout/src/androidTest/kotlin/io/element/android/features/logout/ExampleInstrumentedTest.kt
  57. 20
      features/logout/src/main/AndroidManifest.xml
  58. 32
      features/logout/src/test/kotlin/io/element/android/features/logout/ExampleUnitTest.kt
  59. 2
      features/messages/api/build.gradle.kts
  60. 1
      features/onboarding/.gitignore
  61. 27
      features/onboarding/api/build.gradle.kts
  62. 0
      features/onboarding/api/src/main/kotlin/io/element/android/features/onboarding/api/OnBoardingEntryPoint.kt
  63. 48
      features/onboarding/build.gradle.kts
  64. 0
      features/onboarding/consumer-rules.pro
  65. 16
      features/onboarding/impl/build.gradle.kts
  66. 0
      features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/DefaultOnBoardingEntryPoint.kt
  67. 0
      features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingNode.kt
  68. 0
      features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingScreen.kt
  69. 0
      features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/SplashCarouselData.kt
  70. 1
      features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/SplashCarouselDataFactory.kt
  71. 0
      features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_collaboration.webp
  72. 0
      features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_collaboration_dark.webp
  73. 0
      features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_control.webp
  74. 0
      features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_control_dark.webp
  75. 0
      features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_conversations.webp
  76. 0
      features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_conversations_dark.webp
  77. 0
      features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_secure.webp
  78. 0
      features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_secure_dark.webp
  79. 0
      features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_collaboration.webp
  80. 0
      features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_collaboration_dark.webp
  81. 0
      features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_control.webp
  82. 0
      features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_control_dark.webp
  83. 0
      features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_conversations.webp
  84. 0
      features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_conversations_dark.webp
  85. 0
      features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_secure.webp
  86. 0
      features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_secure_dark.webp
  87. 0
      features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_collaboration.webp
  88. 0
      features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_collaboration_dark.webp
  89. 0
      features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_control.webp
  90. 0
      features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_control_dark.webp
  91. 0
      features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_conversations.webp
  92. 0
      features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_conversations_dark.webp
  93. 0
      features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_secure.webp
  94. 0
      features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_secure_dark.webp
  95. 0
      features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_collaboration.webp
  96. 0
      features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_collaboration_dark.webp
  97. 0
      features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_control.webp
  98. 0
      features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_control_dark.webp
  99. 0
      features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_conversations.webp
  100. 0
      features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_conversations_dark.webp
  101. Some files were not shown because too many files have changed in this diff Show More

2
app/build.gradle.kts

@ -26,8 +26,8 @@ plugins {
id("io.element.android-compose-application") id("io.element.android-compose-application")
alias(libs.plugins.stem) alias(libs.plugins.stem)
alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.android)
alias(libs.plugins.ksp)
alias(libs.plugins.anvil) alias(libs.plugins.anvil)
alias(libs.plugins.ksp)
alias(libs.plugins.kapt) alias(libs.plugins.kapt)
id("com.google.firebase.appdistribution") version "3.0.2" id("com.google.firebase.appdistribution") version "3.0.2"
id("org.jetbrains.kotlinx.knit") version "0.4.0" id("org.jetbrains.kotlinx.knit") version "0.4.0"

2
app/src/main/kotlin/io/element/android/x/initializer/CrashInitializer.kt

@ -18,7 +18,7 @@ package io.element.android.x.initializer
import android.content.Context import android.content.Context
import androidx.startup.Initializer import androidx.startup.Initializer
import io.element.android.features.rageshake.crash.VectorUncaughtExceptionHandler import io.element.android.features.rageshake.impl.crash.VectorUncaughtExceptionHandler
class CrashInitializer : Initializer<Unit> { class CrashInitializer : Initializer<Unit> {

2
app/src/main/kotlin/io/element/android/x/initializer/TimberInitializer.kt

@ -18,7 +18,7 @@ package io.element.android.x.initializer
import android.content.Context import android.content.Context
import androidx.startup.Initializer import androidx.startup.Initializer
import io.element.android.features.rageshake.logs.VectorFileLogger import io.element.android.features.rageshake.impl.logs.VectorFileLogger
import io.element.android.x.BuildConfig import io.element.android.x.BuildConfig
import timber.log.Timber import timber.log.Timber

14
appnav/build.gradle.kts

@ -37,12 +37,12 @@ dependencies {
kapt(libs.dagger.compiler) kapt(libs.dagger.compiler)
implementation(projects.features.messages.api) implementation(projects.features.messages.api)
implementation(projects.features.roomlist) implementation(projects.features.roomlist.api)
implementation(projects.features.rageshake) implementation(projects.features.rageshake.api)
implementation(projects.features.login) implementation(projects.features.login.api)
implementation(projects.features.preferences) implementation(projects.features.preferences.api)
implementation(projects.features.logout) implementation(projects.features.logout.api)
implementation(projects.features.onboarding) implementation(projects.features.onboarding.api)
implementation(projects.libraries.core) implementation(projects.libraries.core)
implementation(projects.libraries.architecture) implementation(projects.libraries.architecture)
@ -58,4 +58,6 @@ dependencies {
testImplementation(libs.test.truth) testImplementation(libs.test.truth)
testImplementation(libs.test.turbine) testImplementation(libs.test.turbine)
testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.matrix.test)
testImplementation(projects.features.rageshake.test)
testImplementation(projects.features.rageshake.impl)
} }

5
appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt

@ -17,7 +17,6 @@
package io.element.android.appnav package io.element.android.appnav
import android.app.Activity import android.app.Activity
import android.content.Context
import android.os.Parcelable import android.os.Parcelable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@ -42,13 +41,12 @@ import io.element.android.anvilannotations.ContributesNode
import io.element.android.appnav.di.MatrixClientsHolder import io.element.android.appnav.di.MatrixClientsHolder
import io.element.android.appnav.root.RootPresenter import io.element.android.appnav.root.RootPresenter
import io.element.android.appnav.root.RootView import io.element.android.appnav.root.RootView
import io.element.android.features.rageshake.bugreport.BugReportEntryPoint import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint
import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.BackstackNode
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
@ -63,7 +61,6 @@ import timber.log.Timber
class RootFlowNode @AssistedInject constructor( class RootFlowNode @AssistedInject constructor(
@Assisted val buildContext: BuildContext, @Assisted val buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
@ApplicationContext private val appContext: Context,
private val authenticationService: MatrixAuthenticationService, private val authenticationService: MatrixAuthenticationService,
private val matrixClientsHolder: MatrixClientsHolder, private val matrixClientsHolder: MatrixClientsHolder,
private val presenter: RootPresenter, private val presenter: RootPresenter,

4
appnav/src/main/kotlin/io/element/android/appnav/root/RootPresenter.kt

@ -19,8 +19,8 @@ package io.element.android.appnav.root
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import io.element.android.features.rageshake.crash.ui.CrashDetectionPresenter import io.element.android.features.rageshake.api.crash.CrashDetectionPresenter
import io.element.android.features.rageshake.detection.RageshakeDetectionPresenter import io.element.android.features.rageshake.api.detection.RageshakeDetectionPresenter
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import javax.inject.Inject import javax.inject.Inject

9
appnav/src/main/kotlin/io/element/android/appnav/root/RootState.kt

@ -16,12 +16,11 @@
package io.element.android.appnav.root package io.element.android.appnav.root
import androidx.compose.runtime.Stable import androidx.compose.runtime.Immutable
import io.element.android.appnav.root.RootEvents import io.element.android.features.rageshake.api.crash.CrashDetectionState
import io.element.android.features.rageshake.crash.ui.CrashDetectionState import io.element.android.features.rageshake.api.detection.RageshakeDetectionState
import io.element.android.features.rageshake.detection.RageshakeDetectionState
@Stable @Immutable
data class RootState( data class RootState(
val isShowkaseButtonVisible: Boolean, val isShowkaseButtonVisible: Boolean,
val rageshakeDetectionState: RageshakeDetectionState, val rageshakeDetectionState: RageshakeDetectionState,

4
appnav/src/main/kotlin/io/element/android/appnav/root/RootStateProvider.kt

@ -17,8 +17,8 @@
package io.element.android.appnav.root package io.element.android.appnav.root
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.rageshake.crash.ui.aCrashDetectionState import io.element.android.features.rageshake.api.crash.aCrashDetectionState
import io.element.android.features.rageshake.detection.aRageshakeDetectionState import io.element.android.features.rageshake.api.detection.aRageshakeDetectionState
open class RootStateProvider : PreviewParameterProvider<RootState> { open class RootStateProvider : PreviewParameterProvider<RootState> {
override val values: Sequence<RootState> override val values: Sequence<RootState>

8
appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt

@ -24,10 +24,10 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.features.rageshake.crash.ui.CrashDetectionEvents import io.element.android.features.rageshake.api.crash.CrashDetectionEvents
import io.element.android.features.rageshake.crash.ui.CrashDetectionView import io.element.android.features.rageshake.api.crash.CrashDetectionView
import io.element.android.features.rageshake.detection.RageshakeDetectionEvents import io.element.android.features.rageshake.api.detection.RageshakeDetectionEvents
import io.element.android.features.rageshake.detection.RageshakeDetectionView import io.element.android.features.rageshake.api.detection.RageshakeDetectionView
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text

70
appnav/src/test/kotlin/io/element/android/appnav/FakeBugReporter.kt

@ -1,70 +0,0 @@
/*
* Copyright (c) 2023 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 io.element.android.appnav
import io.element.android.features.rageshake.reporter.BugReporter
import io.element.android.features.rageshake.reporter.BugReporterListener
import io.element.android.features.rageshake.reporter.ReportType
import io.element.android.libraries.matrix.test.A_FAILURE_REASON
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
// TODO Remove this duplicated class when we will rework modules.
class FakeBugReporter(val mode: FakeBugReporterMode = FakeBugReporterMode.Success) : BugReporter {
override fun sendBugReport(
coroutineScope: CoroutineScope,
reportType: ReportType,
withDevicesLogs: Boolean,
withCrashLogs: Boolean,
withKeyRequestHistory: Boolean,
withScreenshot: Boolean,
theBugDescription: String,
serverVersion: String,
canContact: Boolean,
customFields: Map<String, String>?,
listener: BugReporterListener?,
) {
coroutineScope.launch {
delay(100)
listener?.onProgress(0)
delay(100)
listener?.onProgress(50)
delay(100)
when (mode) {
FakeBugReporterMode.Success -> Unit
FakeBugReporterMode.Failure -> {
listener?.onUploadFailed(A_FAILURE_REASON)
return@launch
}
FakeBugReporterMode.Cancel -> {
listener?.onUploadCancelled()
return@launch
}
}
listener?.onProgress(100)
delay(100)
listener?.onUploadSucceed(null)
}
}
}
enum class FakeBugReporterMode {
Success,
Failure,
Cancel
}

50
appnav/src/test/kotlin/io/element/android/appnav/FakeCrashDataStore.kt

@ -1,50 +0,0 @@
/*
* Copyright (c) 2023 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 io.element.android.appnav
import io.element.android.features.rageshake.crash.CrashDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
const val A_CRASH_DATA = "Some crash data"
// TODO Remove this duplicated class when we will rework modules.
class FakeCrashDataStore(
crashData: String = "",
appHasCrashed: Boolean = false,
) : CrashDataStore {
private val appHasCrashedFlow = MutableStateFlow(appHasCrashed)
private val crashDataFlow = MutableStateFlow(crashData)
override fun setCrashData(crashData: String) {
crashDataFlow.value = crashData
}
override suspend fun resetAppHasCrashed() {
appHasCrashedFlow.value = false
}
override fun appHasCrashed(): Flow<Boolean> = appHasCrashedFlow
override fun crashInfo(): Flow<String> = crashDataFlow
override suspend fun reset() {
appHasCrashedFlow.value = false
crashDataFlow.value = ""
}
}

44
appnav/src/test/kotlin/io/element/android/appnav/FakeRageShake.kt

@ -1,44 +0,0 @@
/*
* Copyright (c) 2023 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 io.element.android.appnav
import io.element.android.features.rageshake.rageshake.RageShake
// TODO Remove this duplicated class when we will rework modules.
class FakeRageShake(
private var isAvailableValue: Boolean = true
) : RageShake {
private var interceptor: (() -> Unit)? = null
override fun isAvailable() = isAvailableValue
override fun start(sensitivity: Float) {
}
override fun stop() {
}
override fun setSensitivity(sensitivity: Float) {
}
override fun setInterceptor(interceptor: (() -> Unit)?) {
this.interceptor = interceptor
}
fun triggerPhoneRageshake() = interceptor?.invoke()
}

46
appnav/src/test/kotlin/io/element/android/appnav/FakeRageshakeDataStore.kt

@ -1,46 +0,0 @@
/*
* Copyright (c) 2023 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 io.element.android.appnav
import io.element.android.features.rageshake.rageshake.RageshakeDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
const val A_SENSITIVITY = 1f
// TODO Remove this duplicated class when we will rework modules.
class FakeRageshakeDataStore(
isEnabled: Boolean = true,
sensitivity: Float = A_SENSITIVITY,
) : RageshakeDataStore {
private val isEnabledFlow = MutableStateFlow(isEnabled)
override fun isEnabled(): Flow<Boolean> = isEnabledFlow
override suspend fun setIsEnabled(isEnabled: Boolean) {
isEnabledFlow.value = isEnabled
}
private val sensitivityFlow = MutableStateFlow(sensitivity)
override fun sensitivity(): Flow<Float> = sensitivityFlow
override suspend fun setSensitivity(sensitivity: Float) {
sensitivityFlow.value = sensitivity
}
override suspend fun reset() = Unit
}

16
appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt

@ -24,9 +24,13 @@ import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.appnav.root.RootEvents import io.element.android.appnav.root.RootEvents
import io.element.android.appnav.root.RootPresenter import io.element.android.appnav.root.RootPresenter
import io.element.android.features.rageshake.crash.ui.CrashDetectionPresenter import io.element.android.features.rageshake.impl.crash.DefaultCrashDetectionPresenter
import io.element.android.features.rageshake.detection.RageshakeDetectionPresenter import io.element.android.features.rageshake.impl.detection.DefaultRageshakeDetectionPresenter
import io.element.android.features.rageshake.preferences.RageshakePreferencesPresenter import io.element.android.features.rageshake.impl.preferences.DefaultRageshakePreferencesPresenter
import io.element.android.features.rageshake.test.crash.FakeCrashDataStore
import io.element.android.features.rageshake.test.rageshake.FakeRageShake
import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataStore
import io.element.android.features.rageshake.test.screenshot.FakeScreenshotHolder
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Test import org.junit.Test
@ -63,13 +67,13 @@ class RootPresenterTest {
val rageshakeDataStore = FakeRageshakeDataStore() val rageshakeDataStore = FakeRageshakeDataStore()
val rageshake = FakeRageShake() val rageshake = FakeRageShake()
val screenshotHolder = FakeScreenshotHolder() val screenshotHolder = FakeScreenshotHolder()
val crashDetectionPresenter = CrashDetectionPresenter( val crashDetectionPresenter = DefaultCrashDetectionPresenter(
crashDataStore = crashDataStore crashDataStore = crashDataStore
) )
val rageshakeDetectionPresenter = RageshakeDetectionPresenter( val rageshakeDetectionPresenter = DefaultRageshakeDetectionPresenter(
screenshotHolder = screenshotHolder, screenshotHolder = screenshotHolder,
rageShake = rageshake, rageShake = rageshake,
preferencesPresenter = RageshakePreferencesPresenter( preferencesPresenter = DefaultRageshakePreferencesPresenter(
rageshake = rageshake, rageshake = rageshake,
rageshakeDataStore = rageshakeDataStore, rageshakeDataStore = rageshakeDataStore,
) )

1
features/login/.gitignore vendored

@ -1 +0,0 @@
/build

27
features/login/api/build.gradle.kts

@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 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.
*/
plugins {
id("io.element.android-library")
}
android {
namespace = "io.element.android.features.login.api"
}
dependencies {
implementation(projects.libraries.architecture)
}

0
features/login/src/main/kotlin/io/element/android/features/login/api/LoginEntryPoint.kt → features/login/api/src/main/kotlin/io/element/android/features/login/api/LoginEntryPoint.kt

0
features/login/consumer-rules.pro

3
features/login/build.gradle.kts → features/login/impl/build.gradle.kts

@ -24,7 +24,7 @@ plugins {
} }
android { android {
namespace = "io.element.android.features.login" namespace = "io.element.android.features.login.impl"
} }
anvil { anvil {
@ -41,6 +41,7 @@ dependencies {
implementation(projects.libraries.elementresources) implementation(projects.libraries.elementresources)
implementation(projects.libraries.testtags) implementation(projects.libraries.testtags)
implementation(projects.libraries.uiStrings) implementation(projects.libraries.uiStrings)
api(projects.features.login.api)
ksp(libs.showkase.processor) ksp(libs.showkase.processor)
testImplementation(libs.test.junit) testImplementation(libs.test.junit)

0
features/login/src/main/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPoint.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPoint.kt

0
features/login/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt

0
features/login/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerEvents.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerEvents.kt

2
features/login/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerNode.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerNode.kt

@ -28,7 +28,7 @@ import com.bumble.appyx.core.plugin.Plugin
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.login.util.LoginConstants import io.element.android.features.login.impl.util.LoginConstants
import io.element.android.libraries.core.data.tryOrNull import io.element.android.libraries.core.data.tryOrNull
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope

2
features/login/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenter.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenter.kt

@ -22,7 +22,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import io.element.android.features.login.util.LoginConstants import io.element.android.features.login.impl.util.LoginConstants
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.execute import io.element.android.libraries.architecture.execute

0
features/login/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerState.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerState.kt

0
features/login/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerStateProvider.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerStateProvider.kt

2
features/login/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt

@ -50,7 +50,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.features.login.R import io.element.android.features.login.impl.R
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.ElementTextStyles import io.element.android.libraries.designsystem.ElementTextStyles
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog

0
features/login/src/main/kotlin/io/element/android/features/login/impl/error/ErrorFormatter.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/error/ErrorFormatter.kt

0
features/login/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootEvents.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootEvents.kt

0
features/login/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootNode.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootNode.kt

5
features/login/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootPresenter.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootPresenter.kt

@ -23,14 +23,12 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import io.element.android.features.login.util.LoginConstants import io.element.android.features.login.impl.util.LoginConstants
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.data.tryOrNull import io.element.android.libraries.core.data.tryOrNull
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@ -87,5 +85,4 @@ class LoginRootPresenter @Inject constructor(private val authenticationService:
private fun updateFormState(formState: MutableState<LoginFormState>, updateLambda: LoginFormState.() -> LoginFormState) { private fun updateFormState(formState: MutableState<LoginFormState>, updateLambda: LoginFormState.() -> LoginFormState) {
formState.value = updateLambda(formState.value) formState.value = updateLambda(formState.value)
} }
} }

0
features/login/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootScreen.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootScreen.kt

0
features/login/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootState.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootState.kt

0
features/login/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootStateProvider.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/root/LoginRootStateProvider.kt

2
features/login/src/main/kotlin/io/element/android/features/login/util/LoginConstants.kt → features/login/impl/src/main/kotlin/io/element/android/features/login/impl/util/LoginConstants.kt

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.login.util package io.element.android.features.login.impl.util
object LoginConstants { object LoginConstants {

0
features/login/src/main/res/drawable/ic_homeserver.xml → features/login/impl/src/main/res/drawable/ic_homeserver.xml

2
features/login/src/test/kotlin/io/element/android/features/login/changeserver/ChangeServerPresenterTest.kt → features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt

@ -16,7 +16,7 @@
@file:OptIn(ExperimentalCoroutinesApi::class) @file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.login.changeserver package io.element.android.features.login.impl.changeserver
import app.cash.molecule.RecompositionClock import app.cash.molecule.RecompositionClock
import app.cash.molecule.moleculeFlow import app.cash.molecule.moleculeFlow

2
features/login/src/test/kotlin/io/element/android/features/login/root/LoginRootPresenterTest.kt → features/login/impl/src/test/kotlin/io/element/android/features/login/impl/root/LoginRootPresenterTest.kt

@ -16,7 +16,7 @@
@file:OptIn(ExperimentalCoroutinesApi::class) @file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.login.root package io.element.android.features.login.impl.root
import app.cash.molecule.RecompositionClock import app.cash.molecule.RecompositionClock
import app.cash.molecule.moleculeFlow import app.cash.molecule.moleculeFlow

21
features/login/proguard-rules.pro vendored

@ -1,21 +0,0 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.kts.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

38
features/login/src/androidTest/kotlin/io/element/android/features/login/ExampleInstrumentedTest.kt

@ -1,38 +0,0 @@
/*
* 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 io.element.android.features.login
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("io.element.android.features.login.test", appContext.packageName)
}
}

20
features/login/src/main/AndroidManifest.xml

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<manifest>
</manifest>

32
features/login/src/test/kotlin/io/element/android/features/login/ExampleUnitTest.kt

@ -1,32 +0,0 @@
/*
* 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 io.element.android.features.login
import org.junit.Assert.assertEquals
import org.junit.Test
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

1
features/logout/.gitignore vendored

@ -1 +0,0 @@
/build

29
features/logout/api/build.gradle.kts

@ -0,0 +1,29 @@
/*
* Copyright (c) 2023 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.
*/
plugins {
id("io.element.android-compose-library")
}
android {
namespace = "io.element.android.features.logout.api"
}
dependencies {
implementation(projects.libraries.architecture)
implementation(projects.libraries.designsystem)
implementation(projects.libraries.uiStrings)
}

2
features/logout/src/main/kotlin/io/element/android/features/logout/LogoutPreferenceEvents.kt → features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferenceEvents.kt

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.logout package io.element.android.features.logout.api
sealed interface LogoutPreferenceEvents { sealed interface LogoutPreferenceEvents {
object Logout : LogoutPreferenceEvents object Logout : LogoutPreferenceEvents

21
features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferencePresenter.kt

@ -0,0 +1,21 @@
/*
* Copyright (c) 2023 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 io.element.android.features.logout.api
import io.element.android.libraries.architecture.Presenter
interface LogoutPreferencePresenter : Presenter<LogoutPreferenceState>

2
features/logout/src/main/kotlin/io/element/android/features/logout/LogoutPreferenceScreen.kt → features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferenceScreen.kt

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.logout package io.element.android.features.logout.api
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Logout import androidx.compose.material.icons.filled.Logout

2
features/logout/src/main/kotlin/io/element/android/features/logout/LogoutPreferenceState.kt → features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferenceState.kt

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.logout package io.element.android.features.logout.api
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async

2
features/logout/src/main/kotlin/io/element/android/features/logout/LogoutPreferenceStateProvider.kt → features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferenceStateProvider.kt

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.logout package io.element.android.features.logout.api
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async

0
features/logout/consumer-rules.pro

6
features/logout/build.gradle.kts → features/logout/impl/build.gradle.kts

@ -23,7 +23,7 @@ plugins {
} }
android { android {
namespace = "io.element.android.features.logout" namespace = "io.element.android.features.logout.impl"
} }
anvil { anvil {
@ -33,12 +33,14 @@ anvil {
dependencies { dependencies {
implementation(projects.anvilannotations) implementation(projects.anvilannotations)
anvil(projects.anvilcodegen) anvil(projects.anvilcodegen)
implementation(projects.libraries.architecture)
implementation(projects.libraries.core) implementation(projects.libraries.core)
implementation(projects.libraries.architecture)
implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrix.api)
implementation(projects.libraries.designsystem) implementation(projects.libraries.designsystem)
implementation(projects.libraries.elementresources) implementation(projects.libraries.elementresources)
implementation(projects.libraries.testtags)
implementation(projects.libraries.uiStrings) implementation(projects.libraries.uiStrings)
api(projects.features.logout.api)
ksp(libs.showkase.processor) ksp(libs.showkase.processor)
testImplementation(libs.test.junit) testImplementation(libs.test.junit)

4
features/preferences/src/main/AndroidManifest.xml → features/logout/impl/src/main/AndroidManifest.xml

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
~ Copyright (c) 2022 New Vector Ltd ~ Copyright (c) 2023 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.
@ -15,6 +15,6 @@
~ limitations under the License. ~ limitations under the License.
--> -->
<manifest> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest> </manifest>

13
features/logout/src/main/kotlin/io/element/android/features/logout/LogoutPreferencePresenter.kt → features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/DefaultLogoutPreferencePresenter.kt

@ -14,23 +14,28 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.logout package io.element.android.features.logout.impl
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.logout.api.LogoutPreferenceEvents
import io.element.android.features.logout.api.LogoutPreferencePresenter
import io.element.android.features.logout.api.LogoutPreferenceState
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.execute import io.element.android.libraries.architecture.execute
import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
class LogoutPreferencePresenter @Inject constructor(private val matrixClient: MatrixClient) : @ContributesBinding(SessionScope::class)
Presenter<LogoutPreferenceState> { class DefaultLogoutPreferencePresenter @Inject constructor(private val matrixClient: MatrixClient) :
LogoutPreferencePresenter {
@Composable @Composable
override fun present(): LogoutPreferenceState { override fun present(): LogoutPreferenceState {

10
features/logout/src/test/kotlin/io/element/android/features/logout/LogoutPreferencePresenterTest.kt → features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPreferencePresenterTest.kt

@ -16,12 +16,14 @@
@file:OptIn(ExperimentalCoroutinesApi::class) @file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.logout package io.element.android.features.logout.impl
import app.cash.molecule.RecompositionClock import app.cash.molecule.RecompositionClock
import app.cash.molecule.moleculeFlow import app.cash.molecule.moleculeFlow
import app.cash.turbine.test import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.features.logout.api.LogoutPreferenceEvents
import io.element.android.features.logout.api.LogoutPreferenceState
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.A_THROWABLE import io.element.android.libraries.matrix.test.A_THROWABLE
@ -33,7 +35,7 @@ import org.junit.Test
class LogoutPreferencePresenterTest { class LogoutPreferencePresenterTest {
@Test @Test
fun `present - initial state`() = runTest { fun `present - initial state`() = runTest {
val presenter = LogoutPreferencePresenter( val presenter = DefaultLogoutPreferencePresenter(
FakeMatrixClient(A_SESSION_ID), FakeMatrixClient(A_SESSION_ID),
) )
moleculeFlow(RecompositionClock.Immediate) { moleculeFlow(RecompositionClock.Immediate) {
@ -46,7 +48,7 @@ class LogoutPreferencePresenterTest {
@Test @Test
fun `present - logout`() = runTest { fun `present - logout`() = runTest {
val presenter = LogoutPreferencePresenter( val presenter = DefaultLogoutPreferencePresenter(
FakeMatrixClient(A_SESSION_ID), FakeMatrixClient(A_SESSION_ID),
) )
moleculeFlow(RecompositionClock.Immediate) { moleculeFlow(RecompositionClock.Immediate) {
@ -64,7 +66,7 @@ class LogoutPreferencePresenterTest {
@Test @Test
fun `present - logout with error`() = runTest { fun `present - logout with error`() = runTest {
val matrixClient = FakeMatrixClient(A_SESSION_ID) val matrixClient = FakeMatrixClient(A_SESSION_ID)
val presenter = LogoutPreferencePresenter( val presenter = DefaultLogoutPreferencePresenter(
matrixClient, matrixClient,
) )
moleculeFlow(RecompositionClock.Immediate) { moleculeFlow(RecompositionClock.Immediate) {

21
features/logout/proguard-rules.pro vendored

@ -1,21 +0,0 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.kts.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

38
features/logout/src/androidTest/kotlin/io/element/android/features/logout/ExampleInstrumentedTest.kt

@ -1,38 +0,0 @@
/*
* 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 io.element.android.features.logout
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("io.element.android.features.login.test", appContext.packageName)
}
}

20
features/logout/src/main/AndroidManifest.xml

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<manifest>
</manifest>

32
features/logout/src/test/kotlin/io/element/android/features/logout/ExampleUnitTest.kt

@ -1,32 +0,0 @@
/*
* 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 io.element.android.features.logout
import org.junit.Assert.assertEquals
import org.junit.Test
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

2
features/messages/api/build.gradle.kts

@ -17,7 +17,7 @@
// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed // TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed
@Suppress("DSL_SCOPE_VIOLATION") @Suppress("DSL_SCOPE_VIOLATION")
plugins { plugins {
id("io.element.android-compose-library") id("io.element.android-library")
} }
android { android {

1
features/onboarding/.gitignore vendored

@ -1 +0,0 @@
/build

27
features/onboarding/api/build.gradle.kts

@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 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.
*/
plugins {
id("io.element.android-library")
}
android {
namespace = "io.element.android.features.onboarding.api"
}
dependencies {
implementation(projects.libraries.architecture)
}

0
features/onboarding/src/main/kotlin/io/element/android/features/onboarding/api/OnBoardingEntryPoint.kt → features/onboarding/api/src/main/kotlin/io/element/android/features/onboarding/api/OnBoardingEntryPoint.kt

48
features/onboarding/build.gradle.kts

@ -1,48 +0,0 @@
/*
* 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.
*/
// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed
@Suppress("DSL_SCOPE_VIOLATION")
plugins {
id("io.element.android-compose-library")
alias(libs.plugins.anvil)
alias(libs.plugins.ksp)
}
android {
namespace = "io.element.android.features.onboarding"
}
anvil {
generateDaggerFactories.set(true)
}
dependencies {
implementation(projects.libraries.core)
implementation(projects.libraries.elementresources)
implementation(projects.anvilannotations)
anvil(projects.anvilcodegen)
implementation(projects.libraries.uiStrings)
implementation(projects.libraries.designsystem)
implementation(projects.libraries.architecture)
implementation(projects.libraries.testtags)
implementation(projects.libraries.androidutils)
implementation(libs.accompanist.pager)
implementation(libs.accompanist.pagerindicator)
testImplementation(libs.test.junit)
androidTestImplementation(libs.test.junitext)
ksp(libs.showkase.processor)
}

0
features/onboarding/consumer-rules.pro

16
features/preferences/build.gradle.kts → features/onboarding/impl/build.gradle.kts

@ -24,7 +24,7 @@ plugins {
} }
android { android {
namespace = "io.element.android.features.preferences" namespace = "io.element.android.features.onboarding.impl"
} }
anvil { anvil {
@ -34,16 +34,17 @@ anvil {
dependencies { dependencies {
implementation(projects.anvilannotations) implementation(projects.anvilannotations)
anvil(projects.anvilcodegen) anvil(projects.anvilcodegen)
implementation(projects.libraries.architecture)
implementation(projects.libraries.core) implementation(projects.libraries.core)
implementation(projects.libraries.matrixui) implementation(projects.libraries.architecture)
implementation(projects.features.rageshake) implementation(projects.libraries.matrix.api)
implementation(projects.features.logout)
implementation(projects.libraries.designsystem) implementation(projects.libraries.designsystem)
implementation(projects.libraries.elementresources) implementation(projects.libraries.elementresources)
implementation(projects.libraries.testtags)
implementation(projects.libraries.uiStrings) implementation(projects.libraries.uiStrings)
implementation(libs.datetime) implementation(libs.accompanist.pager)
implementation(libs.accompanist.placeholder) implementation(libs.accompanist.pagerindicator)
api(projects.features.onboarding.api)
ksp(libs.showkase.processor)
testImplementation(libs.test.junit) testImplementation(libs.test.junit)
testImplementation(libs.coroutines.test) testImplementation(libs.coroutines.test)
@ -53,5 +54,4 @@ dependencies {
testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.matrix.test)
androidTestImplementation(libs.test.junitext) androidTestImplementation(libs.test.junitext)
ksp(libs.showkase.processor)
} }

0
features/onboarding/src/main/kotlin/io/element/android/features/onboarding/impl/DefaultOnBoardingEntryPoint.kt → features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/DefaultOnBoardingEntryPoint.kt

0
features/onboarding/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingNode.kt → features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingNode.kt

0
features/onboarding/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingScreen.kt → features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingScreen.kt

0
features/onboarding/src/main/kotlin/io/element/android/features/onboarding/impl/SplashCarouselData.kt → features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/SplashCarouselData.kt

1
features/onboarding/src/main/kotlin/io/element/android/features/onboarding/impl/SplashCarouselDataFactory.kt → features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/SplashCarouselDataFactory.kt

@ -17,7 +17,6 @@
package io.element.android.features.onboarding.impl package io.element.android.features.onboarding.impl
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import io.element.android.features.onboarding.R
import io.element.android.libraries.ui.strings.R as StringR import io.element.android.libraries.ui.strings.R as StringR
class SplashCarouselDataFactory { class SplashCarouselDataFactory {

0
features/onboarding/src/main/res/drawable-hdpi/ic_splash_collaboration.webp → features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_collaboration.webp

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

0
features/onboarding/src/main/res/drawable-hdpi/ic_splash_collaboration_dark.webp → features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_collaboration_dark.webp

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

0
features/onboarding/src/main/res/drawable-hdpi/ic_splash_control.webp → features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_control.webp

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

0
features/onboarding/src/main/res/drawable-hdpi/ic_splash_control_dark.webp → features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_control_dark.webp

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

0
features/onboarding/src/main/res/drawable-hdpi/ic_splash_conversations.webp → features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_conversations.webp

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

0
features/onboarding/src/main/res/drawable-hdpi/ic_splash_conversations_dark.webp → features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_conversations_dark.webp

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

0
features/onboarding/src/main/res/drawable-hdpi/ic_splash_secure.webp → features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_secure.webp

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

0
features/onboarding/src/main/res/drawable-hdpi/ic_splash_secure_dark.webp → features/onboarding/impl/src/main/res/drawable-hdpi/ic_splash_secure_dark.webp

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

0
features/onboarding/src/main/res/drawable-xhdpi/ic_splash_collaboration.webp → features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_collaboration.webp

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

0
features/onboarding/src/main/res/drawable-xhdpi/ic_splash_collaboration_dark.webp → features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_collaboration_dark.webp

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

0
features/onboarding/src/main/res/drawable-xhdpi/ic_splash_control.webp → features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_control.webp

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

0
features/onboarding/src/main/res/drawable-xhdpi/ic_splash_control_dark.webp → features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_control_dark.webp

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

0
features/onboarding/src/main/res/drawable-xhdpi/ic_splash_conversations.webp → features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_conversations.webp

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

0
features/onboarding/src/main/res/drawable-xhdpi/ic_splash_conversations_dark.webp → features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_conversations_dark.webp

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 140 KiB

0
features/onboarding/src/main/res/drawable-xhdpi/ic_splash_secure.webp → features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_secure.webp

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

0
features/onboarding/src/main/res/drawable-xhdpi/ic_splash_secure_dark.webp → features/onboarding/impl/src/main/res/drawable-xhdpi/ic_splash_secure_dark.webp

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

0
features/onboarding/src/main/res/drawable-xxhdpi/ic_splash_collaboration.webp → features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_collaboration.webp

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

0
features/onboarding/src/main/res/drawable-xxhdpi/ic_splash_collaboration_dark.webp → features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_collaboration_dark.webp

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

0
features/onboarding/src/main/res/drawable-xxhdpi/ic_splash_control.webp → features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_control.webp

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

0
features/onboarding/src/main/res/drawable-xxhdpi/ic_splash_control_dark.webp → features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_control_dark.webp

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

0
features/onboarding/src/main/res/drawable-xxhdpi/ic_splash_conversations.webp → features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_conversations.webp

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

0
features/onboarding/src/main/res/drawable-xxhdpi/ic_splash_conversations_dark.webp → features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_conversations_dark.webp

Before

Width:  |  Height:  |  Size: 277 KiB

After

Width:  |  Height:  |  Size: 277 KiB

0
features/onboarding/src/main/res/drawable-xxhdpi/ic_splash_secure.webp → features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_secure.webp

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

0
features/onboarding/src/main/res/drawable-xxhdpi/ic_splash_secure_dark.webp → features/onboarding/impl/src/main/res/drawable-xxhdpi/ic_splash_secure_dark.webp

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

0
features/onboarding/src/main/res/drawable-xxxhdpi/ic_splash_collaboration.webp → features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_collaboration.webp

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

0
features/onboarding/src/main/res/drawable-xxxhdpi/ic_splash_collaboration_dark.webp → features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_collaboration_dark.webp

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 119 KiB

0
features/onboarding/src/main/res/drawable-xxxhdpi/ic_splash_control.webp → features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_control.webp

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

0
features/onboarding/src/main/res/drawable-xxxhdpi/ic_splash_control_dark.webp → features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_control_dark.webp

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

0
features/onboarding/src/main/res/drawable-xxxhdpi/ic_splash_conversations.webp → features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_conversations.webp

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

0
features/onboarding/src/main/res/drawable-xxxhdpi/ic_splash_conversations_dark.webp → features/onboarding/impl/src/main/res/drawable-xxxhdpi/ic_splash_conversations_dark.webp

Before

Width:  |  Height:  |  Size: 468 KiB

After

Width:  |  Height:  |  Size: 468 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save