Add ability to leave room via overflow menu
This commit is contained in:
parent
3837dd29da
commit
f1e05e0a6f
|
@ -67,7 +67,7 @@ internal fun MessengerScreen(
|
|||
) {
|
||||
val state = viewModel.current
|
||||
|
||||
viewModel.ObserveEvents(galleryLauncher)
|
||||
viewModel.ObserveEvents(galleryLauncher, navigator)
|
||||
LifecycleEffect(
|
||||
onStart = { viewModel.dispatch(ComponentLifecycle.Visible) },
|
||||
onStop = { viewModel.dispatch(ComponentLifecycle.Gone) }
|
||||
|
@ -85,6 +85,30 @@ internal fun MessengerScreen(
|
|||
onImageClick = { viewModel.dispatch(ComposerStateChange.ImagePreview.Show(it)) }
|
||||
)
|
||||
|
||||
when (val dialog = state.dialogState) {
|
||||
null -> {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
is DialogState.PositiveNegative -> {
|
||||
AlertDialog(
|
||||
onDismissRequest = { viewModel.dispatch(ScreenAction.LeaveRoomConfirmation.Deny) },
|
||||
confirmButton = {
|
||||
Button(onClick = { viewModel.dispatch(ScreenAction.LeaveRoomConfirmation.Confirm) }) {
|
||||
Text("Leave room")
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
Button(onClick = { viewModel.dispatch(ScreenAction.LeaveRoomConfirmation.Deny) }) {
|
||||
Text("Cancel")
|
||||
}
|
||||
},
|
||||
title = { Text(dialog.title) },
|
||||
text = { Text(dialog.subtitle) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
Toolbar(onNavigate = { navigator.navigate.upToHome() }, roomTitle, actions = {
|
||||
state.roomState.takeIfContent()?.let {
|
||||
|
@ -98,8 +122,10 @@ internal fun MessengerScreen(
|
|||
viewModel.dispatch(ScreenAction.Notifications.Mute)
|
||||
})
|
||||
}
|
||||
DropdownMenuItem(text = { Text("Leave room", color = MaterialTheme.colorScheme.onSecondaryContainer) }, onClick = {
|
||||
viewModel.dispatch(ScreenAction.LeaveRoom)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -207,7 +233,7 @@ private fun ZoomableImage(viewerState: ViewerState) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun MessengerState.ObserveEvents(galleryLauncher: ActivityResultLauncher<ImageGalleryActivityPayload>) {
|
||||
private fun MessengerState.ObserveEvents(galleryLauncher: ActivityResultLauncher<ImageGalleryActivityPayload>, navigator: Navigator) {
|
||||
val context = LocalContext.current
|
||||
StartObserving {
|
||||
this@ObserveEvents.events.launch {
|
||||
|
@ -221,6 +247,8 @@ private fun MessengerState.ObserveEvents(galleryLauncher: ActivityResultLauncher
|
|||
is MessengerEvent.Toast -> {
|
||||
Toast.makeText(context, it.message, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
MessengerEvent.OnLeftRoom -> navigator.navigate.upToHome()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,19 @@ sealed interface ScreenAction : Action {
|
|||
data class CopyToClipboard(val model: BubbleModel) : ScreenAction
|
||||
object SendMessage : ScreenAction
|
||||
object OpenGalleryPicker : ScreenAction
|
||||
object LeaveRoom : ScreenAction
|
||||
|
||||
sealed interface Notifications : ScreenAction {
|
||||
object Mute : Notifications
|
||||
object Unmute : Notifications
|
||||
}
|
||||
|
||||
sealed interface LeaveRoomConfirmation : ScreenAction {
|
||||
object Confirm : LeaveRoomConfirmation
|
||||
object Deny : LeaveRoomConfirmation
|
||||
}
|
||||
|
||||
data class UpdateDialogState(val dialogState: DialogState?): ScreenAction
|
||||
}
|
||||
|
||||
sealed interface ComponentLifecycle : Action {
|
||||
|
|
|
@ -19,6 +19,7 @@ import app.dapk.st.navigator.MessageAttachment
|
|||
import app.dapk.state.*
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
internal fun messengerReducer(
|
||||
jobBag: JobBag,
|
||||
|
@ -36,6 +37,7 @@ internal fun messengerReducer(
|
|||
roomState = Lce.Loading(),
|
||||
composerState = initialComposerState(initialAttachments),
|
||||
viewerState = null,
|
||||
dialogState = null,
|
||||
),
|
||||
|
||||
async(ComponentLifecycle::class) { action ->
|
||||
|
@ -159,9 +161,43 @@ internal fun messengerReducer(
|
|||
)
|
||||
)
|
||||
},
|
||||
|
||||
change(ScreenAction.UpdateDialogState::class) { action, state ->
|
||||
state.copy(dialogState = action.dialogState)
|
||||
},
|
||||
|
||||
rewrite(ScreenAction.LeaveRoom::class) {
|
||||
ScreenAction.UpdateDialogState(
|
||||
DialogState.PositiveNegative(
|
||||
title = "Leave room",
|
||||
subtitle = "Are you sure you want you leave the room? If the room is private you will need to be invited again to rejoin.",
|
||||
negativeAction = ScreenAction.LeaveRoomConfirmation.Deny,
|
||||
positiveAction = ScreenAction.LeaveRoomConfirmation.Confirm,
|
||||
)
|
||||
)
|
||||
},
|
||||
|
||||
async(ScreenAction.LeaveRoomConfirmation::class) { action ->
|
||||
dispatch(ScreenAction.UpdateDialogState(dialogState = null))
|
||||
|
||||
when (action) {
|
||||
ScreenAction.LeaveRoomConfirmation.Confirm -> {
|
||||
runCatching { chatEngine.rejectRoom(getState().roomId) }.fold(
|
||||
onSuccess = { eventEmitter.invoke(MessengerEvent.OnLeftRoom) },
|
||||
onFailure = { eventEmitter.invoke(MessengerEvent.Toast("Failed to leave room")) },
|
||||
)
|
||||
}
|
||||
|
||||
ScreenAction.LeaveRoomConfirmation.Deny -> {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun <A : Action, S> rewrite(klass: KClass<A>, mapper: (A) -> Action) = async<A, S>(klass) { action -> dispatch(mapper(action)) }
|
||||
|
||||
private suspend fun ChatEngine.sendTextMessage(content: MessengerPageState, composerState: ComposerState.Text) {
|
||||
val roomState = content.roomState
|
||||
val message = SendMessage.TextMessage(
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package app.dapk.st.messenger.state
|
||||
|
||||
import app.dapk.st.core.Lce
|
||||
import app.dapk.st.state.State
|
||||
import app.dapk.st.design.components.BubbleModel
|
||||
import app.dapk.st.engine.MessengerPageState
|
||||
import app.dapk.st.engine.RoomEvent
|
||||
import app.dapk.st.matrix.common.RoomId
|
||||
import app.dapk.st.navigator.MessageAttachment
|
||||
import app.dapk.st.state.State
|
||||
import app.dapk.state.Action
|
||||
|
||||
typealias MessengerState = State<MessengerScreenState, MessengerEvent>
|
||||
|
||||
|
@ -15,15 +16,26 @@ data class MessengerScreenState(
|
|||
val roomState: Lce<MessengerPageState>,
|
||||
val composerState: ComposerState,
|
||||
val viewerState: ViewerState?,
|
||||
val dialogState: DialogState?,
|
||||
)
|
||||
|
||||
data class ViewerState(
|
||||
val event: BubbleModel.Image,
|
||||
)
|
||||
|
||||
sealed interface DialogState {
|
||||
data class PositiveNegative(
|
||||
val title: String,
|
||||
val subtitle: String,
|
||||
val positiveAction: Action,
|
||||
val negativeAction: Action,
|
||||
) : DialogState
|
||||
}
|
||||
|
||||
sealed interface MessengerEvent {
|
||||
object SelectImageAttachment : MessengerEvent
|
||||
data class Toast(val message: String) : MessengerEvent
|
||||
object OnLeftRoom : MessengerEvent
|
||||
}
|
||||
|
||||
sealed interface ComposerState {
|
||||
|
|
Loading…
Reference in New Issue