Merge branch 'develop' into feature/fga/image_loading

This commit is contained in:
ganfra 2023-05-02 15:29:06 +02:00
commit 4b60b14550
182 changed files with 2492 additions and 884 deletions

View file

@ -102,6 +102,7 @@ private fun SheetContent(
// Crashes if sheetContent size is zero
Box(modifier = modifier.size(1.dp))
}
is ActionListState.Target.Success -> {
val actions = target.actions
LazyColumn(
@ -146,5 +147,11 @@ fun SheetContentDarkPreview(@PreviewParameter(ActionListStateProvider::class) st
@Composable
private fun ContentToPreview(state: ActionListState) {
SheetContent(state)
ActionListView(
state = state,
modalBottomSheetState = ModalBottomSheetState(
initialValue = ModalBottomSheetValue.Expanded
),
onActionSelected = { _, _ -> }
)
}

View file

@ -24,4 +24,6 @@ sealed interface MessageComposerEvents {
object CloseSpecialMode : MessageComposerEvents
data class SetMode(val composerMode: MessageComposerMode) : MessageComposerEvents
data class UpdateText(val text: CharSequence) : MessageComposerEvents
object TakePhoto : MessageComposerEvents
}

View file

@ -21,23 +21,37 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.data.StableCharSequence
import io.element.android.libraries.core.data.toStableCharSequence
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.mediapickers.PickerProvider
import io.element.android.libraries.textcomposer.MessageComposerMode
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
class MessageComposerPresenter @Inject constructor(
private val appCoroutineScope: CoroutineScope,
private val room: MatrixRoom
private val room: MatrixRoom,
private val mediaPickerProvider: PickerProvider,
private val featureFlagService: FeatureFlagService,
) : Presenter<MessageComposerState> {
@Composable
override fun present(): MessageComposerState {
val localCoroutineScope = rememberCoroutineScope()
// Example usage of custom pickers
val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker(onResult = { uri ->
Timber.d("Photo saved at $uri")
})
val isFullScreen = rememberSaveable {
mutableStateOf(false)
}
@ -63,9 +77,14 @@ class MessageComposerPresenter @Inject constructor(
text.value = "".toStableCharSequence()
composerMode.setToNormal()
}
is MessageComposerEvents.SendMessage -> appCoroutineScope.sendMessage(event.message, composerMode, text)
is MessageComposerEvents.SetMode -> composerMode.value = event.composerMode
}
MessageComposerEvents.TakePhoto -> localCoroutineScope.launch {
if (featureFlagService.isFeatureEnabled(FeatureFlags.ShowMediaUploadingFlow)) {
cameraPhotoPicker.launch()
}
}}
}
return MessageComposerState(
@ -92,6 +111,7 @@ class MessageComposerPresenter @Inject constructor(
capturedMode.eventId,
text
)
is MessageComposerMode.Quote -> TODO()
is MessageComposerMode.Reply -> room.replyMessage(
capturedMode.eventId,

View file

@ -53,6 +53,9 @@ fun MessageComposerView(
composerMode = state.mode,
onCloseSpecialMode = ::onCloseSpecialMode,
onComposerTextChange = ::onComposerTextChange,
onAddAttachment = {
state.eventSink(MessageComposerEvents.TakePhoto)
},
composerCanSendMessage = state.isSendButtonVisible,
composerText = state.text?.charSequence?.toString(),
isInDarkMode = !ElementTheme.colors.isLight,

View file

@ -80,13 +80,6 @@ class TimelinePresenter @Inject constructor(
.launchIn(this)
}
DisposableEffect(Unit) {
timeline.initialize()
onDispose {
timeline.dispose()
}
}
return TimelineState(
highlightedEventId = highlightedEventId.value,
paginationState = paginationState.value,

View file

@ -99,11 +99,11 @@ fun TimelineView(
itemsIndexed(
items = state.timelineItems,
contentType = { _, timelineItem -> timelineItem.contentType() },
key = { _, timelineItem -> timelineItem.key() },
key = { _, timelineItem -> timelineItem.identifier() },
) { index, timelineItem ->
TimelineItemRow(
timelineItem = timelineItem,
isHighlighted = timelineItem.key() == state.highlightedEventId?.value,
isHighlighted = timelineItem.identifier() == state.highlightedEventId?.value,
onClick = onMessageClicked,
onLongClick = onMessageLongClicked
)
@ -121,21 +121,6 @@ fun TimelineView(
}
}
private fun TimelineItem.key(): String {
return when (this) {
is TimelineItem.Event -> id
is TimelineItem.Virtual -> id
}
}
private fun TimelineItem.contentType(): Int {
// Todo optimize for each subtype
return when (this) {
is TimelineItem.Event -> 0
is TimelineItem.Virtual -> 1
}
}
@Composable
fun TimelineItemRow(
timelineItem: TimelineItem,

View file

@ -25,7 +25,7 @@ internal class CacheInvalidator(private val itemStatesCache: MutableList<Timelin
ListUpdateCallback {
override fun onChanged(position: Int, count: Int, payload: Any?) {
Timber.v("onChanged(position= $position, count= $count")
Timber.d("onChanged(position= $position, count= $count)")
(position until position + count).forEach {
// Invalidate cache
itemStatesCache[it] = null
@ -33,13 +33,13 @@ internal class CacheInvalidator(private val itemStatesCache: MutableList<Timelin
}
override fun onMoved(fromPosition: Int, toPosition: Int) {
Timber.v("onMoved(fromPosition= $fromPosition, toPosition= $toPosition")
Timber.d("onMoved(fromPosition= $fromPosition, toPosition= $toPosition)")
val model = itemStatesCache.removeAt(fromPosition)
itemStatesCache.add(toPosition, model)
}
override fun onInserted(position: Int, count: Int) {
Timber.v("onInserted(position= $position, count= $count")
Timber.d("onInserted(position= $position, count= $count)")
itemStatesCache.invalidateLast()
repeat(count) {
itemStatesCache.add(position, null)
@ -47,7 +47,7 @@ internal class CacheInvalidator(private val itemStatesCache: MutableList<Timelin
}
override fun onRemoved(position: Int, count: Int) {
Timber.v("onRemoved(position= $position, count= $count")
Timber.d("onRemoved(position= $position, count= $count)")
itemStatesCache.invalidateLast()
repeat(count) {
itemStatesCache.removeAt(position)

View file

@ -31,6 +31,11 @@ sealed interface TimelineItem {
is Virtual -> id
}
fun contentType(): String = when (this) {
is Event -> content.type
is Virtual -> model.type
}
@Immutable
data class Virtual(
val id: String,

View file

@ -21,4 +21,6 @@ import org.jsoup.nodes.Document
data class TimelineItemEmoteContent(
override val body: String,
override val htmlDocument: Document?
) : TimelineItemTextBasedContent
) : TimelineItemTextBasedContent {
override val type: String = "TimelineItemEmoteContent"
}

View file

@ -20,4 +20,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecry
data class TimelineItemEncryptedContent(
val data: UnableToDecryptContent.Data
) : TimelineItemEventContent
) : TimelineItemEventContent {
override val type: String = "TimelineItemEncryptedContent"
}

View file

@ -19,4 +19,6 @@ package io.element.android.features.messages.impl.timeline.model.event
import androidx.compose.runtime.Immutable
@Immutable
sealed interface TimelineItemEventContent
sealed interface TimelineItemEventContent {
val type: String
}

View file

@ -23,4 +23,6 @@ data class TimelineItemImageContent(
val mediaRequestData: MediaRequestData,
val blurhash: String?,
val aspectRatio: Float
) : TimelineItemEventContent
) : TimelineItemEventContent{
override val type: String = "TimelineItemImageContent"
}

View file

@ -21,4 +21,6 @@ import org.jsoup.nodes.Document
data class TimelineItemNoticeContent(
override val body: String,
override val htmlDocument: Document?
) : TimelineItemTextBasedContent
) : TimelineItemTextBasedContent {
override val type: String = "TimelineItemNoticeContent"
}

View file

@ -16,4 +16,6 @@
package io.element.android.features.messages.impl.timeline.model.event
object TimelineItemRedactedContent : TimelineItemEventContent
object TimelineItemRedactedContent : TimelineItemEventContent{
override val type: String = "TimelineItemRedactedContent"
}

View file

@ -21,4 +21,6 @@ import org.jsoup.nodes.Document
data class TimelineItemTextContent(
override val body: String,
override val htmlDocument: Document?
) : TimelineItemTextBasedContent
) : TimelineItemTextBasedContent{
override val type: String = "TimelineItemTextContent"
}

View file

@ -16,4 +16,6 @@
package io.element.android.features.messages.impl.timeline.model.event
object TimelineItemUnknownContent : TimelineItemEventContent
object TimelineItemUnknownContent : TimelineItemEventContent {
override val type: String = "TimelineItemUnknownContent"
}

View file

@ -18,4 +18,6 @@ package io.element.android.features.messages.impl.timeline.model.virtual
data class TimelineItemDaySeparatorModel(
val formattedDate: String
) : TimelineItemVirtualModel
) : TimelineItemVirtualModel {
override val type: String = "TimelineItemDaySeparatorModel"
}

View file

@ -16,4 +16,6 @@
package io.element.android.features.messages.impl.timeline.model.virtual
object TimelineItemLoadingModel : TimelineItemVirtualModel
object TimelineItemLoadingModel : TimelineItemVirtualModel {
override val type: String = "TimelineItemLoadingModel"
}

View file

@ -16,4 +16,6 @@
package io.element.android.features.messages.impl.timeline.model.virtual
object TimelineItemReadMarkerModel : TimelineItemVirtualModel
object TimelineItemReadMarkerModel : TimelineItemVirtualModel {
override val type: String = "TimelineItemReadMarkerModel"
}

View file

@ -16,4 +16,6 @@
package io.element.android.features.messages.impl.timeline.model.virtual
object TimelineItemTimelineStartModel : TimelineItemVirtualModel
object TimelineItemTimelineStartModel : TimelineItemVirtualModel {
override val type: String = "TimelineItemTimelineStartModel"
}

View file

@ -16,4 +16,6 @@
package io.element.android.features.messages.impl.timeline.model.virtual
object TimelineItemUnknownVirtualModel : TimelineItemVirtualModel
object TimelineItemUnknownVirtualModel : TimelineItemVirtualModel {
override val type: String = "TimelineItemUnknownVirtualModel"
}

View file

@ -19,4 +19,6 @@ package io.element.android.features.messages.impl.timeline.model.virtual
import androidx.compose.runtime.Immutable
@Immutable
sealed interface TimelineItemVirtualModel
sealed interface TimelineItemVirtualModel {
val type: String
}