commit
6a2881416f
159 changed files with 1580 additions and 985 deletions
1
.idea/dictionaries/shared.xml
generated
1
.idea/dictionaries/shared.xml
generated
|
|
@ -4,6 +4,7 @@
|
|||
<w>backstack</w>
|
||||
<w>ftue</w>
|
||||
<w>homeserver</w>
|
||||
<w>konsist</w>
|
||||
<w>kover</w>
|
||||
<w>measurables</w>
|
||||
<w>onboarding</w>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
* [knit](#knit)
|
||||
* [lint](#lint)
|
||||
* [Unit tests](#unit-tests)
|
||||
* [konsist](#konsist)
|
||||
* [Tests](#tests)
|
||||
* [Accessibility](#accessibility)
|
||||
* [Jetpack Compose](#jetpack-compose)
|
||||
|
|
@ -156,6 +157,10 @@ Make sure the following commands execute without any error:
|
|||
./gradlew test
|
||||
</pre>
|
||||
|
||||
#### konsist
|
||||
|
||||
[konsist](https://github.com/LemonAppDev/konsist) is setup in the project to check that the architecture and the naming rules are followed. Konsist tests are classical Unit tests.
|
||||
|
||||
### Tests
|
||||
|
||||
Element X is currently supported on Android Marshmallow (API 23+): please test your change on an Android device (or Android emulator) running with API 23. Many issues can happen (including crashes) on older devices.
|
||||
|
|
|
|||
|
|
@ -230,6 +230,7 @@ dependencies {
|
|||
testImplementation(libs.test.truth)
|
||||
testImplementation(libs.test.turbine)
|
||||
testImplementation(projects.libraries.matrix.test)
|
||||
testImplementation(libs.test.konsist)
|
||||
|
||||
ksp(libs.showkase.processor)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import com.bumble.appyx.core.integrationpoint.NodeComponentActivity
|
|||
import com.bumble.appyx.core.plugin.NodeReadyObserver
|
||||
import io.element.android.libraries.architecture.bindings
|
||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||
import io.element.android.libraries.designsystem.utils.LocalSnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.LocalSnackbarDispatcher
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
import io.element.android.x.di.AppBindings
|
||||
import io.element.android.x.intent.SafeUriHandler
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ package io.element.android.x.di
|
|||
|
||||
import com.squareup.anvil.annotations.ContributesTo
|
||||
import io.element.android.features.rageshake.api.reporter.BugReporter
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.matrix.api.tracing.TracingService
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import io.element.android.features.messages.impl.timeline.components.customreact
|
|||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.core.meta.BuildType
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.di.DefaultPreferences
|
||||
|
|
|
|||
139
app/src/test/kotlin/io/element/android/app/KonsistTest.kt
Normal file
139
app/src/test/kotlin/io/element/android/app/KonsistTest.kt
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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.app
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.lemonappdev.konsist.api.KoModifier
|
||||
import com.lemonappdev.konsist.api.Konsist
|
||||
import com.lemonappdev.konsist.api.ext.list.constructors
|
||||
import com.lemonappdev.konsist.api.ext.list.modifierprovider.withoutModifier
|
||||
import com.lemonappdev.konsist.api.ext.list.modifierprovider.withoutOverrideModifier
|
||||
import com.lemonappdev.konsist.api.ext.list.parameters
|
||||
import com.lemonappdev.konsist.api.ext.list.properties
|
||||
import com.lemonappdev.konsist.api.ext.list.withAllAnnotationsOf
|
||||
import com.lemonappdev.konsist.api.ext.list.withAllParentsOf
|
||||
import com.lemonappdev.konsist.api.ext.list.withNameEndingWith
|
||||
import com.lemonappdev.konsist.api.ext.list.withReturnType
|
||||
import com.lemonappdev.konsist.api.ext.list.withTopLevel
|
||||
import com.lemonappdev.konsist.api.ext.list.withoutName
|
||||
import com.lemonappdev.konsist.api.ext.list.withoutNameEndingWith
|
||||
import com.lemonappdev.konsist.api.verify.assertFalse
|
||||
import com.lemonappdev.konsist.api.verify.assertTrue
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import org.junit.Test
|
||||
|
||||
class KonsistTest {
|
||||
|
||||
@Test
|
||||
fun `Classes extending 'Presenter' should have 'Presenter' suffix`() {
|
||||
Konsist.scopeFromProject()
|
||||
.classes()
|
||||
.withAllParentsOf(Presenter::class)
|
||||
.assertTrue {
|
||||
it.name.endsWith("Presenter")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Functions with '@PreviewsDayNight' annotation should have 'Preview' suffix`() {
|
||||
Konsist
|
||||
.scopeFromProject()
|
||||
.functions()
|
||||
.withAllAnnotationsOf(PreviewsDayNight::class)
|
||||
.assertTrue {
|
||||
it.hasNameEndingWith("Preview") &&
|
||||
it.hasNameEndingWith("LightPreview").not() &&
|
||||
it.hasNameEndingWith("DarkPreview").not()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Top level function with '@Composable' annotation starting with a upper case should be placed in a file with the same name`() {
|
||||
Konsist
|
||||
.scopeFromProject()
|
||||
.functions()
|
||||
.withTopLevel()
|
||||
.withoutModifier(KoModifier.PRIVATE)
|
||||
.withoutNameEndingWith("Preview")
|
||||
.withAllAnnotationsOf(Composable::class)
|
||||
.withoutName(
|
||||
// Add some exceptions...
|
||||
"OutlinedButton",
|
||||
"TextButton",
|
||||
"SimpleAlertDialogContent",
|
||||
)
|
||||
.assertTrue(
|
||||
additionalMessage =
|
||||
"""
|
||||
Please check the filename. It should match the top level Composable function. If the filename is correct:
|
||||
- consider making the Composable private or moving it to its own file
|
||||
- at last resort, you can add an exception in the Konsist test
|
||||
""".trimIndent()
|
||||
) {
|
||||
if (it.name.first().isLowerCase()) {
|
||||
true
|
||||
} else {
|
||||
val fileName = it.containingFile.name.removeSuffix(".kt")
|
||||
fileName == it.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Data class state MUST not have default value`() {
|
||||
Konsist
|
||||
.scopeFromProject()
|
||||
.classes()
|
||||
.withNameEndingWith("State")
|
||||
.withoutName(
|
||||
"CameraPositionState",
|
||||
)
|
||||
.constructors
|
||||
.parameters
|
||||
.assertTrue { parameterDeclaration ->
|
||||
parameterDeclaration.defaultValue == null &&
|
||||
// Using parameterDeclaration.defaultValue == null is not enough apparently,
|
||||
// Also check that the text does not contain an equal sign
|
||||
parameterDeclaration.text.contains("=").not()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Function which creates Presenter in test MUST be named 'createPresenterName'`() {
|
||||
Konsist
|
||||
.scopeFromTest()
|
||||
.functions()
|
||||
.withReturnType { it.name.endsWith("Presenter") }
|
||||
.withoutOverrideModifier()
|
||||
.assertTrue { functionDeclaration ->
|
||||
functionDeclaration.name == "create${functionDeclaration.returnType?.name}"
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `no field should have 'm' prefix`() {
|
||||
Konsist
|
||||
.scopeFromProject()
|
||||
.classes()
|
||||
.properties()
|
||||
.assertFalse {
|
||||
val secondCharacterIsUppercase = it.name.getOrNull(1)?.isUpperCase() ?: false
|
||||
it.name.startsWith('m') && secondCharacterIsUppercase
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
package io.element.android.appnav
|
||||
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ import io.element.android.libraries.architecture.animation.rememberDefaultTransi
|
|||
import io.element.android.libraries.architecture.createNode
|
||||
import io.element.android.libraries.architecture.waitForChildAttached
|
||||
import io.element.android.libraries.deeplink.DeeplinkData
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.MAIN_SPACE
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class RootPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - initial state`() = runTest {
|
||||
val presenter = createPresenter()
|
||||
val presenter = createRootPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -54,7 +54,7 @@ class RootPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - passes app error state`() = runTest {
|
||||
val presenter = createPresenter(
|
||||
val presenter = createRootPresenter(
|
||||
appErrorService = DefaultAppErrorStateService().apply {
|
||||
showError("Bad news", "Something bad happened")
|
||||
}
|
||||
|
|
@ -75,7 +75,7 @@ class RootPresenterTest {
|
|||
}
|
||||
}
|
||||
|
||||
private fun createPresenter(
|
||||
private fun createRootPresenter(
|
||||
appErrorService: AppErrorStateService = DefaultAppErrorStateService()
|
||||
): RootPresenter {
|
||||
val crashDataStore = FakeCrashDataStore()
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class LoggedInPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - initial state`() = runTest {
|
||||
val presenter = createPresenter()
|
||||
val presenter = createLoggedInPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -54,7 +54,7 @@ class LoggedInPresenterTest {
|
|||
@Test
|
||||
fun `present - show sync spinner`() = runTest {
|
||||
val roomListService = FakeRoomListService()
|
||||
val presenter = createPresenter(roomListService, NetworkStatus.Online)
|
||||
val presenter = createLoggedInPresenter(roomListService, NetworkStatus.Online)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -66,7 +66,7 @@ class LoggedInPresenterTest {
|
|||
}
|
||||
}
|
||||
|
||||
private fun createPresenter(
|
||||
private fun createLoggedInPresenter(
|
||||
roomListService: RoomListService = FakeRoomListService(),
|
||||
networkStatus: NetworkStatus = NetworkStatus.Offline
|
||||
): LoggedInPresenter {
|
||||
|
|
|
|||
1
changelog.d/1526.misc
Normal file
1
changelog.d/1526.misc
Normal file
|
|
@ -0,0 +1 @@
|
|||
Add some Konsist tests.
|
||||
|
|
@ -84,7 +84,7 @@ fun AddPeopleView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AddPeopleViewTopBar(
|
||||
private fun AddPeopleViewTopBar(
|
||||
hasSelectedUsers: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
onBackPressed: () -> Unit = {},
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ fun ConfigureRoomView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ConfigureRoomToolbar(
|
||||
private fun ConfigureRoomToolbar(
|
||||
isNextActionEnabled: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
onBackPressed: () -> Unit = {},
|
||||
|
|
@ -207,7 +207,7 @@ fun ConfigureRoomToolbar(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun RoomNameWithAvatar(
|
||||
private fun RoomNameWithAvatar(
|
||||
avatarUri: Uri?,
|
||||
roomName: String,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -235,7 +235,7 @@ fun RoomNameWithAvatar(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun RoomTopic(
|
||||
private fun RoomTopic(
|
||||
topic: String,
|
||||
modifier: Modifier = Modifier,
|
||||
onTopicChanged: (String) -> Unit = {},
|
||||
|
|
@ -254,7 +254,7 @@ fun RoomTopic(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun RoomPrivacyOptions(
|
||||
private fun RoomPrivacyOptions(
|
||||
selected: RoomPrivacy?,
|
||||
modifier: Modifier = Modifier,
|
||||
onOptionSelected: (RoomPrivacyItem) -> Unit = {},
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ fun CreateRoomRootView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun CreateRoomRootViewTopBar(
|
||||
private fun CreateRoomRootViewTopBar(
|
||||
modifier: Modifier = Modifier,
|
||||
onClosePressed: () -> Unit = {},
|
||||
) {
|
||||
|
|
@ -148,7 +148,7 @@ fun CreateRoomRootViewTopBar(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun CreateRoomActionButtonsList(
|
||||
private fun CreateRoomActionButtonsList(
|
||||
state: CreateRoomRootState,
|
||||
modifier: Modifier = Modifier,
|
||||
onNewRoomClicked: () -> Unit = {},
|
||||
|
|
@ -169,7 +169,7 @@ fun CreateRoomActionButtonsList(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun CreateRoomActionButton(
|
||||
private fun CreateRoomActionButton(
|
||||
@DrawableRes iconRes: Int,
|
||||
text: String,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@ import kotlinx.collections.immutable.ImmutableList
|
|||
@Immutable
|
||||
data class InviteListState(
|
||||
val inviteList: ImmutableList<InviteListInviteSummary>,
|
||||
val declineConfirmationDialog: InviteDeclineConfirmationDialog = InviteDeclineConfirmationDialog.Hidden,
|
||||
val acceptedAction: Async<RoomId> = Async.Uninitialized,
|
||||
val declinedAction: Async<Unit> = Async.Uninitialized,
|
||||
val eventSink: (InviteListEvents) -> Unit = {}
|
||||
val declineConfirmationDialog: InviteDeclineConfirmationDialog,
|
||||
val acceptedAction: Async<RoomId>,
|
||||
val declinedAction: Async<Unit>,
|
||||
val eventSink: (InviteListEvents) -> Unit
|
||||
)
|
||||
|
||||
sealed interface InviteDeclineConfirmationDialog {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@ open class InviteListStateProvider : PreviewParameterProvider<InviteListState> {
|
|||
|
||||
internal fun aInviteListState() = InviteListState(
|
||||
inviteList = aInviteListInviteSummaryList(),
|
||||
declineConfirmationDialog = InviteDeclineConfirmationDialog.Hidden,
|
||||
acceptedAction = Async.Uninitialized,
|
||||
declinedAction = Async.Uninitialized,
|
||||
eventSink = {},
|
||||
)
|
||||
|
||||
internal fun aInviteListInviteSummaryList(): ImmutableList<InviteListInviteSummary> {
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ fun InviteListView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
fun InviteListContent(
|
||||
private fun InviteListContent(
|
||||
state: InviteListState,
|
||||
modifier: Modifier = Modifier,
|
||||
onBackClicked: () -> Unit = {},
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ internal fun InviteSummaryRow(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun DefaultInviteSummaryRow(
|
||||
private fun DefaultInviteSummaryRow(
|
||||
invite: InviteListInviteSummary,
|
||||
onAcceptClicked: () -> Unit = {},
|
||||
onDeclineClicked: () -> Unit = {},
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ package io.element.android.features.leaveroom.api
|
|||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
|
||||
data class LeaveRoomState(
|
||||
val confirmation: Confirmation = Confirmation.Hidden,
|
||||
val progress: Progress = Progress.Hidden,
|
||||
val error: Error = Error.Hidden,
|
||||
val eventSink: (LeaveRoomEvent) -> Unit = {},
|
||||
val confirmation: Confirmation,
|
||||
val progress: Progress,
|
||||
val error: Error,
|
||||
val eventSink: (LeaveRoomEvent) -> Unit,
|
||||
) {
|
||||
sealed interface Confirmation {
|
||||
data object Hidden : Confirmation
|
||||
|
|
|
|||
|
|
@ -22,32 +22,32 @@ import io.element.android.libraries.matrix.api.core.RoomId
|
|||
class LeaveRoomStateProvider : PreviewParameterProvider<LeaveRoomState> {
|
||||
override val values: Sequence<LeaveRoomState>
|
||||
get() = sequenceOf(
|
||||
LeaveRoomState(
|
||||
aLeaveRoomState(
|
||||
confirmation = LeaveRoomState.Confirmation.Hidden,
|
||||
progress = LeaveRoomState.Progress.Hidden,
|
||||
error = LeaveRoomState.Error.Hidden,
|
||||
),
|
||||
LeaveRoomState(
|
||||
aLeaveRoomState(
|
||||
confirmation = LeaveRoomState.Confirmation.Generic(A_ROOM_ID),
|
||||
progress = LeaveRoomState.Progress.Hidden,
|
||||
error = LeaveRoomState.Error.Hidden,
|
||||
),
|
||||
LeaveRoomState(
|
||||
aLeaveRoomState(
|
||||
confirmation = LeaveRoomState.Confirmation.PrivateRoom(A_ROOM_ID),
|
||||
progress = LeaveRoomState.Progress.Hidden,
|
||||
error = LeaveRoomState.Error.Hidden,
|
||||
),
|
||||
LeaveRoomState(
|
||||
aLeaveRoomState(
|
||||
confirmation = LeaveRoomState.Confirmation.LastUserInRoom(A_ROOM_ID),
|
||||
progress = LeaveRoomState.Progress.Hidden,
|
||||
error = LeaveRoomState.Error.Hidden,
|
||||
),
|
||||
LeaveRoomState(
|
||||
aLeaveRoomState(
|
||||
confirmation = LeaveRoomState.Confirmation.Hidden,
|
||||
progress = LeaveRoomState.Progress.Shown,
|
||||
error = LeaveRoomState.Error.Hidden,
|
||||
),
|
||||
LeaveRoomState(
|
||||
aLeaveRoomState(
|
||||
confirmation = LeaveRoomState.Confirmation.Hidden,
|
||||
progress = LeaveRoomState.Progress.Hidden,
|
||||
error = LeaveRoomState.Error.Shown,
|
||||
|
|
@ -56,3 +56,14 @@ class LeaveRoomStateProvider : PreviewParameterProvider<LeaveRoomState> {
|
|||
}
|
||||
|
||||
private val A_ROOM_ID = RoomId("!aRoomId:aDomain")
|
||||
|
||||
fun aLeaveRoomState(
|
||||
confirmation: LeaveRoomState.Confirmation = LeaveRoomState.Confirmation.Hidden,
|
||||
progress: LeaveRoomState.Progress = LeaveRoomState.Progress.Hidden,
|
||||
error: LeaveRoomState.Error = LeaveRoomState.Error.Hidden,
|
||||
) = LeaveRoomState(
|
||||
confirmation = confirmation,
|
||||
progress = progress,
|
||||
error = error,
|
||||
eventSink = {},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class LeaveRoomPresenterImplTest {
|
|||
|
||||
@Test
|
||||
fun `present - initial state hides all dialogs`() = runTest {
|
||||
val presenter = createPresenter()
|
||||
val presenter = createLeaveRoomPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -57,7 +57,7 @@ class LeaveRoomPresenterImplTest {
|
|||
|
||||
@Test
|
||||
fun `present - show generic confirmation`() = runTest {
|
||||
val presenter = createPresenter(
|
||||
val presenter = createLeaveRoomPresenter(
|
||||
client = FakeMatrixClient().apply {
|
||||
givenGetRoomResult(
|
||||
roomId = A_ROOM_ID,
|
||||
|
|
@ -77,7 +77,7 @@ class LeaveRoomPresenterImplTest {
|
|||
|
||||
@Test
|
||||
fun `present - show private room confirmation`() = runTest {
|
||||
val presenter = createPresenter(
|
||||
val presenter = createLeaveRoomPresenter(
|
||||
client = FakeMatrixClient().apply {
|
||||
givenGetRoomResult(
|
||||
roomId = A_ROOM_ID,
|
||||
|
|
@ -97,7 +97,7 @@ class LeaveRoomPresenterImplTest {
|
|||
|
||||
@Test
|
||||
fun `present - show last user in room confirmation`() = runTest {
|
||||
val presenter = createPresenter(
|
||||
val presenter = createLeaveRoomPresenter(
|
||||
client = FakeMatrixClient().apply {
|
||||
givenGetRoomResult(
|
||||
roomId = A_ROOM_ID,
|
||||
|
|
@ -118,7 +118,7 @@ class LeaveRoomPresenterImplTest {
|
|||
@Test
|
||||
fun `present - leaving a room leaves the room`() = runTest {
|
||||
val roomMembershipObserver = RoomMembershipObserver()
|
||||
val presenter = createPresenter(
|
||||
val presenter = createLeaveRoomPresenter(
|
||||
client = FakeMatrixClient().apply {
|
||||
givenGetRoomResult(
|
||||
roomId = A_ROOM_ID,
|
||||
|
|
@ -140,7 +140,7 @@ class LeaveRoomPresenterImplTest {
|
|||
|
||||
@Test
|
||||
fun `present - show error if leave room fails`() = runTest {
|
||||
val presenter = createPresenter(
|
||||
val presenter = createLeaveRoomPresenter(
|
||||
client = FakeMatrixClient().apply {
|
||||
givenGetRoomResult(
|
||||
roomId = A_ROOM_ID,
|
||||
|
|
@ -164,7 +164,7 @@ class LeaveRoomPresenterImplTest {
|
|||
|
||||
@Test
|
||||
fun `present - show progress indicator while leaving a room`() = runTest {
|
||||
val presenter = createPresenter(
|
||||
val presenter = createLeaveRoomPresenter(
|
||||
client = FakeMatrixClient().apply {
|
||||
givenGetRoomResult(
|
||||
roomId = A_ROOM_ID,
|
||||
|
|
@ -186,7 +186,7 @@ class LeaveRoomPresenterImplTest {
|
|||
|
||||
@Test
|
||||
fun `present - hide error hides the error`() = runTest {
|
||||
val presenter = createPresenter(
|
||||
val presenter = createLeaveRoomPresenter(
|
||||
client = FakeMatrixClient().apply {
|
||||
givenGetRoomResult(
|
||||
roomId = A_ROOM_ID,
|
||||
|
|
@ -212,7 +212,7 @@ class LeaveRoomPresenterImplTest {
|
|||
}
|
||||
}
|
||||
|
||||
private fun TestScope.createPresenter(
|
||||
private fun TestScope.createLeaveRoomPresenter(
|
||||
client: MatrixClient = FakeMatrixClient(),
|
||||
roomMembershipObserver: RoomMembershipObserver = RoomMembershipObserver(),
|
||||
): LeaveRoomPresenter = LeaveRoomPresenterImpl(
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import io.element.android.features.leaveroom.api.LeaveRoomEvent
|
|||
import io.element.android.features.leaveroom.api.LeaveRoomPresenter
|
||||
import io.element.android.features.leaveroom.api.LeaveRoomState
|
||||
|
||||
class FakeLeaveRoomPresenter: LeaveRoomPresenter {
|
||||
class FakeLeaveRoomPresenter : LeaveRoomPresenter {
|
||||
|
||||
val events = mutableListOf<LeaveRoomEvent>()
|
||||
|
||||
|
|
@ -29,7 +29,12 @@ class FakeLeaveRoomPresenter: LeaveRoomPresenter {
|
|||
events += event
|
||||
}
|
||||
|
||||
private var state = LeaveRoomState(eventSink = ::handleEvent)
|
||||
private var state = LeaveRoomState(
|
||||
confirmation = LeaveRoomState.Confirmation.Hidden,
|
||||
progress = LeaveRoomState.Progress.Hidden,
|
||||
error = LeaveRoomState.Error.Hidden,
|
||||
eventSink = ::handleEvent,
|
||||
)
|
||||
set(value) {
|
||||
field = value.copy(eventSink = ::handleEvent)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@
|
|||
package io.element.android.features.location.impl.common.permissions
|
||||
|
||||
data class PermissionsState(
|
||||
val permissions: Permissions = Permissions.NoneGranted,
|
||||
val shouldShowRationale: Boolean = false,
|
||||
val eventSink: (PermissionsEvents) -> Unit = {},
|
||||
val permissions: Permissions,
|
||||
val shouldShowRationale: Boolean,
|
||||
val eventSink: (PermissionsEvents) -> Unit,
|
||||
) {
|
||||
sealed interface Permissions {
|
||||
data object AllGranted : Permissions
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@
|
|||
package io.element.android.features.location.impl.send
|
||||
|
||||
data class SendLocationState(
|
||||
val permissionDialog: Dialog = Dialog.None,
|
||||
val mode: Mode = Mode.PinLocation,
|
||||
val hasLocationPermission: Boolean = false,
|
||||
val appName: String = "AppName",
|
||||
val eventSink: (SendLocationEvents) -> Unit = {},
|
||||
val permissionDialog: Dialog,
|
||||
val mode: Mode,
|
||||
val hasLocationPermission: Boolean,
|
||||
val appName: String,
|
||||
val eventSink: (SendLocationEvents) -> Unit,
|
||||
) {
|
||||
sealed interface Mode {
|
||||
data object SenderLocation : Mode
|
||||
|
|
|
|||
|
|
@ -23,35 +23,44 @@ private const val APP_NAME = "ApplicationName"
|
|||
class SendLocationStateProvider : PreviewParameterProvider<SendLocationState> {
|
||||
override val values: Sequence<SendLocationState>
|
||||
get() = sequenceOf(
|
||||
SendLocationState(
|
||||
aSendLocationState(
|
||||
permissionDialog = SendLocationState.Dialog.None,
|
||||
mode = SendLocationState.Mode.PinLocation,
|
||||
hasLocationPermission = false,
|
||||
appName = APP_NAME,
|
||||
),
|
||||
SendLocationState(
|
||||
aSendLocationState(
|
||||
permissionDialog = SendLocationState.Dialog.PermissionDenied,
|
||||
mode = SendLocationState.Mode.PinLocation,
|
||||
hasLocationPermission = false,
|
||||
appName = APP_NAME,
|
||||
),
|
||||
SendLocationState(
|
||||
aSendLocationState(
|
||||
permissionDialog = SendLocationState.Dialog.PermissionRationale,
|
||||
mode = SendLocationState.Mode.PinLocation,
|
||||
hasLocationPermission = false,
|
||||
appName = APP_NAME,
|
||||
),
|
||||
SendLocationState(
|
||||
aSendLocationState(
|
||||
permissionDialog = SendLocationState.Dialog.None,
|
||||
mode = SendLocationState.Mode.PinLocation,
|
||||
hasLocationPermission = true,
|
||||
appName = APP_NAME,
|
||||
),
|
||||
SendLocationState(
|
||||
aSendLocationState(
|
||||
permissionDialog = SendLocationState.Dialog.None,
|
||||
mode = SendLocationState.Mode.SenderLocation,
|
||||
hasLocationPermission = true,
|
||||
appName = APP_NAME,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun aSendLocationState(
|
||||
permissionDialog: SendLocationState.Dialog,
|
||||
mode: SendLocationState.Mode,
|
||||
hasLocationPermission: Boolean,
|
||||
): SendLocationState {
|
||||
return SendLocationState(
|
||||
permissionDialog = permissionDialog,
|
||||
mode = mode,
|
||||
hasLocationPermission = hasLocationPermission,
|
||||
appName = APP_NAME,
|
||||
eventSink = {}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.location.impl
|
||||
|
||||
import io.element.android.features.location.impl.common.permissions.PermissionsState
|
||||
|
||||
fun aPermissionsState(
|
||||
permissions: PermissionsState.Permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale: Boolean = false,
|
||||
): PermissionsState {
|
||||
return PermissionsState(
|
||||
permissions = permissions,
|
||||
shouldShowRationale = shouldShowRationale,
|
||||
eventSink = {},
|
||||
)
|
||||
}
|
||||
|
|
@ -26,7 +26,11 @@ class PermissionsPresenterFake : PermissionsPresenter {
|
|||
events += event
|
||||
}
|
||||
|
||||
private var state = PermissionsState(eventSink = ::handleEvent)
|
||||
private var state = PermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
eventSink = ::handleEvent
|
||||
)
|
||||
set(value) {
|
||||
field = value.copy(eventSink = ::handleEvent)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import app.cash.turbine.test
|
|||
import com.google.common.truth.Truth
|
||||
import im.vector.app.features.analytics.plan.Composer
|
||||
import io.element.android.features.location.api.Location
|
||||
import io.element.android.features.location.impl.aPermissionsState
|
||||
import io.element.android.features.location.impl.common.actions.FakeLocationActions
|
||||
import io.element.android.features.location.impl.common.permissions.PermissionsEvents
|
||||
import io.element.android.features.location.impl.common.permissions.PermissionsPresenter
|
||||
|
|
@ -65,7 +66,7 @@ class SendLocationPresenterTest {
|
|||
@Test
|
||||
fun `initial state with permissions granted`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.AllGranted,
|
||||
shouldShowRationale = false,
|
||||
)
|
||||
|
|
@ -92,7 +93,7 @@ class SendLocationPresenterTest {
|
|||
@Test
|
||||
fun `initial state with permissions partially granted`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.SomeGranted,
|
||||
shouldShowRationale = false,
|
||||
)
|
||||
|
|
@ -119,7 +120,7 @@ class SendLocationPresenterTest {
|
|||
@Test
|
||||
fun `initial state with permissions denied`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
)
|
||||
|
|
@ -145,7 +146,7 @@ class SendLocationPresenterTest {
|
|||
@Test
|
||||
fun `initial state with permissions denied once`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = true,
|
||||
)
|
||||
|
|
@ -171,7 +172,7 @@ class SendLocationPresenterTest {
|
|||
@Test
|
||||
fun `rationale dialog dismiss`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = true,
|
||||
)
|
||||
|
|
@ -202,7 +203,7 @@ class SendLocationPresenterTest {
|
|||
@Test
|
||||
fun `rationale dialog continue`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = true,
|
||||
)
|
||||
|
|
@ -230,7 +231,7 @@ class SendLocationPresenterTest {
|
|||
@Test
|
||||
fun `permission denied dialog dismiss`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
)
|
||||
|
|
@ -261,7 +262,7 @@ class SendLocationPresenterTest {
|
|||
@Test
|
||||
fun `share sender location`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.AllGranted,
|
||||
shouldShowRationale = false,
|
||||
)
|
||||
|
|
@ -317,7 +318,7 @@ class SendLocationPresenterTest {
|
|||
@Test
|
||||
fun `share pin location`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
)
|
||||
|
|
@ -373,7 +374,7 @@ class SendLocationPresenterTest {
|
|||
@Test
|
||||
fun `composer context passes through analytics`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
)
|
||||
|
|
@ -419,7 +420,7 @@ class SendLocationPresenterTest {
|
|||
@Test
|
||||
fun `open settings activity`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import app.cash.molecule.moleculeFlow
|
|||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth
|
||||
import io.element.android.features.location.api.Location
|
||||
import io.element.android.features.location.impl.aPermissionsState
|
||||
import io.element.android.features.location.impl.common.actions.FakeLocationActions
|
||||
import io.element.android.features.location.impl.common.permissions.PermissionsEvents
|
||||
import io.element.android.features.location.impl.common.permissions.PermissionsPresenter
|
||||
|
|
@ -55,7 +56,7 @@ class ShowLocationPresenterTest {
|
|||
@Test
|
||||
fun `emits initial state with no location permission`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
)
|
||||
|
|
@ -75,7 +76,7 @@ class ShowLocationPresenterTest {
|
|||
@Test
|
||||
fun `emits initial state location permission denied once`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = true,
|
||||
)
|
||||
|
|
@ -94,7 +95,7 @@ class ShowLocationPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `emits initial state with location permission`() = runTest {
|
||||
permissionsPresenterFake.givenState(PermissionsState(permissions = PermissionsState.Permissions.AllGranted))
|
||||
permissionsPresenterFake.givenState(aPermissionsState(permissions = PermissionsState.Permissions.AllGranted))
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -109,7 +110,7 @@ class ShowLocationPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `emits initial state with partial location permission`() = runTest {
|
||||
permissionsPresenterFake.givenState(PermissionsState(permissions = PermissionsState.Permissions.SomeGranted))
|
||||
permissionsPresenterFake.givenState(aPermissionsState(permissions = PermissionsState.Permissions.SomeGranted))
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -137,7 +138,7 @@ class ShowLocationPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `centers on user location`() = runTest {
|
||||
permissionsPresenterFake.givenState(PermissionsState(permissions = PermissionsState.Permissions.AllGranted))
|
||||
permissionsPresenterFake.givenState(aPermissionsState(permissions = PermissionsState.Permissions.AllGranted))
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -166,7 +167,7 @@ class ShowLocationPresenterTest {
|
|||
@Test
|
||||
fun `rationale dialog dismiss`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = true,
|
||||
)
|
||||
|
|
@ -197,7 +198,7 @@ class ShowLocationPresenterTest {
|
|||
@Test
|
||||
fun `rationale dialog continue`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = true,
|
||||
)
|
||||
|
|
@ -225,7 +226,7 @@ class ShowLocationPresenterTest {
|
|||
@Test
|
||||
fun `permission denied dialog dismiss`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
)
|
||||
|
|
@ -256,7 +257,7 @@ class ShowLocationPresenterTest {
|
|||
@Test
|
||||
fun `open settings activity`() = runTest {
|
||||
permissionsPresenterFake.givenState(
|
||||
PermissionsState(
|
||||
aPermissionsState(
|
||||
permissions = PermissionsState.Permissions.NoneGranted,
|
||||
shouldShowRationale = false,
|
||||
)
|
||||
|
|
@ -290,7 +291,6 @@ class ShowLocationPresenterTest {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
private const val A_DESCRIPTION = "My happy place"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ fun LoginPasswordView(
|
|||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
internal fun LoginForm(
|
||||
private fun LoginForm(
|
||||
state: LoginPasswordState,
|
||||
isLoading: Boolean,
|
||||
onSubmit: () -> Unit,
|
||||
|
|
@ -272,7 +272,7 @@ internal fun LoginForm(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun LoginErrorDialog(error: Throwable, onDismiss: () -> Unit) {
|
||||
private fun LoginErrorDialog(error: Throwable, onDismiss: () -> Unit) {
|
||||
ErrorDialog(
|
||||
title = stringResource(id = CommonStrings.dialog_title_error),
|
||||
content = stringResource(loginError(error)),
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ fun LogoutPreferenceView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun LogoutPreferenceContent(
|
||||
private fun LogoutPreferenceContent(
|
||||
onClick: () -> Unit = {},
|
||||
) {
|
||||
PreferenceText(
|
||||
|
|
@ -64,9 +64,9 @@ import io.element.android.libraries.architecture.Presenter
|
|||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import io.element.android.features.messages.impl.timeline.components.reactionsum
|
|||
import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuState
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
|
||||
@Immutable
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold
|
|||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.designsystem.utils.LogCompositions
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
|
|
|
|||
|
|
@ -336,7 +336,7 @@ private fun MessageSummary(event: TimelineItem.Event, modifier: Modifier = Modif
|
|||
private val emojiRippleRadius = 24.dp
|
||||
|
||||
@Composable
|
||||
internal fun EmojiReactionsRow(
|
||||
private fun EmojiReactionsRow(
|
||||
highlightedEmojis: ImmutableList<String>,
|
||||
onEmojiReactionClicked: (String) -> Unit,
|
||||
onCustomReactionClicked: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ fun ForwardMessagesView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun SelectedRooms(
|
||||
private fun SelectedRooms(
|
||||
selectedRooms: ImmutableList<RoomSummaryDetails>,
|
||||
onRoomRemoved: (RoomSummaryDetails) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -221,7 +221,7 @@ internal fun SelectedRooms(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun RoomSummaryView(
|
||||
private fun RoomSummaryView(
|
||||
summary: RoomSummaryDetails,
|
||||
isSelected: Boolean,
|
||||
onSelection: (RoomSummaryDetails) -> Unit,
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ private fun MediaImageView(
|
|||
|
||||
@UnstableApi
|
||||
@Composable
|
||||
fun MediaVideoView(
|
||||
private fun MediaVideoView(
|
||||
localMediaViewState: LocalMediaViewState,
|
||||
localMedia: LocalMedia?,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -196,7 +196,7 @@ fun MediaVideoView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun MediaPDFView(
|
||||
private fun MediaPDFView(
|
||||
localMediaViewState: LocalMediaViewState,
|
||||
localMedia: LocalMedia?,
|
||||
zoomableState: ZoomableState,
|
||||
|
|
@ -211,7 +211,7 @@ fun MediaPDFView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun MediaFileView(
|
||||
private fun MediaFileView(
|
||||
localMediaViewState: LocalMediaViewState,
|
||||
uri: Uri?,
|
||||
info: MediaInfo?,
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ import io.element.android.features.messages.impl.media.local.LocalMediaActions
|
|||
import io.element.android.features.messages.impl.media.local.LocalMediaFactory
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
|
||||
import io.element.android.libraries.matrix.api.media.MediaFile
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package io.element.android.features.messages.impl.media.viewer
|
|||
import io.element.android.features.messages.impl.media.local.LocalMedia
|
||||
import io.element.android.features.messages.impl.media.local.MediaInfo
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.media.MediaSource
|
||||
|
||||
data class MediaViewerState(
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ import io.element.android.libraries.designsystem.theme.components.IconButton
|
|||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
|
||||
import io.element.android.libraries.matrix.api.media.MediaSource
|
||||
import io.element.android.libraries.matrix.ui.media.MediaRequestData
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ internal fun AttachmentsBottomSheet(
|
|||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
internal fun AttachmentSourcePickerMenu(
|
||||
private fun AttachmentSourcePickerMenu(
|
||||
state: MessageComposerState,
|
||||
onSendLocationClicked: () -> Unit,
|
||||
onCreatePollClicked: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ import io.element.android.features.messages.impl.attachments.Attachment
|
|||
import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError
|
||||
import io.element.android.features.messages.impl.media.local.LocalMediaFactory
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.di.RoomScope
|
||||
import io.element.android.libraries.di.SingleIn
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ import dagger.assisted.AssistedInject
|
|||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runUpdatingState
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ fun TimelineView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun TimelineItemRow(
|
||||
private fun TimelineItemRow(
|
||||
timelineItem: TimelineItem,
|
||||
highlightedItem: String?,
|
||||
userHasPermissionToSendMessage: Boolean,
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ fun TimelineItemEventRow(
|
|||
* @param content the content to display.
|
||||
*/
|
||||
@Composable
|
||||
fun SwipeSensitivity(
|
||||
private fun SwipeSensitivity(
|
||||
sensitivityFactor: Float,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
|
|
@ -306,7 +306,7 @@ private fun TimelineItemEventRowContent(
|
|||
|
||||
// Reactions
|
||||
if (event.reactionsState.reactions.isNotEmpty()) {
|
||||
TimelineItemReactions(
|
||||
TimelineItemReactionsView(
|
||||
reactionsState = event.reactionsState,
|
||||
isOutgoing = event.isMine,
|
||||
onReactionClicked = onReactionClicked,
|
||||
|
|
@ -315,7 +315,7 @@ private fun TimelineItemEventRowContent(
|
|||
modifier = Modifier
|
||||
.constrainAs(reactions) {
|
||||
top.linkTo(message.bottom, margin = (-4).dp)
|
||||
this.linkStartOrEnd(event)
|
||||
linkStartOrEnd(event)
|
||||
}
|
||||
.zIndex(1f)
|
||||
.padding(start = if (event.isMine) 16.dp else 36.dp, end = 16.dp)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ import io.element.android.libraries.designsystem.utils.CommonDrawables
|
|||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Composable
|
||||
fun TimelineItemReactions(
|
||||
fun TimelineItemReactionsView(
|
||||
reactionsState: TimelineItemReactions,
|
||||
isOutgoing: Boolean,
|
||||
onReactionClicked: (emoji: String) -> Unit,
|
||||
|
|
@ -46,16 +46,16 @@ fun TimelineItemReactions(
|
|||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
var expanded: Boolean by rememberSaveable { mutableStateOf(false) }
|
||||
TimelineItemReactionsView(
|
||||
modifier = modifier,
|
||||
reactions = reactionsState.reactions,
|
||||
expanded = expanded,
|
||||
isOutgoing = isOutgoing,
|
||||
onReactionClick = onReactionClicked,
|
||||
onReactionLongClick = onReactionLongClicked,
|
||||
onMoreReactionsClick = onMoreReactionsClicked,
|
||||
onToggleExpandClick = { expanded = !expanded },
|
||||
)
|
||||
TimelineItemReactionsView(
|
||||
modifier = modifier,
|
||||
reactions = reactionsState.reactions,
|
||||
expanded = expanded,
|
||||
isOutgoing = isOutgoing,
|
||||
onReactionClick = onReactionClicked,
|
||||
onReactionLongClick = onReactionLongClicked,
|
||||
onMoreReactionsClick = onMoreReactionsClicked,
|
||||
onToggleExpandClick = { expanded = !expanded },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -153,7 +153,7 @@ private fun ContentToPreview(
|
|||
reactions: ImmutableList<AggregatedReaction>,
|
||||
isOutgoing: Boolean = false
|
||||
) {
|
||||
TimelineItemReactions(
|
||||
TimelineItemReactionsView(
|
||||
reactionsState = TimelineItemReactions(
|
||||
reactions
|
||||
),
|
||||
|
|
|
|||
|
|
@ -20,5 +20,5 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
|||
|
||||
sealed interface CustomReactionEvents {
|
||||
data class ShowCustomReactionSheet(val event: TimelineItem.Event) : CustomReactionEvents
|
||||
object DismissCustomReactionSheet : CustomReactionEvents
|
||||
data object DismissCustomReactionSheet : CustomReactionEvents
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ private fun SheetContent(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun AggregatedReactionButton(
|
||||
private fun AggregatedReactionButton(
|
||||
reaction: AggregatedReaction,
|
||||
isHighlighted: Boolean,
|
||||
onClick: () -> Unit,
|
||||
|
|
@ -215,7 +215,7 @@ fun AggregatedReactionButton(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun SenderRow(
|
||||
private fun SenderRow(
|
||||
avatarData: AvatarData,
|
||||
name: String,
|
||||
userId: String,
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ internal fun RetrySendMessageMenu(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
internal fun RetrySendMessageMenuBottomSheet(
|
||||
private fun RetrySendMessageMenuBottomSheet(
|
||||
isVisible: Boolean,
|
||||
onRetry: () -> Unit,
|
||||
onRemoveFailed: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,6 @@
|
|||
|
||||
package io.element.android.features.messages.impl.timeline.model.event
|
||||
|
||||
object TimelineItemRedactedContent : TimelineItemEventContent{
|
||||
data object TimelineItemRedactedContent : TimelineItemEventContent {
|
||||
override val type: String = "TimelineItemRedactedContent"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
|||
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||
import io.element.android.libraries.featureflag.test.InMemoryPreferencesStore
|
||||
|
|
@ -96,7 +96,7 @@ class MessagesPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - initial state`() = runTest {
|
||||
val presenter = createMessagePresenter()
|
||||
val presenter = createMessagesPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -117,7 +117,7 @@ class MessagesPresenterTest {
|
|||
fun `present - handle toggling a reaction`() = runTest {
|
||||
val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
|
||||
val room = FakeMatrixRoom()
|
||||
val presenter = createMessagePresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers)
|
||||
val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -137,7 +137,7 @@ class MessagesPresenterTest {
|
|||
fun `present - handle toggling a reaction twice`() = runTest {
|
||||
val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
|
||||
val room = FakeMatrixRoom()
|
||||
val presenter = createMessagePresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers)
|
||||
val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -154,7 +154,7 @@ class MessagesPresenterTest {
|
|||
@Test
|
||||
fun `present - handle action forward`() = runTest {
|
||||
val navigator = FakeMessagesNavigator()
|
||||
val presenter = createMessagePresenter(navigator = navigator)
|
||||
val presenter = createMessagesPresenter(navigator = navigator)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -169,7 +169,7 @@ class MessagesPresenterTest {
|
|||
fun `present - handle action copy`() = runTest {
|
||||
val clipboardHelper = FakeClipboardHelper()
|
||||
val event = aMessageEvent()
|
||||
val presenter = createMessagePresenter(clipboardHelper = clipboardHelper)
|
||||
val presenter = createMessagesPresenter(clipboardHelper = clipboardHelper)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -183,7 +183,7 @@ class MessagesPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - handle action reply`() = runTest {
|
||||
val presenter = createMessagePresenter()
|
||||
val presenter = createMessagesPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -198,7 +198,7 @@ class MessagesPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - handle action reply to an event with no id does nothing`() = runTest {
|
||||
val presenter = createMessagePresenter()
|
||||
val presenter = createMessagesPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -212,7 +212,7 @@ class MessagesPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - handle action reply to an image media message`() = runTest {
|
||||
val presenter = createMessagePresenter()
|
||||
val presenter = createMessagesPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -243,7 +243,7 @@ class MessagesPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - handle action reply to a video media message`() = runTest {
|
||||
val presenter = createMessagePresenter()
|
||||
val presenter = createMessagesPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -275,7 +275,7 @@ class MessagesPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - handle action reply to a file media message`() = runTest {
|
||||
val presenter = createMessagePresenter()
|
||||
val presenter = createMessagesPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -302,7 +302,7 @@ class MessagesPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - handle action edit`() = runTest {
|
||||
val presenter = createMessagePresenter()
|
||||
val presenter = createMessagesPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -319,7 +319,7 @@ class MessagesPresenterTest {
|
|||
fun `present - handle action redact`() = runTest {
|
||||
val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
|
||||
val matrixRoom = FakeMatrixRoom()
|
||||
val presenter = createMessagePresenter(matrixRoom = matrixRoom, coroutineDispatchers = coroutineDispatchers)
|
||||
val presenter = createMessagesPresenter(matrixRoom = matrixRoom, coroutineDispatchers = coroutineDispatchers)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -335,7 +335,7 @@ class MessagesPresenterTest {
|
|||
@Test
|
||||
fun `present - handle action report content`() = runTest {
|
||||
val navigator = FakeMessagesNavigator()
|
||||
val presenter = createMessagePresenter(navigator = navigator)
|
||||
val presenter = createMessagesPresenter(navigator = navigator)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -348,7 +348,7 @@ class MessagesPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - handle dismiss action`() = runTest {
|
||||
val presenter = createMessagePresenter()
|
||||
val presenter = createMessagesPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -362,7 +362,7 @@ class MessagesPresenterTest {
|
|||
@Test
|
||||
fun `present - handle action show developer info`() = runTest {
|
||||
val navigator = FakeMessagesNavigator()
|
||||
val presenter = createMessagePresenter(navigator = navigator)
|
||||
val presenter = createMessagesPresenter(navigator = navigator)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -376,7 +376,7 @@ class MessagesPresenterTest {
|
|||
@Test
|
||||
fun `present - shows prompt to reinvite users in DM`() = runTest {
|
||||
val room = FakeMatrixRoom(sessionId = A_SESSION_ID, isDirect = true, activeMemberCount = 1L)
|
||||
val presenter = createMessagePresenter(matrixRoom = room)
|
||||
val presenter = createMessagesPresenter(matrixRoom = room)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -402,7 +402,7 @@ class MessagesPresenterTest {
|
|||
@Test
|
||||
fun `present - doesn't show reinvite prompt in non-direct room`() = runTest {
|
||||
val room = FakeMatrixRoom(sessionId = A_SESSION_ID, isDirect = false, activeMemberCount = 1L)
|
||||
val presenter = createMessagePresenter(matrixRoom = room)
|
||||
val presenter = createMessagesPresenter(matrixRoom = room)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -418,7 +418,7 @@ class MessagesPresenterTest {
|
|||
@Test
|
||||
fun `present - doesn't show reinvite prompt if other party is present`() = runTest {
|
||||
val room = FakeMatrixRoom(sessionId = A_SESSION_ID, isDirect = true, activeMemberCount = 2L)
|
||||
val presenter = createMessagePresenter(matrixRoom = room)
|
||||
val presenter = createMessagesPresenter(matrixRoom = room)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -442,7 +442,7 @@ class MessagesPresenterTest {
|
|||
)
|
||||
)
|
||||
)
|
||||
val presenter = createMessagePresenter(matrixRoom = room)
|
||||
val presenter = createMessagesPresenter(matrixRoom = room)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -469,7 +469,7 @@ class MessagesPresenterTest {
|
|||
)
|
||||
)
|
||||
)
|
||||
val presenter = createMessagePresenter(matrixRoom = room)
|
||||
val presenter = createMessagesPresenter(matrixRoom = room)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -490,7 +490,7 @@ class MessagesPresenterTest {
|
|||
fun `present - handle reinviting other user when memberlist is not ready`() = runTest {
|
||||
val room = FakeMatrixRoom(sessionId = A_SESSION_ID)
|
||||
room.givenRoomMembersState(MatrixRoomMembersState.Unknown)
|
||||
val presenter = createMessagePresenter(matrixRoom = room)
|
||||
val presenter = createMessagesPresenter(matrixRoom = room)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -516,7 +516,7 @@ class MessagesPresenterTest {
|
|||
)
|
||||
)
|
||||
room.givenInviteUserResult(Result.failure(Throwable("Oops!")))
|
||||
val presenter = createMessagePresenter(matrixRoom = room)
|
||||
val presenter = createMessagesPresenter(matrixRoom = room)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -537,7 +537,7 @@ class MessagesPresenterTest {
|
|||
fun `present - permission to post`() = runTest {
|
||||
val matrixRoom = FakeMatrixRoom()
|
||||
matrixRoom.givenCanSendEventResult(MessageEventType.ROOM_MESSAGE, Result.success(true))
|
||||
val presenter = createMessagePresenter(matrixRoom = matrixRoom)
|
||||
val presenter = createMessagesPresenter(matrixRoom = matrixRoom)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -550,7 +550,7 @@ class MessagesPresenterTest {
|
|||
fun `present - no permission to post`() = runTest {
|
||||
val matrixRoom = FakeMatrixRoom()
|
||||
matrixRoom.givenCanSendEventResult(MessageEventType.ROOM_MESSAGE, Result.success(false))
|
||||
val presenter = createMessagePresenter(matrixRoom = matrixRoom)
|
||||
val presenter = createMessagesPresenter(matrixRoom = matrixRoom)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -565,7 +565,7 @@ class MessagesPresenterTest {
|
|||
@Test
|
||||
fun `present - permission to redact`() = runTest {
|
||||
val matrixRoom = FakeMatrixRoom(canRedact = true)
|
||||
val presenter = createMessagePresenter(matrixRoom = matrixRoom)
|
||||
val presenter = createMessagesPresenter(matrixRoom = matrixRoom)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -579,7 +579,7 @@ class MessagesPresenterTest {
|
|||
fun `present - handle poll end`() = runTest {
|
||||
val room = FakeMatrixRoom()
|
||||
val analyticsService = FakeAnalyticsService()
|
||||
val presenter = createMessagePresenter(
|
||||
val presenter = createMessagesPresenter(
|
||||
matrixRoom = room,
|
||||
analyticsService = analyticsService,
|
||||
)
|
||||
|
|
@ -598,7 +598,7 @@ class MessagesPresenterTest {
|
|||
}
|
||||
}
|
||||
|
||||
private fun TestScope.createMessagePresenter(
|
||||
private fun TestScope.createMessagesPresenter(
|
||||
coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
|
||||
matrixRoom: MatrixRoom = FakeMatrixRoom(),
|
||||
navigator: FakeMessagesNavigator = FakeMessagesNavigator(),
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - initial state`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = true)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -57,7 +57,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - compute for message from me redacted`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = true)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -82,7 +82,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - compute for message from others redacted`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = true)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -107,7 +107,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - compute for others message`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = true)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -139,7 +139,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - compute for others message cannot sent message`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = true)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -170,7 +170,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - compute for others message and can redact`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = true)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -201,7 +201,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - compute for my message`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = true)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -234,7 +234,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - compute for a media item`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = true)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -265,7 +265,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - compute for a state item in debug build`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = true)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -294,7 +294,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - compute for a state item in non-debuggable build`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = false)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = false)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -322,7 +322,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - compute message in non-debuggable build`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = false)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = false)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -354,7 +354,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - compute message with no actions`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = false)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = false)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -381,7 +381,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - compute not sent message`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = false)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = false)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -410,7 +410,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - compute for poll message`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = false)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = false)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -436,7 +436,7 @@ class ActionListPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - compute for ended poll message`() = runTest {
|
||||
val presenter = anActionListPresenter(isDeveloperModeEnabled = false)
|
||||
val presenter = createActionListPresenter(isDeveloperModeEnabled = false)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -460,7 +460,7 @@ class ActionListPresenterTest {
|
|||
}
|
||||
}
|
||||
|
||||
private fun anActionListPresenter(isDeveloperModeEnabled: Boolean): ActionListPresenter {
|
||||
private fun createActionListPresenter(isDeveloperModeEnabled: Boolean): ActionListPresenter {
|
||||
val preferencesStore = InMemoryPreferencesStore(isDeveloperModeEnabled = isDeveloperModeEnabled)
|
||||
return ActionListPresenter(preferencesStore = preferencesStore)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class AttachmentsPreviewPresenterTest {
|
|||
Pair(10, 10)
|
||||
)
|
||||
)
|
||||
val presenter = anAttachmentsPreviewPresenter(room = room)
|
||||
val presenter = createAttachmentsPreviewPresenter(room = room)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -81,7 +81,7 @@ class AttachmentsPreviewPresenterTest {
|
|||
val room = FakeMatrixRoom()
|
||||
val failure = MediaPreProcessor.Failure(null)
|
||||
room.givenSendMediaResult(Result.failure(failure))
|
||||
val presenter = anAttachmentsPreviewPresenter(room = room)
|
||||
val presenter = createAttachmentsPreviewPresenter(room = room)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -101,7 +101,7 @@ class AttachmentsPreviewPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `present - dismissing the progress dialog stops media upload`() = runTest {
|
||||
val presenter = anAttachmentsPreviewPresenter()
|
||||
val presenter = createAttachmentsPreviewPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -114,7 +114,7 @@ class AttachmentsPreviewPresenterTest {
|
|||
}
|
||||
}
|
||||
|
||||
private fun anAttachmentsPreviewPresenter(
|
||||
private fun createAttachmentsPreviewPresenter(
|
||||
localMedia: LocalMedia = aLocalMedia(
|
||||
uri = mockMediaUrl,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import io.element.android.features.messages.impl.media.viewer.MediaViewerPresent
|
|||
import io.element.android.features.messages.media.FakeLocalMediaActions
|
||||
import io.element.android.features.messages.media.FakeLocalMediaFactory
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.matrix.test.media.FakeMediaLoader
|
||||
import io.element.android.libraries.matrix.test.media.aMediaSource
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
|
|
@ -55,7 +55,7 @@ class MediaViewerPresenterTest {
|
|||
fun `present - download media success scenario`() = runTest {
|
||||
val mediaLoader = FakeMediaLoader()
|
||||
val mediaActions = FakeLocalMediaActions()
|
||||
val presenter = aMediaViewerPresenter(mediaLoader, mediaActions)
|
||||
val presenter = createMediaViewerPresenter(mediaLoader, mediaActions)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -76,7 +76,7 @@ class MediaViewerPresenterTest {
|
|||
val mediaLoader = FakeMediaLoader()
|
||||
val mediaActions = FakeLocalMediaActions()
|
||||
val snackbarDispatcher = SnackbarDispatcher()
|
||||
val presenter = aMediaViewerPresenter(mediaLoader, mediaActions, snackbarDispatcher)
|
||||
val presenter = createMediaViewerPresenter(mediaLoader, mediaActions, snackbarDispatcher)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -122,7 +122,7 @@ class MediaViewerPresenterTest {
|
|||
fun `present - download media failure then retry with success scenario`() = runTest {
|
||||
val mediaLoader = FakeMediaLoader()
|
||||
val mediaActions = FakeLocalMediaActions()
|
||||
val presenter = aMediaViewerPresenter(mediaLoader, mediaActions)
|
||||
val presenter = createMediaViewerPresenter(mediaLoader, mediaActions)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -147,7 +147,7 @@ class MediaViewerPresenterTest {
|
|||
}
|
||||
}
|
||||
|
||||
private fun aMediaViewerPresenter(
|
||||
private fun createMediaViewerPresenter(
|
||||
mediaLoader: FakeMediaLoader,
|
||||
localMediaActions: FakeLocalMediaActions,
|
||||
snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(),
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import com.google.common.truth.Truth.assertThat
|
|||
import io.element.android.features.messages.impl.report.ReportMessageEvents
|
||||
import io.element.android.features.messages.impl.report.ReportMessagePresenter
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer
|
|||
import io.element.android.features.messages.impl.messagecomposer.MessageComposerState
|
||||
import io.element.android.features.messages.media.FakeLocalMediaFactory
|
||||
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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.networkmonitor.api.ui
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.MutableTransitionState
|
||||
import androidx.compose.animation.core.Spring
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.animation.expandVertically
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.statusBars
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalInspectionMode
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
/**
|
||||
* A view that displays a connectivity indicator when the device is offline, passing the padding
|
||||
* needed to make sure the status bar is not overlapped to its content views.
|
||||
*/
|
||||
@Composable
|
||||
fun ConnectivityIndicatorContainer(
|
||||
isOnline: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable (topPadding: Dp) -> Unit = {},
|
||||
) {
|
||||
val isIndicatorVisible = remember { MutableTransitionState(!isOnline) }.apply { targetState = !isOnline }
|
||||
|
||||
val statusBarTopPadding = if (LocalInspectionMode.current) {
|
||||
// Needed to get valid UI previews
|
||||
24.dp
|
||||
} else {
|
||||
WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + 6.dp
|
||||
}
|
||||
val target = remember(isIndicatorVisible.targetState, statusBarTopPadding) {
|
||||
if (!isIndicatorVisible.targetState) 0.dp else statusBarTopPadding
|
||||
}
|
||||
val animationStateOffset by animateDpAsState(
|
||||
targetValue = target,
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessMediumLow,
|
||||
visibilityThreshold = 1.dp,
|
||||
),
|
||||
label = "insets-animation",
|
||||
)
|
||||
|
||||
content(animationStateOffset)
|
||||
|
||||
// Display the network indicator with an animation
|
||||
AnimatedVisibility(
|
||||
visibleState = isIndicatorVisible,
|
||||
enter = fadeIn() + expandVertically(),
|
||||
exit = fadeOut() + shrinkVertically(),
|
||||
) {
|
||||
Indicator(modifier)
|
||||
}
|
||||
}
|
||||
|
|
@ -18,44 +18,17 @@ package io.element.android.features.networkmonitor.api.ui
|
|||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.MutableTransitionState
|
||||
import androidx.compose.animation.core.Spring
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.animation.expandVertically
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBars
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalInspectionMode
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.text.toDp
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
/**
|
||||
* A view that displays a connectivity indicator when the device is offline, adding a default
|
||||
|
|
@ -88,75 +61,6 @@ fun ConnectivityIndicatorView(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A view that displays a connectivity indicator when the device is offline, passing the padding
|
||||
* needed to make sure the status bar is not overlapped to its content views.
|
||||
*/
|
||||
@Composable
|
||||
fun ConnectivityIndicatorContainer(
|
||||
isOnline: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable (topPadding: Dp) -> Unit,
|
||||
) {
|
||||
val isIndicatorVisible = remember { MutableTransitionState(!isOnline) }.apply { targetState = !isOnline }
|
||||
|
||||
val statusBarTopPadding = if (LocalInspectionMode.current) {
|
||||
// Needed to get valid UI previews
|
||||
24.dp
|
||||
} else {
|
||||
WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + 6.dp
|
||||
}
|
||||
val target = remember(isIndicatorVisible.targetState, statusBarTopPadding) {
|
||||
if (!isIndicatorVisible.targetState) 0.dp else statusBarTopPadding
|
||||
}
|
||||
val animationStateOffset by animateDpAsState(
|
||||
targetValue = target,
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessMediumLow,
|
||||
visibilityThreshold = 1.dp,
|
||||
),
|
||||
label = "insets-animation",
|
||||
)
|
||||
|
||||
content(animationStateOffset)
|
||||
|
||||
// Display the network indicator with an animation
|
||||
AnimatedVisibility(
|
||||
visibleState = isIndicatorVisible,
|
||||
enter = fadeIn() + expandVertically(),
|
||||
exit = fadeOut() + shrinkVertically(),
|
||||
) {
|
||||
Indicator(modifier)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Indicator(modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.background(MaterialTheme.colorScheme.secondaryContainer)
|
||||
.statusBarsPadding()
|
||||
.padding(vertical = 6.dp),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
val tint = MaterialTheme.colorScheme.primary
|
||||
Icon(
|
||||
resourceId = CommonDrawables.ic_compound_offline,
|
||||
contentDescription = null,
|
||||
tint = tint,
|
||||
modifier = Modifier.size(16.sp.toDp()),
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(
|
||||
text = stringResource(CommonStrings.common_offline),
|
||||
style = ElementTheme.typography.fontBodyMdMedium,
|
||||
color = tint,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun StatusBarPaddingSpacer(modifier: Modifier = Modifier) {
|
||||
Spacer(modifier = modifier.statusBarsPadding())
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.networkmonitor.api.ui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.libraries.designsystem.text.toDp
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@Composable
|
||||
internal fun Indicator(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.background(MaterialTheme.colorScheme.secondaryContainer)
|
||||
.statusBarsPadding()
|
||||
.padding(vertical = 6.dp),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
val tint = MaterialTheme.colorScheme.primary
|
||||
Icon(
|
||||
resourceId = CommonDrawables.ic_compound_offline,
|
||||
contentDescription = null,
|
||||
tint = tint,
|
||||
modifier = Modifier.size(16.sp.toDp()),
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(
|
||||
text = stringResource(CommonStrings.common_offline),
|
||||
style = ElementTheme.typography.fontBodyMdMedium,
|
||||
color = tint,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ data class CreatePollState(
|
|||
val answers: ImmutableList<Answer>,
|
||||
val pollKind: PollKind,
|
||||
val showConfirmation: Boolean,
|
||||
val eventSink: (CreatePollEvents) -> Unit = {},
|
||||
val eventSink: (CreatePollEvents) -> Unit,
|
||||
)
|
||||
|
||||
data class Answer(
|
||||
|
|
|
|||
|
|
@ -18,12 +18,13 @@ package io.element.android.features.poll.impl.create
|
|||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.libraries.matrix.api.poll.PollKind
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
|
||||
override val values: Sequence<CreatePollState>
|
||||
get() = sequenceOf(
|
||||
CreatePollState(
|
||||
aCreatePollState(
|
||||
canCreate = false,
|
||||
canAddAnswer = true,
|
||||
question = "",
|
||||
|
|
@ -34,7 +35,7 @@ class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
|
|||
pollKind = PollKind.Disclosed,
|
||||
showConfirmation = false,
|
||||
),
|
||||
CreatePollState(
|
||||
aCreatePollState(
|
||||
canCreate = true,
|
||||
canAddAnswer = true,
|
||||
question = "What type of food should we have?",
|
||||
|
|
@ -45,7 +46,7 @@ class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
|
|||
showConfirmation = false,
|
||||
pollKind = PollKind.Undisclosed,
|
||||
),
|
||||
CreatePollState(
|
||||
aCreatePollState(
|
||||
canCreate = true,
|
||||
canAddAnswer = true,
|
||||
question = "What type of food should we have?",
|
||||
|
|
@ -56,7 +57,7 @@ class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
|
|||
showConfirmation = true,
|
||||
pollKind = PollKind.Undisclosed,
|
||||
),
|
||||
CreatePollState(
|
||||
aCreatePollState(
|
||||
canCreate = true,
|
||||
canAddAnswer = true,
|
||||
question = "What type of food should we have?",
|
||||
|
|
@ -69,7 +70,7 @@ class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
|
|||
showConfirmation = false,
|
||||
pollKind = PollKind.Undisclosed,
|
||||
),
|
||||
CreatePollState(
|
||||
aCreatePollState(
|
||||
canCreate = true,
|
||||
canAddAnswer = false,
|
||||
question = "Should there be more than 20 answers?",
|
||||
|
|
@ -98,7 +99,7 @@ class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
|
|||
showConfirmation = false,
|
||||
pollKind = PollKind.Undisclosed,
|
||||
),
|
||||
CreatePollState(
|
||||
aCreatePollState(
|
||||
canCreate = true,
|
||||
canAddAnswer = true,
|
||||
question = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." +
|
||||
|
|
@ -122,3 +123,22 @@ class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
|
|||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun aCreatePollState(
|
||||
canCreate: Boolean,
|
||||
canAddAnswer: Boolean,
|
||||
question: String,
|
||||
answers: PersistentList<Answer>,
|
||||
showConfirmation: Boolean,
|
||||
pollKind: PollKind
|
||||
): CreatePollState {
|
||||
return CreatePollState(
|
||||
canCreate = canCreate,
|
||||
canAddAnswer = canAddAnswer,
|
||||
question = question,
|
||||
answers = answers,
|
||||
showConfirmation = showConfirmation,
|
||||
pollKind = pollKind,
|
||||
eventSink = {}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -33,7 +33,7 @@ fun AboutView(
|
|||
onBackPressed: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
modifier = modifier,
|
||||
onBackPressed = onBackPressed,
|
||||
title = stringResource(id = CommonStrings.common_about)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import io.element.android.features.preferences.impl.R
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -33,7 +33,7 @@ fun AdvancedSettingsView(
|
|||
onBackPressed: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
modifier = modifier,
|
||||
onBackPressed = onBackPressed,
|
||||
title = stringResource(id = CommonStrings.common_advanced_settings)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -32,7 +32,7 @@ fun AnalyticsSettingsView(
|
|||
onBackPressed: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
modifier = modifier,
|
||||
onBackPressed = onBackPressed,
|
||||
title = stringResource(id = CommonStrings.common_analytics)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
|||
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.featureflag.ui.FeatureListView
|
||||
|
|
@ -38,7 +38,7 @@ fun DeveloperSettingsView(
|
|||
onBackPressed: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
modifier = modifier,
|
||||
onBackPressed = onBackPressed,
|
||||
title = stringResource(id = CommonStrings.common_developer_options)
|
||||
|
|
@ -85,7 +85,7 @@ fun DeveloperSettingsView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun FeatureListContent(
|
||||
private fun FeatureListContent(
|
||||
state: DeveloperSettingsState,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ fun ConfigureTracingView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun CrateListContent(
|
||||
private fun CrateListContent(
|
||||
state: ConfigureTracingState,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
|
|
@ -178,7 +178,7 @@ private fun TargetAndLogLevelListView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun TargetAndLogLevelView(
|
||||
private fun TargetAndLogLevelView(
|
||||
target: Target,
|
||||
logLevel: LogLevel,
|
||||
onLogLevelChange: (LogLevel) -> Unit,
|
||||
|
|
@ -197,7 +197,7 @@ fun TargetAndLogLevelView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun LogLevelDropdownMenu(
|
||||
private fun LogLevelDropdownMenu(
|
||||
logLevel: LogLevel,
|
||||
onLogLevelChange: (LogLevel) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
|||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
|
|
@ -67,7 +67,7 @@ fun NotificationSettingsView(
|
|||
else -> Unit
|
||||
}
|
||||
}
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
modifier = modifier,
|
||||
onBackPressed = onBackPressed,
|
||||
title = stringResource(id = CommonStrings.screen_notification_settings_title)
|
||||
|
|
@ -79,7 +79,7 @@ fun NotificationSettingsView(
|
|||
onContinueClicked = { state.eventSink(NotificationSettingsEvents.FixConfigurationMismatch) },
|
||||
onDismissError = { state.eventSink(NotificationSettingsEvents.ClearConfigurationMismatchError) },
|
||||
)
|
||||
NotificationSettingsState.MatrixSettings.Uninitialized -> return@PreferenceView
|
||||
NotificationSettingsState.MatrixSettings.Uninitialized -> return@PreferencePage
|
||||
is NotificationSettingsState.MatrixSettings.Valid -> NotificationSettingsContentView(
|
||||
matrixSettings = state.matrixSettings,
|
||||
systemSettings = state.appSettings,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ fun EditDefaultNotificationSettingView(
|
|||
} else {
|
||||
CommonStrings.screen_notification_settings_group_chats
|
||||
}
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
modifier = modifier,
|
||||
onBackPressed = onBackPressed,
|
||||
title = stringResource(id = title)
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
|||
import io.element.android.features.logout.api.LogoutPreferencePresenter
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.meta.BuildType
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
package io.element.android.features.preferences.impl.root
|
||||
|
||||
import io.element.android.features.logout.api.LogoutPreferenceState
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
|
||||
data class PreferencesRootState(
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
package io.element.android.features.preferences.impl.root
|
||||
|
||||
import io.element.android.features.logout.api.aLogoutPreferenceState
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
fun aPreferencesRootState() = PreferencesRootState(
|
||||
|
|
|
|||
|
|
@ -31,15 +31,15 @@ import androidx.compose.ui.unit.dp
|
|||
import io.element.android.features.logout.api.LogoutPreferenceView
|
||||
import io.element.android.features.preferences.impl.user.UserPreferences
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight
|
||||
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.ui.components.MatrixUserProvider
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
|
|
@ -64,7 +64,7 @@ fun PreferencesRootView(
|
|||
val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage)
|
||||
|
||||
// Include pref from other modules
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
modifier = modifier,
|
||||
onBackPressed = onBackPressed,
|
||||
title = stringResource(id = CommonStrings.common_settings),
|
||||
|
|
@ -151,7 +151,7 @@ fun PreferencesRootView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun DeveloperPreferencesView(onOpenDeveloperSettings: () -> Unit) {
|
||||
private fun DeveloperPreferencesView(onOpenDeveloperSettings: () -> Unit) {
|
||||
PreferenceText(
|
||||
title = stringResource(id = CommonStrings.common_developer_options),
|
||||
iconResourceId = CommonDrawables.ic_developer_mode,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import kotlin.time.Duration.Companion.milliseconds
|
|||
class NotificationSettingsPresenterTests {
|
||||
@Test
|
||||
fun `present - ensures initial state is correct`() = runTest {
|
||||
val presenter = aNotificationPresenter()
|
||||
val presenter = createNotificationSettingsPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -58,7 +58,7 @@ class NotificationSettingsPresenterTests {
|
|||
@Test
|
||||
fun `present - default group notification mode changed`() = runTest {
|
||||
val notificationSettingsService = FakeNotificationSettingsService()
|
||||
val presenter = aNotificationPresenter(notificationSettingsService)
|
||||
val presenter = createNotificationSettingsPresenter(notificationSettingsService)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -77,7 +77,7 @@ class NotificationSettingsPresenterTests {
|
|||
@Test
|
||||
fun `present - notification settings mismatched`() = runTest {
|
||||
val notificationSettingsService = FakeNotificationSettingsService()
|
||||
val presenter = aNotificationPresenter(notificationSettingsService)
|
||||
val presenter = createNotificationSettingsPresenter(notificationSettingsService)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -108,7 +108,7 @@ class NotificationSettingsPresenterTests {
|
|||
initialEncryptedOneToOneDefaultMode = RoomNotificationMode.ALL_MESSAGES,
|
||||
initialOneToOneDefaultMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
|
||||
)
|
||||
val presenter = aNotificationPresenter(notificationSettingsService)
|
||||
val presenter = createNotificationSettingsPresenter(notificationSettingsService)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -125,7 +125,7 @@ class NotificationSettingsPresenterTests {
|
|||
|
||||
@Test
|
||||
fun `present - set notifications enabled`() = runTest {
|
||||
val presenter = aNotificationPresenter()
|
||||
val presenter = createNotificationSettingsPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -145,7 +145,7 @@ class NotificationSettingsPresenterTests {
|
|||
|
||||
@Test
|
||||
fun `present - set call notifications enabled`() = runTest {
|
||||
val presenter = aNotificationPresenter()
|
||||
val presenter = createNotificationSettingsPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -167,7 +167,7 @@ class NotificationSettingsPresenterTests {
|
|||
|
||||
@Test
|
||||
fun `present - set atRoom notifications enabled`() = runTest {
|
||||
val presenter = aNotificationPresenter()
|
||||
val presenter = createNotificationSettingsPresenter()
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -187,7 +187,7 @@ class NotificationSettingsPresenterTests {
|
|||
}
|
||||
}
|
||||
|
||||
private fun aNotificationPresenter(
|
||||
private fun createNotificationSettingsPresenter(
|
||||
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService()
|
||||
) : NotificationSettingsPresenter {
|
||||
val matrixClient = FakeMatrixClient(notificationSettingsService = notificationSettingsService)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import com.google.common.truth.Truth.assertThat
|
|||
import io.element.android.features.logout.impl.DefaultLogoutPreferencePresenter
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.core.meta.BuildType
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ fun CrashDetectionView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun CrashDetectionContent(
|
||||
private fun CrashDetectionContent(
|
||||
onNoClicked: () -> Unit = { },
|
||||
onYesClicked: () -> Unit = { },
|
||||
onDismiss: () -> Unit = { },
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ private fun TakeScreenshot(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun RageshakeDialogContent(
|
||||
private fun RageshakeDialogContent(
|
||||
onNoClicked: () -> Unit = { },
|
||||
onDisableClicked: () -> Unit = { },
|
||||
onYesClicked: () -> Unit = { },
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
|||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceRow
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.debugPlaceholderBackground
|
||||
|
|
@ -72,7 +72,7 @@ fun BugReportView(
|
|||
}
|
||||
|
||||
Box(modifier = modifier) {
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
title = stringResource(id = CommonStrings.common_report_a_bug),
|
||||
onBackPressed = onBackPressed
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ import java.util.logging.LogRecord
|
|||
internal class LogFormatter : Formatter() {
|
||||
|
||||
override fun format(r: LogRecord): String {
|
||||
if (!mIsTimeZoneSet) {
|
||||
if (!isTimeZoneSet) {
|
||||
DATE_FORMAT.timeZone = TimeZone.getTimeZone("UTC")
|
||||
mIsTimeZoneSet = true
|
||||
isTimeZoneSet = true
|
||||
}
|
||||
|
||||
val thrown = r.thrown
|
||||
|
|
@ -59,6 +59,6 @@ internal class LogFormatter : Formatter() {
|
|||
// private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
|
||||
private val DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss*SSSZZZZ", Locale.US)
|
||||
|
||||
private var mIsTimeZoneSet = false
|
||||
private var isTimeZoneSet = false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,10 +101,10 @@ class DefaultBugReporter @Inject constructor(
|
|||
}
|
||||
|
||||
// the pending bug report call
|
||||
private var mBugReportCall: Call? = null
|
||||
private var bugReportCall: Call? = null
|
||||
|
||||
// boolean to cancel the bug report
|
||||
private val mIsCancelled = false
|
||||
private val isCancelled = false
|
||||
|
||||
/*
|
||||
val adapter = MatrixJsonParser.getMoshi()
|
||||
|
|
@ -151,7 +151,7 @@ class DefaultBugReporter @Inject constructor(
|
|||
listener: BugReporterListener?
|
||||
) {
|
||||
// enumerate files to delete
|
||||
val mBugReportFiles: MutableList<File> = ArrayList()
|
||||
val bugReportFiles: MutableList<File> = ArrayList()
|
||||
|
||||
try {
|
||||
|
||||
|
|
@ -172,7 +172,7 @@ class DefaultBugReporter @Inject constructor(
|
|||
val files = getLogFiles()
|
||||
files.mapNotNullTo(gzippedFiles) { f ->
|
||||
when {
|
||||
mIsCancelled -> null
|
||||
isCancelled -> null
|
||||
f.extension == "gz" -> f
|
||||
else -> compressFile(f)
|
||||
}
|
||||
|
|
@ -180,7 +180,7 @@ class DefaultBugReporter @Inject constructor(
|
|||
files.deleteAllExceptMostRecent()
|
||||
}
|
||||
|
||||
if (!mIsCancelled && (withCrashLogs || withDevicesLogs)) {
|
||||
if (!isCancelled && (withCrashLogs || withDevicesLogs)) {
|
||||
val gzippedLogcat = saveLogCat(false)
|
||||
|
||||
if (null != gzippedLogcat) {
|
||||
|
|
@ -215,7 +215,7 @@ class DefaultBugReporter @Inject constructor(
|
|||
val userId = sessionData?.userId ?: "undefined"
|
||||
var olmVersion = "undefined"
|
||||
|
||||
if (!mIsCancelled) {
|
||||
if (!isCancelled) {
|
||||
val text = when (reportType) {
|
||||
ReportType.BUG_REPORT -> bugDescription
|
||||
ReportType.SUGGESTION -> "[Suggestion] $bugDescription"
|
||||
|
|
@ -268,7 +268,7 @@ class DefaultBugReporter @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
mBugReportFiles.addAll(gzippedFiles)
|
||||
bugReportFiles.addAll(gzippedFiles)
|
||||
|
||||
if (gzippedFiles.isNotEmpty() && !uploadedSomeLogs) {
|
||||
serverError = "Couldn't upload any logs, please retry."
|
||||
|
|
@ -336,8 +336,8 @@ class DefaultBugReporter @Inject constructor(
|
|||
0
|
||||
}
|
||||
|
||||
if (mIsCancelled && null != mBugReportCall) {
|
||||
mBugReportCall!!.cancel()
|
||||
if (isCancelled && null != bugReportCall) {
|
||||
bugReportCall!!.cancel()
|
||||
}
|
||||
|
||||
Timber.v("## onWrite() : $percentage%")
|
||||
|
|
@ -360,8 +360,8 @@ class DefaultBugReporter @Inject constructor(
|
|||
|
||||
// trigger the request
|
||||
try {
|
||||
mBugReportCall = okHttpClient.get().newCall(request)
|
||||
response = mBugReportCall!!.execute()
|
||||
bugReportCall = okHttpClient.get().newCall(request)
|
||||
response = bugReportCall!!.execute()
|
||||
responseCode = response.code
|
||||
} catch (e: CancellationException) {
|
||||
throw e
|
||||
|
|
@ -423,11 +423,11 @@ class DefaultBugReporter @Inject constructor(
|
|||
}
|
||||
|
||||
withContext(coroutineDispatchers.main) {
|
||||
mBugReportCall = null
|
||||
bugReportCall = null
|
||||
|
||||
if (null != listener) {
|
||||
try {
|
||||
if (mIsCancelled) {
|
||||
if (isCancelled) {
|
||||
listener.onUploadCancelled()
|
||||
} else if (null == serverError) {
|
||||
listener.onUploadSucceed(reportURL)
|
||||
|
|
@ -443,7 +443,7 @@ class DefaultBugReporter @Inject constructor(
|
|||
}
|
||||
} finally {
|
||||
// delete the generated files when the bug report process has finished
|
||||
for (file in mBugReportFiles) {
|
||||
for (file in bugReportFiles) {
|
||||
file.safeDelete()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class RoomDetailsFlowNode @AssistedInject constructor(
|
|||
data object InviteMembers : NavTarget
|
||||
|
||||
@Parcelize
|
||||
object RoomNotificationSettings : NavTarget
|
||||
data object RoomNotificationSettings : NavTarget
|
||||
|
||||
@Parcelize
|
||||
data class RoomMemberDetails(val roomMemberId: UserId) : NavTarget
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package io.element.android.features.roomdetails.impl
|
|||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.features.leaveroom.api.LeaveRoomState
|
||||
import io.element.android.features.leaveroom.api.aLeaveRoomState
|
||||
import io.element.android.features.roomdetails.impl.members.details.aRoomMemberDetailsState
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
|
|
@ -80,7 +81,7 @@ fun aRoomDetailsState() = RoomDetailsState(
|
|||
canShowNotificationSettings = true,
|
||||
roomType = RoomDetailsType.Room,
|
||||
roomMemberDetailsState = null,
|
||||
leaveRoomState = LeaveRoomState(),
|
||||
leaveRoomState = aLeaveRoomState(),
|
||||
roomNotificationSettings = RoomNotificationSettings(mode = RoomNotificationMode.MUTE, isDefault = false),
|
||||
eventSink = {}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ fun RoomDetailsView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
internal fun RoomDetailsTopBar(
|
||||
private fun RoomDetailsTopBar(
|
||||
goBack: () -> Unit,
|
||||
onActionClicked: (RoomDetailsAction) -> Unit,
|
||||
showEdit: Boolean,
|
||||
|
|
@ -220,7 +220,7 @@ internal fun RoomDetailsTopBar(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun MainActionsSection(state: RoomDetailsState, onShareRoom: () -> Unit, modifier: Modifier = Modifier) {
|
||||
private fun MainActionsSection(state: RoomDetailsState, onShareRoom: () -> Unit, modifier: Modifier = Modifier) {
|
||||
Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
|
||||
val roomNotificationSettings = state.roomNotificationSettings
|
||||
if (state.canShowNotificationSettings && roomNotificationSettings != null) {
|
||||
|
|
@ -252,7 +252,7 @@ internal fun MainActionsSection(state: RoomDetailsState, onShareRoom: () -> Unit
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun RoomHeaderSection(
|
||||
private fun RoomHeaderSection(
|
||||
avatarUrl: String?,
|
||||
roomId: String,
|
||||
roomName: String,
|
||||
|
|
@ -289,7 +289,7 @@ internal fun RoomHeaderSection(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun TopicSection(
|
||||
private fun TopicSection(
|
||||
roomTopic: RoomTopicState,
|
||||
onActionClicked: (RoomDetailsAction) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
|
|
@ -315,7 +315,7 @@ internal fun TopicSection(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun NotificationSection(
|
||||
private fun NotificationSection(
|
||||
isDefaultMode: Boolean,
|
||||
openRoomNotificationSettings: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
|
|
@ -336,7 +336,7 @@ internal fun NotificationSection(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun MembersSection(
|
||||
private fun MembersSection(
|
||||
memberCount: Long,
|
||||
openRoomMemberList: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -352,7 +352,7 @@ internal fun MembersSection(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun InviteSection(
|
||||
private fun InviteSection(
|
||||
invitePeople: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
|
|
@ -366,7 +366,7 @@ internal fun InviteSection(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun SecuritySection(modifier: Modifier = Modifier) {
|
||||
private fun SecuritySection(modifier: Modifier = Modifier) {
|
||||
PreferenceCategory(title = stringResource(R.string.screen_room_details_security_title), modifier = modifier) {
|
||||
PreferenceText(
|
||||
title = stringResource(R.string.screen_room_details_encryption_enabled_title),
|
||||
|
|
@ -377,7 +377,7 @@ internal fun SecuritySection(modifier: Modifier = Modifier) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun OtherActionsSection(onLeaveRoom: () -> Unit, modifier: Modifier = Modifier) {
|
||||
private fun OtherActionsSection(onLeaveRoom: () -> Unit, modifier: Modifier = Modifier) {
|
||||
PreferenceCategory(showDivider = false, modifier = modifier) {
|
||||
PreferenceText(
|
||||
title = stringResource(R.string.screen_room_details_leave_room_title),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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.roomdetails.impl.blockuser
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import io.element.android.features.roomdetails.impl.R
|
||||
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsEvents
|
||||
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsState
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
||||
|
||||
@Composable
|
||||
fun BlockUserDialogs(state: RoomMemberDetailsState) {
|
||||
when (state.displayConfirmationDialog) {
|
||||
null -> Unit
|
||||
RoomMemberDetailsState.ConfirmationDialog.Block -> {
|
||||
BlockConfirmationDialog(
|
||||
onBlockAction = {
|
||||
state.eventSink(
|
||||
RoomMemberDetailsEvents.BlockUser(
|
||||
needsConfirmation = false
|
||||
)
|
||||
)
|
||||
},
|
||||
onDismiss = { state.eventSink(RoomMemberDetailsEvents.ClearConfirmationDialog) }
|
||||
)
|
||||
}
|
||||
RoomMemberDetailsState.ConfirmationDialog.Unblock -> {
|
||||
UnblockConfirmationDialog(
|
||||
onUnblockAction = {
|
||||
state.eventSink(
|
||||
RoomMemberDetailsEvents.UnblockUser(
|
||||
needsConfirmation = false
|
||||
)
|
||||
)
|
||||
},
|
||||
onDismiss = { state.eventSink(RoomMemberDetailsEvents.ClearConfirmationDialog) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BlockConfirmationDialog(onBlockAction: () -> Unit, onDismiss: () -> Unit) {
|
||||
ConfirmationDialog(
|
||||
title = stringResource(R.string.screen_dm_details_block_user),
|
||||
content = stringResource(R.string.screen_dm_details_block_alert_description),
|
||||
submitText = stringResource(R.string.screen_dm_details_block_alert_action),
|
||||
onSubmitClicked = onBlockAction,
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun UnblockConfirmationDialog(onUnblockAction: () -> Unit, onDismiss: () -> Unit) {
|
||||
ConfirmationDialog(
|
||||
title = stringResource(R.string.screen_dm_details_unblock_user),
|
||||
content = stringResource(R.string.screen_dm_details_unblock_alert_description),
|
||||
submitText = stringResource(R.string.screen_dm_details_unblock_alert_action),
|
||||
onSubmitClicked = onUnblockAction,
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
}
|
||||
|
|
@ -27,7 +27,6 @@ import io.element.android.features.roomdetails.impl.members.details.RoomMemberDe
|
|||
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsState
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
||||
import io.element.android.libraries.designsystem.components.dialogs.RetryDialog
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
|
|
@ -85,44 +84,3 @@ private fun PreferenceBlockUser(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun BlockUserDialogs(state: RoomMemberDetailsState) {
|
||||
when (state.displayConfirmationDialog) {
|
||||
null -> Unit
|
||||
RoomMemberDetailsState.ConfirmationDialog.Block -> {
|
||||
BlockConfirmationDialog(
|
||||
onBlockAction = { state.eventSink(RoomMemberDetailsEvents.BlockUser(needsConfirmation = false)) },
|
||||
onDismiss = { state.eventSink(RoomMemberDetailsEvents.ClearConfirmationDialog) }
|
||||
)
|
||||
}
|
||||
RoomMemberDetailsState.ConfirmationDialog.Unblock -> {
|
||||
UnblockConfirmationDialog(
|
||||
onUnblockAction = { state.eventSink(RoomMemberDetailsEvents.UnblockUser(needsConfirmation = false)) },
|
||||
onDismiss = { state.eventSink(RoomMemberDetailsEvents.ClearConfirmationDialog) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun BlockConfirmationDialog(onBlockAction: () -> Unit, onDismiss: () -> Unit) {
|
||||
ConfirmationDialog(
|
||||
title = stringResource(R.string.screen_dm_details_block_user),
|
||||
content = stringResource(R.string.screen_dm_details_block_alert_description),
|
||||
submitText = stringResource(R.string.screen_dm_details_block_alert_action),
|
||||
onSubmitClicked = onBlockAction,
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun UnblockConfirmationDialog(onUnblockAction: () -> Unit, onDismiss: () -> Unit) {
|
||||
ConfirmationDialog(
|
||||
title = stringResource(R.string.screen_dm_details_unblock_user),
|
||||
content = stringResource(R.string.screen_dm_details_unblock_alert_description),
|
||||
submitText = stringResource(R.string.screen_dm_details_unblock_alert_action),
|
||||
onSubmitClicked = onUnblockAction,
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,15 +19,14 @@ package io.element.android.features.roomdetails.impl.invite
|
|||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
data class RoomInviteMembersState(
|
||||
val canInvite: Boolean = false,
|
||||
val searchQuery: String = "",
|
||||
val searchResults: SearchBarResultState<ImmutableList<InvitableUser>> = SearchBarResultState.NotSearching(),
|
||||
val selectedUsers: ImmutableList<MatrixUser> = persistentListOf(),
|
||||
val isSearchActive: Boolean = false,
|
||||
val eventSink: (RoomInviteMembersEvents) -> Unit = {},
|
||||
val canInvite: Boolean,
|
||||
val searchQuery: String,
|
||||
val searchResults: SearchBarResultState<ImmutableList<InvitableUser>>,
|
||||
val selectedUsers: ImmutableList<MatrixUser>,
|
||||
val isSearchActive: Boolean,
|
||||
val eventSink: (RoomInviteMembersEvents) -> Unit,
|
||||
)
|
||||
|
||||
data class InvitableUser(
|
||||
|
|
|
|||
|
|
@ -18,20 +18,22 @@ package io.element.android.features.roomdetails.impl.invite
|
|||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.ui.components.aMatrixUser
|
||||
import io.element.android.libraries.matrix.ui.components.aMatrixUserList
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
internal class RoomInviteMembersStateProvider : PreviewParameterProvider<RoomInviteMembersState> {
|
||||
override val values: Sequence<RoomInviteMembersState>
|
||||
get() = sequenceOf(
|
||||
RoomInviteMembersState(),
|
||||
RoomInviteMembersState(canInvite = true, selectedUsers = aMatrixUserList().toImmutableList()),
|
||||
RoomInviteMembersState(isSearchActive = true, searchQuery = "some query"),
|
||||
RoomInviteMembersState(isSearchActive = true, searchQuery = "some query", selectedUsers = aMatrixUserList().toImmutableList()),
|
||||
RoomInviteMembersState(isSearchActive = true, searchQuery = "some query", searchResults = SearchBarResultState.NoResults()),
|
||||
RoomInviteMembersState(
|
||||
aRoomInviteMembersState(),
|
||||
aRoomInviteMembersState(canInvite = true, selectedUsers = aMatrixUserList().toImmutableList()),
|
||||
aRoomInviteMembersState(isSearchActive = true, searchQuery = "some query"),
|
||||
aRoomInviteMembersState(isSearchActive = true, searchQuery = "some query", selectedUsers = aMatrixUserList().toImmutableList()),
|
||||
aRoomInviteMembersState(isSearchActive = true, searchQuery = "some query", searchResults = SearchBarResultState.NoResults()),
|
||||
aRoomInviteMembersState(
|
||||
isSearchActive = true,
|
||||
canInvite = true,
|
||||
searchQuery = "some query",
|
||||
|
|
@ -48,7 +50,7 @@ internal class RoomInviteMembersStateProvider : PreviewParameterProvider<RoomInv
|
|||
)
|
||||
)
|
||||
),
|
||||
RoomInviteMembersState(
|
||||
aRoomInviteMembersState(
|
||||
isSearchActive = true,
|
||||
canInvite = true,
|
||||
searchQuery = "@alice:server.org",
|
||||
|
|
@ -64,3 +66,20 @@ internal class RoomInviteMembersStateProvider : PreviewParameterProvider<RoomInv
|
|||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun aRoomInviteMembersState(
|
||||
canInvite: Boolean = false,
|
||||
searchQuery: String = "",
|
||||
searchResults: SearchBarResultState<ImmutableList<InvitableUser>> = SearchBarResultState.NotSearching(),
|
||||
selectedUsers: ImmutableList<MatrixUser> = persistentListOf(),
|
||||
isSearchActive: Boolean = false,
|
||||
): RoomInviteMembersState {
|
||||
return RoomInviteMembersState(
|
||||
canInvite = canInvite,
|
||||
searchQuery = searchQuery,
|
||||
searchResults = searchResults,
|
||||
selectedUsers = selectedUsers,
|
||||
isSearchActive = isSearchActive,
|
||||
eventSink = {},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ fun RoomInviteMembersView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun RoomInviteMembersTopBar(
|
||||
private fun RoomInviteMembersTopBar(
|
||||
canSend: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
onBackPressed: () -> Unit = {},
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ data class RoomMemberDetailsState(
|
|||
val userName: String?,
|
||||
val avatarUrl: String?,
|
||||
val isBlocked: Async<Boolean>,
|
||||
val displayConfirmationDialog: ConfirmationDialog? = null,
|
||||
val displayConfirmationDialog: ConfirmationDialog?,
|
||||
val isCurrentUser: Boolean,
|
||||
val eventSink: (RoomMemberDetailsEvents) -> Unit
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ fun aRoomMemberDetailsState() = RoomMemberDetailsState(
|
|||
userName = "Daniel",
|
||||
avatarUrl = null,
|
||||
isBlocked = Async.Success(false),
|
||||
displayConfirmationDialog = null,
|
||||
isCurrentUser = false,
|
||||
eventSink = {},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,49 +16,27 @@
|
|||
|
||||
package io.element.android.features.roomdetails.impl.members.details
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.ChatBubbleOutline
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.features.roomdetails.impl.blockuser.BlockUserDialogs
|
||||
import io.element.android.features.roomdetails.impl.blockuser.BlockUserSection
|
||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.components.button.MainActionButton
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
|
|
@ -103,51 +81,9 @@ fun RoomMemberDetailsView(
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@Composable
|
||||
internal fun RoomMemberHeaderSection(
|
||||
avatarUrl: String?,
|
||||
userId: String,
|
||||
userName: String?,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Column(modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Box(modifier = Modifier.size(70.dp)) {
|
||||
Avatar(
|
||||
avatarData = AvatarData(userId, userName, avatarUrl, AvatarSize.UserHeader),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
if (userName != null) {
|
||||
Text(text = userName, style = ElementTheme.typography.fontHeadingLgBold)
|
||||
Spacer(modifier = Modifier.height(6.dp))
|
||||
}
|
||||
Text(
|
||||
text = userId,
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
Spacer(Modifier.height(40.dp))
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun RoomMemberMainActionsSection(onShareUser: () -> Unit, modifier: Modifier = Modifier) {
|
||||
Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
|
||||
MainActionButton(
|
||||
title = stringResource(CommonStrings.action_share),
|
||||
iconResourceId = CommonDrawables.ic_compound_share_android,
|
||||
onClick = onShareUser
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun SendMessageSection(onSendMessage: () -> Unit, modifier: Modifier = Modifier) {
|
||||
private fun SendMessageSection(onSendMessage: () -> Unit, modifier: Modifier = Modifier) {
|
||||
PreferenceCategory(modifier = modifier) {
|
||||
PreferenceText(
|
||||
title = stringResource(CommonStrings.action_send_message),
|
||||
|
|
@ -156,6 +92,7 @@ internal fun SendMessageSection(onSendMessage: () -> Unit, modifier: Modifier =
|
|||
)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@PreviewWithLargeHeight
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.roomdetails.impl.members.details
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
|
||||
@Composable
|
||||
fun RoomMemberHeaderSection(
|
||||
avatarUrl: String?,
|
||||
userId: String,
|
||||
userName: String?,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Column(modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Box(modifier = Modifier.size(70.dp)) {
|
||||
Avatar(
|
||||
avatarData = AvatarData(userId, userName, avatarUrl, AvatarSize.UserHeader),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
if (userName != null) {
|
||||
Text(text = userName, style = ElementTheme.typography.fontHeadingLgBold)
|
||||
Spacer(modifier = Modifier.height(6.dp))
|
||||
}
|
||||
Text(
|
||||
text = userId,
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
Spacer(Modifier.height(40.dp))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.roomdetails.impl.members.details
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import io.element.android.libraries.designsystem.components.button.MainActionButton
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@Composable
|
||||
fun RoomMemberMainActionsSection(onShareUser: () -> Unit, modifier: Modifier = Modifier) {
|
||||
Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
|
||||
MainActionButton(
|
||||
title = stringResource(CommonStrings.action_share),
|
||||
iconResourceId = CommonDrawables.ic_compound_share_android,
|
||||
onClick = onShareUser
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -108,7 +108,7 @@ fun RoomNotificationSettingsView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun RoomNotificationSettingsTopBar(
|
||||
private fun RoomNotificationSettingsTopBar(
|
||||
modifier: Modifier = Modifier,
|
||||
onBackPressed: () -> Unit = {},
|
||||
) {
|
||||
|
|
@ -125,7 +125,7 @@ fun RoomNotificationSettingsTopBar(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun RoomNotificationSettingsOptions(
|
||||
private fun RoomNotificationSettingsOptions(
|
||||
selected: RoomNotificationMode?,
|
||||
enabled: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ class RoomDetailsPresenterTests {
|
|||
|
||||
@get:Rule
|
||||
val warmUpRule = WarmUpRule()
|
||||
private fun aRoomDetailsPresenter(
|
||||
|
||||
private fun createRoomDetailsPresenter(
|
||||
room: MatrixRoom,
|
||||
leaveRoomPresenter: LeaveRoomPresenter = FakeLeaveRoomPresenter(),
|
||||
dispatchers: CoroutineDispatchers,
|
||||
|
|
@ -88,7 +89,7 @@ class RoomDetailsPresenterTests {
|
|||
@Test
|
||||
fun `present - initial state is created from room info`() = runTest {
|
||||
val room = aMatrixRoom()
|
||||
val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -107,7 +108,7 @@ class RoomDetailsPresenterTests {
|
|||
@Test
|
||||
fun `present - initial state with no room name`() = runTest {
|
||||
val room = aMatrixRoom(name = null)
|
||||
val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -129,7 +130,7 @@ class RoomDetailsPresenterTests {
|
|||
val roomMembers = listOf(myRoomMember, otherRoomMember)
|
||||
givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers))
|
||||
}
|
||||
val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -145,7 +146,7 @@ class RoomDetailsPresenterTests {
|
|||
val room = aMatrixRoom().apply {
|
||||
givenCanInviteResult(Result.success(true))
|
||||
}
|
||||
val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -163,7 +164,7 @@ class RoomDetailsPresenterTests {
|
|||
val room = aMatrixRoom().apply {
|
||||
givenCanInviteResult(Result.success(false))
|
||||
}
|
||||
val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -178,7 +179,7 @@ class RoomDetailsPresenterTests {
|
|||
val room = aMatrixRoom().apply {
|
||||
givenCanInviteResult(Result.failure(Throwable("Whoops")))
|
||||
}
|
||||
val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -196,7 +197,7 @@ class RoomDetailsPresenterTests {
|
|||
givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.failure(Throwable("Whelp")))
|
||||
givenCanInviteResult(Result.success(false))
|
||||
}
|
||||
val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -225,7 +226,7 @@ class RoomDetailsPresenterTests {
|
|||
givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true))
|
||||
givenCanInviteResult(Result.success(false))
|
||||
}
|
||||
val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -254,7 +255,7 @@ class RoomDetailsPresenterTests {
|
|||
|
||||
givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true))
|
||||
}
|
||||
val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -275,7 +276,7 @@ class RoomDetailsPresenterTests {
|
|||
givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true))
|
||||
givenCanInviteResult(Result.success(false))
|
||||
}
|
||||
val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -296,7 +297,7 @@ class RoomDetailsPresenterTests {
|
|||
givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(false))
|
||||
givenCanInviteResult(Result.success(false))
|
||||
}
|
||||
val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -314,7 +315,7 @@ class RoomDetailsPresenterTests {
|
|||
givenCanInviteResult(Result.success(false))
|
||||
}
|
||||
|
||||
val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -332,7 +333,7 @@ class RoomDetailsPresenterTests {
|
|||
givenCanInviteResult(Result.success(false))
|
||||
}
|
||||
|
||||
val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -350,7 +351,7 @@ class RoomDetailsPresenterTests {
|
|||
fun `present - leave room event is passed on to leave room presenter`() = runTest {
|
||||
val leaveRoomPresenter = FakeLeaveRoomPresenter()
|
||||
val room = aMatrixRoom()
|
||||
val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers())
|
||||
val presenter = createRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers())
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -367,7 +368,7 @@ class RoomDetailsPresenterTests {
|
|||
val leaveRoomPresenter = FakeLeaveRoomPresenter()
|
||||
val notificationSettingsService = FakeNotificationSettingsService()
|
||||
val room = aMatrixRoom(notificationSettingsService = notificationSettingsService)
|
||||
val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService)
|
||||
val presenter = createRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -386,7 +387,7 @@ class RoomDetailsPresenterTests {
|
|||
val leaveRoomPresenter = FakeLeaveRoomPresenter()
|
||||
val notificationSettingsService = FakeNotificationSettingsService(initialRoomMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
|
||||
val room = aMatrixRoom(notificationSettingsService = notificationSettingsService)
|
||||
val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService)
|
||||
val presenter = createRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -407,7 +408,7 @@ class RoomDetailsPresenterTests {
|
|||
initialEncryptedGroupDefaultMode = RoomNotificationMode.ALL_MESSAGES
|
||||
)
|
||||
val room = aMatrixRoom(notificationSettingsService = notificationSettingsService)
|
||||
val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService)
|
||||
val presenter = createRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class RoomDetailsEditPresenterTest {
|
|||
unmockkAll()
|
||||
}
|
||||
|
||||
private fun aRoomDetailsEditPresenter(
|
||||
private fun createRoomDetailsEditPresenter(
|
||||
room: MatrixRoom,
|
||||
permissionsPresenter: PermissionsPresenter = FakePermissionsPresenter(),
|
||||
): RoomDetailsEditPresenter {
|
||||
|
|
@ -92,7 +92,7 @@ class RoomDetailsEditPresenterTest {
|
|||
@Test
|
||||
fun `present - initial state is created from room info`() = runTest {
|
||||
val room = aMatrixRoom(avatarUrl = AN_AVATAR_URL)
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -119,7 +119,7 @@ class RoomDetailsEditPresenterTest {
|
|||
givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(false))
|
||||
givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.failure(Throwable("Oops")))
|
||||
}
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -145,7 +145,7 @@ class RoomDetailsEditPresenterTest {
|
|||
givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true))
|
||||
givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.failure(Throwable("Oops")))
|
||||
}
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -171,7 +171,7 @@ class RoomDetailsEditPresenterTest {
|
|||
givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.failure(Throwable("Oops")))
|
||||
givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true))
|
||||
}
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -193,7 +193,7 @@ class RoomDetailsEditPresenterTest {
|
|||
@Test
|
||||
fun `present - updates state in response to changes`() = runTest {
|
||||
val room = aMatrixRoom(topic = "My topic", name = "Name", avatarUrl = AN_AVATAR_URL)
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -239,7 +239,7 @@ class RoomDetailsEditPresenterTest {
|
|||
|
||||
fakePickerProvider.givenResult(anotherAvatarUri)
|
||||
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -260,7 +260,7 @@ class RoomDetailsEditPresenterTest {
|
|||
|
||||
fakePickerProvider.givenResult(anotherAvatarUri)
|
||||
val fakePermissionsPresenter = FakePermissionsPresenter()
|
||||
val presenter = aRoomDetailsEditPresenter(
|
||||
val presenter = createRoomDetailsEditPresenter(
|
||||
room = room,
|
||||
permissionsPresenter = fakePermissionsPresenter,
|
||||
)
|
||||
|
|
@ -293,7 +293,7 @@ class RoomDetailsEditPresenterTest {
|
|||
|
||||
fakePickerProvider.givenResult(roomAvatarUri)
|
||||
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -345,7 +345,7 @@ class RoomDetailsEditPresenterTest {
|
|||
|
||||
fakePickerProvider.givenResult(roomAvatarUri)
|
||||
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -395,7 +395,7 @@ class RoomDetailsEditPresenterTest {
|
|||
fun `present - save changes room details if different`() = runTest {
|
||||
val room = aMatrixRoom(topic = "My topic", name = "Name", avatarUrl = AN_AVATAR_URL)
|
||||
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -420,7 +420,7 @@ class RoomDetailsEditPresenterTest {
|
|||
fun `present - save doesn't change room details if they're the same trimmed`() = runTest {
|
||||
val room = aMatrixRoom(topic = "My topic", name = "Name", avatarUrl = AN_AVATAR_URL)
|
||||
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -444,7 +444,7 @@ class RoomDetailsEditPresenterTest {
|
|||
fun `present - save doesn't change topic if it was unset and is now blank`() = runTest {
|
||||
val room = aMatrixRoom(topic = null, name = "Name", avatarUrl = AN_AVATAR_URL)
|
||||
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -467,7 +467,7 @@ class RoomDetailsEditPresenterTest {
|
|||
fun `present - save doesn't change name if it's now empty`() = runTest {
|
||||
val room = aMatrixRoom(topic = "My topic", name = "Name", avatarUrl = AN_AVATAR_URL)
|
||||
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -492,7 +492,7 @@ class RoomDetailsEditPresenterTest {
|
|||
|
||||
givenPickerReturnsFile()
|
||||
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -517,7 +517,7 @@ class RoomDetailsEditPresenterTest {
|
|||
fakePickerProvider.givenResult(anotherAvatarUri)
|
||||
fakeMediaPreProcessor.givenResult(Result.failure(Throwable("Oh no")))
|
||||
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -583,7 +583,7 @@ class RoomDetailsEditPresenterTest {
|
|||
givenSetTopicResult(Result.failure(Throwable("!")))
|
||||
}
|
||||
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -602,7 +602,7 @@ class RoomDetailsEditPresenterTest {
|
|||
}
|
||||
|
||||
private suspend fun saveAndAssertFailure(room: MatrixRoom, event: RoomDetailsEditEvents) {
|
||||
val presenter = aRoomDetailsEditPresenter(room)
|
||||
val presenter = createRoomDetailsEditPresenter(room)
|
||||
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ import io.element.android.features.networkmonitor.api.NetworkStatus
|
|||
import io.element.android.features.roomlist.impl.datasource.InviteStateDataSource
|
||||
import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.api.user.getCurrentUser
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package io.element.android.features.roomlist.impl
|
|||
import androidx.compose.runtime.Immutable
|
||||
import io.element.android.features.leaveroom.api.LeaveRoomState
|
||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue