diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 316915d..a1da7f7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -49,7 +49,7 @@ android:theme="@style/Theme.TwoM" /> () { + data class Result( + val name: String, + val description: String, + val avatarUri: Uri?, + ) + + class Contract : ActivityResultContract() { override fun createIntent(context: Context, input: Unit): Intent { - return Intent(context, CreateRoomActivity::class.java) + return Intent(context, ConfigureRoomActivity::class.java) } - override fun parseResult(resultCode: Int, intent: Intent?): CreateRoomActivityResult? { + override fun parseResult(resultCode: Int, intent: Intent?): Result? { return when (resultCode) { - RESULT_OK -> CreateRoomActivityResult( - name = intent!!.getStringExtra(NAME_EXTRA)!!, - description = intent.getStringExtra(DESCRIPTION_EXTRA)!!, - avatarUri = intent.getStringExtra(AVATAR_EXTRA), - ) + RESULT_OK -> { + intent!! + val name = intent.getStringExtra(NAME_EXTRA)!! + val description = intent.getStringExtra(DESCRIPTION_EXTRA)!! + val avatar = intent.getStringExtra(AVATAR_EXTRA) + + Result( + name = name, + description = description, + avatarUri = if (avatar != null) Uri.parse(avatar) else null, + ) + } else -> null } diff --git a/app/src/main/java/eu/steffo/twom/activities/InviteUserActivity.kt b/app/src/main/java/eu/steffo/twom/activities/InviteUserActivity.kt index ff615a2..26d8676 100644 --- a/app/src/main/java/eu/steffo/twom/activities/InviteUserActivity.kt +++ b/app/src/main/java/eu/steffo/twom/activities/InviteUserActivity.kt @@ -16,7 +16,7 @@ class InviteUserActivity : ComponentActivity() { class Contract : ActivityResultContract() { override fun createIntent(context: Context, input: Unit): Intent { - return Intent(context, CreateRoomActivity::class.java) + return Intent(context, ConfigureRoomActivity::class.java) } override fun parseResult(resultCode: Int, intent: Intent?): String? { diff --git a/app/src/main/java/eu/steffo/twom/activities/MainActivity.kt b/app/src/main/java/eu/steffo/twom/activities/MainActivity.kt index ef062be..d37a353 100644 --- a/app/src/main/java/eu/steffo/twom/activities/MainActivity.kt +++ b/app/src/main/java/eu/steffo/twom/activities/MainActivity.kt @@ -1,12 +1,9 @@ package eu.steffo.twom.activities -import android.content.Intent -import android.net.Uri import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.activity.result.ActivityResult import androidx.core.net.toFile import androidx.lifecycle.lifecycleScope import eu.steffo.twom.composables.main.MainScaffold @@ -74,118 +71,6 @@ class MainActivity : ComponentActivity() { } } - private fun onCreate(result: ActivityResult) { - Log.d("Main", "Received result from create activity: $result") - if (result.resultCode == RESULT_OK) { - val intent: Intent = result.data!! - val name = intent.getStringExtra(CreateRoomActivity.NAME_EXTRA) - val description = intent.getStringExtra(CreateRoomActivity.DESCRIPTION_EXTRA) - @Suppress("DEPRECATION") val avatarUri = - intent.getParcelableExtra(CreateRoomActivity.AVATAR_EXTRA) - - if (name == null) { - Log.w("Main", "Result from create activity did not have `name` extra set") - return - } - if (description == null) { - Log.w("Main", "Result from create activity did not have `description` extra set") - return - } - - lifecycleScope.launch { - val currentSession = session - - val createRoomParams = CreateRoomParams() - - createRoomParams.name = name - createRoomParams.topic = description - createRoomParams.preset = CreateRoomPreset.PRESET_PRIVATE_CHAT - createRoomParams.roomType = TwoMGlobals.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) { - false -> { - Log.e( - "Main", - "Avatar has been deleted from cache before room could possibly be created, ignoring..." - ) - } - - true -> { - Log.d( - "Main", - "Avatar seems to exist at: $avatarUri" - ) - createRoomParams.avatarUri = avatarUri - } - - null -> { - Log.d( - "Main", - "Avatar was not set, ignoring..." - ) - } - } - - Log.d( - "Main", - "Creating room '$name' with description '$description' and avatar '$avatarUri'..." - ) - val roomId = currentSession!!.roomService().createRoom(createRoomParams) - - Log.d( - "Main", - "Created room '$name' with description '$description' and avatar '$avatarUri': $roomId" - ) - } - } - } - private fun resetContent() { Log.d("Main", "Recomposing...") setContent { @@ -215,6 +100,99 @@ class MainActivity : ComponentActivity() { Log.d("Main", "Done logging out!") }, + processCreate = { name, description, avatarUri -> + lifecycleScope.launch { + val currentSession = session + + val createRoomParams = CreateRoomParams() + + createRoomParams.name = name + createRoomParams.topic = description + createRoomParams.preset = CreateRoomPreset.PRESET_PRIVATE_CHAT + createRoomParams.roomType = TwoMGlobals.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) { + false -> { + Log.e( + "Main", + "Avatar has been deleted from cache before room could possibly be created, ignoring..." + ) + } + + true -> { + Log.d( + "Main", + "Avatar seems to exist at: $avatarUri" + ) + createRoomParams.avatarUri = avatarUri + } + + null -> { + Log.d( + "Main", + "Avatar was not set, ignoring..." + ) + } + } + + Log.d( + "Main", + "Creating room '$name' with description '$description' and avatar '$avatarUri'..." + ) + val roomId = currentSession!!.roomService().createRoom(createRoomParams) + + Log.d( + "Main", + "Created room '$name' with description '$description' and avatar '$avatarUri': $roomId" + ) + } + } ) } } diff --git a/app/src/main/java/eu/steffo/twom/composables/createroom/CreateRoomScaffold.kt b/app/src/main/java/eu/steffo/twom/composables/createroom/CreateRoomScaffold.kt index 9516d9c..52fcdde 100644 --- a/app/src/main/java/eu/steffo/twom/composables/createroom/CreateRoomScaffold.kt +++ b/app/src/main/java/eu/steffo/twom/composables/createroom/CreateRoomScaffold.kt @@ -10,7 +10,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview -import eu.steffo.twom.activities.CreateRoomActivity +import eu.steffo.twom.activities.ConfigureRoomActivity import eu.steffo.twom.composables.theme.TwoMTheme @Composable @@ -21,11 +21,11 @@ fun CreateRoomScaffold() { fun submitActivity(name: String, description: String, avatarUri: Uri?) { val resultIntent = Intent() - resultIntent.putExtra(CreateRoomActivity.NAME_EXTRA, name) - resultIntent.putExtra(CreateRoomActivity.DESCRIPTION_EXTRA, description) + resultIntent.putExtra(ConfigureRoomActivity.NAME_EXTRA, name) + resultIntent.putExtra(ConfigureRoomActivity.DESCRIPTION_EXTRA, description) // Kotlin cannot use nullable types in Java interop generics if (avatarUri != null) { - resultIntent.putExtra(CreateRoomActivity.AVATAR_EXTRA, avatarUri) + resultIntent.putExtra(ConfigureRoomActivity.AVATAR_EXTRA, avatarUri) } activity.setResult(ComponentActivity.RESULT_OK, resultIntent) activity.finish() diff --git a/app/src/main/java/eu/steffo/twom/composables/main/CreateRoomFAB.kt b/app/src/main/java/eu/steffo/twom/composables/main/CreateRoomFAB.kt index 50ecbad..ca7a7bd 100644 --- a/app/src/main/java/eu/steffo/twom/composables/main/CreateRoomFAB.kt +++ b/app/src/main/java/eu/steffo/twom/composables/main/CreateRoomFAB.kt @@ -1,5 +1,6 @@ package eu.steffo.twom.composables.main +import android.net.Uri import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.launch import androidx.compose.material.icons.Icons @@ -12,16 +13,16 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import eu.steffo.twom.R -import eu.steffo.twom.activities.CreateRoomActivity +import eu.steffo.twom.activities.ConfigureRoomActivity @Composable @Preview fun CreateRoomFAB( modifier: Modifier = Modifier, - onCreateParamsSelected: (name: String, description: String, avatarUri: String?) -> Unit = { _, _, _ -> }, + onCreateParamsSelected: (name: String, description: String, avatarUri: Uri?) -> Unit = { _, _, _ -> }, ) { val launcher = - rememberLauncherForActivityResult(CreateRoomActivity.Contract()) { + rememberLauncherForActivityResult(ConfigureRoomActivity.Contract()) { if (it != null) { onCreateParamsSelected(it.name, it.description, it.avatarUri) } diff --git a/app/src/main/java/eu/steffo/twom/composables/main/MainScaffold.kt b/app/src/main/java/eu/steffo/twom/composables/main/MainScaffold.kt index 59c2a04..3a05a1d 100644 --- a/app/src/main/java/eu/steffo/twom/composables/main/MainScaffold.kt +++ b/app/src/main/java/eu/steffo/twom/composables/main/MainScaffold.kt @@ -1,5 +1,6 @@ package eu.steffo.twom.composables.main +import android.net.Uri import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable @@ -15,7 +16,7 @@ import org.matrix.android.sdk.api.session.Session fun MainScaffold( processLogin: () -> Unit = {}, processLogout: () -> Unit = {}, - processCreate: (name: String, description: String, avatarUri: String?) -> Unit = { _, _, _ -> }, + processCreate: (name: String, description: String, avatarUri: Uri?) -> Unit = { _, _, _ -> }, session: Session? = null, ) { TwoMTheme { diff --git a/app/src/main/java/eu/steffo/twom/composables/viewroom/RSVPChipRow.kt b/app/src/main/java/eu/steffo/twom/composables/viewroom/RSVPChipRow.kt index 1c82e64..5f208f4 100644 --- a/app/src/main/java/eu/steffo/twom/composables/viewroom/RSVPChipRow.kt +++ b/app/src/main/java/eu/steffo/twom/composables/viewroom/RSVPChipRow.kt @@ -16,14 +16,14 @@ import eu.steffo.twom.utils.RSVPAnswer @Preview fun RSVPChipRow( modifier: Modifier = Modifier, - value: RSVPAnswer = RSVPAnswer.UNKNOWN, + value: RSVPAnswer = RSVPAnswer.LOADING, onChange: (answer: RSVPAnswer) -> Unit = {}, ) { fun toggleSwitch(representing: RSVPAnswer): () -> Unit { return { onChange( when (value) { - representing -> RSVPAnswer.UNKNOWN + representing -> RSVPAnswer.NONE else -> representing } ) diff --git a/app/src/main/java/eu/steffo/twom/composables/viewroom/ViewRoomTopBar.kt b/app/src/main/java/eu/steffo/twom/composables/viewroom/ViewRoomTopBar.kt index 8c11506..556f6da 100644 --- a/app/src/main/java/eu/steffo/twom/composables/viewroom/ViewRoomTopBar.kt +++ b/app/src/main/java/eu/steffo/twom/composables/viewroom/ViewRoomTopBar.kt @@ -12,6 +12,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import eu.steffo.twom.R import eu.steffo.twom.composables.errorhandling.ErrorIconButton +import eu.steffo.twom.composables.errorhandling.ErrorText import eu.steffo.twom.composables.errorhandling.LocalizableError import eu.steffo.twom.composables.navigation.BackIconButton @@ -26,6 +27,16 @@ fun ViewRoomTopBar( isLoading: Boolean = false, error: LocalizableError? = null, ) { + + val roomSummaryRequest = LocalRoomSummary.current + val isLoading = (roomSummaryRequest == null) + + val roomSummary = roomSummaryRequest.getOrNull() + if (roomSummary == null) { + ErrorText(stringResource(R.string.room_error_roomsummary_notfound)) + return + } + TopAppBar( modifier = modifier, navigationIcon = { diff --git a/app/src/main/java/eu/steffo/twom/composables/viewroom/observeRSVP.kt b/app/src/main/java/eu/steffo/twom/composables/viewroom/observeRSVP.kt index 80e3371..8f1aa3f 100644 --- a/app/src/main/java/eu/steffo/twom/composables/viewroom/observeRSVP.kt +++ b/app/src/main/java/eu/steffo/twom/composables/viewroom/observeRSVP.kt @@ -65,7 +65,7 @@ fun observeRSVP(room: Room, member: RoomMemberSummary): RSVP { val answerField = content[TwoMGlobals.RSVP_STATE_ANSWER_FIELD] ?: return RSVP( event = event, - answer = RSVPAnswer.UNKNOWN, + answer = RSVPAnswer.NONE, comment = comment, ) @@ -81,6 +81,7 @@ fun observeRSVP(room: Room, member: RoomMemberSummary): RSVP { RSVPAnswer.LATER.value -> RSVPAnswer.LATER RSVPAnswer.MAYBE.value -> RSVPAnswer.MAYBE RSVPAnswer.NOWAY.value -> RSVPAnswer.NOWAY + RSVPAnswer.NONE.value -> RSVPAnswer.NONE else -> RSVPAnswer.UNKNOWN } diff --git a/app/src/main/java/eu/steffo/twom/utils/RSVPAnswer.kt b/app/src/main/java/eu/steffo/twom/utils/RSVPAnswer.kt index 0187a02..b1e1d24 100644 --- a/app/src/main/java/eu/steffo/twom/utils/RSVPAnswer.kt +++ b/app/src/main/java/eu/steffo/twom/utils/RSVPAnswer.kt @@ -119,8 +119,8 @@ enum class RSVPAnswer { // An option differing from the previous ones. UNKNOWN { - override val value: String? - get() = null + override val value: String + get() = "" override val staticColorRole: StaticColorRole get() = NullishColorRole @@ -143,8 +143,8 @@ enum class RSVPAnswer { // The answer is still being loaded. LOADING { - override val value: String? - get() = null + override val value: String + get() = "" override val staticColorRole: StaticColorRole get() = NullishColorRole @@ -166,8 +166,8 @@ enum class RSVPAnswer { // No answer has been provided yet. NONE { - override val value: String? - get() = null + override val value: String + get() = "" override val staticColorRole: StaticColorRole get() = NullishColorRole @@ -190,8 +190,8 @@ enum class RSVPAnswer { // Has been invited, but has not accepted yet. PENDING { - override val value: String? - get() = null + override val value: String + get() = "" override val staticColorRole: StaticColorRole get() = NullishColorRole @@ -212,7 +212,7 @@ enum class RSVPAnswer { stringResource(R.string.room_rsvp_nullish_placeholder) }; - abstract val value: String? + abstract val value: String abstract val staticColorRole: StaticColorRole abstract val icon: ImageVector