moving the image gallery to the messenger module and attaching to a attachment button

This commit is contained in:
Adam Brown 2022-09-29 14:32:04 +01:00
parent c61646bbd3
commit 3f956d1903
11 changed files with 80 additions and 58 deletions

View File

@ -3,7 +3,6 @@
<application>
<activity android:name="app.dapk.st.home.MainActivity"/>
<activity android:name="app.dapk.st.home.gallery.ImageGalleryActivity"/>
</application>
</manifest>

View File

@ -1,7 +1,6 @@
package app.dapk.st.home
import android.os.Bundle
import android.widget.Toast
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Surface
@ -11,15 +10,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.lifecycle.lifecycleScope
import app.dapk.st.core.DapkActivity
import app.dapk.st.core.Lce
import app.dapk.st.core.module
import app.dapk.st.core.viewModel
import app.dapk.st.design.components.Route
import app.dapk.st.design.components.SpiderPage
import app.dapk.st.directory.DirectoryModule
import app.dapk.st.home.gallery.Folder
import app.dapk.st.home.gallery.GetImageFromGallery
import app.dapk.st.home.gallery.Media
import app.dapk.st.login.LoginModule
import app.dapk.st.profile.ProfileModule
import kotlinx.coroutines.flow.launchIn
@ -41,11 +34,6 @@ class MainActivity : DapkActivity() {
}
}.launchIn(lifecycleScope)
registerForActivityResult(GetImageFromGallery()) {
Toast.makeText(this, it.toString(), Toast.LENGTH_SHORT).show()
}.launch(null)
setContent {
if (homeViewModel.hasVersionChanged()) {
BetaUpgradeDialog()
@ -73,22 +61,3 @@ class MainActivity : DapkActivity() {
)
}
}
data class ImageGalleryState(
val page: SpiderPage<out ImageGalleryPage>,
)
sealed interface ImageGalleryPage {
data class Folders(val content: Lce<List<Folder>>) : ImageGalleryPage
data class Files(val content: Lce<List<Media>>) : ImageGalleryPage
object Routes {
val folders = Route<Folders>("Folders")
val files = Route<Files>("Files")
}
}
sealed interface ImageGalleryEvent

View File

@ -9,6 +9,7 @@
android:windowSoftInputMode="adjustResize"/>
<activity android:name=".roomsettings.RoomSettingsActivity"/>
<activity android:name=".gallery.ImageGalleryActivity"/>
</application>

View File

