Skip to content

Feature : Report room #4654

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 34 commits into from
May 2, 2025
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
ba54875
feature (report room) : introduce all presentation classes.
ganfra Apr 14, 2025
10d765d
feature (report room) : branch entry point in the room list
ganfra Apr 15, 2025
6abc8e0
refactor (matrix ui) : move some code from appnav to matrix ui
ganfra Apr 15, 2025
2c4213f
feature (report room) : add api on room
ganfra Apr 15, 2025
f064a94
feature (report room) : adjust ui
ganfra Apr 15, 2025
cc027ff
feature (report room) : branch api
ganfra Apr 15, 2025
53b73c0
feature (decline invite and block) : move things around and introduce…
ganfra Apr 16, 2025
a551508
feature (decline invite and block) : continue to move things
ganfra Apr 17, 2025
f6c99fc
feature (report room) : remove reference to "conversation" for now
ganfra Apr 23, 2025
49b9f54
Merge branch 'develop' into feature/fga/report_room
ganfra Apr 23, 2025
ee43330
feature (report room) : add report room action to room detail screen
ganfra Apr 23, 2025
cc34409
feature (report room) : enabled button state
ganfra Apr 23, 2025
05d9a4c
Merge branch 'develop' into feature/fga/report_room
ganfra Apr 23, 2025
cd6c81e
feature (report room) : improve code and reuse
ganfra Apr 24, 2025
a611f01
feature (report room) : add feature flag
ganfra Apr 24, 2025
64a3c96
feature (report room) : change feature flag to static bool
ganfra Apr 25, 2025
5538858
feature (report room) : add tests
ganfra Apr 25, 2025
4b80f3d
Merge branch 'develop' into feature/fga/report_room
ganfra Apr 25, 2025
ac6ddb4
feature (report room) : fix ui with new api on ListItem
ganfra Apr 25, 2025
04b4aef
feature (report room) : clean up and add more tests.
ganfra Apr 28, 2025
dc1e590
Update screenshots
ElementBot Apr 28, 2025
ceb9772
feature (report room) : more test and fix issue
ganfra Apr 29, 2025
4154748
Merge branch 'develop' into feature/fga/report_room
ganfra Apr 29, 2025
1b026c8
feature (report room) : update strings
ganfra Apr 29, 2025
d355dff
feature (report room) : fix konsist preview
ganfra Apr 29, 2025
2630797
feature (report room) : disable feature
ganfra Apr 29, 2025
4a89653
Merge branch 'develop' into feature/fga/report_room
ganfra Apr 29, 2025
0e5ecbf
Update screenshots
ElementBot Apr 29, 2025
589b5be
var -> val
bmarty May 2, 2025
34420af
Improve preview of AcceptDeclineInviteView
bmarty May 2, 2025
2161474
Improve preview consistency
bmarty May 2, 2025
9acf1e1
Add missing test on DismissErrorAndHideContent
bmarty May 2, 2025
ab05c8b
Update screenshots
ElementBot May 2, 2025
6ca22ef
Add missing tests
bmarty May 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ package io.element.android.appconfig
object MatrixConfiguration {
const val MATRIX_TO_PERMALINK_BASE_URL: String = "https://matrix.to/#/"
val clientPermalinkBaseUrl: String? = null

// TODO remove this when report is fixed
const val CAN_REPORT_ROOM = false
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import io.element.android.anvilannotations.ContributesNode
import io.element.android.appnav.room.joined.JoinedRoomFlowNode
import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode
import io.element.android.appnav.room.joined.LoadingRoomNodeView
import io.element.android.appnav.room.joined.LoadingRoomState
import io.element.android.features.joinroom.api.JoinRoomEntryPoint
import io.element.android.features.roomaliasesolver.api.RoomAliasResolverEntryPoint
import io.element.android.features.roomdirectory.api.RoomDescription
Expand All @@ -49,6 +48,7 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
import io.element.android.libraries.matrix.api.sync.SyncService
import io.element.android.libraries.matrix.ui.room.LoadingRoomState
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.sync.SyncService
import io.element.android.libraries.matrix.ui.room.LoadingRoomState
import io.element.android.libraries.matrix.ui.room.LoadingRoomStateFlowFactory
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import io.element.android.libraries.designsystem.theme.components.CircularProgre
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.matrix.ui.room.LoadingRoomState
import io.element.android.libraries.matrix.ui.room.LoadingRoomStateProvider
import io.element.android.libraries.ui.strings.CommonStrings

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ package io.element.android.appnav.room

import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.appnav.room.joined.LoadingRoomState
import io.element.android.appnav.room.joined.LoadingRoomStateFlowFactory
import io.element.android.libraries.matrix.api.roomlist.RoomList
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
import io.element.android.libraries.matrix.ui.room.LoadingRoomState
import io.element.android.libraries.matrix.ui.room.LoadingRoomStateFlowFactory
import kotlinx.coroutines.test.runTest
import org.junit.Test

Expand Down
3 changes: 3 additions & 0 deletions features/invite/api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

plugins {
id("io.element.android-compose-library")
id("kotlin-parcelize")
}

android {
Expand All @@ -16,5 +17,7 @@ android {
dependencies {
implementation(projects.libraries.architecture)
implementation(projects.libraries.matrix.api)
implementation(projects.libraries.matrixui)
implementation(projects.libraries.designsystem)
implementation(projects.services.analytics.api)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/

package io.element.android.features.invite.api

import android.os.Parcelable
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.RoomInfo
import io.element.android.libraries.matrix.api.room.isDm
import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
import kotlinx.parcelize.Parcelize

@Parcelize

Check warning on line 17 in features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt

View check run for this annotation

Codecov / codecov/patch

features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt#L17

Added line #L17 was not covered by tests
data class InviteData(
val roomId: RoomId,
val roomName: String,
val isDm: Boolean,
) : Parcelable

Check warning on line 22 in features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt

View check run for this annotation

Codecov / codecov/patch

features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt#L22

Added line #L22 was not covered by tests

fun RoomPreviewInfo.toInviteData(): InviteData {
return InviteData(
roomId = roomId,

Check warning on line 26 in features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt

View check run for this annotation

Codecov / codecov/patch

features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt#L25-L26

Added lines #L25 - L26 were not covered by tests
roomName = name ?: roomId.value,
isDm = false,

Check warning on line 28 in features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt

View check run for this annotation

Codecov / codecov/patch

features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt#L28

Added line #L28 was not covered by tests
)
}

fun RoomInfo.toInviteData(): InviteData {
return InviteData(
roomId = id,
roomName = name ?: id.value,
isDm = isDm,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/

package io.element.android.features.invite.api.acceptdecline

import io.element.android.features.invite.api.InviteData

interface AcceptDeclineInviteEvents {
data class AcceptInvite(val invite: InviteData) : AcceptDeclineInviteEvents
data class DeclineInvite(val invite: InviteData, val blockUser: Boolean, val shouldConfirm: Boolean) : AcceptDeclineInviteEvents
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/

package io.element.android.features.invite.api.response
package io.element.android.features.invite.api.acceptdecline

import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.core.RoomId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,21 @@
* Please see LICENSE files in the repository root for full details.
*/

package io.element.android.features.invite.api.response
package io.element.android.features.invite.api.acceptdecline

import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.invite.api.InviteData
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId

open class AcceptDeclineInviteStateProvider : PreviewParameterProvider<AcceptDeclineInviteState> {
override val values: Sequence<AcceptDeclineInviteState>
get() = sequenceOf(
anAcceptDeclineInviteState(),
anAcceptDeclineInviteState(
declineAction = ConfirmingDeclineInvite(
InviteData(roomId = RoomId("!room:matrix.org"), isDm = true, roomName = "Alice", senderId = UserId("@alice:matrix.org")),
blockUser = false,
),
),
anAcceptDeclineInviteState(
declineAction = ConfirmingDeclineInvite(
InviteData(roomId = RoomId("!room:matrix.org"), isDm = false, roomName = "Some room", senderId = UserId("@alice:matrix.org")),
blockUser = false,
),
),
anAcceptDeclineInviteState(
declineAction = ConfirmingDeclineInvite(
InviteData(roomId = RoomId("!room:matrix.org"), isDm = true, roomName = "Alice", senderId = UserId("@alice:matrix.org")),
blockUser = true,
InviteData(roomId = RoomId("!room:matrix.org"), isDm = true, roomName = "Alice"),
blockUser = false
),
),
anAcceptDeclineInviteState(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/

package io.element.android.features.invite.api.response
package io.element.android.features.invite.api.acceptdecline

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
Expand All @@ -15,8 +15,8 @@ interface AcceptDeclineInviteView {
@Composable
fun Render(
state: AcceptDeclineInviteState,
onAcceptInvite: (RoomId) -> Unit,
onDeclineInvite: (RoomId) -> Unit,
onAcceptInviteSuccess: (RoomId) -> Unit,
onDeclineInviteSuccess: (RoomId) -> Unit,
modifier: Modifier,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
* Please see LICENSE files in the repository root for full details.
*/

package io.element.android.features.invite.api.response
package io.element.android.features.invite.api.acceptdecline

import io.element.android.features.invite.api.InviteData
import io.element.android.libraries.architecture.AsyncAction

data class ConfirmingDeclineInvite(
val inviteData: InviteData,
val blockUser: Boolean,
) : AsyncAction.Confirming
data class ConfirmingDeclineInvite(val inviteData: InviteData, val blockUser: Boolean) : AsyncAction.Confirming
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/

package io.element.android.features.invite.api.declineandblock

import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import io.element.android.features.invite.api.InviteData
import io.element.android.libraries.architecture.FeatureEntryPoint

interface DeclineInviteAndBlockEntryPoint : FeatureEntryPoint {
fun createNode(parentNode: Node, buildContext: BuildContext, inviteData: InviteData): Node
}

This file was deleted.

This file was deleted.

8 changes: 8 additions & 0 deletions features/invite/impl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ plugins {

android {
namespace = "io.element.android.features.invite.impl"
testOptions {
unitTests {
isIncludeAndroidResources = true
}
}
}

setupAnvil()
Expand All @@ -36,9 +41,12 @@ dependencies {
testImplementation(libs.molecule.runtime)
testImplementation(libs.test.truth)
testImplementation(libs.test.turbine)
testImplementation(libs.test.robolectric)
testImplementation(projects.features.invite.test)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.push.test)
testImplementation(projects.services.analytics.test)
testImplementation(projects.tests.testutils)
testImplementation(libs.androidx.compose.ui.test.junit)
testReleaseImplementation(libs.androidx.compose.ui.test.manifest)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/

package io.element.android.features.invite.impl

import com.squareup.anvil.annotations.ContributesBinding
import im.vector.app.features.analytics.plan.JoinedRoom
import io.element.android.features.invite.api.SeenInvitesStore
import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.room.join.JoinRoom
import io.element.android.libraries.push.api.notifications.NotificationCleaner
import javax.inject.Inject

interface AcceptInvite {
suspend operator fun invoke(roomId: RoomId): Result<RoomId>
}

@ContributesBinding(SessionScope::class)
class DefaultAcceptInvite @Inject constructor(
private val client: MatrixClient,
private val joinRoom: JoinRoom,
private val notificationCleaner: NotificationCleaner,
private val seenInvitesStore: SeenInvitesStore,
) : AcceptInvite {
override suspend fun invoke(roomId: RoomId): Result<RoomId> {
return joinRoom(
roomIdOrAlias = roomId.toRoomIdOrAlias(),
serverNames = emptyList(),
trigger = JoinedRoom.Trigger.Invite,
).onSuccess {
notificationCleaner.clearMembershipNotificationForRoom(client.sessionId, roomId)
seenInvitesStore.markAsUnSeen(roomId)
}.map { roomId }
}
}
Loading
Loading