mirror of
https://github.com/Steffo99/twom.git
synced 2024-11-22 08:04:26 +00:00
It works!
This commit is contained in:
parent
a6e562c14b
commit
acf9f34f59
10 changed files with 284 additions and 115 deletions
|
@ -19,6 +19,7 @@ import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomStateEvent
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
@ -176,6 +177,52 @@ class MainActivity : ComponentActivity() {
|
||||||
createRoomParams.topic = description
|
createRoomParams.topic = description
|
||||||
createRoomParams.preset = CreateRoomPreset.PRESET_PRIVATE_CHAT
|
createRoomParams.preset = CreateRoomPreset.PRESET_PRIVATE_CHAT
|
||||||
createRoomParams.roomType = TwoMMatrix.ROOM_TYPE
|
createRoomParams.roomType = TwoMMatrix.ROOM_TYPE
|
||||||
|
createRoomParams.initialStates = mutableListOf(
|
||||||
|
CreateRoomStateEvent(
|
||||||
|
type = "m.room.power_levels",
|
||||||
|
content = mapOf(
|
||||||
|
// Users start with a power level of 0
|
||||||
|
"users_default" to 0,
|
||||||
|
// Allow only the party creator to send arbitrary events
|
||||||
|
"events_default" to 100,
|
||||||
|
// Allow only the party creator to send arbitrary states
|
||||||
|
"state_default" to 100,
|
||||||
|
|
||||||
|
// Allow only party officers to send invites
|
||||||
|
"invite" to 50,
|
||||||
|
// Allow only party officers to kick invitees
|
||||||
|
"kick" to 50,
|
||||||
|
// Allow only party officers to ban invitees
|
||||||
|
"ban" to 50,
|
||||||
|
// Allow only party officers to redact other people's events
|
||||||
|
"redact" to 50,
|
||||||
|
|
||||||
|
"notifications" to mapOf(
|
||||||
|
// Allow only party officers to ping the room
|
||||||
|
"room" to 50,
|
||||||
|
),
|
||||||
|
|
||||||
|
"events" to mapOf(
|
||||||
|
// Allow party officers to rename the room
|
||||||
|
"m.room.name" to 50,
|
||||||
|
// Allow party officers to change the room avatar
|
||||||
|
"m.room.avatar" to 50,
|
||||||
|
// Allow party officers to change the room topic
|
||||||
|
"m.room.topic" to 50,
|
||||||
|
// Allow everyone to redact their own states
|
||||||
|
"m.room.redaction" to 0,
|
||||||
|
// Allow everyone to set RSVPs
|
||||||
|
// FIXME: Do we really want everyone to set RSVPs? Maybe we should use m.room.member instead?
|
||||||
|
"eu.steffo.twom.rsvp" to 0,
|
||||||
|
),
|
||||||
|
|
||||||
|
"users" to mapOf(
|
||||||
|
// Give ourselves admin permissions
|
||||||
|
session!!.myUserId to 100,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
when (avatarUri?.toFile()?.isFile) {
|
when (avatarUri?.toFile()?.isFile) {
|
||||||
false -> {
|
false -> {
|
||||||
|
|
|
@ -25,8 +25,8 @@ fun MemberListItem(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
memberId: String,
|
memberId: String,
|
||||||
onClickMember: (memberId: String) -> Unit = {},
|
onClickMember: (memberId: String) -> Unit = {},
|
||||||
rsvpAnswer: RSVPAnswer? = null,
|
rsvpAnswer: RSVPAnswer,
|
||||||
rsvpComment: String = "",
|
rsvpComment: String,
|
||||||
) {
|
) {
|
||||||
val session = LocalSession.current
|
val session = LocalSession.current
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package eu.steffo.twom.room
|
package eu.steffo.twom.room
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.State
|
||||||
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import eu.steffo.twom.R
|
import eu.steffo.twom.R
|
||||||
import eu.steffo.twom.theme.StaticColorRole
|
import eu.steffo.twom.theme.StaticColorRole
|
||||||
|
@ -14,33 +16,37 @@ import eu.steffo.twom.theme.iconMaybe
|
||||||
import eu.steffo.twom.theme.iconNoway
|
import eu.steffo.twom.theme.iconNoway
|
||||||
import eu.steffo.twom.theme.iconSure
|
import eu.steffo.twom.theme.iconSure
|
||||||
import eu.steffo.twom.theme.iconUnknown
|
import eu.steffo.twom.theme.iconUnknown
|
||||||
import org.matrix.android.sdk.api.util.JsonDict
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
|
import org.matrix.android.sdk.api.session.room.Room
|
||||||
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
|
|
||||||
enum class RSVPAnswer : JsonDict {
|
enum class RSVPAnswer {
|
||||||
SURE,
|
SURE,
|
||||||
LATER,
|
LATER,
|
||||||
MAYBE,
|
MAYBE,
|
||||||
NOWAY,
|
NOWAY,
|
||||||
|
UNKNOWN,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RSVPAnswer?.toStaticColorRole(): StaticColorRole {
|
fun RSVPAnswer.toStaticColorRole(): StaticColorRole {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
RSVPAnswer.SURE -> colorRoleSure()
|
RSVPAnswer.SURE -> colorRoleSure()
|
||||||
RSVPAnswer.LATER -> colorRoleLater()
|
RSVPAnswer.LATER -> colorRoleLater()
|
||||||
RSVPAnswer.MAYBE -> colorRoleMaybe()
|
RSVPAnswer.MAYBE -> colorRoleMaybe()
|
||||||
RSVPAnswer.NOWAY -> colorRoleNoway()
|
RSVPAnswer.NOWAY -> colorRoleNoway()
|
||||||
null -> colorRoleUnknown()
|
RSVPAnswer.UNKNOWN -> colorRoleUnknown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun RSVPAnswer?.toIcon(): ImageVector {
|
fun RSVPAnswer.toIcon(): ImageVector {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
RSVPAnswer.SURE -> iconSure
|
RSVPAnswer.SURE -> iconSure
|
||||||
RSVPAnswer.LATER -> iconLater
|
RSVPAnswer.LATER -> iconLater
|
||||||
RSVPAnswer.MAYBE -> iconMaybe
|
RSVPAnswer.MAYBE -> iconMaybe
|
||||||
RSVPAnswer.NOWAY -> iconNoway
|
RSVPAnswer.NOWAY -> iconNoway
|
||||||
null -> iconUnknown
|
RSVPAnswer.UNKNOWN -> iconUnknown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,25 +56,72 @@ fun RSVPAnswer.toLabelResourceId(): Int {
|
||||||
RSVPAnswer.LATER -> R.string.room_rsvp_later_label
|
RSVPAnswer.LATER -> R.string.room_rsvp_later_label
|
||||||
RSVPAnswer.MAYBE -> R.string.room_rsvp_maybe_label
|
RSVPAnswer.MAYBE -> R.string.room_rsvp_maybe_label
|
||||||
RSVPAnswer.NOWAY -> R.string.room_rsvp_noway_label
|
RSVPAnswer.NOWAY -> R.string.room_rsvp_noway_label
|
||||||
|
RSVPAnswer.UNKNOWN -> R.string.room_rsvp_unknown_label
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun RSVPAnswer?.toResponseResourceId(): Int {
|
fun RSVPAnswer.toResponseResourceId(): Int {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
RSVPAnswer.SURE -> R.string.room_rsvp_sure_response
|
RSVPAnswer.SURE -> R.string.room_rsvp_sure_response
|
||||||
RSVPAnswer.LATER -> R.string.room_rsvp_later_response
|
RSVPAnswer.LATER -> R.string.room_rsvp_later_response
|
||||||
RSVPAnswer.MAYBE -> R.string.room_rsvp_maybe_response
|
RSVPAnswer.MAYBE -> R.string.room_rsvp_maybe_response
|
||||||
RSVPAnswer.NOWAY -> R.string.room_rsvp_noway_response
|
RSVPAnswer.NOWAY -> R.string.room_rsvp_noway_response
|
||||||
null -> R.string.room_rsvp_unknown_response
|
RSVPAnswer.UNKNOWN -> R.string.room_rsvp_unknown_response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun RSVPAnswer?.toPlaceholderResourceId(): Int {
|
fun RSVPAnswer.toPlaceholderResourceId(): Int {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
RSVPAnswer.SURE -> R.string.room_rsvp_sure_placeholder
|
RSVPAnswer.SURE -> R.string.room_rsvp_sure_placeholder
|
||||||
RSVPAnswer.LATER -> R.string.room_rsvp_later_placeholder
|
RSVPAnswer.LATER -> R.string.room_rsvp_later_placeholder
|
||||||
RSVPAnswer.MAYBE -> R.string.room_rsvp_maybe_placeholder
|
RSVPAnswer.MAYBE -> R.string.room_rsvp_maybe_placeholder
|
||||||
RSVPAnswer.NOWAY -> R.string.room_rsvp_noway_placeholder
|
RSVPAnswer.NOWAY -> R.string.room_rsvp_noway_placeholder
|
||||||
null -> R.string.room_rsvp_unknown_placeholder
|
RSVPAnswer.UNKNOWN -> R.string.room_rsvp_unknown_placeholder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun RSVPAnswer.toEmoji(): String {
|
||||||
|
return when (this) {
|
||||||
|
RSVPAnswer.SURE -> "✅"
|
||||||
|
RSVPAnswer.LATER -> "\uD83D\uDD52️"
|
||||||
|
RSVPAnswer.MAYBE -> "❔"
|
||||||
|
RSVPAnswer.NOWAY -> "⛔️"
|
||||||
|
RSVPAnswer.UNKNOWN -> "ℹ️"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun makeRSVP(request: State<Optional<Event>?>?): Triple<Event, RSVPAnswer, String>? {
|
||||||
|
val event = request?.value?.getOrNull() ?: return null
|
||||||
|
val content = event.content ?: return null
|
||||||
|
|
||||||
|
val answerAny = content["answer"]
|
||||||
|
val commentAny = content["comment"]
|
||||||
|
|
||||||
|
val answer = if (answerAny is String) {
|
||||||
|
try {
|
||||||
|
RSVPAnswer.valueOf(answerAny)
|
||||||
|
} catch (_: IllegalArgumentException) {
|
||||||
|
RSVPAnswer.UNKNOWN
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RSVPAnswer.UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
val comment = if (commentAny is String) {
|
||||||
|
commentAny
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
|
return Triple(event, answer, comment)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun observeRsvpAsLiveState(room: Room, userId: String): Triple<Event, RSVPAnswer, String>? {
|
||||||
|
val request = room.stateService().getStateEventLive(
|
||||||
|
eventType = "eu.steffo.twom.rsvp",
|
||||||
|
stateKey = QueryStringValue.Equals(userId),
|
||||||
|
).observeAsState()
|
||||||
|
|
||||||
|
return makeRSVP(request)
|
||||||
|
}
|
|
@ -15,14 +15,14 @@ import eu.steffo.twom.theme.TwoMPadding
|
||||||
@Preview
|
@Preview
|
||||||
fun RSVPAnswerSelectRow(
|
fun RSVPAnswerSelectRow(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
value: RSVPAnswer? = null,
|
value: RSVPAnswer = RSVPAnswer.UNKNOWN,
|
||||||
onChange: (answer: RSVPAnswer?) -> Unit = {},
|
onChange: (answer: RSVPAnswer) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
fun toggleSwitch(representing: RSVPAnswer): () -> Unit {
|
fun toggleSwitch(representing: RSVPAnswer): () -> Unit {
|
||||||
return {
|
return {
|
||||||
onChange(
|
onChange(
|
||||||
when (value) {
|
when (value) {
|
||||||
representing -> null
|
representing -> RSVPAnswer.UNKNOWN
|
||||||
else -> representing
|
else -> representing
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -35,7 +35,7 @@ fun RSVPAnswerSelectRow(
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 10.dp, end = 10.dp)
|
.padding(start = 8.dp, end = 8.dp)
|
||||||
) {
|
) {
|
||||||
RSVPAnswerFilterChip(
|
RSVPAnswerFilterChip(
|
||||||
modifier = TwoMPadding.chips,
|
modifier = TwoMPadding.chips,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package eu.steffo.twom.room
|
package eu.steffo.twom.room
|
||||||
|
|
||||||
import androidx.compose.material3.LocalContentColor
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.OutlinedTextFieldDefaults
|
import androidx.compose.material3.OutlinedTextFieldDefaults
|
||||||
|
@ -16,9 +15,9 @@ fun RSVPCommentField(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
value: String = "",
|
value: String = "",
|
||||||
onChange: (value: String) -> Unit = {},
|
onChange: (value: String) -> Unit = {},
|
||||||
currentRsvpAnswer: RSVPAnswer? = null,
|
rsvpAnswer: RSVPAnswer = RSVPAnswer.UNKNOWN,
|
||||||
) {
|
) {
|
||||||
val colorRole = currentRsvpAnswer.toStaticColorRole()
|
val colorRole = rsvpAnswer.toStaticColorRole()
|
||||||
|
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
@ -28,24 +27,17 @@ fun RSVPCommentField(
|
||||||
shape = MaterialTheme.shapes.small,
|
shape = MaterialTheme.shapes.small,
|
||||||
placeholder = {
|
placeholder = {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(currentRsvpAnswer.toPlaceholderResourceId())
|
text = stringResource(rsvpAnswer.toPlaceholderResourceId())
|
||||||
)
|
|
||||||
},
|
|
||||||
colors = if (currentRsvpAnswer != null) {
|
|
||||||
OutlinedTextFieldDefaults.colors(
|
|
||||||
focusedContainerColor = colorRole.valueContainer,
|
|
||||||
unfocusedContainerColor = colorRole.valueContainer,
|
|
||||||
focusedTextColor = colorRole.onValueContainer,
|
|
||||||
unfocusedTextColor = colorRole.onValueContainer,
|
|
||||||
focusedBorderColor = colorRole.onValueContainer,
|
|
||||||
unfocusedBorderColor = colorRole.onValueContainer.copy(alpha = 0.3f),
|
|
||||||
cursorColor = colorRole.onValueContainer,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
OutlinedTextFieldDefaults.colors(
|
|
||||||
focusedBorderColor = LocalContentColor.current,
|
|
||||||
unfocusedBorderColor = MaterialTheme.colorScheme.surfaceVariant,
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
colors = OutlinedTextFieldDefaults.colors(
|
||||||
|
focusedContainerColor = colorRole.valueContainer,
|
||||||
|
unfocusedContainerColor = colorRole.valueContainer,
|
||||||
|
focusedTextColor = colorRole.onValueContainer,
|
||||||
|
unfocusedTextColor = colorRole.onValueContainer,
|
||||||
|
focusedBorderColor = colorRole.onValueContainer,
|
||||||
|
unfocusedBorderColor = colorRole.onValueContainer.copy(alpha = 0.3f),
|
||||||
|
cursorColor = colorRole.onValueContainer,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@ fun RSVPUpdateButton(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
enabled: Boolean = true,
|
enabled: Boolean = true,
|
||||||
onClick: () -> Unit = {},
|
onClick: () -> Unit = {},
|
||||||
currentRsvpAnswer: RSVPAnswer? = null,
|
rsvpAnswer: RSVPAnswer = RSVPAnswer.UNKNOWN,
|
||||||
) {
|
) {
|
||||||
val colorRole = currentRsvpAnswer.toStaticColorRole()
|
val colorRole = rsvpAnswer.toStaticColorRole()
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
|
|
@ -14,9 +14,10 @@ import androidx.compose.ui.unit.dp
|
||||||
@Composable
|
@Composable
|
||||||
@Preview
|
@Preview
|
||||||
fun RoomActivityAnswerForm(
|
fun RoomActivityAnswerForm(
|
||||||
currentRsvpAnswer: RSVPAnswer? = null,
|
currentRsvpAnswer: RSVPAnswer = RSVPAnswer.UNKNOWN,
|
||||||
currentRsvpComment: String = "",
|
currentRsvpComment: String = "",
|
||||||
onUpdate: (rsvpAnswer: RSVPAnswer?, rsvpComment: String) -> Unit = { _, _ -> },
|
onUpdate: (rsvpAnswer: RSVPAnswer, rsvpComment: String) -> Unit = { _, _ -> },
|
||||||
|
isUpdating: Boolean = false,
|
||||||
) {
|
) {
|
||||||
var rsvpAnswer by rememberSaveable { mutableStateOf(currentRsvpAnswer) }
|
var rsvpAnswer by rememberSaveable { mutableStateOf(currentRsvpAnswer) }
|
||||||
var rsvpComment by rememberSaveable { mutableStateOf(currentRsvpComment) }
|
var rsvpComment by rememberSaveable { mutableStateOf(currentRsvpComment) }
|
||||||
|
@ -33,14 +34,14 @@ fun RoomActivityAnswerForm(
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
value = rsvpComment,
|
value = rsvpComment,
|
||||||
onChange = { rsvpComment = it },
|
onChange = { rsvpComment = it },
|
||||||
currentRsvpAnswer = rsvpAnswer,
|
rsvpAnswer = rsvpAnswer,
|
||||||
)
|
)
|
||||||
RSVPUpdateButton(
|
RSVPUpdateButton(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 10.dp, end = 10.dp, top = 4.dp, bottom = 4.dp)
|
.padding(start = 10.dp, end = 10.dp, top = 4.dp, bottom = 4.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
onClick = { onUpdate(rsvpAnswer, rsvpComment) },
|
onClick = { onUpdate(rsvpAnswer, rsvpComment) },
|
||||||
enabled = hasChanged,
|
enabled = hasChanged && !isUpdating,
|
||||||
currentRsvpAnswer = rsvpAnswer,
|
rsvpAnswer = rsvpAnswer,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
package eu.steffo.twom.room
|
package eu.steffo.twom.room
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import eu.steffo.twom.R
|
import eu.steffo.twom.R
|
||||||
|
@ -14,7 +19,7 @@ import eu.steffo.twom.matrix.LocalSession
|
||||||
import eu.steffo.twom.theme.ErrorText
|
import eu.steffo.twom.theme.ErrorText
|
||||||
import eu.steffo.twom.theme.TwoMPadding
|
import eu.steffo.twom.theme.TwoMPadding
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.failure.Failure
|
||||||
import kotlin.jvm.optionals.getOrNull
|
import kotlin.jvm.optionals.getOrNull
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,52 +30,88 @@ fun RoomActivityContent(
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
val session = LocalSession.current
|
val session = LocalSession.current
|
||||||
val roomRequest = LocalRoom.current
|
if (session == null) {
|
||||||
val room = roomRequest?.getOrNull()
|
ErrorText(stringResource(R.string.room_error_session_missing))
|
||||||
val roomSummaryRequest = LocalRoomSummary.current
|
return
|
||||||
val roomSummary = roomSummaryRequest?.getOrNull()
|
}
|
||||||
|
|
||||||
val myRsvp = room?.stateService()?.getStateEventLive(
|
val roomRequest = LocalRoom.current
|
||||||
eventType = "eu.steffo.twom.rsvp",
|
if (roomRequest == null) {
|
||||||
stateKey = QueryStringValue.Equals(session!!.myUserId),
|
ErrorText(stringResource(R.string.room_error_room_missing))
|
||||||
)?.observeAsState()
|
return
|
||||||
// TODO: I stopped here; how to retrieve the RSVP from this?
|
}
|
||||||
|
|
||||||
|
val room = roomRequest.getOrNull()
|
||||||
|
if (room == null) {
|
||||||
|
ErrorText(stringResource(R.string.room_error_room_notfound))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val roomSummaryRequest = LocalRoomSummary.current
|
||||||
|
if (roomSummaryRequest == null) {
|
||||||
|
ErrorText(stringResource(R.string.room_error_roomsummary_missing))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val roomSummary = roomSummaryRequest.getOrNull()
|
||||||
|
if (roomSummary == null) {
|
||||||
|
ErrorText(stringResource(R.string.room_error_roomsummary_notfound))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(roomSummary.otherMemberIds) ResolveUnknownUsers@{
|
||||||
|
// Resolve unknown users, one at a time
|
||||||
|
roomSummary.otherMemberIds.map {
|
||||||
|
if (session.userService().getUser(it) == null) {
|
||||||
|
Log.i("Room", "Resolving unknown user: $it")
|
||||||
|
session.userService().resolveUser(it)
|
||||||
|
Log.d("Room", "Successfully resolved unknown user: $it")
|
||||||
|
} else {
|
||||||
|
Log.v("Room", "Not resolving known user: $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val myRsvpRequest = observeRsvpAsLiveState(room = room, userId = session.myUserId)
|
||||||
|
val otherRsvpRequests =
|
||||||
|
roomSummary.otherMemberIds.map { it to observeRsvpAsLiveState(room = room, userId = it) }
|
||||||
|
|
||||||
|
var isUpdatingMyRsvp by rememberSaveable { mutableStateOf(false) }
|
||||||
|
var errorMyRsvp by rememberSaveable { mutableStateOf<Failure.ServerError?>(null) }
|
||||||
|
|
||||||
Column(modifier) {
|
Column(modifier) {
|
||||||
if (session == null) {
|
Row(TwoMPadding.base) {
|
||||||
ErrorText(stringResource(R.string.room_error_session_missing))
|
Text(
|
||||||
} else if (roomRequest == null) {
|
text = stringResource(R.string.room_topic_title),
|
||||||
ErrorText(stringResource(R.string.room_error_room_missing))
|
style = MaterialTheme.typography.labelLarge,
|
||||||
} else if (!roomRequest.isPresent) {
|
)
|
||||||
ErrorText(stringResource(R.string.room_error_room_notfound))
|
}
|
||||||
} else if (roomSummaryRequest == null) {
|
Row(TwoMPadding.base) {
|
||||||
// Loading
|
Text(roomSummary.topic)
|
||||||
} else if (!roomSummaryRequest.hasValue()) {
|
}
|
||||||
ErrorText(stringResource(R.string.room_error_room_notfound))
|
|
||||||
} else if (roomSummary != null) {
|
|
||||||
Row(TwoMPadding.base) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.room_topic_title),
|
|
||||||
style = MaterialTheme.typography.labelLarge,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Row(TwoMPadding.base) {
|
|
||||||
Text(roomSummary.topic)
|
|
||||||
}
|
|
||||||
|
|
||||||
Row(TwoMPadding.base) {
|
Row(TwoMPadding.base) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.room_rsvp_title),
|
text = stringResource(R.string.room_rsvp_title),
|
||||||
style = MaterialTheme.typography.labelLarge,
|
style = MaterialTheme.typography.labelLarge,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
RoomActivityAnswerForm(
|
RoomActivityAnswerForm(
|
||||||
currentRsvpAnswer = myRsvp,
|
// FIXME: This always set the request to UNKNOWN
|
||||||
currentRsvpComment = myRsvp,
|
currentRsvpAnswer = myRsvpRequest?.second ?: RSVPAnswer.UNKNOWN,
|
||||||
onUpdate = { answer, comment ->
|
currentRsvpComment = myRsvpRequest?.third ?: "",
|
||||||
scope.launch SendStateEvent@{
|
onUpdate = { answer, comment ->
|
||||||
room!!.stateService().sendStateEvent(
|
isUpdatingMyRsvp = true
|
||||||
|
errorMyRsvp = null
|
||||||
|
|
||||||
|
scope.launch SendRSVP@{
|
||||||
|
Log.d(
|
||||||
|
"Room",
|
||||||
|
"Updating eu.steffo.twom.rsvp with answer `$answer` and comment `$comment`..."
|
||||||
|
)
|
||||||
|
try {
|
||||||
|
room.stateService().sendStateEvent(
|
||||||
eventType = "eu.steffo.twom.rsvp",
|
eventType = "eu.steffo.twom.rsvp",
|
||||||
stateKey = session.myUserId,
|
stateKey = session.myUserId,
|
||||||
body = mapOf(
|
body = mapOf(
|
||||||
|
@ -80,38 +121,70 @@ fun RoomActivityContent(
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
} catch (error: Failure.ServerError) {
|
||||||
|
Log.e("Room", "Failed to update eu.steffo.twom.rsvp: $error")
|
||||||
|
errorMyRsvp = error
|
||||||
|
isUpdatingMyRsvp = false
|
||||||
|
return@SendRSVP
|
||||||
}
|
}
|
||||||
|
Log.d(
|
||||||
|
"Room",
|
||||||
|
"Updated eu.steffo.twom.rsvp with answer `$answer` and comment `$comment`!"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (myRsvpRequest != null) {
|
||||||
|
val myRsvpRequestEventId = myRsvpRequest.first.eventId
|
||||||
|
Log.d(
|
||||||
|
"Room",
|
||||||
|
"Attempting to redact old eu.steffo.twom.rsvp event `${myRsvpRequestEventId}`..."
|
||||||
|
)
|
||||||
|
try {
|
||||||
|
room.sendService()
|
||||||
|
.redactEvent(myRsvpRequest.first, "Replaced with new information")
|
||||||
|
} catch (error: Failure.ServerError) {
|
||||||
|
Log.e("Room", "Failed to redact the old eu.steffo.twom.rsvp: $error")
|
||||||
|
errorMyRsvp = error
|
||||||
|
isUpdatingMyRsvp = false
|
||||||
|
return@SendRSVP
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.d("Room", "Not doing anything else; there isn't anything to redact.")
|
||||||
|
}
|
||||||
|
|
||||||
|
isUpdatingMyRsvp = false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
isUpdating = isUpdatingMyRsvp,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (errorMyRsvp != null) {
|
||||||
|
// TODO: Maybe add an human-friendly error message?
|
||||||
|
Row(TwoMPadding.base) {
|
||||||
|
ErrorText(
|
||||||
|
errorMyRsvp.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(TwoMPadding.base) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.room_invitees_title),
|
||||||
|
style = MaterialTheme.typography.labelLarge,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(TwoMPadding.base) {
|
||||||
|
MemberListItem(
|
||||||
|
memberId = LocalSession.current!!.myUserId,
|
||||||
|
rsvpAnswer = myRsvpRequest?.second ?: RSVPAnswer.UNKNOWN,
|
||||||
|
rsvpComment = myRsvpRequest?.third ?: "",
|
||||||
)
|
)
|
||||||
|
|
||||||
Row(TwoMPadding.base) {
|
otherRsvpRequests.forEach {
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.room_invitees_title),
|
|
||||||
style = MaterialTheme.typography.labelLarge,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Column(TwoMPadding.base) {
|
|
||||||
MemberListItem(
|
MemberListItem(
|
||||||
memberId = LocalSession.current!!.myUserId,
|
memberId = it.first,
|
||||||
rsvpAnswer = rsvpAnswer,
|
rsvpAnswer = it.second?.second ?: RSVPAnswer.UNKNOWN,
|
||||||
rsvpComment = rsvpComment,
|
rsvpComment = it.second?.third ?: "",
|
||||||
)
|
|
||||||
|
|
||||||
roomSummary.otherMemberIds.forEach {
|
|
||||||
MemberListItem(
|
|
||||||
memberId = it,
|
|
||||||
rsvpAnswer = null,
|
|
||||||
rsvpComment = "",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (isError) {
|
|
||||||
Row(TwoMPadding.base) {
|
|
||||||
Text(
|
|
||||||
// TODO: Maybe add a better error string
|
|
||||||
text = stringResource(R.string.error),
|
|
||||||
color = MaterialTheme.colorScheme.error,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ fun colorRoleUnknown(): StaticColorRole {
|
||||||
return StaticColorRole(
|
return StaticColorRole(
|
||||||
value = MaterialTheme.colorScheme.inverseSurface,
|
value = MaterialTheme.colorScheme.inverseSurface,
|
||||||
onValue = MaterialTheme.colorScheme.inverseOnSurface,
|
onValue = MaterialTheme.colorScheme.inverseOnSurface,
|
||||||
valueContainer = MaterialTheme.colorScheme.surfaceVariant,
|
valueContainer = MaterialTheme.colorScheme.surface,
|
||||||
onValueContainer = MaterialTheme.colorScheme.onSurfaceVariant,
|
onValueContainer = MaterialTheme.colorScheme.onSurface,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,4 +58,7 @@
|
||||||
<string name="room_error_session_missing">The Matrix session context has not been initialized.</string>
|
<string name="room_error_session_missing">The Matrix session context has not been initialized.</string>
|
||||||
<string name="room_error_room_notfound">Could not find the requested Matrix room.</string>
|
<string name="room_error_room_notfound">Could not find the requested Matrix room.</string>
|
||||||
<string name="room_error_room_missing">The Matrix room context has not been initialized.</string>
|
<string name="room_error_room_missing">The Matrix room context has not been initialized.</string>
|
||||||
|
<string name="room_rsvp_unknown_label">No answer</string>
|
||||||
|
<string name="room_error_roomsummary_missing">The Matrix room summary context has not been initialized.</string>
|
||||||
|
<string name="room_error_roomsummary_notfound">Could not find the requested Matrix room summary.</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in a new issue