diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferListAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferListAdapter.kt index 05ea46dc965b30531b786d6bc2dc80287623c06d..b17dc281a6222e3869ee814a98ca83611dbf5fd4 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferListAdapter.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferListAdapter.kt @@ -7,7 +7,6 @@ import android.arch.lifecycle.Observer import android.graphics.drawable.Drawable import android.support.v4.graphics.drawable.DrawableCompat import android.support.v7.util.DiffUtil -import android.support.v7.widget.AppCompatImageButton import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View @@ -17,6 +16,7 @@ import android.widget.TextView import butterknife.BindView import butterknife.ButterKnife import de.kuschku.libquassel.protocol.BufferId +import de.kuschku.libquassel.protocol.Buffer_Activity import de.kuschku.libquassel.protocol.NetworkId import de.kuschku.libquassel.quassel.BufferInfo import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork @@ -138,7 +138,9 @@ class BufferListAdapter( val info: BufferInfo, val network: INetwork.NetworkInfo, val bufferStatus: BufferStatus, - val description: String + val description: String, + val activity: Buffer_Activity, + val highlights: Int = 0 ) data class BufferState( @@ -160,7 +162,7 @@ class BufferListAdapter( private val expansionListener: ((NetworkId) -> Unit)? = null ) : BufferViewHolder(itemView) { @BindView(R.id.status) - lateinit var status: AppCompatImageButton + lateinit var status: ImageView @BindView(R.id.name) lateinit var name: TextView @@ -214,6 +216,11 @@ class BufferListAdapter( private val online: Drawable private val offline: Drawable + private var none: Int = 0 + private var activity: Int = 0 + private var message: Int = 0 + private var highlight: Int = 0 + init { ButterKnife.bind(this, itemView) itemView.setOnClickListener { @@ -225,9 +232,18 @@ class BufferListAdapter( online = itemView.context.getCompatDrawable(R.drawable.ic_status) offline = itemView.context.getCompatDrawable(R.drawable.ic_status_offline) - itemView.context.theme.styledAttributes(R.attr.colorAccent, R.attr.colorAway) { + itemView.context.theme.styledAttributes( + R.attr.colorAccent, R.attr.colorAway, + R.attr.colorForeground, R.attr.colorTintActivity, R.attr.colorTintMessage, + R.attr.colorTintHighlight + ) { DrawableCompat.setTint(online, getColor(0, 0)) DrawableCompat.setTint(offline, getColor(1, 0)) + + none = getColor(2, 0) + activity = getColor(3, 0) + message = getColor(4, 0) + highlight = getColor(5, 0) } } @@ -237,6 +253,15 @@ class BufferListAdapter( name.text = props.info.bufferName description.text = props.description + name.setTextColor( + when (props.activity) { + Buffer_Activity.NoActivity -> none + Buffer_Activity.OtherActivity -> activity + Buffer_Activity.NewMessage -> message + Buffer_Activity.Highlight -> highlight + } + ) + description.visibility = if (props.description == "") { View.GONE } else { @@ -270,6 +295,11 @@ class BufferListAdapter( private val online: Drawable private val offline: Drawable + private var none: Int = 0 + private var activity: Int = 0 + private var message: Int = 0 + private var highlight: Int = 0 + init { ButterKnife.bind(this, itemView) itemView.setOnClickListener { @@ -281,9 +311,18 @@ class BufferListAdapter( online = itemView.context.getCompatDrawable(R.drawable.ic_status_channel) offline = itemView.context.getCompatDrawable(R.drawable.ic_status_channel_offline) - itemView.context.theme.styledAttributes(R.attr.colorAccent, R.attr.colorAway) { + itemView.context.theme.styledAttributes( + R.attr.colorAccent, R.attr.colorAway, + R.attr.colorForeground, R.attr.colorTintActivity, R.attr.colorTintMessage, + R.attr.colorTintHighlight + ) { DrawableCompat.setTint(online, getColor(0, 0)) DrawableCompat.setTint(offline, getColor(1, 0)) + + none = getColor(2, 0) + activity = getColor(3, 0) + message = getColor(4, 0) + highlight = getColor(5, 0) } } @@ -293,6 +332,15 @@ class BufferListAdapter( name.text = props.info.bufferName description.text = props.description + name.setTextColor( + when (props.activity) { + Buffer_Activity.NoActivity -> none + Buffer_Activity.OtherActivity -> activity + Buffer_Activity.NewMessage -> message + Buffer_Activity.Highlight -> highlight + } + ) + description.visibility = if (props.description == "") { View.GONE } else { @@ -327,6 +375,11 @@ class BufferListAdapter( private val away: Drawable private val offline: Drawable + private var none: Int = 0 + private var activity: Int = 0 + private var message: Int = 0 + private var highlight: Int = 0 + init { ButterKnife.bind(this, itemView) itemView.setOnClickListener { @@ -339,10 +392,19 @@ class BufferListAdapter( away = itemView.context.getCompatDrawable(R.drawable.ic_status) offline = itemView.context.getCompatDrawable(R.drawable.ic_status_offline) - itemView.context.theme.styledAttributes(R.attr.colorAccent, R.attr.colorAway) { + itemView.context.theme.styledAttributes( + R.attr.colorAccent, R.attr.colorAway, + R.attr.colorForeground, R.attr.colorTintActivity, R.attr.colorTintMessage, + R.attr.colorTintHighlight + ) { DrawableCompat.setTint(online, getColor(0, 0)) DrawableCompat.setTint(away, getColor(1, 0)) DrawableCompat.setTint(offline, getColor(1, 0)) + + none = getColor(2, 0) + activity = getColor(3, 0) + message = getColor(4, 0) + highlight = getColor(5, 0) } } @@ -352,6 +414,15 @@ class BufferListAdapter( name.text = props.info.bufferName description.text = props.description + name.setTextColor( + when (props.activity) { + Buffer_Activity.NoActivity -> none + Buffer_Activity.OtherActivity -> activity + Buffer_Activity.NewMessage -> message + Buffer_Activity.Highlight -> highlight + } + ) + description.visibility = if (props.description == "") { View.GONE } else { 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 3deed0c90e1b875c599ccefad029e0875f6e5480..b0cc94e298a8e85472512654a057cba72ee1f041 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 @@ -11,12 +11,15 @@ import android.widget.AdapterView import butterknife.BindView import butterknife.ButterKnife import de.kuschku.libquassel.protocol.BufferId +import de.kuschku.libquassel.protocol.Buffer_Activity +import de.kuschku.libquassel.protocol.Message import de.kuschku.libquassel.protocol.NetworkId import de.kuschku.libquassel.quassel.BufferInfo import de.kuschku.libquassel.quassel.syncables.* import de.kuschku.libquassel.session.Backend import de.kuschku.libquassel.session.ISession import de.kuschku.libquassel.session.SessionManager +import de.kuschku.libquassel.util.hasFlag import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.util.AndroidHandlerThread import de.kuschku.quasseldroid_ng.util.helper.map @@ -76,76 +79,97 @@ class BufferViewConfigFragment : ServiceBoundFragment() { private val bufferList: LiveData<List<BufferListAdapter.BufferProps>?> = sessionManager.switchMap { manager -> bufferIdList.switchMapRx { ids -> - Observable.combineLatest( - ids.mapNotNull { id -> - manager.bufferSyncer?.bufferInfo( - id - ) - }.mapNotNull { - val network = manager.networks[it.networkId] - if (network == null) { - null - } else { - it to network - } - }.map { (info, network) -> - when (info.type.toInt()) { - BufferInfo.Type.QueryBuffer.toInt() -> { - network.liveIrcUser(info.bufferName).distinctUntilChanged().switchMap { user -> - user.live_away.switchMap { away -> - user.live_realName.map { realName -> + val bufferSyncer = manager.bufferSyncer + if (bufferSyncer != null) { + Observable.combineLatest( + ids.mapNotNull { id -> + manager.bufferSyncer?.bufferInfo( + id + ) + }.mapNotNull { + val network = manager.networks[it.networkId] + if (network == null) { + null + } else { + it to network + } + }.map { (info, network) -> + bufferSyncer.liveActivity(info.bufferId).map { activity -> + when { + activity.hasFlag(Message.MessageType.Plain) || + activity.hasFlag(Message.MessageType.Notice) || + activity.hasFlag(Message.MessageType.Action) -> Buffer_Activity.NewMessage + activity.nonEmpty() -> Buffer_Activity.OtherActivity + else -> Buffer_Activity.NoActivity + } + }.switchMap { activity -> + when (info.type.toInt()) { + BufferInfo.Type.QueryBuffer.toInt() -> { + network.liveIrcUser(info.bufferName).switchMap { user -> + user.live_away.switchMap { away -> + user.live_realName.map { realName -> + BufferListAdapter.BufferProps( + info = info, + network = network.networkInfo(), + bufferStatus = when { + user == IrcUser.NULL -> BufferListAdapter.BufferStatus.OFFLINE + away -> BufferListAdapter.BufferStatus.AWAY + else -> BufferListAdapter.BufferStatus.ONLINE + }, + description = realName, + activity = activity + ) + } + } + } + } + BufferInfo.Type.ChannelBuffer.toInt() -> { + network.liveIrcChannel( + info.bufferName + ).switchMap { channel -> + channel.live_topic.map { topic -> + BufferListAdapter.BufferProps( + info = info, + network = network.networkInfo(), + bufferStatus = when (channel) { + IrcChannel.NULL -> BufferListAdapter.BufferStatus.OFFLINE + else -> BufferListAdapter.BufferStatus.ONLINE + }, + description = topic, + activity = activity + ) + } + } + } + BufferInfo.Type.StatusBuffer.toInt() -> { + network.liveConnectionState.map { BufferListAdapter.BufferProps( info = info, network = network.networkInfo(), - bufferStatus = when { - user == IrcUser.NULL -> BufferListAdapter.BufferStatus.OFFLINE - away -> BufferListAdapter.BufferStatus.AWAY - else -> BufferListAdapter.BufferStatus.ONLINE - }, - description = realName + bufferStatus = BufferListAdapter.BufferStatus.OFFLINE, + description = "", + activity = activity ) } } - } - } - BufferInfo.Type.ChannelBuffer.toInt() -> { - network.liveIrcChannel(info.bufferName).distinctUntilChanged().switchMap { channel -> - channel.live_topic.map { topic -> + else -> Observable.just( BufferListAdapter.BufferProps( info = info, network = network.networkInfo(), - bufferStatus = when (channel) { - IrcChannel.NULL -> BufferListAdapter.BufferStatus.OFFLINE - else -> BufferListAdapter.BufferStatus.ONLINE - }, - description = topic + bufferStatus = BufferListAdapter.BufferStatus.OFFLINE, + description = "", + activity = activity ) - } - } - } - BufferInfo.Type.StatusBuffer.toInt() -> { - network.liveConnectionState.map { - BufferListAdapter.BufferProps( - info = info, - network = network.networkInfo(), - bufferStatus = BufferListAdapter.BufferStatus.OFFLINE, - description = "" ) } } - else -> Observable.just( - BufferListAdapter.BufferProps( - info = info, - network = network.networkInfo(), - bufferStatus = BufferListAdapter.BufferStatus.OFFLINE, - description = "" - ) - ) + }, { array: Array<Any> -> + array.toList() as List<BufferListAdapter.BufferProps> } - }, { array: Array<Any> -> - array.toList() as List<BufferListAdapter.BufferProps> - } - ) + ) + } else { + Observable.empty() + } } } diff --git a/app/src/main/res/layout/widget_buffer.xml b/app/src/main/res/layout/widget_buffer.xml index 4e1e095d18bbab557015251f378fdb2350c43445..fdf7d6c7118645c5700f909077d4c3ad0298f23e 100644 --- a/app/src/main/res/layout/widget_buffer.xml +++ b/app/src/main/res/layout/widget_buffer.xml @@ -3,6 +3,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" + android:foreground="?attr/selectableItemBackgroundBorderless" android:minHeight="48dp" android:paddingBottom="8dp" android:paddingLeft="16dp" diff --git a/app/src/main/res/layout/widget_network.xml b/app/src/main/res/layout/widget_network.xml index 974a81e407c94d5b5d701f730f2c37624bbef395..fa16ceb4fc0d01aa86fd03fcc425c93cb74c6bae 100644 --- a/app/src/main/res/layout/widget_network.xml +++ b/app/src/main/res/layout/widget_network.xml @@ -4,6 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" + android:foreground="?attr/selectableItemBackgroundBorderless" android:minHeight="48dp" tools:background="@android:color/background_light" tools:theme="@style/Theme.ChatTheme.Quassel_Light"> @@ -24,13 +25,10 @@ android:textStyle="bold" tools:text="Freenode" /> - <android.support.v7.widget.AppCompatImageButton + <ImageView android:id="@+id/status" - style="?attr/buttonStyleSmall" android:layout_width="wrap_content" android:layout_height="match_parent" - android:background="@null" - android:foreground="?attr/selectableItemBackgroundBorderless" android:minWidth="72dp" android:paddingBottom="12dp" android:paddingEnd="16dp" 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 dea8e0f27094b10689f0a26e9517c90babe243bf..04d4f643702bb5bba6c166512c000869afcbde81 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 @@ -5,6 +5,8 @@ import de.kuschku.libquassel.protocol.Type import de.kuschku.libquassel.quassel.BufferInfo import de.kuschku.libquassel.quassel.syncables.interfaces.IBufferSyncer import de.kuschku.libquassel.session.SignalProxy +import io.reactivex.Observable +import io.reactivex.subjects.BehaviorSubject class BufferSyncer constructor( proxy: SignalProxy @@ -12,6 +14,8 @@ class BufferSyncer constructor( fun lastSeenMsg(buffer: BufferId): MsgId = _lastSeenMsg[buffer] ?: 0 fun markerLine(buffer: BufferId): MsgId = _markerLines[buffer] ?: 0 fun activity(buffer: BufferId): Message_Types = _bufferActivities[buffer] ?: Message_Types.of() + fun liveActivity(buffer: BufferId): Observable<Message_Types> + = live_bufferActivities.map { activity(buffer) }.distinctUntilChanged() override fun toVariantMap(): QVariantMap = mapOf( "Activities" to QVariant_(initActivities(), Type.QVariantList), @@ -125,10 +129,14 @@ class BufferSyncer constructor( val flags = Message_Types.of<Message_Type>(activity) super.setBufferActivity(buffer, activity) _bufferActivities[buffer] = flags + live_bufferActivities.onNext(_bufferActivities) } private val _lastSeenMsg: MutableMap<BufferId, MsgId> = mutableMapOf() private val _markerLines: MutableMap<BufferId, MsgId> = mutableMapOf() private val _bufferActivities: MutableMap<BufferId, Message_Types> = mutableMapOf() + private val live_bufferActivities = BehaviorSubject.createDefault( + mutableMapOf<BufferId, Message_Types>() + ) private val _bufferInfos = mutableMapOf<BufferId, BufferInfo>() } diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt index 2e672826d1c46361a169ff45c48e8dab89744266..294ef1b7f5cfab6a1e5956881aa7c225475ad2ee 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt @@ -336,7 +336,12 @@ class Network constructor( } fun ircUser(nickName: String?) = _ircUsers[nickName?.toLowerCase(Locale.ENGLISH)] - fun liveIrcUser(nickName: String?) = live_ircUsers.map { ircUser(nickName) ?: IrcUser.NULL } + fun liveIrcUser(nickName: String?) = live_ircUsers.map { + ircUser( + nickName + ) ?: IrcUser.NULL + }.distinctUntilChanged() + fun ircUsers() = _ircUsers.values.toList() fun ircUserCount(): UInt = _ircUsers.size fun newIrcChannel(channelName: String, initData: QVariantMap = emptyMap()): IrcChannel { @@ -363,7 +368,7 @@ class Network constructor( ircChannel( channelName ) ?: IrcChannel.NULL - } + }.distinctUntilChanged() fun ircChannels() = _ircChannels.values.toList() fun ircChannelCount(): UInt = _ircChannels.size diff --git a/lib/src/main/java/de/kuschku/libquassel/util/Flag.kt b/lib/src/main/java/de/kuschku/libquassel/util/Flag.kt index e670ed8b4f25baf06d7993037d44d47ef7238724..3cf89ad0ffb86b88bdeb72188670e908eb387d20 100644 --- a/lib/src/main/java/de/kuschku/libquassel/util/Flag.kt +++ b/lib/src/main/java/de/kuschku/libquassel/util/Flag.kt @@ -36,6 +36,9 @@ data class Flags<E>( fun enabledValues() = values?.filter { hasFlag(it) }?.toSet() ?: emptySet() + fun empty() = value == 0 + fun nonEmpty() = !empty() + override fun toString() = if (values != null) { enabledValues().joinToString("|", "[", "]") } else {