mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-02-02 12:16:55 +01:00
Fix some timeline issues and rename EnrichedEvent to TimelineEvent as it's only used in this context.
This commit is contained in:
parent
34e08705dd
commit
b2cdeb87f4
@ -3,7 +3,7 @@ package im.vector.riotredesign.core.extensions
|
|||||||
import android.arch.lifecycle.LifecycleOwner
|
import android.arch.lifecycle.LifecycleOwner
|
||||||
import android.arch.lifecycle.LiveData
|
import android.arch.lifecycle.LiveData
|
||||||
import android.arch.lifecycle.Observer
|
import android.arch.lifecycle.Observer
|
||||||
import im.vector.riotredesign.core.utils.Event
|
import im.vector.riotredesign.core.utils.LiveEvent
|
||||||
import im.vector.riotredesign.core.utils.EventObserver
|
import im.vector.riotredesign.core.utils.EventObserver
|
||||||
|
|
||||||
inline fun <T> LiveData<T>.observeK(owner: LifecycleOwner, crossinline observer: (T?) -> Unit) {
|
inline fun <T> LiveData<T>.observeK(owner: LifecycleOwner, crossinline observer: (T?) -> Unit) {
|
||||||
@ -14,6 +14,6 @@ inline fun <T> LiveData<T>.observeNotNull(owner: LifecycleOwner, crossinline obs
|
|||||||
this.observe(owner, Observer { it?.run(observer) })
|
this.observe(owner, Observer { it?.run(observer) })
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <T> LiveData<Event<T>>.observeEvent(owner: LifecycleOwner, crossinline observer: (T) -> Unit) {
|
inline fun <T> LiveData<LiveEvent<T>>.observeEvent(owner: LifecycleOwner, crossinline observer: (T) -> Unit) {
|
||||||
this.observe(owner, EventObserver { it.run(observer) })
|
this.observe(owner, EventObserver { it.run(observer) })
|
||||||
}
|
}
|
@ -1,6 +0,0 @@
|
|||||||
package im.vector.riotredesign.core.utils
|
|
||||||
|
|
||||||
object Constants {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
package im.vector.riotredesign.core.utils
|
|
||||||
|
|
||||||
import android.os.Binder
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.support.v4.app.BundleCompat
|
|
||||||
import android.support.v4.app.Fragment
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
class FragmentArgumentDelegate<T : Any> : kotlin.properties.ReadWriteProperty<Fragment, T?> {
|
|
||||||
|
|
||||||
var value: T? = null
|
|
||||||
|
|
||||||
override operator fun getValue(thisRef: android.support.v4.app.Fragment, property: kotlin.reflect.KProperty<*>): T? {
|
|
||||||
if (value == null) {
|
|
||||||
val args = thisRef.arguments
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
value = args?.get(property.name) as T?
|
|
||||||
}
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
override operator fun setValue(thisRef: Fragment, property: KProperty<*>, value: T?) {
|
|
||||||
if (value == null) return
|
|
||||||
|
|
||||||
if (thisRef.arguments == null) {
|
|
||||||
thisRef.arguments = Bundle()
|
|
||||||
}
|
|
||||||
val args = thisRef.arguments!!
|
|
||||||
val key = property.name
|
|
||||||
|
|
||||||
when (value) {
|
|
||||||
is String -> args.putString(key, value)
|
|
||||||
is Int -> args.putInt(key, value)
|
|
||||||
is Short -> args.putShort(key, value)
|
|
||||||
is Long -> args.putLong(key, value)
|
|
||||||
is Byte -> args.putByte(key, value)
|
|
||||||
is ByteArray -> args.putByteArray(key, value)
|
|
||||||
is Char -> args.putChar(key, value)
|
|
||||||
is CharArray -> args.putCharArray(key, value)
|
|
||||||
is CharSequence -> args.putCharSequence(key, value)
|
|
||||||
is Float -> args.putFloat(key, value)
|
|
||||||
is Bundle -> args.putBundle(key, value)
|
|
||||||
is Binder -> BundleCompat.putBinder(args, key, value)
|
|
||||||
is android.os.Parcelable -> args.putParcelable(key, value)
|
|
||||||
is java.io.Serializable -> args.putSerializable(key, value)
|
|
||||||
else -> throw IllegalStateException("Type ${value.javaClass.name} of property ${property.name} is not supported")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class UnsafeFragmentArgumentDelegate<T : Any> : kotlin.properties.ReadWriteProperty<Fragment, T> {
|
|
||||||
|
|
||||||
private val innerDelegate = FragmentArgumentDelegate<T>()
|
|
||||||
|
|
||||||
override fun setValue(thisRef: Fragment, property: KProperty<*>, value: T) {
|
|
||||||
innerDelegate.setValue(thisRef, property, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
|
|
||||||
return innerDelegate.getValue(thisRef, property)!!
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -2,7 +2,7 @@ package im.vector.riotredesign.core.utils
|
|||||||
|
|
||||||
import android.arch.lifecycle.Observer
|
import android.arch.lifecycle.Observer
|
||||||
|
|
||||||
open class Event<out T>(private val content: T) {
|
open class LiveEvent<out T>(private val content: T) {
|
||||||
|
|
||||||
var hasBeenHandled = false
|
var hasBeenHandled = false
|
||||||
private set // Allow external read but not write
|
private set // Allow external read but not write
|
||||||
@ -26,13 +26,13 @@ open class Event<out T>(private val content: T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An [Observer] for [Event]s, simplifying the pattern of checking if the [Event]'s content has
|
* An [Observer] for [LiveEvent]s, simplifying the pattern of checking if the [LiveEvent]'s content has
|
||||||
* already been handled.
|
* already been handled.
|
||||||
*
|
*
|
||||||
* [onEventUnhandledContent] is *only* called if the [Event]'s contents has not been handled.
|
* [onEventUnhandledContent] is *only* called if the [LiveEvent]'s contents has not been handled.
|
||||||
*/
|
*/
|
||||||
class EventObserver<T>(private val onEventUnhandledContent: (T) -> Unit) : Observer<Event<T>> {
|
class EventObserver<T>(private val onEventUnhandledContent: (T) -> Unit) : Observer<LiveEvent<T>> {
|
||||||
override fun onChanged(event: Event<T>?) {
|
override fun onChanged(event: LiveEvent<T>?) {
|
||||||
event?.getContentIfNotHandled()?.let { value ->
|
event?.getContentIfNotHandled()?.let { value ->
|
||||||
onEventUnhandledContent(value)
|
onEventUnhandledContent(value)
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ import im.vector.matrix.android.api.Matrix
|
|||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.rx.rx
|
import im.vector.matrix.rx.rx
|
||||||
import im.vector.riotredesign.core.platform.RiotViewModel
|
import im.vector.riotredesign.core.platform.RiotViewModel
|
||||||
import im.vector.riotredesign.core.utils.Event
|
import im.vector.riotredesign.core.utils.LiveEvent
|
||||||
import im.vector.riotredesign.features.home.room.list.RoomSelectionRepository
|
import im.vector.riotredesign.features.home.room.list.RoomSelectionRepository
|
||||||
import io.reactivex.rxkotlin.subscribeBy
|
import io.reactivex.rxkotlin.subscribeBy
|
||||||
import org.koin.android.ext.android.get
|
import org.koin.android.ext.android.get
|
||||||
@ -31,8 +31,8 @@ class HomeActivityViewModel(state: EmptyState,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val _openRoomLiveData = MutableLiveData<Event<String>>()
|
private val _openRoomLiveData = MutableLiveData<LiveEvent<String>>()
|
||||||
val openRoomLiveData: LiveData<Event<String>>
|
val openRoomLiveData: LiveData<LiveEvent<String>>
|
||||||
get() = _openRoomLiveData
|
get() = _openRoomLiveData
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -40,7 +40,7 @@ class HomeActivityViewModel(state: EmptyState,
|
|||||||
if (lastSelectedRoom == null) {
|
if (lastSelectedRoom == null) {
|
||||||
getTheFirstRoomWhenAvailable()
|
getTheFirstRoomWhenAvailable()
|
||||||
} else {
|
} else {
|
||||||
_openRoomLiveData.postValue(Event(lastSelectedRoom))
|
_openRoomLiveData.postValue(LiveEvent(lastSelectedRoom))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ class HomeActivityViewModel(state: EmptyState,
|
|||||||
.subscribeBy {
|
.subscribeBy {
|
||||||
val firstRoom = it.firstOrNull()
|
val firstRoom = it.firstOrNull()
|
||||||
if (firstRoom != null) {
|
if (firstRoom != null) {
|
||||||
_openRoomLiveData.postValue(Event(firstRoom.roomId))
|
_openRoomLiveData.postValue(LiveEvent(firstRoom.roomId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.disposeOnClear()
|
.disposeOnClear()
|
||||||
|
@ -23,7 +23,6 @@ class HomeNavigator {
|
|||||||
if (!addToBackstack && isRoomOpened(roomId)) {
|
if (!addToBackstack && isRoomOpened(roomId)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
currentRoomId = roomId
|
|
||||||
activity?.let {
|
activity?.let {
|
||||||
val args = RoomDetailArgs(roomId, eventId)
|
val args = RoomDetailArgs(roomId, eventId)
|
||||||
val roomDetailFragment = RoomDetailFragment.newInstance(args)
|
val roomDetailFragment = RoomDetailFragment.newInstance(args)
|
||||||
@ -31,6 +30,7 @@ class HomeNavigator {
|
|||||||
if (addToBackstack) {
|
if (addToBackstack) {
|
||||||
it.addFragmentToBackstack(roomDetailFragment, R.id.homeDetailFragmentContainer, roomId)
|
it.addFragmentToBackstack(roomDetailFragment, R.id.homeDetailFragmentContainer, roomId)
|
||||||
} else {
|
} else {
|
||||||
|
currentRoomId = roomId
|
||||||
clearBackStack(it.supportFragmentManager)
|
clearBackStack(it.supportFragmentManager)
|
||||||
it.replaceFragment(roomDetailFragment, R.id.homeDetailFragmentContainer)
|
it.replaceFragment(roomDetailFragment, R.id.homeDetailFragmentContainer)
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ class RoomDetailFragment : RiotFragment(), TimelineEventController.Callback {
|
|||||||
scrollOnNewMessageCallback = ScrollOnNewMessageCallback(layoutManager)
|
scrollOnNewMessageCallback = ScrollOnNewMessageCallback(layoutManager)
|
||||||
recyclerView.layoutManager = layoutManager
|
recyclerView.layoutManager = layoutManager
|
||||||
recyclerView.setHasFixedSize(true)
|
recyclerView.setHasFixedSize(true)
|
||||||
//timelineEventController.addModelBuildListener { it.dispatchTo(scrollOnNewMessageCallback) }
|
timelineEventController.addModelBuildListener { it.dispatchTo(scrollOnNewMessageCallback) }
|
||||||
recyclerView.setController(timelineEventController)
|
recyclerView.setController(timelineEventController)
|
||||||
timelineEventController.callback = this
|
timelineEventController.callback = this
|
||||||
}
|
}
|
||||||
@ -95,8 +95,15 @@ class RoomDetailFragment : RiotFragment(), TimelineEventController.Callback {
|
|||||||
|
|
||||||
private fun renderTimeline(state: RoomDetailViewState) {
|
private fun renderTimeline(state: RoomDetailViewState) {
|
||||||
when (state.asyncTimelineData) {
|
when (state.asyncTimelineData) {
|
||||||
is Success -> timelineEventController.update(state.asyncTimelineData())
|
is Success -> {
|
||||||
|
val timelineData = state.asyncTimelineData()
|
||||||
|
val lockAutoScroll = timelineData?.let {
|
||||||
|
it.events == timelineEventController.currentList && it.isLoadingForward
|
||||||
|
} ?: true
|
||||||
|
|
||||||
|
scrollOnNewMessageCallback.isLocked.set(lockAutoScroll)
|
||||||
|
timelineEventController.update(timelineData)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@ import java.util.concurrent.atomic.AtomicBoolean
|
|||||||
|
|
||||||
class ScrollOnNewMessageCallback(private val layoutManager: LinearLayoutManager) : DefaultListUpdateCallback {
|
class ScrollOnNewMessageCallback(private val layoutManager: LinearLayoutManager) : DefaultListUpdateCallback {
|
||||||
|
|
||||||
val hasBeenUpdated = AtomicBoolean(false)
|
var isLocked = AtomicBoolean(true)
|
||||||
|
|
||||||
override fun onInserted(position: Int, count: Int) {
|
override fun onInserted(position: Int, count: Int) {
|
||||||
if (hasBeenUpdated.compareAndSet(true, false) && position == 0 && layoutManager.findFirstVisibleItemPosition() == 0) {
|
if (isLocked.compareAndSet(false, true) && position == 0 && layoutManager.findFirstVisibleItemPosition() == 0) {
|
||||||
layoutManager.scrollToPosition(0)
|
layoutManager.scrollToPosition(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import android.text.SpannableStringBuilder
|
|||||||
import android.text.util.Linkify
|
import android.text.util.Linkify
|
||||||
import im.vector.matrix.android.api.permalinks.MatrixLinkify
|
import im.vector.matrix.android.api.permalinks.MatrixLinkify
|
||||||
import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
|
import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
|
||||||
import im.vector.matrix.android.api.session.events.model.EnrichedEvent
|
import im.vector.matrix.android.api.session.events.model.TimelineEvent
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
import im.vector.matrix.android.api.session.room.model.MessageContent
|
import im.vector.matrix.android.api.session.room.model.MessageContent
|
||||||
import org.threeten.bp.LocalDateTime
|
import org.threeten.bp.LocalDateTime
|
||||||
@ -13,8 +13,8 @@ class MessageItemFactory(private val timelineDateFormatter: TimelineDateFormatte
|
|||||||
|
|
||||||
private val messagesDisplayedWithInformation = HashSet<String?>()
|
private val messagesDisplayedWithInformation = HashSet<String?>()
|
||||||
|
|
||||||
fun create(event: EnrichedEvent,
|
fun create(event: TimelineEvent,
|
||||||
nextEvent: EnrichedEvent?,
|
nextEvent: TimelineEvent?,
|
||||||
addDaySeparator: Boolean,
|
addDaySeparator: Boolean,
|
||||||
date: LocalDateTime,
|
date: LocalDateTime,
|
||||||
callback: TimelineEventController.Callback?
|
callback: TimelineEventController.Callback?
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package im.vector.riotredesign.features.home.room.detail.timeline
|
package im.vector.riotredesign.features.home.room.detail.timeline
|
||||||
|
|
||||||
import im.vector.matrix.android.api.session.events.model.EnrichedEvent
|
import im.vector.matrix.android.api.session.events.model.TimelineEvent
|
||||||
|
|
||||||
class TextItemFactory {
|
class TextItemFactory {
|
||||||
|
|
||||||
fun create(event: EnrichedEvent): TextItem? {
|
fun create(event: TimelineEvent): TextItem? {
|
||||||
val text = "${event.root.type} events are not yet handled"
|
val text = "${event.root.type} events are not yet handled"
|
||||||
return TextItem(text = text)
|
return TextItem(text = text)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package im.vector.riotredesign.features.home.room.detail.timeline
|
|||||||
|
|
||||||
import com.airbnb.epoxy.EpoxyAsyncUtil
|
import com.airbnb.epoxy.EpoxyAsyncUtil
|
||||||
import com.airbnb.epoxy.EpoxyModel
|
import com.airbnb.epoxy.EpoxyModel
|
||||||
import im.vector.matrix.android.api.session.events.model.EnrichedEvent
|
import im.vector.matrix.android.api.session.events.model.TimelineEvent
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineData
|
import im.vector.matrix.android.api.session.room.timeline.TimelineData
|
||||||
import im.vector.riotredesign.core.extensions.localDateTime
|
import im.vector.riotredesign.core.extensions.localDateTime
|
||||||
@ -13,7 +13,7 @@ class TimelineEventController(private val roomId: String,
|
|||||||
private val messageItemFactory: MessageItemFactory,
|
private val messageItemFactory: MessageItemFactory,
|
||||||
private val textItemFactory: TextItemFactory,
|
private val textItemFactory: TextItemFactory,
|
||||||
private val dateFormatter: TimelineDateFormatter
|
private val dateFormatter: TimelineDateFormatter
|
||||||
) : PagedListEpoxyController<EnrichedEvent>(
|
) : PagedListEpoxyController<TimelineEvent>(
|
||||||
EpoxyAsyncUtil.getAsyncBackgroundHandler(),
|
EpoxyAsyncUtil.getAsyncBackgroundHandler(),
|
||||||
EpoxyAsyncUtil.getAsyncBackgroundHandler()
|
EpoxyAsyncUtil.getAsyncBackgroundHandler()
|
||||||
) {
|
) {
|
||||||
@ -38,7 +38,7 @@ class TimelineEventController(private val roomId: String,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun buildItemModels(currentPosition: Int, items: List<EnrichedEvent?>): List<EpoxyModel<*>> {
|
override fun buildItemModels(currentPosition: Int, items: List<TimelineEvent?>): List<EpoxyModel<*>> {
|
||||||
if (items.isNullOrEmpty()) {
|
if (items.isNullOrEmpty()) {
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,9 @@ abstract class PagedListEpoxyController<T>(
|
|||||||
modelBuildingHandler = modelBuildingHandler
|
modelBuildingHandler = modelBuildingHandler
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var currentList: PagedList<T>? = null
|
||||||
|
private set
|
||||||
|
|
||||||
final override fun buildModels() {
|
final override fun buildModels() {
|
||||||
addModels(modelCache.getModels())
|
addModels(modelCache.getModels())
|
||||||
}
|
}
|
||||||
@ -107,6 +110,7 @@ abstract class PagedListEpoxyController<T>(
|
|||||||
* to [buildItemModel] with items from the previous list.
|
* to [buildItemModel] with items from the previous list.
|
||||||
*/
|
*/
|
||||||
fun submitList(newList: PagedList<T>?) {
|
fun submitList(newList: PagedList<T>?) {
|
||||||
|
currentList = newList
|
||||||
modelCache.submitList(newList)
|
modelCache.submitList(newList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import im.vector.matrix.android.InstrumentedTest
|
|||||||
import im.vector.matrix.android.LiveDataTestObserver
|
import im.vector.matrix.android.LiveDataTestObserver
|
||||||
import im.vector.matrix.android.api.thread.MainThreadExecutor
|
import im.vector.matrix.android.api.thread.MainThreadExecutor
|
||||||
import im.vector.matrix.android.internal.session.room.members.RoomMemberExtractor
|
import im.vector.matrix.android.internal.session.room.members.RoomMemberExtractor
|
||||||
import im.vector.matrix.android.internal.session.room.timeline.DefaultTimelineHolder
|
import im.vector.matrix.android.internal.session.room.timeline.DefaultTimelineService
|
||||||
import im.vector.matrix.android.internal.session.room.timeline.TimelineBoundaryCallback
|
import im.vector.matrix.android.internal.session.room.timeline.TimelineBoundaryCallback
|
||||||
import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEventPersistor
|
import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEventPersistor
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
@ -44,17 +44,17 @@ internal class TimelineHolderTest : InstrumentedTest {
|
|||||||
val boundaryCallback = TimelineBoundaryCallback(roomId, taskExecutor, paginationTask, monarchy, PagingRequestHelper(MainThreadExecutor()))
|
val boundaryCallback = TimelineBoundaryCallback(roomId, taskExecutor, paginationTask, monarchy, PagingRequestHelper(MainThreadExecutor()))
|
||||||
|
|
||||||
RoomDataHelper.fakeInitialSync(monarchy, roomId)
|
RoomDataHelper.fakeInitialSync(monarchy, roomId)
|
||||||
val timelineHolder = DefaultTimelineHolder(roomId, monarchy, taskExecutor, boundaryCallback, getContextOfEventTask, RoomMemberExtractor(monarchy, roomId))
|
val timelineHolder = DefaultTimelineService(roomId, monarchy, taskExecutor, boundaryCallback, getContextOfEventTask, RoomMemberExtractor(monarchy, roomId))
|
||||||
val timelineObserver = LiveDataTestObserver.test(timelineHolder.timeline())
|
val timelineObserver = LiveDataTestObserver.test(timelineHolder.timeline())
|
||||||
timelineObserver.awaitNextValue().assertHasValue()
|
timelineObserver.awaitNextValue().assertHasValue()
|
||||||
var pagedList = timelineObserver.value()
|
var timelineData = timelineObserver.value()
|
||||||
pagedList.size shouldEqual 30
|
timelineData.events.size shouldEqual 30
|
||||||
(0 until pagedList.size).map {
|
(0 until timelineData.events.size).map {
|
||||||
pagedList.loadAround(it)
|
timelineData.events.loadAround(it)
|
||||||
}
|
}
|
||||||
timelineObserver.awaitNextValue().assertHasValue()
|
timelineObserver.awaitNextValue().assertHasValue()
|
||||||
pagedList = timelineObserver.value()
|
timelineData = timelineObserver.value()
|
||||||
pagedList.size shouldEqual 60
|
timelineData.events.size shouldEqual 60
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,4 +15,12 @@ interface Session : RoomService, GroupService {
|
|||||||
@MainThread
|
@MainThread
|
||||||
fun close()
|
fun close()
|
||||||
|
|
||||||
|
fun addListener(listener: Listener)
|
||||||
|
|
||||||
|
fun removeListener(listener: Listener)
|
||||||
|
|
||||||
|
// Not used at the moment
|
||||||
|
interface Listener
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,12 +0,0 @@
|
|||||||
package im.vector.matrix.android.api.session.events.interceptor
|
|
||||||
|
|
||||||
import im.vector.matrix.android.api.session.events.model.EnrichedEvent
|
|
||||||
|
|
||||||
interface EnrichedEventInterceptor {
|
|
||||||
|
|
||||||
fun canEnrich(event: EnrichedEvent): Boolean
|
|
||||||
|
|
||||||
fun enrich(event: EnrichedEvent)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
|||||||
|
package im.vector.matrix.android.api.session.events.interceptor
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.events.model.TimelineEvent
|
||||||
|
|
||||||
|
interface TimelineEventInterceptor {
|
||||||
|
|
||||||
|
fun canEnrich(event: TimelineEvent): Boolean
|
||||||
|
|
||||||
|
fun enrich(event: TimelineEvent)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ package im.vector.matrix.android.api.session.events.model
|
|||||||
|
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||||
|
|
||||||
data class EnrichedEvent(
|
data class TimelineEvent(
|
||||||
val root: Event,
|
val root: Event,
|
||||||
val localId: String,
|
val localId: String,
|
||||||
val roomMember: RoomMember?
|
val roomMember: RoomMember?
|
@ -1,10 +1,10 @@
|
|||||||
package im.vector.matrix.android.api.session.room.timeline
|
package im.vector.matrix.android.api.session.room.timeline
|
||||||
|
|
||||||
import android.arch.paging.PagedList
|
import android.arch.paging.PagedList
|
||||||
import im.vector.matrix.android.api.session.events.model.EnrichedEvent
|
import im.vector.matrix.android.api.session.events.model.TimelineEvent
|
||||||
|
|
||||||
data class TimelineData(
|
data class TimelineData(
|
||||||
val events: PagedList<EnrichedEvent>,
|
val events: PagedList<TimelineEvent>,
|
||||||
val isLoadingForward: Boolean = false,
|
val isLoadingForward: Boolean = false,
|
||||||
val isLoadingBackward: Boolean = false
|
val isLoadingBackward: Boolean = false
|
||||||
)
|
)
|
||||||
|
@ -4,7 +4,6 @@ import android.arch.lifecycle.LiveData
|
|||||||
import android.arch.lifecycle.Observer
|
import android.arch.lifecycle.Observer
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
import io.realm.RealmResults
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
internal interface LiveEntityObserver {
|
internal interface LiveEntityObserver {
|
||||||
@ -39,11 +38,15 @@ internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val m
|
|||||||
if (changeSet == null) {
|
if (changeSet == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val updateIndexes = changeSet.orderedCollectionChangeSet.changes + changeSet.orderedCollectionChangeSet.insertions
|
val insertionIndexes = changeSet.orderedCollectionChangeSet.insertions
|
||||||
|
val updateIndexes = changeSet.orderedCollectionChangeSet.changes
|
||||||
val deletionIndexes = changeSet.orderedCollectionChangeSet.deletions
|
val deletionIndexes = changeSet.orderedCollectionChangeSet.deletions
|
||||||
process(changeSet.realmResults, updateIndexes, deletionIndexes)
|
val inserted = changeSet.realmResults.filterIndexed { index, _ -> insertionIndexes.contains(index) }
|
||||||
|
val updated = changeSet.realmResults.filterIndexed { index, _ -> updateIndexes.contains(index) }
|
||||||
|
val deleted = changeSet.realmResults.filterIndexed { index, _ -> deletionIndexes.contains(index) }
|
||||||
|
process(inserted, updated, deleted)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun process(results: RealmResults<T>, updateIndexes: IntArray, deletionIndexes: IntArray)
|
abstract fun process(inserted: List<T>, updated: List<T>, deleted: List<T>)
|
||||||
|
|
||||||
}
|
}
|
@ -26,12 +26,13 @@ internal fun EventEntity.Companion.where(realm: Realm,
|
|||||||
query.equalTo(EventEntityFields.TYPE, type)
|
query.equalTo(EventEntityFields.TYPE, type)
|
||||||
}
|
}
|
||||||
return when (linkFilterMode) {
|
return when (linkFilterMode) {
|
||||||
LINKED_ONLY -> query.equalTo(EventEntityFields.IS_UNLINKED, false)
|
LINKED_ONLY -> query.equalTo(EventEntityFields.IS_UNLINKED, false)
|
||||||
UNLINKED_ONLY -> query.equalTo(EventEntityFields.IS_UNLINKED, true)
|
UNLINKED_ONLY -> query.equalTo(EventEntityFields.IS_UNLINKED, true)
|
||||||
BOTH -> query
|
BOTH -> query
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun RealmQuery<EventEntity>.next(from: Int? = null, strict: Boolean = true): EventEntity? {
|
internal fun RealmQuery<EventEntity>.next(from: Int? = null, strict: Boolean = true): EventEntity? {
|
||||||
if (from != null) {
|
if (from != null) {
|
||||||
if (strict) {
|
if (strict) {
|
||||||
|
@ -31,6 +31,7 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi
|
|||||||
private lateinit var scope: Scope
|
private lateinit var scope: Scope
|
||||||
|
|
||||||
private val liveEntityUpdaters by inject<List<LiveEntityObserver>>()
|
private val liveEntityUpdaters by inject<List<LiveEntityObserver>>()
|
||||||
|
private val sessionListeners by inject<SessionListeners>()
|
||||||
private val roomService by inject<RoomService>()
|
private val roomService by inject<RoomService>()
|
||||||
private val groupService by inject<GroupService>()
|
private val groupService by inject<GroupService>()
|
||||||
private val syncThread by inject<SyncThread>()
|
private val syncThread by inject<SyncThread>()
|
||||||
@ -62,6 +63,14 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi
|
|||||||
isOpen = false
|
isOpen = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun addListener(listener: Session.Listener) {
|
||||||
|
sessionListeners.addListener(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeListener(listener: Session.Listener) {
|
||||||
|
sessionListeners.removeListener(listener)
|
||||||
|
}
|
||||||
|
|
||||||
// ROOM SERVICE
|
// ROOM SERVICE
|
||||||
|
|
||||||
override fun getRoom(roomId: String): Room? {
|
override fun getRoom(roomId: String): Room? {
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package im.vector.matrix.android.internal.session
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
|
||||||
|
internal class SessionListeners {
|
||||||
|
|
||||||
|
private val listeners = ArrayList<Session.Listener>()
|
||||||
|
|
||||||
|
fun addListener(listener: Session.Listener) {
|
||||||
|
listeners.add(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeListener(listener: Session.Listener) {
|
||||||
|
listeners.remove(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -6,7 +6,6 @@ import im.vector.matrix.android.api.auth.data.SessionParams
|
|||||||
import im.vector.matrix.android.api.session.group.GroupService
|
import im.vector.matrix.android.api.session.group.GroupService
|
||||||
import im.vector.matrix.android.api.session.room.RoomService
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
import im.vector.matrix.android.internal.database.LiveEntityObserver
|
import im.vector.matrix.android.internal.database.LiveEntityObserver
|
||||||
import im.vector.matrix.android.internal.session.room.prune.EventsPruner
|
|
||||||
import im.vector.matrix.android.internal.session.group.DefaultGroupService
|
import im.vector.matrix.android.internal.session.group.DefaultGroupService
|
||||||
import im.vector.matrix.android.internal.session.group.GroupSummaryUpdater
|
import im.vector.matrix.android.internal.session.group.GroupSummaryUpdater
|
||||||
import im.vector.matrix.android.internal.session.room.DefaultRoomService
|
import im.vector.matrix.android.internal.session.room.DefaultRoomService
|
||||||
@ -14,6 +13,7 @@ import im.vector.matrix.android.internal.session.room.RoomAvatarResolver
|
|||||||
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
|
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
|
||||||
import im.vector.matrix.android.internal.session.room.members.RoomDisplayNameResolver
|
import im.vector.matrix.android.internal.session.room.members.RoomDisplayNameResolver
|
||||||
import im.vector.matrix.android.internal.session.room.members.RoomMemberDisplayNameResolver
|
import im.vector.matrix.android.internal.session.room.members.RoomMemberDisplayNameResolver
|
||||||
|
import im.vector.matrix.android.internal.session.room.prune.EventsPruner
|
||||||
import im.vector.matrix.android.internal.util.md5
|
import im.vector.matrix.android.internal.util.md5
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
import org.koin.dsl.module.module
|
import org.koin.dsl.module.module
|
||||||
@ -75,7 +75,10 @@ internal class SessionModule(private val sessionParams: SessionParams) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scope(DefaultSession.SCOPE) {
|
scope(DefaultSession.SCOPE) {
|
||||||
|
SessionListeners()
|
||||||
|
}
|
||||||
|
|
||||||
|
scope(DefaultSession.SCOPE) {
|
||||||
val roomSummaryUpdater = RoomSummaryUpdater(get(), get(), get(), get(), sessionParams.credentials)
|
val roomSummaryUpdater = RoomSummaryUpdater(get(), get(), get(), get(), sessionParams.credentials)
|
||||||
val groupSummaryUpdater = GroupSummaryUpdater(get())
|
val groupSummaryUpdater = GroupSummaryUpdater(get())
|
||||||
val eventsPruner = EventsPruner(get())
|
val eventsPruner = EventsPruner(get())
|
||||||
|
@ -15,9 +15,7 @@ internal class GetGroupDataWorker(context: Context,
|
|||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
internal data class Params(
|
internal data class Params(
|
||||||
val groupIds: List<String>,
|
val groupIds: List<String>
|
||||||
val updateIndexes: List<Int>,
|
|
||||||
val deletionIndexes: List<Int>
|
|
||||||
)
|
)
|
||||||
|
|
||||||
private val getGroupDataTask by inject<GetGroupDataTask>()
|
private val getGroupDataTask by inject<GetGroupDataTask>()
|
||||||
@ -26,8 +24,7 @@ internal class GetGroupDataWorker(context: Context,
|
|||||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||||
?: return Result.failure()
|
?: return Result.failure()
|
||||||
|
|
||||||
val results = params.updateIndexes.map { index ->
|
val results = params.groupIds.map { groupId ->
|
||||||
val groupId = params.groupIds[index]
|
|
||||||
fetchGroupData(groupId)
|
fetchGroupData(groupId)
|
||||||
}
|
}
|
||||||
val isSuccessful = results.none { it.isFailure() }
|
val isSuccessful = results.none { it.isFailure() }
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package im.vector.matrix.android.internal.session.group
|
package im.vector.matrix.android.internal.session.group
|
||||||
|
|
||||||
import androidx.work.*
|
import androidx.work.Constraints
|
||||||
|
import androidx.work.ExistingWorkPolicy
|
||||||
|
import androidx.work.NetworkType
|
||||||
|
import androidx.work.OneTimeWorkRequestBuilder
|
||||||
|
import androidx.work.WorkManager
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
||||||
import im.vector.matrix.android.internal.database.model.GroupEntity
|
import im.vector.matrix.android.internal.database.model.GroupEntity
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.util.WorkerParamsFactory
|
import im.vector.matrix.android.internal.util.WorkerParamsFactory
|
||||||
import io.realm.RealmResults
|
|
||||||
|
|
||||||
private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER"
|
private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER"
|
||||||
|
|
||||||
@ -19,9 +22,9 @@ internal class GroupSummaryUpdater(monarchy: Monarchy
|
|||||||
.setRequiredNetworkType(NetworkType.CONNECTED)
|
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
override fun process(results: RealmResults<GroupEntity>, updateIndexes: IntArray, deletionIndexes: IntArray) {
|
override fun process(inserted: List<GroupEntity>, updated: List<GroupEntity>, deleted: List<GroupEntity>) {
|
||||||
val groupIds = results.map { it.groupId }
|
val newGroupIds = inserted.map { it.groupId }
|
||||||
val getGroupDataWorkerParams = GetGroupDataWorker.Params(groupIds, updateIndexes.toList(), deletionIndexes.toList())
|
val getGroupDataWorkerParams = GetGroupDataWorker.Params(newGroupIds)
|
||||||
val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams)
|
val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams)
|
||||||
|
|
||||||
val sendWork = OneTimeWorkRequestBuilder<GetGroupDataWorker>()
|
val sendWork = OneTimeWorkRequestBuilder<GetGroupDataWorker>()
|
||||||
|
@ -2,24 +2,23 @@ package im.vector.matrix.android.internal.session.room
|
|||||||
|
|
||||||
import android.arch.lifecycle.LiveData
|
import android.arch.lifecycle.LiveData
|
||||||
import android.arch.lifecycle.Transformations
|
import android.arch.lifecycle.Transformations
|
||||||
import android.arch.paging.PagedList
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.session.events.model.EnrichedEvent
|
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.room.Room
|
import im.vector.matrix.android.api.session.room.Room
|
||||||
import im.vector.matrix.android.api.session.room.SendService
|
import im.vector.matrix.android.api.session.room.SendService
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineService
|
|
||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.api.session.room.model.MyMembership
|
import im.vector.matrix.android.api.session.room.model.MyMembership
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineData
|
import im.vector.matrix.android.api.session.room.timeline.TimelineData
|
||||||
|
import im.vector.matrix.android.api.session.room.timeline.TimelineService
|
||||||
import im.vector.matrix.android.api.util.Cancelable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
import im.vector.matrix.android.internal.database.mapper.asDomain
|
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.di.MatrixKoinComponent
|
import im.vector.matrix.android.internal.di.MatrixKoinComponent
|
||||||
|
import im.vector.matrix.android.internal.session.SessionListeners
|
||||||
import im.vector.matrix.android.internal.session.room.members.LoadRoomMembersTask
|
import im.vector.matrix.android.internal.session.room.members.LoadRoomMembersTask
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
@ -62,4 +61,5 @@ internal data class DefaultRoom(
|
|||||||
return sendService.sendTextMessage(text, callback)
|
return sendService.sendTextMessage(text, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -17,7 +17,6 @@ import im.vector.matrix.android.internal.database.query.where
|
|||||||
import im.vector.matrix.android.internal.session.room.members.RoomDisplayNameResolver
|
import im.vector.matrix.android.internal.session.room.members.RoomDisplayNameResolver
|
||||||
import im.vector.matrix.android.internal.session.room.members.RoomMembers
|
import im.vector.matrix.android.internal.session.room.members.RoomMembers
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmResults
|
|
||||||
import io.realm.kotlin.createObject
|
import io.realm.kotlin.createObject
|
||||||
|
|
||||||
internal class RoomSummaryUpdater(monarchy: Monarchy,
|
internal class RoomSummaryUpdater(monarchy: Monarchy,
|
||||||
@ -29,13 +28,10 @@ internal class RoomSummaryUpdater(monarchy: Monarchy,
|
|||||||
|
|
||||||
override val query = Monarchy.Query<RoomEntity> { RoomEntity.where(it) }
|
override val query = Monarchy.Query<RoomEntity> { RoomEntity.where(it) }
|
||||||
|
|
||||||
override fun process(results: RealmResults<RoomEntity>, updateIndexes: IntArray, deletionIndexes: IntArray) {
|
override fun process(inserted: List<RoomEntity>, updated: List<RoomEntity>, deleted: List<RoomEntity>) {
|
||||||
val rooms = results.map { it.asDomain() }
|
val rooms = (inserted + updated).map { it.asDomain() }
|
||||||
monarchy.writeAsync { realm ->
|
monarchy.writeAsync { realm ->
|
||||||
updateIndexes.forEach { index ->
|
rooms.forEach { updateRoom(realm, it) }
|
||||||
val data = rooms[index]
|
|
||||||
updateRoom(realm, data)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import im.vector.matrix.android.internal.database.mapper.asDomain
|
|||||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.util.WorkerParamsFactory
|
import im.vector.matrix.android.internal.util.WorkerParamsFactory
|
||||||
import io.realm.RealmResults
|
|
||||||
|
|
||||||
private const val PRUNE_EVENT_WORKER = "PRUNE_EVENT_WORKER"
|
private const val PRUNE_EVENT_WORKER = "PRUNE_EVENT_WORKER"
|
||||||
|
|
||||||
@ -19,9 +18,9 @@ internal class EventsPruner(monarchy: Monarchy) :
|
|||||||
|
|
||||||
override val query = Monarchy.Query<EventEntity> { EventEntity.where(it, type = EventType.REDACTION) }
|
override val query = Monarchy.Query<EventEntity> { EventEntity.where(it, type = EventType.REDACTION) }
|
||||||
|
|
||||||
override fun process(results: RealmResults<EventEntity>, updateIndexes: IntArray, deletionIndexes: IntArray) {
|
override fun process(inserted: List<EventEntity>, updated: List<EventEntity>, deleted: List<EventEntity>) {
|
||||||
val redactionEvents = results.map { it.asDomain() }
|
val redactionEvents = inserted.map { it.asDomain() }
|
||||||
val pruneEventWorkerParams = PruneEventWorker.Params(redactionEvents, updateIndexes.toList(), deletionIndexes.toList())
|
val pruneEventWorkerParams = PruneEventWorker.Params(redactionEvents)
|
||||||
val workData = WorkerParamsFactory.toData(pruneEventWorkerParams)
|
val workData = WorkerParamsFactory.toData(pruneEventWorkerParams)
|
||||||
|
|
||||||
val sendWork = OneTimeWorkRequestBuilder<PruneEventWorker>()
|
val sendWork = OneTimeWorkRequestBuilder<PruneEventWorker>()
|
||||||
|
@ -13,6 +13,7 @@ import im.vector.matrix.android.internal.database.query.where
|
|||||||
import im.vector.matrix.android.internal.di.MatrixKoinComponent
|
import im.vector.matrix.android.internal.di.MatrixKoinComponent
|
||||||
import im.vector.matrix.android.internal.util.WorkerParamsFactory
|
import im.vector.matrix.android.internal.util.WorkerParamsFactory
|
||||||
import im.vector.matrix.android.internal.util.tryTransactionAsync
|
import im.vector.matrix.android.internal.util.tryTransactionAsync
|
||||||
|
import im.vector.matrix.android.internal.util.tryTransactionSync
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import org.koin.standalone.inject
|
import org.koin.standalone.inject
|
||||||
|
|
||||||
@ -22,9 +23,7 @@ internal class PruneEventWorker(context: Context,
|
|||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
internal data class Params(
|
internal data class Params(
|
||||||
val redactionEvents: List<Event>,
|
val redactionEvents: List<Event>
|
||||||
val updateIndexes: List<Int>,
|
|
||||||
val deletionIndexes: List<Int>
|
|
||||||
)
|
)
|
||||||
|
|
||||||
private val monarchy by inject<Monarchy>()
|
private val monarchy by inject<Monarchy>()
|
||||||
@ -33,10 +32,9 @@ internal class PruneEventWorker(context: Context,
|
|||||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||||
?: return Result.failure()
|
?: return Result.failure()
|
||||||
|
|
||||||
val result = monarchy.tryTransactionAsync { realm ->
|
val result = monarchy.tryTransactionSync { realm ->
|
||||||
params.updateIndexes.forEach { index ->
|
params.redactionEvents.forEach { event ->
|
||||||
val data = params.redactionEvents[index]
|
pruneEvent(realm, event)
|
||||||
pruneEvent(realm, data)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result.fold({ Result.retry() }, { Result.success() })
|
return result.fold({ Result.retry() }, { Result.success() })
|
||||||
|
@ -4,8 +4,8 @@ import android.arch.lifecycle.LiveData
|
|||||||
import android.arch.paging.LivePagedListBuilder
|
import android.arch.paging.LivePagedListBuilder
|
||||||
import android.arch.paging.PagedList
|
import android.arch.paging.PagedList
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.session.events.interceptor.EnrichedEventInterceptor
|
import im.vector.matrix.android.api.session.events.interceptor.TimelineEventInterceptor
|
||||||
import im.vector.matrix.android.api.session.events.model.EnrichedEvent
|
import im.vector.matrix.android.api.session.events.model.TimelineEvent
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineData
|
import im.vector.matrix.android.api.session.room.timeline.TimelineData
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineService
|
import im.vector.matrix.android.api.session.room.timeline.TimelineService
|
||||||
import im.vector.matrix.android.internal.database.mapper.asDomain
|
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||||
@ -34,35 +34,21 @@ internal class DefaultTimelineService(private val roomId: String,
|
|||||||
private val roomMemberExtractor: RoomMemberExtractor
|
private val roomMemberExtractor: RoomMemberExtractor
|
||||||
) : TimelineService {
|
) : TimelineService {
|
||||||
|
|
||||||
private val eventInterceptors = ArrayList<EnrichedEventInterceptor>()
|
private val eventInterceptors = ArrayList<TimelineEventInterceptor>()
|
||||||
|
|
||||||
override fun timeline(eventId: String?): LiveData<TimelineData> {
|
override fun timeline(eventId: String?): LiveData<TimelineData> {
|
||||||
clearUnlinkedEvents()
|
clearUnlinkedEvents()
|
||||||
var initialLoadKey = 0
|
val initialLoadKey = getInitialLoadKey(eventId)
|
||||||
if (eventId != null) {
|
|
||||||
val indexOfEvent = indexOfEvent(eventId)
|
|
||||||
if (indexOfEvent == EVENT_NOT_FOUND_INDEX) {
|
|
||||||
val params = GetContextOfEventTask.Params(roomId, eventId)
|
|
||||||
contextOfEventTask.configureWith(params).executeBy(taskExecutor)
|
|
||||||
} else {
|
|
||||||
initialLoadKey = indexOfEvent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val realmDataSourceFactory = monarchy.createDataSourceFactory {
|
val realmDataSourceFactory = monarchy.createDataSourceFactory {
|
||||||
buildDataSourceFactoryQuery(it, eventId)
|
buildDataSourceFactoryQuery(it, eventId)
|
||||||
}
|
}
|
||||||
val domainSourceFactory = realmDataSourceFactory
|
val domainSourceFactory = realmDataSourceFactory
|
||||||
.map { eventEntity ->
|
.map { eventEntity ->
|
||||||
val roomMember = roomMemberExtractor.extractFrom(eventEntity)
|
val roomMember = roomMemberExtractor.extractFrom(eventEntity)
|
||||||
EnrichedEvent(eventEntity.asDomain(), eventEntity.localId, roomMember)
|
TimelineEvent(eventEntity.asDomain(), eventEntity.localId, roomMember)
|
||||||
}
|
}
|
||||||
|
|
||||||
val pagedListConfig = PagedList.Config.Builder()
|
val pagedListConfig = buildPagedListConfig()
|
||||||
.setEnablePlaceholders(false)
|
|
||||||
.setPageSize(PAGE_SIZE)
|
|
||||||
.setInitialLoadSizeHint(2 * PAGE_SIZE)
|
|
||||||
.setPrefetchDistance(PREFETCH_DISTANCE)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val livePagedListBuilder = LivePagedListBuilder(domainSourceFactory, pagedListConfig)
|
val livePagedListBuilder = LivePagedListBuilder(domainSourceFactory, pagedListConfig)
|
||||||
.setBoundaryCallback(boundaryCallback)
|
.setBoundaryCallback(boundaryCallback)
|
||||||
@ -77,6 +63,35 @@ internal class DefaultTimelineService(private val roomId: String,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PRIVATE FUNCTIONS ***************************************************************************
|
||||||
|
|
||||||
|
private fun getInitialLoadKey(eventId: String?): Int {
|
||||||
|
var initialLoadKey = 0
|
||||||
|
if (eventId != null) {
|
||||||
|
val indexOfEvent = indexOfEvent(eventId)
|
||||||
|
if (indexOfEvent == EVENT_NOT_FOUND_INDEX) {
|
||||||
|
fetchEvent(eventId)
|
||||||
|
} else {
|
||||||
|
initialLoadKey = indexOfEvent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return initialLoadKey
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun fetchEvent(eventId: String) {
|
||||||
|
val params = GetContextOfEventTask.Params(roomId, eventId)
|
||||||
|
contextOfEventTask.configureWith(params).executeBy(taskExecutor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildPagedListConfig(): PagedList.Config {
|
||||||
|
return PagedList.Config.Builder()
|
||||||
|
.setEnablePlaceholders(false)
|
||||||
|
.setPageSize(PAGE_SIZE)
|
||||||
|
.setInitialLoadSizeHint(2 * PAGE_SIZE)
|
||||||
|
.setPrefetchDistance(PREFETCH_DISTANCE)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
private fun clearUnlinkedEvents() {
|
private fun clearUnlinkedEvents() {
|
||||||
monarchy.tryTransactionAsync { realm ->
|
monarchy.tryTransactionAsync { realm ->
|
||||||
|
@ -4,7 +4,7 @@ import android.arch.lifecycle.LiveData
|
|||||||
import android.arch.paging.PagedList
|
import android.arch.paging.PagedList
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.session.events.model.EnrichedEvent
|
import im.vector.matrix.android.api.session.events.model.TimelineEvent
|
||||||
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
||||||
import im.vector.matrix.android.internal.database.query.findIncludingEvent
|
import im.vector.matrix.android.internal.database.query.findIncludingEvent
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
@ -16,7 +16,7 @@ internal class TimelineBoundaryCallback(private val roomId: String,
|
|||||||
private val paginationTask: PaginationTask,
|
private val paginationTask: PaginationTask,
|
||||||
private val monarchy: Monarchy,
|
private val monarchy: Monarchy,
|
||||||
private val helper: PagingRequestHelper
|
private val helper: PagingRequestHelper
|
||||||
) : PagedList.BoundaryCallback<EnrichedEvent>() {
|
) : PagedList.BoundaryCallback<TimelineEvent>() {
|
||||||
|
|
||||||
var limit = 30
|
var limit = 30
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ internal class TimelineBoundaryCallback(private val roomId: String,
|
|||||||
// actually, it's not possible
|
// actually, it's not possible
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemAtEndLoaded(itemAtEnd: EnrichedEvent) {
|
override fun onItemAtEndLoaded(itemAtEnd: TimelineEvent) {
|
||||||
val token = itemAtEnd.root.eventId?.let { getToken(it, PaginationDirection.BACKWARDS) }
|
val token = itemAtEnd.root.eventId?.let { getToken(it, PaginationDirection.BACKWARDS) }
|
||||||
?: return
|
?: return
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ internal class TimelineBoundaryCallback(private val roomId: String,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemAtFrontLoaded(itemAtFront: EnrichedEvent) {
|
override fun onItemAtFrontLoaded(itemAtFront: TimelineEvent) {
|
||||||
val token = itemAtFront.root.eventId?.let { getToken(it, PaginationDirection.FORWARDS) }
|
val token = itemAtFront.root.eventId?.let { getToken(it, PaginationDirection.FORWARDS) }
|
||||||
?: return
|
?: return
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user