@ -5,16 +5,16 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.Parcelable
import android.widget.Toast
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Surface
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.Modifier
import app.dapk.st.core.DapkActivity
import app.dapk.st.core.*
import app.dapk.st.core.extensions.unsafeLazy
import app.dapk.st.core.module
import app.dapk.st.core.viewModel
import app.dapk.st.matrix.common.RoomId
import app.dapk.st.messenger.gallery.GetImageFromGallery
import app.dapk.st.navigator.MessageAttachment
import kotlinx.parcelize.Parcelize
@ -51,10 +51,25 @@ class MessengerActivity : DapkActivity() {
super.onCreate(savedInstanceState)
val payload = readPayload<MessagerActivityPayload>()
val factory = module.decryptingFetcherFactory(RoomId(payload.roomId))
val galleryLauncher = registerForActivityResult(GetImageFromGallery()) {
it?.let { uri ->
viewModel.post(
MessengerAction.ComposerImageUpdate(
MessageAttachment(
AndroidUri(it.toString()),
MimeType.Image,
)
)
)
}
}
setContent {
Surface(Modifier.fillMaxSize()) {
CompositionLocalProvider(LocalDecyptingFetcherFactory provides factory) {
MessengerScreen(RoomId(payload.roomId), payload.attachments, viewModel, navigator)
MessengerScreen(RoomId(payload.roomId), payload.attachments, viewModel, navigator, galleryLauncher)
}
}
}

View File

@ -1,9 +1,11 @@
package app.dapk.st.messenger
import android.content.res.Configuration
import androidx.activity.result.ActivityResultLauncher
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.*
import androidx.compose.foundation.shape.CircleShape
@ -11,9 +13,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Send
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
@ -47,10 +47,16 @@ import coil.request.ImageRequest
import kotlinx.coroutines.launch
@Composable
internal fun MessengerScreen(roomId: RoomId, attachments: List<MessageAttachment>?, viewModel: MessengerViewModel, navigator: Navigator) {
internal fun MessengerScreen(
roomId: RoomId,
attachments: List<MessageAttachment>?,
viewModel: MessengerViewModel,
navigator: Navigator,
galleryLauncher: ActivityResultLauncher<*>
) {
val state = viewModel.state
viewModel.ObserveEvents()
viewModel.ObserveEvents(galleryLauncher)
LifecycleEffect(
onStart = { viewModel.post(MessengerAction.OnMessengerVisible(roomId, attachments)) },
onStop = { viewModel.post(MessengerAction.OnMessengerGone) }
@ -74,6 +80,7 @@ internal fun MessengerScreen(roomId: RoomId, attachments: List<MessageAttachment
state.composerState,
onTextChange = { viewModel.post(MessengerAction.ComposerTextUpdate(it)) },
onSend = { viewModel.post(MessengerAction.ComposerSendText) },
onAttach = { viewModel.startAttachment() }
)
}
@ -89,10 +96,12 @@ internal fun MessengerScreen(roomId: RoomId, attachments: List<MessageAttachment
}
@Composable
private fun MessengerViewModel.ObserveEvents() {
private fun MessengerViewModel.ObserveEvents(galleryLauncher: ActivityResultLauncher<*>) {
StartObserving {
this@ObserveEvents.events.launch {
// TODO()
when (it) {
MessengerEvent.SelectImageAttachment -> galleryLauncher.launch(null)
}
}
}
}
@ -553,7 +562,7 @@ private fun RowScope.SendStatus(message: RoomEvent) {
}
@Composable
private fun TextComposer(state: ComposerState.Text, onTextChange: (String) -> Unit, onSend: () -> Unit) {
private fun TextComposer(state: ComposerState.Text, onTextChange: (String) -> Unit, onSend: () -> Unit, onAttach: () -> Unit) {
Row(
Modifier
.fillMaxWidth()
@ -579,7 +588,16 @@ private fun TextComposer(state: ComposerState.Text, onTextChange: (String) -> Un
onValueChange = { onTextChange(it) },
cursorBrush = SolidColor(MaterialTheme.colorScheme.primary),
textStyle = LocalTextStyle.current.copy(color = SmallTalkTheme.extendedColors.onOthersBubble),
keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences, autoCorrect = true)
keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences, autoCorrect = true),
decorationBox = {
Box {
Icon(
modifier = Modifier.align(Alignment.CenterEnd).clickable { onAttach() },
imageVector = Icons.Filled.Image,
contentDescription = "",
)
}
}
)
}
}

View File

@ -10,7 +10,9 @@ data class MessengerScreenState(
val composerState: ComposerState,
)
sealed interface MessengerEvent
sealed interface MessengerEvent {
object SelectImageAttachment : MessengerEvent
}
sealed interface ComposerState {

View File

@ -48,6 +48,7 @@ internal class MessengerViewModel(
is MessengerAction.ComposerTextUpdate -> updateState { copy(composerState = ComposerState.Text(action.newValue)) }
MessengerAction.ComposerSendText -> sendMessage()
MessengerAction.ComposerClear -> updateState { copy(composerState = ComposerState.Text("")) }
is MessengerAction.ComposerImageUpdate -> updateState { copy(composerState = ComposerState.Attachments(listOf(action.newValue))) }
}
}
@ -100,6 +101,7 @@ internal class MessengerViewModel(
}
}
}
is ComposerState.Attachments -> {
val copy = composerState.copy()
updateState { copy(composerState = ComposerState.Text("")) }
@ -123,6 +125,10 @@ internal class MessengerViewModel(
}
}
fun startAttachment() {
_events.tryEmit(MessengerEvent.SelectImageAttachment)
}
}
private fun MessengerState.latestMessageEventFromOthers(self: UserId) = this.roomState.events
@ -133,6 +139,7 @@ private fun MessengerState.latestMessageEventFromOthers(self: UserId) = this.roo
sealed interface MessengerAction {
data class ComposerTextUpdate(val newValue: String) : MessengerAction
data class ComposerImageUpdate(val newValue: MessageAttachment) : MessengerAction
object ComposerSendText : MessengerAction
object ComposerClear : MessengerAction
data class OnMessengerVisible(val roomId: RoomId, val attachments: List<MessageAttachment>?) : MessengerAction

View File

@ -1,4 +1,4 @@
package app.dapk.st.home.gallery
package app.dapk.st.messenger.gallery
import android.content.ContentResolver
import android.content.ContentUris

View File

@ -1,4 +1,4 @@
package app.dapk.st.home.gallery
package app.dapk.st.messenger.gallery
import android.Manifest
import android.app.Activity
@ -15,7 +15,6 @@ import androidx.lifecycle.lifecycleScope
import app.dapk.st.core.DapkActivity
import app.dapk.st.core.Lce
import app.dapk.st.core.PermissionResult
import app.dapk.st.home.ImageGalleryScreen
import kotlinx.coroutines.launch
class ImageGalleryActivity : DapkActivity() {

View File

@ -1,4 +1,4 @@
package app.dapk.st.home
package app.dapk.st.messenger.gallery
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@ -24,9 +24,6 @@ import app.dapk.st.core.components.CenteredLoading
import app.dapk.st.design.components.GenericError
import app.dapk.st.design.components.Spider
import app.dapk.st.design.components.SpiderPage
import app.dapk.st.home.gallery.Folder
import app.dapk.st.home.gallery.ImageGalleryViewModel
import app.dapk.st.home.gallery.Media
import coil.compose.rememberAsyncImagePainter
import coil.request.ImageRequest

View File

@ -1,11 +1,9 @@
package app.dapk.st.home.gallery
package app.dapk.st.messenger.gallery
import androidx.lifecycle.viewModelScope
import app.dapk.st.core.Lce
import app.dapk.st.design.components.Route
import app.dapk.st.design.components.SpiderPage
import app.dapk.st.home.ImageGalleryEvent
import app.dapk.st.home.ImageGalleryPage
import app.dapk.st.home.ImageGalleryState
import app.dapk.st.viewmodel.DapkViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
@ -70,4 +68,21 @@ class ImageGalleryViewModel(
updateState { copy(page = (page as SpiderPage<S>).copy(state = block(page.state))) }
}
}
}
data class ImageGalleryState(
val page: SpiderPage<out ImageGalleryPage>,
)
sealed interface ImageGalleryPage {
data class Folders(val content: Lce<List<Folder>>) : ImageGalleryPage
data class Files(val content: Lce<List<Media>>) : ImageGalleryPage
object Routes {
val folders = Route<Folders>("Folders")
val files = Route<Files>("Files")
}
}
sealed interface ImageGalleryEvent