From ca89fa4b1875c849ac8d6fda37d86b83ede316bc Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Wed, 21 Feb 2018 12:40:23 +0100 Subject: [PATCH] Implement markerline display --- app/build.gradle.kts | 2 + .../ui/chat/BufferViewConfigFragment.kt | 2 +- .../ui/chat/FormattedMessage.kt | 3 +- .../quasseldroid_ng/ui/chat/MessageAdapter.kt | 38 +++++++--- .../ui/chat/MessageListFragment.kt | 21 +++++- .../ui/chat/MessageRenderer.kt | 3 +- .../ui/chat/QuasselMessageRenderer.kt | 45 ++++++++---- .../ui/chat/QuasselMessageViewHolder.kt | 3 + .../ui/chat/ToolbarFragment.kt | 2 +- .../util/helper/LiveDataHelper.kt | 12 +-- .../res/layout/widget_chatmessage_action.xml | 64 +++++++++------- .../res/layout/widget_chatmessage_error.xml | 31 +++++--- .../res/layout/widget_chatmessage_info.xml | 31 +++++--- .../res/layout/widget_chatmessage_notice.xml | 31 +++++--- .../layout/widget_chatmessage_placeholder.xml | 10 ++- .../res/layout/widget_chatmessage_plain.xml | 30 +++++--- .../res/layout/widget_chatmessage_server.xml | 31 +++++--- app/src/main/res/values/attrs.xml | 3 +- app/src/main/res/values/themes_quassel.xml | 2 + lib/build.gradle.kts | 2 + .../quassel/syncables/BufferSyncer.kt | 73 +++++++++++++------ 21 files changed, 302 insertions(+), 137 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e4bad8b79..2831cb257 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -137,6 +137,7 @@ dependencies { androidTestImplementation("com.android.support.test.espresso", "espresso-core", "3.0.1") } +/* tasks.withType(KotlinCompile::class.java) { kotlinOptions { freeCompilerArgs = listOf( @@ -145,6 +146,7 @@ tasks.withType(KotlinCompile::class.java) { ) } } +*/ fun cmd(vararg command: String) = try { val stdOut = ByteArrayOutputStream() diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigFragment.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigFragment.kt index 23d8508c7..f0de1e7bd 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigFragment.kt @@ -92,7 +92,7 @@ class BufferViewConfigFragment : ServiceBoundFragment() { config.live_buffers.switchMap { ids -> val bufferSyncer = manager.bufferSyncer if (bufferSyncer != null) { - bufferSyncer.live_bufferInfos.switchMap { + bufferSyncer.liveBufferInfos().switchMap { Observable.combineLatest( ids.mapNotNull { id -> bufferSyncer.bufferInfo(id) diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/FormattedMessage.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/FormattedMessage.kt index d245270de..68f1c9748 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/FormattedMessage.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/FormattedMessage.kt @@ -3,5 +3,6 @@ package de.kuschku.quasseldroid_ng.ui.chat class FormattedMessage( val id: Int, val time: CharSequence, - val content: CharSequence + val content: CharSequence, + val markerline: Boolean ) \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageAdapter.kt index 547b5601f..02e301411 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageAdapter.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageAdapter.kt @@ -1,23 +1,35 @@ package de.kuschku.quasseldroid_ng.ui.chat +import android.arch.lifecycle.LiveData import android.arch.paging.PagedListAdapter import android.content.Context +import android.support.v7.recyclerview.extensions.DiffCallback import android.util.LruCache import android.view.LayoutInflater import android.view.ViewGroup -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.protocol.* import de.kuschku.libquassel.util.hasFlag import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase +import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase.DatabaseMessage import de.kuschku.quasseldroid_ng.ui.settings.data.RenderingSettings import de.kuschku.quasseldroid_ng.util.helper.getOrPut -class MessageAdapter(context: Context) : - PagedListAdapter<QuasselDatabase.DatabaseMessage, QuasselMessageViewHolder>( - QuasselDatabase.DatabaseMessage.MessageDiffCallback - ) { +class MessageAdapter( + context: Context, + private val markerLine: LiveData<Pair<MsgId, MsgId>?> +) : PagedListAdapter<QuasselDatabase.DatabaseMessage, QuasselMessageViewHolder>( + object : DiffCallback<QuasselDatabase.DatabaseMessage>() { + override fun areItemsTheSame(oldItem: QuasselDatabase.DatabaseMessage, + newItem: QuasselDatabase.DatabaseMessage) + = DatabaseMessage.MessageDiffCallback.areItemsTheSame(oldItem, newItem) + + override fun areContentsTheSame(oldItem: QuasselDatabase.DatabaseMessage, + newItem: QuasselDatabase.DatabaseMessage) + = DatabaseMessage.MessageDiffCallback.areContentsTheSame(oldItem, newItem) && + oldItem.messageId != markerLine.value?.first && + oldItem.messageId != markerLine.value?.second + } +) { private val messageRenderer: MessageRenderer = QuasselMessageRenderer( context, RenderingSettings( @@ -34,8 +46,14 @@ class MessageAdapter(context: Context) : getItem(position)?.let { messageRenderer.bind( holder, - messageCache.getOrPut(it.messageId) { - messageRenderer.render(it) + if (it.messageId == markerLine.value?.second || it.messageId == markerLine.value?.first) { + val value = messageRenderer.render(it, markerLine.value?.second ?: -1) + messageCache.put(it.messageId, value) + value + } else { + messageCache.getOrPut(it.messageId) { + messageRenderer.render(it, markerLine.value?.second ?: -1) + } } ) } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageListFragment.kt index 757575c1f..6ed8b5ce5 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageListFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageListFragment.kt @@ -15,6 +15,7 @@ import android.view.ViewGroup import butterknife.BindView import butterknife.ButterKnife import de.kuschku.libquassel.protocol.BufferId +import de.kuschku.libquassel.protocol.MsgId import de.kuschku.libquassel.session.Backend import de.kuschku.libquassel.session.SessionManager import de.kuschku.quasseldroid_ng.R @@ -22,6 +23,8 @@ import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase import de.kuschku.quasseldroid_ng.util.AndroidHandlerThread import de.kuschku.quasseldroid_ng.util.helper.* import de.kuschku.quasseldroid_ng.util.service.ServiceBoundFragment +import io.reactivex.Observable +import io.reactivex.functions.BiFunction class MessageListFragment : ServiceBoundFragment() { val currentBuffer: MutableLiveData<LiveData<BufferId?>?> = MutableLiveData() @@ -29,6 +32,19 @@ class MessageListFragment : ServiceBoundFragment() { private val sessionManager: LiveData<SessionManager?> = backend.map(Backend::sessionManager) + val markerLine = buffer.switchMap { buffer -> + sessionManager.switchMapRx { manager -> + manager.session.switchMap { session -> + val raw = session.bufferSyncer?.liveMarkerLine(buffer) + Observable.zip( + Observable.just(-1).concatWith(raw), + raw, + BiFunction<MsgId, MsgId, Pair<MsgId, MsgId>> { a, b -> a to b } + ) + } + } + } + private val handler = AndroidHandlerThread("Chat") private lateinit var database: QuasselDatabase @@ -60,12 +76,13 @@ class MessageListFragment : ServiceBoundFragment() { val view = inflater.inflate(R.layout.fragment_messages, container, false) ButterKnife.bind(this, view) - val adapter = MessageAdapter(context!!) + val adapter = MessageAdapter(context!!, markerLine) messageList.adapter = adapter val linearLayoutManager = LinearLayoutManager(context) linearLayoutManager.reverseLayout = true messageList.layoutManager = linearLayoutManager + messageList.itemAnimator = null messageList.setItemViewCacheSize(20) messageList.addOnScrollListener( @@ -117,6 +134,8 @@ class MessageListFragment : ServiceBoundFragment() { ) } + markerLine.observe(this, Observer { adapter.notifyDataSetChanged() }) + data.observe( this, Observer { list -> val findFirstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition() diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageRenderer.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageRenderer.kt index 99403809e..206b100ae 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageRenderer.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageRenderer.kt @@ -2,6 +2,7 @@ package de.kuschku.quasseldroid_ng.ui.chat import android.support.annotation.LayoutRes import de.kuschku.libquassel.protocol.Message_Type +import de.kuschku.libquassel.protocol.MsgId import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase interface MessageRenderer { @@ -9,7 +10,7 @@ interface MessageRenderer { fun layout(type: Message_Type?, hasHighlight: Boolean): Int fun bind(holder: QuasselMessageViewHolder, message: FormattedMessage) - fun render(message: QuasselDatabase.DatabaseMessage): FormattedMessage + fun render(message: QuasselDatabase.DatabaseMessage, markerLine: MsgId): FormattedMessage fun init(viewHolder: QuasselMessageViewHolder, messageType: Message_Type?, hasHighlight: Boolean) { diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/QuasselMessageRenderer.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/QuasselMessageRenderer.kt index 4829aef05..48d1f87ec 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/QuasselMessageRenderer.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/QuasselMessageRenderer.kt @@ -11,6 +11,7 @@ import android.text.style.URLSpan 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_ng.R import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase @@ -18,6 +19,7 @@ import de.kuschku.quasseldroid_ng.ui.settings.data.RenderingSettings import de.kuschku.quasseldroid_ng.ui.settings.data.RenderingSettings.ColorizeNicknamesMode import de.kuschku.quasseldroid_ng.ui.settings.data.RenderingSettings.ShowPrefixMode import de.kuschku.quasseldroid_ng.util.helper.styledAttributes +import de.kuschku.quasseldroid_ng.util.helper.visibleIf import de.kuschku.quasseldroid_ng.util.irc.format.IrcFormatDeserializer import de.kuschku.quasseldroid_ng.util.quassel.IrcUserUtils import de.kuschku.quasseldroid_ng.util.ui.SpanFormatter @@ -81,9 +83,11 @@ class QuasselMessageRenderer( override fun bind(holder: QuasselMessageViewHolder, message: FormattedMessage) { holder.time.text = message.time holder.content.text = message.content + holder.markerline.visibleIf(message.markerline) } - override fun render(message: QuasselDatabase.DatabaseMessage): FormattedMessage { + override fun render(message: QuasselDatabase.DatabaseMessage, + markerLine: MsgId): FormattedMessage { return when (Message_Type.of(message.type).enabledValues().firstOrNull()) { Message_Type.Plain -> FormattedMessage( message.messageId, @@ -93,7 +97,8 @@ class QuasselMessageRenderer( formatPrefix(message.senderPrefixes), formatNick(message.sender, Message_Flag.of(message.flag).hasFlag(Message_Flag.Self)), formatContent(message.content) - ) + ), + message.messageId == markerLine ) Message_Type.Action -> FormattedMessage( message.messageId, @@ -103,7 +108,8 @@ class QuasselMessageRenderer( formatPrefix(message.senderPrefixes), formatNick(message.sender, Message_Flag.of(message.flag).hasFlag(Message_Flag.Self)), formatContent(message.content) - ) + ), + message.messageId == markerLine ) Message_Type.Notice -> FormattedMessage( message.messageId, @@ -113,7 +119,8 @@ class QuasselMessageRenderer( formatPrefix(message.senderPrefixes), formatNick(message.sender, Message_Flag.of(message.flag).hasFlag(Message_Flag.Self)), formatContent(message.content) - ) + ), + message.messageId == markerLine ) Message_Type.Nick -> FormattedMessage( message.messageId, @@ -124,7 +131,8 @@ class QuasselMessageRenderer( formatNick(message.sender, Message_Flag.of(message.flag).hasFlag(Message_Flag.Self)), formatPrefix(message.senderPrefixes), formatNick(message.content, Message_Flag.of(message.flag).hasFlag(Message_Flag.Self)) - ) + ), + message.messageId == markerLine ) Message_Type.Mode -> FormattedMessage( message.messageId, @@ -134,7 +142,8 @@ class QuasselMessageRenderer( message.content, formatPrefix(message.senderPrefixes), formatNick(message.sender, Message_Flag.of(message.flag).hasFlag(Message_Flag.Self)) - ) + ), + message.messageId == markerLine ) Message_Type.Join -> FormattedMessage( message.messageId, @@ -143,7 +152,8 @@ class QuasselMessageRenderer( context.getString(R.string.message_format_join), formatPrefix(message.senderPrefixes), formatNick(message.sender, Message_Flag.of(message.flag).hasFlag(Message_Flag.Self)) - ) + ), + message.messageId == markerLine ) Message_Type.Part -> FormattedMessage( message.messageId, @@ -161,7 +171,8 @@ class QuasselMessageRenderer( formatNick(message.sender, Message_Flag.of(message.flag).hasFlag(Message_Flag.Self)), message.content ) - } + }, + message.messageId == markerLine ) Message_Type.Quit -> FormattedMessage( message.messageId, @@ -179,7 +190,8 @@ class QuasselMessageRenderer( formatNick(message.sender, Message_Flag.of(message.flag).hasFlag(Message_Flag.Self)), message.content ) - } + }, + message.messageId == markerLine ) Message_Type.NetsplitJoin -> { val split = message.content.split("#:#") @@ -190,7 +202,8 @@ class QuasselMessageRenderer( timeFormatter.format(message.time.atZone(zoneId)), context.resources.getQuantityString( R.plurals.message_netsplit_join, usersAffected, server1, server2, usersAffected - ) + ), + message.messageId == markerLine ) } Message_Type.NetsplitQuit -> { @@ -202,7 +215,8 @@ class QuasselMessageRenderer( timeFormatter.format(message.time.atZone(zoneId)), context.resources.getQuantityString( R.plurals.message_netsplit_quit, usersAffected, server1, server2, usersAffected - ) + ), + message.messageId == markerLine ) } Message_Type.Server, @@ -210,12 +224,14 @@ class QuasselMessageRenderer( Message_Type.Error -> FormattedMessage( message.messageId, timeFormatter.format(message.time.atZone(zoneId)), - formatContent(message.content) + formatContent(message.content), + message.messageId == markerLine ) Message_Type.Topic -> FormattedMessage( message.messageId, timeFormatter.format(message.time.atZone(zoneId)), - formatContent(message.content) + formatContent(message.content), + message.messageId == markerLine ) else -> FormattedMessage( message.messageId, @@ -226,7 +242,8 @@ class QuasselMessageRenderer( formatPrefix(message.senderPrefixes), formatNick(message.sender, Message_Flag.of(message.flag).hasFlag(Message_Flag.Self)), message.content - ) + ), + message.messageId == markerLine ) } } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/QuasselMessageViewHolder.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/QuasselMessageViewHolder.kt index cf54d42c9..cfddcb3e5 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/QuasselMessageViewHolder.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/QuasselMessageViewHolder.kt @@ -15,6 +15,9 @@ class QuasselMessageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemVie @BindView(R.id.content) lateinit var content: TextView + @BindView(R.id.markerline) + lateinit var markerline: View + init { ButterKnife.bind(this, itemView) content.movementMethod = LinkMovementMethod.getInstance() diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ToolbarFragment.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ToolbarFragment.kt index 4ef64d13b..0e3176638 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ToolbarFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ToolbarFragment.kt @@ -59,7 +59,7 @@ class ToolbarFragment : ServiceBoundFragment() { manager.session.switchMap { val bufferSyncer = it.bufferSyncer if (bufferSyncer != null) { - bufferSyncer.live_bufferInfos.switchMap { + bufferSyncer.liveBufferInfos().switchMap { val info = bufferSyncer.bufferInfo(id) val network = manager.networks[info?.networkId] if (info == null) { diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/LiveDataHelper.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/LiveDataHelper.kt index 17c04403f..a72e74e0e 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/LiveDataHelper.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/LiveDataHelper.kt @@ -7,7 +7,7 @@ import io.reactivex.Observable @MainThread inline fun <X, Y> LiveData<X?>.switchMap( - noinline func: (X) -> LiveData<Y>? + crossinline func: (X) -> LiveData<Y>? ): LiveData<Y> { val result = MediatorLiveData<Y>() result.addSource( @@ -35,7 +35,7 @@ inline fun <X, Y> LiveData<X?>.switchMap( @MainThread inline fun <X, Y> LiveData<X?>.switchMapRx( strategy: BackpressureStrategy, - noinline func: (X) -> Observable<Y>? + crossinline func: (X) -> Observable<Y>? ): LiveData<Y?> { val result = MediatorLiveData<Y>() result.addSource( @@ -61,13 +61,13 @@ inline fun <X, Y> LiveData<X?>.switchMapRx( } @MainThread -inline fun <X, Y> LiveData<X?>.switchMapRx( - noinline func: (X) -> Observable<Y>? +inline fun <X, Y> LiveData<out X?>.switchMapRx( + crossinline func: (X) -> Observable<Y>? ): LiveData<Y?> = switchMapRx(BackpressureStrategy.LATEST, func) @MainThread inline fun <X, Y> LiveData<X?>.map( - noinline func: (X) -> Y? + crossinline func: (X) -> Y? ): LiveData<Y?> { val result = MediatorLiveData<Y?>() result.addSource(this) { x -> @@ -78,7 +78,7 @@ inline fun <X, Y> LiveData<X?>.map( @MainThread inline fun <X> LiveData<X>.orElse( - noinline func: () -> X + crossinline func: () -> X ): LiveData<X> { val result = object : MediatorLiveData<X>() { override fun getValue() = super.getValue() ?: func() diff --git a/app/src/main/res/layout/widget_chatmessage_action.xml b/app/src/main/res/layout/widget_chatmessage_action.xml index dee8b8853..b23606b69 100644 --- a/app/src/main/res/layout/widget_chatmessage_action.xml +++ b/app/src/main/res/layout/widget_chatmessage_action.xml @@ -25,35 +25,47 @@ android:layout_height="wrap_content" android:clickable="true" android:focusable="true" - android:gravity="top" - android:orientation="horizontal" - android:paddingBottom="@dimen/message_vertical" - android:paddingEnd="@dimen/message_horizontal" - android:paddingLeft="@dimen/message_horizontal" - android:paddingRight="@dimen/message_horizontal" - android:paddingStart="@dimen/message_horizontal" - android:paddingTop="@dimen/message_vertical" + android:orientation="vertical" android:textAppearance="?android:attr/textAppearanceListItemSmall" tools:background="@android:color/background_light" tools:theme="@style/Theme.ChatTheme.Quassel_Light"> - <TextView - android:id="@+id/time" - android:layout_width="wrap_content" + <LinearLayout + android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/message_horizontal" - android:layout_marginRight="@dimen/message_horizontal" - android:textColor="?attr/colorForegroundSecondary" - android:typeface="monospace" - tools:text="[15:55]" /> + android:orientation="horizontal" + android:paddingBottom="@dimen/message_vertical" + android:paddingEnd="@dimen/message_horizontal" + android:paddingLeft="@dimen/message_horizontal" + android:paddingRight="@dimen/message_horizontal" + android:paddingStart="@dimen/message_horizontal" + android:paddingTop="@dimen/message_vertical"> - <TextView - android:id="@+id/content" - android:layout_width="0dip" - android:layout_height="wrap_content" - android:layout_weight="1" - android:textColor="?attr/colorForegroundAction" - android:textIsSelectable="true" - android:textStyle="italic" - tools:text="-*- justJanne loves the new version" /> -</LinearLayout> + <TextView + android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/message_horizontal" + android:layout_marginRight="@dimen/message_horizontal" + android:textColor="?attr/colorForegroundSecondary" + android:typeface="monospace" + tools:text="[15:55]" /> + + <TextView + android:id="@+id/content" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="?attr/colorForegroundAction" + android:textIsSelectable="true" + android:textStyle="italic" + tools:text="-*- justJanne loves the new version" /> + </LinearLayout> + + <View + android:id="@+id/markerline" + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?colorMarkerLine" + android:visibility="gone" /> +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/widget_chatmessage_error.xml b/app/src/main/res/layout/widget_chatmessage_error.xml index 55547dc3a..1485a969a 100644 --- a/app/src/main/res/layout/widget_chatmessage_error.xml +++ b/app/src/main/res/layout/widget_chatmessage_error.xml @@ -3,21 +3,24 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="?attr/colorBackgroundSecondary" android:clickable="true" android:focusable="true" - android:gravity="top" - android:orientation="horizontal" - android:paddingBottom="@dimen/message_vertical" - android:paddingEnd="@dimen/message_horizontal" - android:paddingLeft="@dimen/message_horizontal" - android:paddingRight="@dimen/message_horizontal" - android:paddingStart="@dimen/message_horizontal" - android:paddingTop="@dimen/message_vertical" + android:orientation="vertical" android:textAppearance="?android:attr/textAppearanceListItemSmall" tools:background="@android:color/background_light" tools:theme="@style/Theme.ChatTheme.Quassel_Light"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:paddingBottom="@dimen/message_vertical" + android:paddingEnd="@dimen/message_horizontal" + android:paddingLeft="@dimen/message_horizontal" + android:paddingRight="@dimen/message_horizontal" + android:paddingStart="@dimen/message_horizontal" + android:paddingTop="@dimen/message_vertical"> + <TextView android:id="@+id/time" android:layout_width="wrap_content" @@ -36,4 +39,12 @@ android:textColor="?attr/colorForegroundError" android:textIsSelectable="true" tools:text="everyone: deserves a chance to fly. No such channel" /> -</LinearLayout> + </LinearLayout> + + <View + android:id="@+id/markerline" + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?colorMarkerLine" + android:visibility="gone" /> +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/widget_chatmessage_info.xml b/app/src/main/res/layout/widget_chatmessage_info.xml index 0530deda0..b6d1f048c 100644 --- a/app/src/main/res/layout/widget_chatmessage_info.xml +++ b/app/src/main/res/layout/widget_chatmessage_info.xml @@ -3,21 +3,24 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="?attr/colorBackgroundSecondary" android:clickable="true" android:focusable="true" - android:gravity="top" - android:orientation="horizontal" - android:paddingBottom="@dimen/message_vertical" - android:paddingEnd="@dimen/message_horizontal" - android:paddingLeft="@dimen/message_horizontal" - android:paddingRight="@dimen/message_horizontal" - android:paddingStart="@dimen/message_horizontal" - android:paddingTop="@dimen/message_vertical" + android:orientation="vertical" android:textAppearance="?android:attr/textAppearanceListItemSmall" tools:background="@android:color/background_light" tools:theme="@style/Theme.ChatTheme.Quassel_Light"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:paddingBottom="@dimen/message_vertical" + android:paddingEnd="@dimen/message_horizontal" + android:paddingLeft="@dimen/message_horizontal" + android:paddingRight="@dimen/message_horizontal" + android:paddingStart="@dimen/message_horizontal" + android:paddingTop="@dimen/message_vertical"> + <TextView android:id="@+id/time" android:layout_width="wrap_content" @@ -37,4 +40,12 @@ android:textIsSelectable="true" android:textStyle="italic" tools:text="Connecting to irc.freenode.net:6667..." /> -</LinearLayout> + </LinearLayout> + + <View + android:id="@+id/markerline" + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?colorMarkerLine" + android:visibility="gone" /> +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/widget_chatmessage_notice.xml b/app/src/main/res/layout/widget_chatmessage_notice.xml index 0d785dd05..755a7d100 100644 --- a/app/src/main/res/layout/widget_chatmessage_notice.xml +++ b/app/src/main/res/layout/widget_chatmessage_notice.xml @@ -3,21 +3,24 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="?attr/colorBackgroundSecondary" android:clickable="true" android:focusable="true" - android:gravity="top" - android:orientation="horizontal" - android:paddingBottom="@dimen/message_vertical" - android:paddingEnd="@dimen/message_horizontal" - android:paddingLeft="@dimen/message_horizontal" - android:paddingRight="@dimen/message_horizontal" - android:paddingStart="@dimen/message_horizontal" - android:paddingTop="@dimen/message_vertical" + android:orientation="vertical" android:textAppearance="?android:attr/textAppearanceListItemSmall" tools:background="@android:color/background_light" tools:theme="@style/Theme.ChatTheme.Quassel_Light"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:paddingBottom="@dimen/message_vertical" + android:paddingEnd="@dimen/message_horizontal" + android:paddingLeft="@dimen/message_horizontal" + android:paddingRight="@dimen/message_horizontal" + android:paddingStart="@dimen/message_horizontal" + android:paddingTop="@dimen/message_vertical"> + <TextView android:id="@+id/time" android:layout_width="wrap_content" @@ -36,4 +39,12 @@ android:textColor="?attr/colorForegroundNotice" android:textIsSelectable="true" tools:text="Connecting to irc.freenode.net:6667..." /> -</LinearLayout> + </LinearLayout> + + <View + android:id="@+id/markerline" + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?colorMarkerLine" + android:visibility="gone" /> +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/widget_chatmessage_placeholder.xml b/app/src/main/res/layout/widget_chatmessage_placeholder.xml index be8f116d7..5021308b2 100644 --- a/app/src/main/res/layout/widget_chatmessage_placeholder.xml +++ b/app/src/main/res/layout/widget_chatmessage_placeholder.xml @@ -3,8 +3,6 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="48dp" - android:gravity="top" - android:orientation="horizontal" tools:background="@android:color/background_light" tools:theme="@style/Theme.ChatTheme.Quassel_Light"> @@ -19,4 +17,10 @@ android:layout_width="0dip" android:layout_height="0dip" android:visibility="gone" /> -</LinearLayout> + + <View + android:id="@+id/markerline" + android:layout_width="0dip" + android:layout_height="0dip" + android:visibility="gone" /> +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/widget_chatmessage_plain.xml b/app/src/main/res/layout/widget_chatmessage_plain.xml index 1f52573c3..54b7db732 100644 --- a/app/src/main/res/layout/widget_chatmessage_plain.xml +++ b/app/src/main/res/layout/widget_chatmessage_plain.xml @@ -5,18 +5,22 @@ android:layout_height="wrap_content" android:clickable="true" android:focusable="true" - android:gravity="top" - android:orientation="horizontal" - android:paddingBottom="@dimen/message_vertical" - android:paddingEnd="@dimen/message_horizontal" - android:paddingLeft="@dimen/message_horizontal" - android:paddingRight="@dimen/message_horizontal" - android:paddingStart="@dimen/message_horizontal" - android:paddingTop="@dimen/message_vertical" + android:orientation="vertical" android:textAppearance="?android:attr/textAppearanceListItemSmall" tools:background="@android:color/background_light" tools:theme="@style/Theme.ChatTheme.Quassel_Light"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:paddingBottom="@dimen/message_vertical" + android:paddingEnd="@dimen/message_horizontal" + android:paddingLeft="@dimen/message_horizontal" + android:paddingRight="@dimen/message_horizontal" + android:paddingStart="@dimen/message_horizontal" + android:paddingTop="@dimen/message_vertical"> + <TextView android:id="@+id/time" android:layout_width="wrap_content" @@ -35,4 +39,12 @@ android:textColor="?attr/colorForeground" android:textIsSelectable="true" tools:text="justJanne: hiii" /> -</LinearLayout> + </LinearLayout> + + <View + android:id="@+id/markerline" + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?colorMarkerLine" + android:visibility="gone" /> +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/widget_chatmessage_server.xml b/app/src/main/res/layout/widget_chatmessage_server.xml index 59248a6ab..b9ba45aec 100644 --- a/app/src/main/res/layout/widget_chatmessage_server.xml +++ b/app/src/main/res/layout/widget_chatmessage_server.xml @@ -3,21 +3,24 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="?attr/colorBackgroundSecondary" android:clickable="true" android:focusable="true" - android:gravity="top" - android:orientation="horizontal" - android:paddingBottom="@dimen/message_vertical" - android:paddingEnd="@dimen/message_horizontal" - android:paddingLeft="@dimen/message_horizontal" - android:paddingRight="@dimen/message_horizontal" - android:paddingStart="@dimen/message_horizontal" - android:paddingTop="@dimen/message_vertical" + android:orientation="vertical" android:textAppearance="?android:attr/textAppearanceListItemSmall" tools:background="@android:color/background_light" tools:theme="@style/Theme.ChatTheme.Quassel_Light"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:paddingBottom="@dimen/message_vertical" + android:paddingEnd="@dimen/message_horizontal" + android:paddingLeft="@dimen/message_horizontal" + android:paddingRight="@dimen/message_horizontal" + android:paddingStart="@dimen/message_horizontal" + android:paddingTop="@dimen/message_vertical"> + <TextView android:id="@+id/time" android:layout_width="wrap_content" @@ -37,4 +40,12 @@ android:textIsSelectable="true" android:typeface="monospace" tools:text="Connecting to irc.freenode.net:6667..." /> -</LinearLayout> + </LinearLayout> + + <View + android:id="@+id/markerline" + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?colorMarkerLine" + android:visibility="gone" /> +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index cc5cf114c..eeb7e7e31 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -55,11 +55,12 @@ <attr name="colorBackgroundCard" format="color" /> <attr name="colorBackgroundDialog" format="color" /> + <attr name="colorMarkerLine" format="color" /> + <!-- Tint colors for drawer --> <attr name="colorTintActivity" format="color" /> <attr name="colorTintMessage" format="color" /> <attr name="colorTintHighlight" format="color" /> - <attr name="chatlineExpandedSize" /> <!-- Icons --> <attr name="colorOffline" format="color" /> diff --git a/app/src/main/res/values/themes_quassel.xml b/app/src/main/res/values/themes_quassel.xml index f83e1fffb..3d9c05174 100644 --- a/app/src/main/res/values/themes_quassel.xml +++ b/app/src/main/res/values/themes_quassel.xml @@ -37,6 +37,8 @@ <item name="colorBackgroundCard">#FFFFFF</item> <item name="colorBackgroundDialog">#FAFAFA</item> + <item name="colorMarkerLine">#ff0000</item> + <item name="colorTintActivity">#88cc33</item> <item name="colorTintMessage">#2277dd</item> <item name="colorTintHighlight">#ff8811</item> diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 1c33f64cc..a7cc8e972 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -23,6 +23,7 @@ dependencies { testImplementation("junit:junit:4.12") } +/* tasks.withType(KotlinCompile::class.java) { kotlinOptions { freeCompilerArgs = listOf( @@ -31,6 +32,7 @@ tasks.withType(KotlinCompile::class.java) { ) } } +*/ /** * Builds the dependency notation for the named AppCompat [module] at the given [version]. diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt index 0e0bbb12c..20279400a 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt @@ -12,15 +12,35 @@ class BufferSyncer constructor( proxy: SignalProxy ) : SyncableObject(proxy, "BufferSyncer"), IBufferSyncer { fun lastSeenMsg(buffer: BufferId): MsgId = _lastSeenMsg[buffer] ?: 0 + fun liveLastSeenMsg(buffer: BufferId): Observable<MsgId> + = live_lastSeenMsg.map { markerLine(buffer) }.distinctUntilChanged() + + fun liveLastSeenMsgs(): Observable<Map<BufferId, MsgId>> = live_lastSeenMsg + fun markerLine(buffer: BufferId): MsgId = _markerLines[buffer] ?: 0 + fun liveMarkerLine(buffer: BufferId): Observable<MsgId> + = live_markerLines.map { markerLine(buffer) }.distinctUntilChanged() + + fun liveMarkerLines(): Observable<Map<BufferId, MsgId>> = live_markerLines + fun activity(buffer: BufferId): Message_Types = _bufferActivities[buffer] ?: Message_Types.of() fun liveActivity(buffer: BufferId): Observable<Message_Types> = live_bufferActivities.map { activity(buffer) }.distinctUntilChanged() + fun liveActivities(): Observable<Map<BufferId, Message_Types>> = live_bufferActivities + fun highlightCount(buffer: BufferId): Int = _highlightCounts[buffer] ?: 0 fun liveHighlightCount(buffer: BufferId): Observable<Int> = live_highlightCounts.map { highlightCount(buffer) }.distinctUntilChanged() + fun liveHighlightCounts(): Observable<Map<BufferId, Int>> = live_highlightCounts + + fun bufferInfo(bufferId: BufferId) = _bufferInfos[bufferId] + fun liveBufferInfo(bufferId: BufferId) + = live_bufferInfos.map { bufferInfo(bufferId) }.distinctUntilChanged() + + fun liveBufferInfos(): Observable<Map<BufferId, BufferInfo>> = live_bufferInfos + override fun toVariantMap(): QVariantMap = mapOf( "Activities" to QVariant_(initActivities(), Type.QVariantList), "HighlightCounts" to QVariant_(initHighlightCounts(), Type.QVariantList), @@ -77,6 +97,7 @@ class BufferSyncer constructor( }.forEach { (buffer, activity) -> setBufferActivity(buffer, activity) } + live_bufferActivities.onNext(_bufferActivities) } override fun initSetHighlightCounts(data: QVariantList) { @@ -85,6 +106,7 @@ class BufferSyncer constructor( }.forEach { (buffer, count) -> setHighlightCount(buffer, count) } + live_highlightCounts.onNext(_highlightCounts) } override fun initSetLastSeenMsg(data: QVariantList) { @@ -93,6 +115,7 @@ class BufferSyncer constructor( }.forEach { (buffer, msgId) -> setLastSeenMsg(buffer, msgId) } + live_lastSeenMsg.onNext(_lastSeenMsg) } override fun initSetMarkerLines(data: QVariantList) { @@ -101,6 +124,7 @@ class BufferSyncer constructor( }.forEach { (buffer, msgId) -> setMarkerLine(buffer, msgId) } + live_markerLines.onNext(_markerLines) } fun initSetBufferInfos(infos: QVariantList?) { @@ -110,20 +134,19 @@ class BufferSyncer constructor( } override fun mergeBuffersPermanently(buffer1: BufferId, buffer2: BufferId) { - _lastSeenMsg.remove(buffer2) - _markerLines.remove(buffer2) - _bufferActivities.remove(buffer2) - _highlightCounts.remove(buffer2) - live_bufferInfos.onNext(_bufferInfos) + _lastSeenMsg.remove(buffer2);live_lastSeenMsg.onNext(_lastSeenMsg) + _markerLines.remove(buffer2);live_markerLines.onNext(_markerLines) + _bufferActivities.remove(buffer2);live_bufferActivities.onNext(_bufferActivities) + _highlightCounts.remove(buffer2);live_highlightCounts.onNext(_highlightCounts) + _bufferInfos.remove(buffer2);live_bufferInfos.onNext(_bufferInfos) } override fun removeBuffer(buffer: BufferId) { - _lastSeenMsg.remove(buffer) - _markerLines.remove(buffer) - _bufferActivities.remove(buffer) - _highlightCounts.remove(buffer) - _bufferInfos.remove(buffer) - live_bufferInfos.onNext(_bufferInfos) + _lastSeenMsg.remove(buffer);live_lastSeenMsg.onNext(_lastSeenMsg) + _markerLines.remove(buffer);live_markerLines.onNext(_markerLines) + _bufferActivities.remove(buffer);live_bufferActivities.onNext(_bufferActivities) + _highlightCounts.remove(buffer);live_highlightCounts.onNext(_highlightCounts) + _bufferInfos.remove(buffer);live_bufferInfos.onNext(_bufferInfos) } override fun renameBuffer(buffer: BufferId, newName: String) { @@ -134,11 +157,6 @@ class BufferSyncer constructor( } } - fun bufferInfo(bufferId: BufferId) = _bufferInfos[bufferId] - fun liveBufferInfo(bufferId: BufferId) = live_bufferInfos.distinctUntilChanged().map { - bufferInfo(bufferId) - } - fun bufferInfoUpdated(info: BufferInfo) { if (info != _bufferInfos[info.bufferId]) { _bufferInfos[info.bufferId] = info @@ -153,6 +171,7 @@ class BufferSyncer constructor( val oldLastSeenMsg = lastSeenMsg(buffer) if (oldLastSeenMsg < msgId) { _lastSeenMsg[buffer] = msgId + live_lastSeenMsg.onNext(_lastSeenMsg) super.setLastSeenMsg(buffer, msgId) } } @@ -162,6 +181,7 @@ class BufferSyncer constructor( return _markerLines[buffer] = msgId + live_markerLines.onNext(_markerLines) super.setMarkerLine(buffer, msgId) } @@ -179,15 +199,22 @@ class BufferSyncer constructor( } private val _lastSeenMsg: MutableMap<BufferId, MsgId> = mutableMapOf() + private val live_lastSeenMsg + = BehaviorSubject.createDefault(mapOf<BufferId, MsgId>()) + private val _markerLines: MutableMap<BufferId, MsgId> = mutableMapOf() + private val live_markerLines + = BehaviorSubject.createDefault(mapOf<BufferId, MsgId>()) + private val _bufferActivities: MutableMap<BufferId, Message_Types> = mutableMapOf() - private val live_bufferActivities = BehaviorSubject.createDefault( - mutableMapOf<BufferId, Message_Types>() - ) + private val live_bufferActivities + = BehaviorSubject.createDefault(mapOf<BufferId, Message_Types>()) + private val _highlightCounts: MutableMap<BufferId, Int> = mutableMapOf() - private val live_highlightCounts = BehaviorSubject.createDefault( - mutableMapOf<BufferId, Int>() - ) + private val live_highlightCounts + = BehaviorSubject.createDefault(mapOf<BufferId, Int>()) + private val _bufferInfos = mutableMapOf<BufferId, BufferInfo>() - val live_bufferInfos = BehaviorSubject.createDefault(mutableMapOf<BufferId, BufferInfo>()) + private val live_bufferInfos + = BehaviorSubject.createDefault(mapOf<BufferId, BufferInfo>()) } -- GitLab