knock requests : cleaning up
This commit is contained in:
parent
affd0570dc
commit
63c4ac81b8
9 changed files with 57 additions and 32 deletions
|
|
@ -5,8 +5,6 @@
|
||||||
* Please see LICENSE in the repository root for full details.
|
* Please see LICENSE in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import extension.setupAnvil
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("io.element.android-library")
|
id("io.element.android-library")
|
||||||
}
|
}
|
||||||
|
|
@ -19,4 +17,3 @@ dependencies {
|
||||||
implementation(projects.libraries.architecture)
|
implementation(projects.libraries.architecture)
|
||||||
implementation(projects.libraries.matrix.api)
|
implementation(projects.libraries.matrix.api)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ package io.element.android.features.knockrequests.impl
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
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.avatar.AvatarSize
|
||||||
import io.element.android.libraries.matrix.api.core.UserId
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
|
||||||
|
|
||||||
data class KnockRequest(
|
data class KnockRequest(
|
||||||
val userId: UserId,
|
val userId: UserId,
|
||||||
|
|
@ -30,6 +29,3 @@ fun KnockRequest.getAvatarData(size: AvatarSize) = AvatarData(
|
||||||
fun KnockRequest.getBestName(): String {
|
fun KnockRequest.getBestName(): String {
|
||||||
return displayName?.takeIf { it.isNotEmpty() } ?: userId.value
|
return displayName?.takeIf { it.isNotEmpty() } ?: userId.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ import com.bumble.appyx.core.plugin.Plugin
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.libraries.di.AppScope
|
|
||||||
import io.element.android.libraries.di.RoomScope
|
import io.element.android.libraries.di.RoomScope
|
||||||
|
|
||||||
@ContributesNode(RoomScope::class)
|
@ContributesNode(RoomScope::class)
|
||||||
|
|
@ -24,7 +23,6 @@ class KnockRequestsListNode @AssistedInject constructor(
|
||||||
@Assisted plugins: List<Plugin>,
|
@Assisted plugins: List<Plugin>,
|
||||||
private val presenter: KnockRequestsListPresenter,
|
private val presenter: KnockRequestsListPresenter,
|
||||||
) : Node(buildContext, plugins = plugins) {
|
) : Node(buildContext, plugins = plugins) {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun View(modifier: Modifier) {
|
override fun View(modifier: Modifier) {
|
||||||
val state = presenter.present()
|
val state = presenter.present()
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ import javax.inject.Inject
|
||||||
class KnockRequestsListPresenter @Inject constructor(
|
class KnockRequestsListPresenter @Inject constructor(
|
||||||
private val room: MatrixRoom,
|
private val room: MatrixRoom,
|
||||||
) : Presenter<KnockRequestsListState> {
|
) : Presenter<KnockRequestsListState> {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): KnockRequestsListState {
|
override fun present(): KnockRequestsListState {
|
||||||
val currentAction = remember { mutableStateOf<KnockRequestsCurrentAction>(KnockRequestsCurrentAction.None) }
|
val currentAction = remember { mutableStateOf<KnockRequestsCurrentAction>(KnockRequestsCurrentAction.None) }
|
||||||
|
|
@ -56,7 +55,7 @@ class KnockRequestsListPresenter @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(currentAction) {
|
LaunchedEffect(currentAction) {
|
||||||
when (val action = currentAction.value) {
|
when (currentAction.value) {
|
||||||
is KnockRequestsCurrentAction.Accept -> {
|
is KnockRequestsCurrentAction.Accept -> {
|
||||||
// Accept the knock request
|
// Accept the knock request
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||||
|
|
@ -28,7 +29,9 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
|
@ -36,6 +39,7 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clipToBounds
|
import androidx.compose.ui.draw.clipToBounds
|
||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.layout.onSizeChanged
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
|
|
@ -43,6 +47,7 @@ import androidx.compose.ui.unit.dp
|
||||||
import io.element.android.compound.theme.ElementTheme
|
import io.element.android.compound.theme.ElementTheme
|
||||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||||
import io.element.android.features.knockrequests.impl.KnockRequest
|
import io.element.android.features.knockrequests.impl.KnockRequest
|
||||||
|
import io.element.android.features.knockrequests.impl.R
|
||||||
import io.element.android.features.knockrequests.impl.getAvatarData
|
import io.element.android.features.knockrequests.impl.getAvatarData
|
||||||
import io.element.android.features.knockrequests.impl.getBestName
|
import io.element.android.features.knockrequests.impl.getBestName
|
||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
|
|
@ -54,6 +59,7 @@ 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.BackButton
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
|
import io.element.android.libraries.designsystem.text.toDp
|
||||||
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
|
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
|
||||||
import io.element.android.libraries.designsystem.theme.components.Button
|
import io.element.android.libraries.designsystem.theme.components.Button
|
||||||
import io.element.android.libraries.designsystem.theme.components.ButtonSize
|
import io.element.android.libraries.designsystem.theme.components.ButtonSize
|
||||||
|
|
@ -90,8 +96,10 @@ fun KnockRequestsListView(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun KnockRequestsListContent(state: KnockRequestsListState, modifier: Modifier) {
|
private fun KnockRequestsListContent(
|
||||||
|
state: KnockRequestsListState,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
fun onAcceptClick(knockRequest: KnockRequest) {
|
fun onAcceptClick(knockRequest: KnockRequest) {
|
||||||
state.eventSink(KnockRequestsListEvents.Accept(knockRequest))
|
state.eventSink(KnockRequestsListEvents.Accept(knockRequest))
|
||||||
}
|
}
|
||||||
|
|
@ -100,6 +108,8 @@ private fun KnockRequestsListContent(state: KnockRequestsListState, modifier: Mo
|
||||||
state.eventSink(KnockRequestsListEvents.Decline(knockRequest))
|
state.eventSink(KnockRequestsListEvents.Decline(knockRequest))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bottomPaddingInPixels by remember { mutableIntStateOf(0) }
|
||||||
|
|
||||||
Box(modifier.fillMaxSize()) {
|
Box(modifier.fillMaxSize()) {
|
||||||
when (state.knockRequests) {
|
when (state.knockRequests) {
|
||||||
is AsyncData.Success -> {
|
is AsyncData.Success -> {
|
||||||
|
|
@ -114,6 +124,7 @@ private fun KnockRequestsListContent(state: KnockRequestsListState, modifier: Mo
|
||||||
canBan = state.canBan,
|
canBan = state.canBan,
|
||||||
onAcceptClick = ::onAcceptClick,
|
onAcceptClick = ::onAcceptClick,
|
||||||
onDeclineClick = ::onDeclineClick,
|
onDeclineClick = ::onDeclineClick,
|
||||||
|
contentPadding = PaddingValues(bottom = bottomPaddingInPixels.toDp()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -130,6 +141,9 @@ private fun KnockRequestsListContent(state: KnockRequestsListState, modifier: Mo
|
||||||
onClick = {
|
onClick = {
|
||||||
state.eventSink(KnockRequestsListEvents.AcceptAll)
|
state.eventSink(KnockRequestsListEvents.AcceptAll)
|
||||||
},
|
},
|
||||||
|
onHeightChange = { height ->
|
||||||
|
bottomPaddingInPixels = height
|
||||||
|
},
|
||||||
modifier = Modifier.align(Alignment.BottomCenter),
|
modifier = Modifier.align(Alignment.BottomCenter),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -186,8 +200,12 @@ private fun KnockRequestsList(
|
||||||
onAcceptClick: (KnockRequest) -> Unit,
|
onAcceptClick: (KnockRequest) -> Unit,
|
||||||
onDeclineClick: (KnockRequest) -> Unit,
|
onDeclineClick: (KnockRequest) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
contentPadding: PaddingValues = PaddingValues(0.dp),
|
||||||
) {
|
) {
|
||||||
LazyColumn(modifier = modifier) {
|
LazyColumn(
|
||||||
|
modifier = modifier.fillMaxSize(),
|
||||||
|
contentPadding = contentPadding,
|
||||||
|
) {
|
||||||
itemsIndexed(knockRequests) { index, knockRequest ->
|
itemsIndexed(knockRequests) { index, knockRequest ->
|
||||||
KnockRequestItem(
|
KnockRequestItem(
|
||||||
knockRequest = knockRequest,
|
knockRequest = knockRequest,
|
||||||
|
|
@ -316,7 +334,7 @@ private fun KnockRequestItem(
|
||||||
if (canBan) {
|
if (canBan) {
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
TextButton(
|
TextButton(
|
||||||
text = stringResource(CommonStrings.screen_knock_requests_list_decline_and_ban_action_title),
|
text = stringResource(R.string.screen_knock_requests_list_decline_and_ban_action_title),
|
||||||
onClick = {
|
onClick = {
|
||||||
onAcceptClick(knockRequest)
|
onAcceptClick(knockRequest)
|
||||||
},
|
},
|
||||||
|
|
@ -325,22 +343,25 @@ private fun KnockRequestItem(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun KnockRequestsAcceptAll(onClick: () -> Unit, modifier: Modifier) {
|
private fun KnockRequestsAcceptAll(
|
||||||
|
onClick: () -> Unit,
|
||||||
|
onHeightChange: (Int) -> Unit,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.shadow(elevation = 24.dp, spotColor = Color.Transparent)
|
.shadow(elevation = 24.dp, spotColor = Color.Transparent)
|
||||||
.background(color = ElementTheme.colors.bgCanvasDefault)
|
.background(color = ElementTheme.colors.bgCanvasDefault)
|
||||||
.padding(vertical = 12.dp, horizontal = 16.dp)
|
.padding(vertical = 12.dp, horizontal = 16.dp)
|
||||||
)
|
.onSizeChanged { onHeightChange(it.height) }
|
||||||
{
|
) {
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
text = ("Accept all"),
|
text = stringResource(R.string.screen_knock_requests_list_accept_all_button_title),
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
size = ButtonSize.Medium,
|
size = ButtonSize.Medium,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
|
@ -360,8 +381,8 @@ private fun KnockRequestsEmptyList(
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
IconTitleSubtitleMolecule(
|
IconTitleSubtitleMolecule(
|
||||||
title = "No pending request to join",
|
title = stringResource(R.string.screen_knock_requests_list_empty_state_title),
|
||||||
subTitle = "When somebody will ask to join the room, you’ll be able to see their request here.",
|
subTitle = stringResource(R.string.screen_knock_requests_list_empty_state_description),
|
||||||
iconStyle = BigIcon.Style.Default(CompoundIcons.Pin()),
|
iconStyle = BigIcon.Style.Default(CompoundIcons.Pin()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -373,7 +394,7 @@ private fun KnockRequestsListTopBar(onBackClick: () -> Unit) {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
text = "Requests to join",
|
text = stringResource(R.string.screen_knock_requests_list_title),
|
||||||
style = ElementTheme.typography.aliasScreenTitle,
|
style = ElementTheme.typography.aliasScreenTitle,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
17
features/knockrequests/impl/src/main/res/values/localazy.xml
Normal file
17
features/knockrequests/impl/src/main/res/values/localazy.xml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="screen_knock_requests_list_accept_all_alert_confirm_button_title">"Yes, accept all"</string>
|
||||||
|
<string name="screen_knock_requests_list_accept_all_alert_description">"Are you sure you want to accept all requests to join?"</string>
|
||||||
|
<string name="screen_knock_requests_list_accept_all_alert_title">"Accept all requests"</string>
|
||||||
|
<string name="screen_knock_requests_list_accept_all_button_title">"Accept all"</string>
|
||||||
|
<string name="screen_knock_requests_list_ban_alert_confirm_button_title">"Yes, decline and ban"</string>
|
||||||
|
<string name="screen_knock_requests_list_ban_alert_description">"Are you sure you want to decline and ban %1$s? This user won’t be able to request access to join this room again."</string>
|
||||||
|
<string name="screen_knock_requests_list_ban_alert_title">"Decline and ban from accessing"</string>
|
||||||
|
<string name="screen_knock_requests_list_decline_alert_confirm_button_title">"Yes, decline"</string>
|
||||||
|
<string name="screen_knock_requests_list_decline_alert_description">"Are you sure you want to decline %1$s request to join this room?"</string>
|
||||||
|
<string name="screen_knock_requests_list_decline_alert_title">"Decline access"</string>
|
||||||
|
<string name="screen_knock_requests_list_decline_and_ban_action_title">"Decline and ban"</string>
|
||||||
|
<string name="screen_knock_requests_list_empty_state_description">"When somebody will ask to join the room, you’ll be able to see their request here."</string>
|
||||||
|
<string name="screen_knock_requests_list_empty_state_title">"No pending request to join"</string>
|
||||||
|
<string name="screen_knock_requests_list_title">"Requests to join"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -169,10 +169,6 @@ class RoomDetailsPresenter @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCanBan(membersState: MatrixRoomMembersState): Any {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun roomMemberDetailsPresenter(dmMemberState: RoomMember?) = remember(dmMemberState) {
|
private fun roomMemberDetailsPresenter(dmMemberState: RoomMember?) = remember(dmMemberState) {
|
||||||
dmMemberState?.let { roomMember ->
|
dmMemberState?.let { roomMember ->
|
||||||
|
|
|
||||||
|
|
@ -296,11 +296,6 @@ Reason: %1$s."</string>
|
||||||
<string name="invite_friends_text">"Hey, talk to me on %1$s: %2$s"</string>
|
<string name="invite_friends_text">"Hey, talk to me on %1$s: %2$s"</string>
|
||||||
<string name="login_initial_device_name_android">"%1$s Android"</string>
|
<string name="login_initial_device_name_android">"%1$s Android"</string>
|
||||||
<string name="preference_rageshake">"Rageshake to report bug"</string>
|
<string name="preference_rageshake">"Rageshake to report bug"</string>
|
||||||
<string name="screen_knock_requests_list_accept_all_button_title">"Accept all"</string>
|
|
||||||
<string name="screen_knock_requests_list_decline_and_ban_action_title">"Decline and ban"</string>
|
|
||||||
<string name="screen_knock_requests_list_empty_state_description">"When somebody will ask to join the room, you’ll be able to see their request here."</string>
|
|
||||||
<string name="screen_knock_requests_list_empty_state_title">"No pending request to join"</string>
|
|
||||||
<string name="screen_knock_requests_list_title">"Requests to join"</string>
|
|
||||||
<string name="screen_media_picker_error_failed_selection">"Failed selecting media, please try again."</string>
|
<string name="screen_media_picker_error_failed_selection">"Failed selecting media, please try again."</string>
|
||||||
<string name="screen_media_upload_preview_error_failed_processing">"Failed processing media to upload, please try again."</string>
|
<string name="screen_media_upload_preview_error_failed_processing">"Failed processing media to upload, please try again."</string>
|
||||||
<string name="screen_media_upload_preview_error_failed_sending">"Failed uploading media, please try again."</string>
|
<string name="screen_media_upload_preview_error_failed_sending">"Failed uploading media, please try again."</string>
|
||||||
|
|
|
||||||
|
|
@ -286,6 +286,12 @@
|
||||||
"screen_join_room_.*",
|
"screen_join_room_.*",
|
||||||
"screen\\.join_room\\..*"
|
"screen\\.join_room\\..*"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : ":features:knockrequests:impl",
|
||||||
|
"includeRegex" : [
|
||||||
|
"screen\\.knock_requests_list\\..*"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue