diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/DisplayMessage.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/DisplayMessage.kt new file mode 100644 index 0000000000000000000000000000000000000000..ad6401441368012da2f2c5db0e546d7d959975bf --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/DisplayMessage.kt @@ -0,0 +1,20 @@ +package de.kuschku.quasseldroid.ui.chat.messages + +import de.kuschku.libquassel.protocol.MsgId +import de.kuschku.quasseldroid.persistence.QuasselDatabase + +data class DisplayMessage( + val content: QuasselDatabase.DatabaseMessage, + val isSelected: Boolean, + val isExpanded: Boolean, + val isMarkerLine: Boolean +) { + data class Tag( + val id: MsgId, + val isSelected: Boolean, + val isExpanded: Boolean, + val isMarkerLine: Boolean + ) + + val tag = Tag(content.messageId, isSelected, isExpanded, isMarkerLine) +} \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt index 9f744ce6a7e15f3a8f0d3bd9e448bf2224421bbe..53e801e5b8d62b7e5f09531fe9e0e02d5a929a98 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt @@ -5,26 +5,25 @@ import android.support.v7.util.DiffUtil import android.util.LruCache import android.view.LayoutInflater import android.view.ViewGroup -import de.kuschku.libquassel.protocol.* +import de.kuschku.libquassel.protocol.Message_Flag +import de.kuschku.libquassel.protocol.Message_Flags +import de.kuschku.libquassel.protocol.Message_Type +import de.kuschku.libquassel.protocol.Message_Types import de.kuschku.libquassel.util.hasFlag -import de.kuschku.quasseldroid.persistence.QuasselDatabase.DatabaseMessage import de.kuschku.quasseldroid.util.helper.getOrPut class MessageAdapter( - private val messageRenderer: MessageRenderer, - var markerLinePosition: Pair<MsgId, MsgId>? = null -) : PagedListAdapter<DatabaseMessage, QuasselMessageViewHolder>( - object : DiffUtil.ItemCallback<DatabaseMessage>() { - override fun areItemsTheSame(oldItem: DatabaseMessage, newItem: DatabaseMessage) = - oldItem.messageId == newItem.messageId + private val messageRenderer: MessageRenderer +) : PagedListAdapter<DisplayMessage, QuasselMessageViewHolder>( + object : DiffUtil.ItemCallback<DisplayMessage>() { + override fun areItemsTheSame(oldItem: DisplayMessage, newItem: DisplayMessage) = + oldItem.content.messageId == newItem.content.messageId - override fun areContentsTheSame(oldItem: DatabaseMessage, newItem: DatabaseMessage) = - oldItem == newItem && - oldItem.messageId != markerLinePosition?.first && - oldItem.messageId != markerLinePosition?.second + override fun areContentsTheSame(oldItem: DisplayMessage, newItem: DisplayMessage) = + oldItem == newItem }) { - private val messageCache = LruCache<Int, FormattedMessage>(512) + private val messageCache = LruCache<DisplayMessage.Tag, FormattedMessage>(512) fun clearCache() { messageCache.evictAll() @@ -34,24 +33,15 @@ class MessageAdapter( getItem(position)?.let { messageRenderer.bind( holder, - if (it.messageId == markerLinePosition?.second || it.messageId == markerLinePosition?.first) { - val value = messageRenderer.render( - holder.itemView.context, it, markerLinePosition?.second ?: -1 - ) - messageCache.put(it.messageId, value) - value - } else { - messageCache.getOrPut(it.messageId) { - messageRenderer.render( - holder.itemView.context, it, markerLinePosition?.second ?: -1 - ) - } - }) + messageCache.getOrPut(it.tag) { + messageRenderer.render(holder.itemView.context, it) + } + ) } } override fun getItemViewType(position: Int) = getItem(position)?.let { - viewType(Message_Flags.of(it.type), Message_Flags.of(it.flag)) + viewType(Message_Flags.of(it.content.type), Message_Flags.of(it.content.flag)) } ?: 0 private fun viewType(type: Message_Types, flags: Message_Flags) = @@ -62,7 +52,7 @@ class MessageAdapter( } override fun getItemId(position: Int): Long { - return getItem(position)?.messageId?.toLong() ?: 0L + return getItem(position)?.content?.messageId?.toLong() ?: 0L } private fun messageType(viewType: Int): Message_Type? = diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt index bf0625c4bb5554b92cbd3f6f2f8ffa8846dba310..c7565fce76dfaaadd1577ef251b5be06e220183d 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt @@ -21,10 +21,7 @@ import de.kuschku.quasseldroid.R import de.kuschku.quasseldroid.persistence.QuasselDatabase import de.kuschku.quasseldroid.settings.AppearanceSettings import de.kuschku.quasseldroid.settings.BacklogSettings -import de.kuschku.quasseldroid.util.helper.invoke -import de.kuschku.quasseldroid.util.helper.switchMapNotNull -import de.kuschku.quasseldroid.util.helper.toggle -import de.kuschku.quasseldroid.util.helper.zip +import de.kuschku.quasseldroid.util.helper.* import de.kuschku.quasseldroid.util.service.ServiceBoundFragment import de.kuschku.quasseldroid.viewmodel.QuasselViewModel import javax.inject.Inject @@ -62,9 +59,10 @@ class MessageListFragment : ServiceBoundFragment() { } private val boundaryCallback = object : - PagedList.BoundaryCallback<QuasselDatabase.DatabaseMessage>() { - override fun onItemAtFrontLoaded(itemAtFront: QuasselDatabase.DatabaseMessage) = Unit - override fun onItemAtEndLoaded(itemAtEnd: QuasselDatabase.DatabaseMessage) = loadMore() + PagedList.BoundaryCallback<DisplayMessage>() { + override fun onItemAtFrontLoaded(itemAtFront: DisplayMessage) = Unit + override fun onItemAtEndLoaded(itemAtEnd: DisplayMessage) = + loadMore(lastMessageId = itemAtEnd.content.messageId) } override fun onCreateView( @@ -103,19 +101,30 @@ class MessageListFragment : ServiceBoundFragment() { } }) - val data = viewModel.buffer_liveData.switchMapNotNull { buffer -> - database.filtered().listen(accountId, buffer).switchMapNotNull { filtered -> - LivePagedListBuilder( - database.message().findByBufferIdPaged(buffer, filtered), - PagedList.Config.Builder() - .setPageSize(backlogSettings.pageSize) - .setPrefetchDistance(backlogSettings.pageSize) - .setInitialLoadSizeHint(backlogSettings.pageSize) - .setEnablePlaceholders(true) - .build() - ).setBoundaryCallback(boundaryCallback).build() + val data = combineLatest(viewModel.buffer, + viewModel.selectedMessages, + viewModel.expandedMessages, + viewModel.markerLine) + .toLiveData().switchMapNotNull { (buffer, selected, expanded, markerLine) -> + database.filtered().listen(accountId, buffer).switchMapNotNull { filtered -> + LivePagedListBuilder( + database.message().findByBufferIdPaged(buffer, filtered).map { + DisplayMessage( + content = it, + isSelected = selected.contains(it.messageId), + isExpanded = expanded.contains(it.messageId), + isMarkerLine = markerLine.orNull() == it.messageId + ) + }, + PagedList.Config.Builder() + .setPageSize(backlogSettings.pageSize) + .setPrefetchDistance(backlogSettings.pageSize) + .setInitialLoadSizeHint(backlogSettings.pageSize) + .setEnablePlaceholders(true) + .build() + ).setBoundaryCallback(boundaryCallback).build() + } } - } val lastMessageId = viewModel.buffer_liveData.switchMapNotNull { database.message().lastMsgId(it) @@ -123,7 +132,6 @@ class MessageListFragment : ServiceBoundFragment() { viewModel.sessionManager_liveData.zip(lastMessageId).observe( this, Observer { - val firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition() runInBackground { val session = it?.first?.orNull() val message = it?.second @@ -135,13 +143,6 @@ class MessageListFragment : ServiceBoundFragment() { } }) - viewModel.markerLine_liveData.observe(this, Observer { - it?.ifPresent { - adapter.markerLinePosition = it - adapter.notifyDataSetChanged() - } - }) - fun checkScroll() { if (linearLayoutManager.findFirstVisibleItemPosition() < 2 && !isScrolling) { messageList.scrollToPosition(0) @@ -156,7 +157,7 @@ class MessageListFragment : ServiceBoundFragment() { var lastBuffer = -1 data.observe(this, Observer { list -> val firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition() - val firstVisibleMessageId = adapter[firstVisibleItemPosition]?.messageId + val firstVisibleMessageId = adapter[firstVisibleItemPosition]?.content?.messageId runInBackground { activity?.runOnUiThread { list?.let(adapter::submitList) @@ -200,7 +201,7 @@ class MessageListFragment : ServiceBoundFragment() { override fun onPause() { val previous = lastBuffer val firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition() - val messageId = adapter[firstVisibleItemPosition]?.messageId + val messageId = adapter[firstVisibleItemPosition]?.content?.messageId val bufferSyncer = viewModel.session.value?.orNull()?.bufferSyncer if (previous != null && messageId != null) { bufferSyncer?.requestSetMarkerLine(previous, messageId) @@ -208,13 +209,13 @@ class MessageListFragment : ServiceBoundFragment() { super.onPause() } - private fun loadMore(initial: Boolean = false) { + private fun loadMore(initial: Boolean = false, lastMessageId: MsgId? = null) { runInBackground { viewModel.buffer { bufferId -> viewModel.session { it.orNull()?.backlogManager?.requestBacklog( bufferId = bufferId, - last = database.message().findFirstByBufferId( + last = lastMessageId ?: database.message().findFirstByBufferId( bufferId )?.messageId ?: -1, limit = if (initial) backlogSettings.initialAmount else backlogSettings.pageSize @@ -223,4 +224,5 @@ class MessageListFragment : ServiceBoundFragment() { } } } + } \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageRenderer.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageRenderer.kt index abfc89b57fba916107393808cf481fd3f2242c59..65179bc540a863e27eb5acf6fbbae1e7e39b533d 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageRenderer.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageRenderer.kt @@ -3,17 +3,13 @@ package de.kuschku.quasseldroid.ui.chat.messages import android.content.Context import android.support.annotation.LayoutRes import de.kuschku.libquassel.protocol.Message_Type -import de.kuschku.libquassel.protocol.MsgId -import de.kuschku.quasseldroid.persistence.QuasselDatabase interface MessageRenderer { @LayoutRes fun layout(type: Message_Type?, hasHighlight: Boolean): Int fun bind(holder: QuasselMessageViewHolder, message: FormattedMessage) - fun render(context: Context, - message: QuasselDatabase.DatabaseMessage, - markerLine: MsgId): FormattedMessage + fun render(context: Context, message: DisplayMessage): FormattedMessage fun init(viewHolder: QuasselMessageViewHolder, messageType: Message_Type?, diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt index 928c8f02641d020715c337960445d86fb056dec8..9716c95ab4fef30299d2c16067777974e9f635ba 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt @@ -12,10 +12,8 @@ import android.util.TypedValue import de.kuschku.libquassel.protocol.Message.MessageType.* import de.kuschku.libquassel.protocol.Message_Flag import de.kuschku.libquassel.protocol.Message_Type -import de.kuschku.libquassel.protocol.MsgId import de.kuschku.libquassel.util.hasFlag import de.kuschku.quasseldroid.R -import de.kuschku.quasseldroid.persistence.QuasselDatabase import de.kuschku.quasseldroid.settings.AppearanceSettings import de.kuschku.quasseldroid.settings.AppearanceSettings.ColorizeNicknamesMode import de.kuschku.quasseldroid.settings.AppearanceSettings.ShowPrefixMode @@ -95,8 +93,7 @@ class QuasselMessageRenderer @Inject constructor( } override fun render(context: Context, - message: QuasselDatabase.DatabaseMessage, - markerLine: MsgId): FormattedMessage { + message: DisplayMessage): FormattedMessage { context.theme.styledAttributes( R.attr.senderColor0, R.attr.senderColor1, R.attr.senderColor2, R.attr.senderColor3, R.attr.senderColor4, R.attr.senderColor5, R.attr.senderColor6, R.attr.senderColor7, @@ -108,224 +105,224 @@ class QuasselMessageRenderer @Inject constructor( } } - val self = Message_Flag.of(message.flag).hasFlag(Message_Flag.Self) - val highlight = Message_Flag.of(message.flag).hasFlag(Message_Flag.Highlight) - return when (Message_Type.of(message.type).enabledValues().firstOrNull()) { + val self = Message_Flag.of(message.content.flag).hasFlag(Message_Flag.Self) + val highlight = Message_Flag.of(message.content.flag).hasFlag(Message_Flag.Highlight) + return when (Message_Type.of(message.content.type).enabledValues().firstOrNull()) { Message_Type.Plain -> FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), SpanFormatter.format( context.getString(R.string.message_format_plain), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, self, highlight, false), - formatContent(context, message.content, highlight) + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, self, highlight, false), + formatContent(context, message.content.content, highlight) ), - message.messageId == markerLine + message.isMarkerLine ) Message_Type.Action -> FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), SpanFormatter.format( context.getString(R.string.message_format_action), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, self, highlight, false), - formatContent(context, message.content, highlight) + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, self, highlight, false), + formatContent(context, message.content.content, highlight) ), - message.messageId == markerLine + message.isMarkerLine ) Message_Type.Notice -> FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), SpanFormatter.format( context.getString(R.string.message_format_notice), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, self, highlight, false), - formatContent(context, message.content, highlight) + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, self, highlight, false), + formatContent(context, message.content.content, highlight) ), - message.messageId == markerLine + message.isMarkerLine ) Message_Type.Nick -> { - val nickSelf = message.sender == message.content || self + val nickSelf = message.content.sender == message.content.content || self FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), if (nickSelf) { SpanFormatter.format( context.getString(R.string.message_format_nick_self), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, nickSelf, highlight, false) + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, nickSelf, highlight, false) ) } else { SpanFormatter.format( context.getString(R.string.message_format_nick), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, nickSelf, highlight, false), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.content, nickSelf, highlight, false) + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, nickSelf, highlight, false), + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.content, nickSelf, highlight, false) ) }, - message.messageId == markerLine + message.isMarkerLine ) } Message_Type.Mode -> FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), SpanFormatter.format( context.getString(R.string.message_format_mode), - message.content, - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, self, highlight, false) + message.content.content, + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, self, highlight, false) ), - message.messageId == markerLine + message.isMarkerLine ) Message_Type.Join -> FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), SpanFormatter.format( context.getString(R.string.message_format_join), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, self, highlight, true), - message.content + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, self, highlight, true), + message.content.content ), - message.messageId == markerLine + message.isMarkerLine ) Message_Type.Part -> FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), - if (message.content.isBlank()) { + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), + if (message.content.content.isBlank()) { SpanFormatter.format( context.getString(R.string.message_format_part_1), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, self, highlight, true) + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, self, highlight, true) ) } else { SpanFormatter.format( context.getString(R.string.message_format_part_2), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, self, highlight, true), - formatContent(context, message.content, highlight) + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, self, highlight, true), + formatContent(context, message.content.content, highlight) ) }, - message.messageId == markerLine + message.isMarkerLine ) Message_Type.Quit -> FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), - if (message.content.isBlank()) { + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), + if (message.content.content.isBlank()) { SpanFormatter.format( context.getString(R.string.message_format_quit_1), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, self, highlight, true) + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, self, highlight, true) ) } else { SpanFormatter.format( context.getString(R.string.message_format_quit_2), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, self, highlight, true), - formatContent(context, message.content, highlight) + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, self, highlight, true), + formatContent(context, message.content.content, highlight) ) }, - message.messageId == markerLine + message.isMarkerLine ) Message_Type.Kick -> { - val (user, reason) = message.content.split(' ', limit = 2) + listOf("", "") + val (user, reason) = message.content.content.split(' ', limit = 2) + listOf("", "") FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), if (reason.isBlank()) { SpanFormatter.format( context.getString(R.string.message_format_kick_1), formatNick(user, false, highlight, false), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, self, highlight, true) + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, self, highlight, true) ) } else { SpanFormatter.format( context.getString(R.string.message_format_kick_2), formatNick(user, false, highlight, false), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, self, highlight, true), + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, self, highlight, true), formatContent(context, reason, highlight) ) }, - message.messageId == markerLine + message.isMarkerLine ) } Message_Type.Kill -> { - val (user, reason) = message.content.split(' ', limit = 2) + listOf("", "") + val (user, reason) = message.content.content.split(' ', limit = 2) + listOf("", "") FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), if (reason.isBlank()) { SpanFormatter.format( context.getString(R.string.message_format_kill_1), formatNick(user, false, highlight, false), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, self, highlight, true) + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, self, highlight, true) ) } else { SpanFormatter.format( context.getString(R.string.message_format_kill_2), formatNick(user, false, highlight, false), - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, self, highlight, true), + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, self, highlight, true), formatContent(context, reason, highlight) ) }, - message.messageId == markerLine + message.isMarkerLine ) } Message_Type.NetsplitJoin -> { - val split = message.content.split("#:#") + val split = message.content.content.split("#:#") val (server1, server2) = split.last().split(' ') val usersAffected = split.size - 1 FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), context.resources.getQuantityString( R.plurals.message_netsplit_join, usersAffected, server1, server2, usersAffected ), - message.messageId == markerLine + message.isMarkerLine ) } Message_Type.NetsplitQuit -> { - val split = message.content.split("#:#") + val split = message.content.content.split("#:#") val (server1, server2) = split.last().split(' ') val usersAffected = split.size - 1 FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), context.resources.getQuantityString( R.plurals.message_netsplit_quit, usersAffected, server1, server2, usersAffected ), - message.messageId == markerLine + message.isMarkerLine ) } Message_Type.Server, Message_Type.Info, Message_Type.Error -> FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), - formatContent(context, message.content, highlight), - message.messageId == markerLine + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), + formatContent(context, message.content.content, highlight), + message.isMarkerLine ) Message_Type.Topic -> FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), - formatContent(context, message.content, highlight), - message.messageId == markerLine + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), + formatContent(context, message.content.content, highlight), + message.isMarkerLine ) else -> FormattedMessage( - message.messageId, - timeFormatter.format(message.time.atZone(zoneId)), + message.content.messageId, + timeFormatter.format(message.content.time.atZone(zoneId)), SpanFormatter.format( "[%d] %s%s: %s", - message.type, - formatPrefix(message.senderPrefixes, highlight), - formatNick(message.sender, self, highlight, true), - message.content + message.content.type, + formatPrefix(message.content.senderPrefixes, highlight), + formatNick(message.content.sender, self, highlight, true), + message.content.content ), - message.messageId == markerLine + message.isMarkerLine ) } } diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt index 2e725b3625b3d2084dd9e1a198312d366d4d995d..42d72e1277a95769584b78e9730c80f5044f4dc9 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt @@ -20,12 +20,37 @@ inline fun <reified A, B, C> combineLatest( a: ObservableSource<A>, b: ObservableSource<B>, c: ObservableSource<C> -): Observable<Triple<A, B, C>> = Observable.combineLatest(listOf(a, b, c), { (t0, t1, t2) -> - Triple(t0, t1, t2) as Triple<A, B, C> -}) +): Observable<Triple<A, B, C>> = Observable.combineLatest( + listOf(a, b, c), + { (t0, t1, t2) -> + Triple(t0, t1, t2) as Triple<A, B, C> + } +) + +inline fun <reified A, B, C, D> combineLatest( + a: ObservableSource<A>, + b: ObservableSource<B>, + c: ObservableSource<C>, + d: ObservableSource<D> +): Observable<Tuple4<A, B, C, D>> = Observable.combineLatest( + listOf(a, b, c, d), + { (t0, t1, t2, t3) -> + Tuple4(t0, + t1, + t2, + t3) as Tuple4<A, B, C, D> + } +) inline fun <reified T> combineLatest(sources: Iterable<ObservableSource<out T>?>) = Observable.combineLatest(sources) { t -> t.toList() as List<T> } inline operator fun <T, U> Observable<T>.invoke(f: (T) -> U?) = - blockingLatest().firstOrNull()?.let(f) \ No newline at end of file + blockingLatest().firstOrNull()?.let(f) + +data class Tuple4<out A, out B, out C, out D>( + val first: A, + val second: B, + val third: C, + val fourth: D +) \ No newline at end of file diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt index 9544f2fa70226184c63e33e5194906a01da19a5e..f7088caf186775f06ccad71fc50450e21ba439a7 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt @@ -3,6 +3,7 @@ package de.kuschku.quasseldroid.viewmodel import android.arch.lifecycle.ViewModel import de.kuschku.libquassel.protocol.BufferId import de.kuschku.libquassel.protocol.Buffer_Type +import de.kuschku.libquassel.protocol.MsgId import de.kuschku.libquassel.protocol.NetworkId import de.kuschku.libquassel.quassel.BufferInfo import de.kuschku.libquassel.quassel.syncables.BufferViewConfig @@ -27,6 +28,9 @@ import java.util.concurrent.TimeUnit class QuasselViewModel : ViewModel() { val backendWrapper = BehaviorSubject.createDefault(Observable.empty<Optional<Backend>>()) + val selectedMessages = BehaviorSubject.createDefault(emptyList<MsgId>()) + val expandedMessages = BehaviorSubject.createDefault(emptyList<MsgId>()) + val buffer = BehaviorSubject.createDefault(-1) val buffer_liveData = buffer.toLiveData() @@ -69,8 +73,7 @@ class QuasselViewModel : ViewModel() { val markerLine = session.mapSwitchMap { currentSession -> buffer.switchMap { currentBuffer -> // Get a stream of the latest marker line - val raw = currentSession.bufferSyncer?.liveMarkerLine(currentBuffer) ?: Observable.empty() - raw.scan(Pair(-1, -1)) { (_, previous), next -> Pair(previous, next) } + currentSession.bufferSyncer?.liveMarkerLine(currentBuffer) ?: Observable.empty() } } val markerLine_liveData = markerLine.toLiveData()