From 4cf5fa57f5b9bca1565ad3b2129481679d03a5b8 Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Sat, 17 Feb 2018 15:03:47 +0100 Subject: [PATCH] Improved nick list, added drawer toggle --- .../ui/chat/BufferListAdapter.kt | 28 +--- .../quasseldroid_ng/ui/chat/ChatActivity.kt | 13 +- .../ui/chat/NickListAdapter.kt | 124 ++++++++++++++++++ .../ui/chat/NickListFragment.kt | 122 +++++++++++++++++ .../quasseldroid_ng/util/helper/ViewHelper.kt | 9 ++ app/src/main/res/drawable/bg_badge.xml | 10 ++ app/src/main/res/layout/activity_main.xml | 8 +- .../main/res/layout/fragment_nick_list.xml | 1 - app/src/main/res/layout/widget_buffer.xml | 2 +- app/src/main/res/layout/widget_network.xml | 3 +- app/src/main/res/layout/widget_nick.xml | 72 ++++++++++ app/src/main/res/layout/widget_nick_away.xml | 74 +++++++++++ .../primitive/serializer/StringSerializer.kt | 4 + .../libquassel/quassel/syncables/Network.kt | 42 +++--- 14 files changed, 467 insertions(+), 45 deletions(-) create mode 100644 app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListAdapter.kt create mode 100644 app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListFragment.kt create mode 100644 app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/ViewHelper.kt create mode 100644 app/src/main/res/drawable/bg_badge.xml create mode 100644 app/src/main/res/layout/widget_nick.xml create mode 100644 app/src/main/res/layout/widget_nick_away.xml 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 17bc32a3d..21b8c0bca 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 @@ -17,6 +17,7 @@ import butterknife.BindView import butterknife.ButterKnife import de.kuschku.libquassel.protocol.BufferId import de.kuschku.libquassel.protocol.Buffer_Activity +import de.kuschku.libquassel.protocol.Buffer_Type import de.kuschku.libquassel.protocol.NetworkId import de.kuschku.libquassel.quassel.BufferInfo import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork @@ -24,6 +25,7 @@ import de.kuschku.libquassel.util.hasFlag import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.util.helper.getCompatDrawable import de.kuschku.quasseldroid_ng.util.helper.styledAttributes +import de.kuschku.quasseldroid_ng.util.helper.visibleIf import de.kuschku.quasseldroid_ng.util.helper.zip class BufferListAdapter( @@ -55,6 +57,8 @@ class BufferListAdapter( val old: List<BufferListItem> = data val new: List<BufferListItem> = list.sortedBy { props -> + !props.info.type.hasFlag(Buffer_Type.StatusBuffer) + }.sortedBy { props -> props.network.networkName }.map { props -> BufferListItem( @@ -150,12 +154,6 @@ class BufferListAdapter( abstract class BufferViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { abstract fun bind(props: BufferProps, state: BufferState) - fun <T> status(target: T, actual: T) = if (target == actual) { - View.VISIBLE - } else { - View.GONE - } - class StatusBuffer( itemView: View, private val clickListener: ((BufferId) -> Unit)? = null, @@ -286,11 +284,7 @@ class BufferListAdapter( } ) - description.visibility = if (props.description == "") { - View.GONE - } else { - View.VISIBLE - } + description.visibleIf(props.description.isNotBlank()) status.setImageDrawable( when (props.bufferStatus) { @@ -365,11 +359,7 @@ class BufferListAdapter( } ) - description.visibility = if (props.description == "") { - View.GONE - } else { - View.VISIBLE - } + description.visibleIf(props.description.isNotBlank()) status.setImageDrawable( when (props.bufferStatus) { @@ -447,11 +437,7 @@ class BufferListAdapter( } ) - description.visibility = if (props.description == "") { - View.GONE - } else { - View.VISIBLE - } + description.visibleIf(props.description.isNotBlank()) status.setImageDrawable( when (props.bufferStatus) { diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt index 679b94aa2..1b4b2d5c4 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt @@ -34,6 +34,7 @@ import de.kuschku.quasseldroid_ng.util.ui.MaterialContentLoadingProgressBar class ChatActivity : ServiceBoundActivity() { private var contentMessages: MessageListFragment? = null private var chatListFragment: BufferViewConfigFragment? = null + private var nickListFragment: NickListFragment? = null @BindView(R.id.drawerLayout) lateinit var drawerLayout: DrawerLayout @@ -78,10 +79,14 @@ class ChatActivity : ServiceBoundActivity() { chatListFragment = supportFragmentManager.findFragmentById( R.id.chatListFragment ) as? BufferViewConfigFragment + nickListFragment = supportFragmentManager.findFragmentById( + R.id.nickListFragment + ) as? NickListFragment setSupportActionBar(toolbar) chatListFragment?.currentBuffer?.value = currentBuffer + nickListFragment?.currentBuffer?.value = currentBuffer contentMessages?.currentBuffer?.value = currentBuffer chatListFragment?.clickListeners?.add { @@ -97,6 +102,7 @@ class ChatActivity : ServiceBoundActivity() { } ) + supportActionBar?.setDisplayHomeAsUpEnabled(true) drawerToggle = ActionBarDrawerToggle( this, drawerLayout, @@ -185,7 +191,10 @@ class ChatActivity : ServiceBoundActivity() { } override fun onOptionsItemSelected(item: MenuItem?) = when (item?.itemId) { - R.id.disconnect -> { + android.R.id.home -> { + drawerToggle.onOptionsItemSelected(item) + } + R.id.disconnect -> { handler.post { getSharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE).editApply { putBoolean(Keys.Status.reconnect, false) @@ -196,7 +205,7 @@ class ChatActivity : ServiceBoundActivity() { } true } - else -> super.onOptionsItemSelected(item) + else -> super.onOptionsItemSelected(item) } override fun onDestroy() { diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListAdapter.kt new file mode 100644 index 000000000..dea956b64 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListAdapter.kt @@ -0,0 +1,124 @@ +package de.kuschku.quasseldroid_ng.ui.chat + +import android.arch.lifecycle.LifecycleOwner +import android.arch.lifecycle.LiveData +import android.arch.lifecycle.Observer +import android.support.v7.util.DiffUtil +import android.support.v7.widget.RecyclerView +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import butterknife.BindView +import butterknife.ButterKnife +import de.kuschku.quasseldroid_ng.R +import de.kuschku.quasseldroid_ng.util.helper.visibleIf + +class NickListAdapter( + lifecycleOwner: LifecycleOwner, + liveData: LiveData<List<IrcUserItem>?>, + runInBackground: (() -> Unit) -> Any, + runOnUiThread: (Runnable) -> Any, + private val clickListener: ((String) -> Unit)? = null +) : RecyclerView.Adapter<NickListAdapter.NickViewHolder>() { + var data = mutableListOf<IrcUserItem>() + + init { + liveData.observe( + lifecycleOwner, Observer { it: List<IrcUserItem>? -> + runInBackground { + val list = it ?: emptyList() + val old: List<IrcUserItem> = data + val new: List<IrcUserItem> = list.sortedBy { it.lowestMode } + val result = DiffUtil.calculateDiff( + object : DiffUtil.Callback() { + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) + = old[oldItemPosition].nick == new[newItemPosition].nick + + override fun getOldListSize() = old.size + override fun getNewListSize() = new.size + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) + = old[oldItemPosition] == new[newItemPosition] + }, true + ) + runOnUiThread( + Runnable { + data.clear() + data.addAll(new) + result.dispatchUpdatesTo(this@NickListAdapter) + } + ) + } + } + ) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = NickViewHolder( + LayoutInflater.from(parent.context).inflate( + when (viewType) { + VIEWTYPE_AWAY -> R.layout.widget_nick_away + else -> R.layout.widget_nick + }, parent, false + ), + clickListener = clickListener + ) + + override fun onBindViewHolder(holder: NickViewHolder, position: Int) + = holder.bind(data[position]) + + override fun getItemCount() = data.size + + override fun getItemViewType(position: Int) = if (data[position].away) { + VIEWTYPE_AWAY + } else { + VIEWTYPE_ACTIVE + } + + data class IrcUserItem( + val nick: String, + val modes: String, + val lowestMode: Int, + val realname: String, + val away: Boolean + ) + + class NickViewHolder( + itemView: View, + private val clickListener: ((String) -> Unit)? = null + ) : RecyclerView.ViewHolder(itemView) { + @BindView(R.id.modes) + lateinit var modes: TextView + + @BindView(R.id.nick) + lateinit var nick: TextView + + @BindView(R.id.realname) + lateinit var realname: TextView + + var user: String? = null + + init { + ButterKnife.bind(this, itemView) + itemView.setOnClickListener { + val nick = user + if (nick != null) + clickListener?.invoke(nick) + } + } + + fun bind(data: IrcUserItem) { + user = data.nick + + nick.text = data.nick + modes.text = data.modes + realname.text = data.realname + + modes.visibleIf(data.modes.isNotBlank()) + } + } + + companion object { + val VIEWTYPE_ACTIVE = 0 + val VIEWTYPE_AWAY = 1 + } +} \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListFragment.kt new file mode 100644 index 000000000..39d97df1a --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListFragment.kt @@ -0,0 +1,122 @@ +package de.kuschku.quasseldroid_ng.ui.chat + +import android.arch.lifecycle.LiveData +import android.arch.lifecycle.MutableLiveData +import android.os.Bundle +import android.support.v7.widget.DefaultItemAnimator +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import butterknife.BindView +import butterknife.ButterKnife +import de.kuschku.libquassel.protocol.BufferId +import de.kuschku.libquassel.protocol.Buffer_Type +import de.kuschku.libquassel.session.Backend +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 +import de.kuschku.quasseldroid_ng.util.helper.switchMap +import de.kuschku.quasseldroid_ng.util.helper.switchMapRx +import de.kuschku.quasseldroid_ng.util.service.ServiceBoundFragment +import io.reactivex.Observable +import io.reactivex.Observable.zip +import io.reactivex.functions.BiFunction + +class NickListFragment : ServiceBoundFragment() { + private val handlerThread = AndroidHandlerThread("NickList") + + @BindView(R.id.nickList) + lateinit var nickList: RecyclerView + + val currentBuffer: MutableLiveData<LiveData<BufferId?>?> = MutableLiveData() + val buffer = currentBuffer.switchMap { it } + + private val sessionManager: LiveData<SessionManager?> + = backend.map(Backend::sessionManager) + + private val ircChannel: LiveData<List<NickListAdapter.IrcUserItem>?> + = sessionManager.switchMapRx(SessionManager::session).switchMap { session -> + buffer.switchMapRx { + val bufferSyncer = session.bufferSyncer + val bufferInfo = bufferSyncer?.bufferInfo(it) + if (bufferInfo?.type?.hasFlag(Buffer_Type.ChannelBuffer) == true) { + val network = session.networks[bufferInfo.networkId] + val ircChannel = network?.ircChannel(bufferInfo.bufferName) + if (ircChannel != null) { + Observable.combineLatest( + ircChannel.ircUsers().map { user -> + zip( + user.live_realName, user.live_away, + BiFunction<String, Boolean, Pair<String, Boolean>> { a, b -> Pair(a, b) } + ).map { (realName, away) -> + val userModes = ircChannel.userModes(user) + val prefixModes = network.prefixModes() + + val lowestMode = userModes.mapNotNull { + prefixModes.indexOf(it) + }.min() ?: prefixModes.size + + NickListAdapter.IrcUserItem( + user.nick(), + network.modesToPrefixes(userModes), + lowestMode, + realName, + away + ) + } + }, { array: Array<Any> -> + array.toList() as List<NickListAdapter.IrcUserItem> + } + ) + } else { + Observable.just(emptyList()) + } + } else { + Observable.just(emptyList()) + } + } + } + + private val nicks: LiveData<List<NickListAdapter.IrcUserItem>?> = ircChannel + + override fun onCreate(savedInstanceState: Bundle?) { + handlerThread.onCreate() + super.onCreate(savedInstanceState) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + val view = inflater.inflate(R.layout.fragment_nick_list, container, false) + ButterKnife.bind(this, view) + + nickList.adapter = NickListAdapter( + this, + nicks, + handlerThread::post, + activity!!::runOnUiThread, + clickListener + ) + + nickList.layoutManager = LinearLayoutManager(context) + nickList.itemAnimator = DefaultItemAnimator() + + return view + } + + override fun onDestroy() { + handlerThread.onDestroy() + super.onDestroy() + } + + val clickListeners = mutableListOf<(String) -> Unit>() + + private val clickListener: ((String) -> Unit)? = { + for (clickListener in clickListeners) { + clickListener.invoke(it) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/ViewHelper.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/ViewHelper.kt new file mode 100644 index 000000000..c7b18b2e6 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/ViewHelper.kt @@ -0,0 +1,9 @@ +package de.kuschku.quasseldroid_ng.util.helper + +import android.view.View + +fun View.visibleIf(check: Boolean) = if (check) { + this.visibility = View.VISIBLE +} else { + this.visibility = View.GONE +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_badge.xml b/app/src/main/res/drawable/bg_badge.xml new file mode 100644 index 000000000..da40f3172 --- /dev/null +++ b/app/src/main/res/drawable/bg_badge.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid /> + <padding + android:bottom="4dp" + android:left="8dp" + android:right="8dp" + android:top="4dp" /> + <corners android:radius="16dp" /> +</shape> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 98bd94628..4ba82b1eb 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -137,7 +137,13 @@ </LinearLayout> - <include layout="@layout/fragment_nick_list" /> + <fragment + android:id="@+id/nickListFragment" + android:name="de.kuschku.quasseldroid_ng.ui.chat.NickListFragment" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="end" + tools:layout="@layout/fragment_nick_list" /> <de.kuschku.quasseldroid_ng.util.ui.NavigationDrawerLayout android:layout_width="match_parent" diff --git a/app/src/main/res/layout/fragment_nick_list.xml b/app/src/main/res/layout/fragment_nick_list.xml index eba412b14..e7b01adea 100644 --- a/app/src/main/res/layout/fragment_nick_list.xml +++ b/app/src/main/res/layout/fragment_nick_list.xml @@ -3,7 +3,6 @@ android:id="@+id/nickList" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_gravity="end" android:background="?attr/colorBackground" android:clipToPadding="false" android:fitsSystemWindows="true" diff --git a/app/src/main/res/layout/widget_buffer.xml b/app/src/main/res/layout/widget_buffer.xml index f057d26ad..12fdcea15 100644 --- a/app/src/main/res/layout/widget_buffer.xml +++ b/app/src/main/res/layout/widget_buffer.xml @@ -34,10 +34,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" + android:fontFamily="sans-serif-medium" android:singleLine="true" android:textColor="?attr/colorTextPrimary" android:textSize="13sp" - android:textStyle="bold" tools:text="#quasseldroid" /> <TextView diff --git a/app/src/main/res/layout/widget_network.xml b/app/src/main/res/layout/widget_network.xml index 0ec8859d2..8d68d7c8e 100644 --- a/app/src/main/res/layout/widget_network.xml +++ b/app/src/main/res/layout/widget_network.xml @@ -29,10 +29,10 @@ android:layout_marginRight="16dp" android:layout_marginTop="8dp" android:layout_weight="1" + android:fontFamily="sans-serif-medium" android:singleLine="true" android:textColor="?attr/colorTextSecondary" android:textSize="14sp" - android:textStyle="bold" tools:text="Freenode" /> <ImageView @@ -41,7 +41,6 @@ android:layout_height="match_parent" android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true" - android:contentDescription="Expand" android:focusable="true" android:minWidth="72dp" android:paddingBottom="12dp" diff --git a/app/src/main/res/layout/widget_nick.xml b/app/src/main/res/layout/widget_nick.xml new file mode 100644 index 000000000..ea3530b17 --- /dev/null +++ b/app/src/main/res/layout/widget_nick.xml @@ -0,0 +1,72 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="56dp" + android:background="?selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:orientation="horizontal" + android:paddingEnd="?listPreferredItemPaddingRight" + android:paddingLeft="?listPreferredItemPaddingLeft" + android:paddingRight="?listPreferredItemPaddingRight" + android:paddingStart="?listPreferredItemPaddingLeft" + tools:background="@android:color/background_light" + tools:theme="@style/Theme.ChatTheme.Quassel_Light"> + + <FrameLayout + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:minWidth="40dp"> + + <android.support.v7.widget.AppCompatTextView + android:id="@+id/modes" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginBottom="8dp" + android:layout_marginTop="8dp" + android:background="@drawable/bg_badge" + android:fontFamily="monospace" + android:gravity="center" + android:minHeight="24dp" + android:minWidth="24dp" + android:textColor="?colorBackground" + android:textSize="12sp" + android:textStyle="bold" + app:backgroundTint="@color/colorAccent" + tools:text="\@" /> + </FrameLayout> + + <LinearLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_marginLeft="16dp" + android:layout_marginStart="16dp" + android:layout_weight="1" + android:gravity="center_vertical|start" + android:orientation="vertical"> + + <TextView + android:id="@+id/nick" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:fontFamily="sans-serif-medium" + android:gravity="center_vertical|start" + android:singleLine="true" + android:textColor="?colorTextPrimary" + android:textSize="13sp" + tools:text="justJanne" /> + + <TextView + android:id="@+id/realname" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:fontFamily="sans-serif" + android:gravity="center_vertical|start" + android:singleLine="true" + android:textColor="?colorTextSecondary" + android:textSize="12sp" + tools:text="Janne Koschinski: https://kuschku.de/" /> + </LinearLayout> +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/widget_nick_away.xml b/app/src/main/res/layout/widget_nick_away.xml new file mode 100644 index 000000000..3e82539c8 --- /dev/null +++ b/app/src/main/res/layout/widget_nick_away.xml @@ -0,0 +1,74 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="56dp" + android:background="?selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:orientation="horizontal" + android:paddingEnd="?listPreferredItemPaddingRight" + android:paddingLeft="?listPreferredItemPaddingLeft" + android:paddingRight="?listPreferredItemPaddingRight" + android:paddingStart="?listPreferredItemPaddingLeft" + tools:background="@android:color/background_light" + tools:theme="@style/Theme.ChatTheme.Quassel_Light"> + + <FrameLayout + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:minWidth="40dp"> + + <android.support.v7.widget.AppCompatTextView + android:id="@+id/modes" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginBottom="8dp" + android:layout_marginTop="8dp" + android:background="@drawable/bg_badge" + android:fontFamily="monospace" + android:gravity="center" + android:minHeight="24dp" + android:minWidth="24dp" + android:textColor="?colorBackground" + android:textSize="12sp" + android:textStyle="bold" + app:backgroundTint="@color/colorAccent" + tools:text="\@" /> + </FrameLayout> + + <LinearLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_marginLeft="16dp" + android:layout_marginStart="16dp" + android:layout_weight="1" + android:gravity="center_vertical|start" + android:orientation="vertical"> + + <TextView + android:id="@+id/nick" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:fontFamily="sans-serif-medium" + android:gravity="center_vertical|start" + android:singleLine="true" + android:textColor="?colorTextSecondary" + android:textSize="13sp" + android:textStyle="italic" + tools:text="justJanne" /> + + <TextView + android:id="@+id/realname" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:fontFamily="sans-serif" + android:gravity="center_vertical|start" + android:singleLine="true" + android:textColor="?colorTextSecondary" + android:textSize="12sp" + android:textStyle="italic" + tools:text="Janne Koschinski: https://kuschku.de/" /> + </LinearLayout> +</LinearLayout> \ No newline at end of file diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt index e0328ec12..9f49f4d62 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt @@ -42,6 +42,7 @@ abstract class StringSerializer( return buf } + @Synchronized override fun serialize(buffer: ChainedByteBuffer, data: String?, features: Quassel_Features) { if (data == null) { IntSerializer.serialize(buffer, -1, features) @@ -58,6 +59,7 @@ abstract class StringSerializer( } } + @Synchronized fun serialize(data: String?): ByteBuffer = if (data == null) { ByteBuffer.allocate(0) } else { @@ -68,6 +70,7 @@ abstract class StringSerializer( encoder.encode(charBuffer) } + @Synchronized fun deserializeAll(buffer: ByteBuffer): String? { val len = buffer.remaining() return if (len == -1) { @@ -85,6 +88,7 @@ abstract class StringSerializer( } } + @Synchronized override fun deserialize(buffer: ByteBuffer, features: Quassel_Features): String? { val len = IntSerializer.deserialize(buffer, features) return if (len == -1) { 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 f08a638c7..680286716 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 @@ -69,13 +69,21 @@ class Network constructor( = prefixModes().elementAtOrNull(prefixes().indexOf(prefix)) fun prefixesToModes(prefixes: String): String - = prefixes.mapNotNull(this::prefixToMode).joinToString() + = prefixes.mapNotNull { + prefixes().indexOf(it) + }.sorted().mapNotNull { + prefixModes().elementAtOrNull(it) + }.joinToString("") fun modeToPrefix(mode: Char): Char? = prefixes().elementAtOrNull(prefixModes().indexOf(mode)) fun modesToPrefixes(modes: String): String - = modes.mapNotNull(this::modeToPrefix).joinToString() + = modes.mapNotNull { + prefixModes().indexOf(it) + }.sorted().mapNotNull { + prefixes().elementAtOrNull(it) + }.joinToString("") fun channelModeType(mode: Char): ChannelModeType { if (_channelModes == null) @@ -204,31 +212,31 @@ class Network constructor( setUnlimitedMessageRate(info.unlimitedMessageRate) } - fun prefixes(): Set<Char> { + fun prefixes(): List<Char> { if (_prefixes == null) determinePrefixes() - return _prefixes!! + return _prefixes ?: emptyList() } - fun prefixModes(): Set<Char> { + fun prefixModes(): List<Char> { if (_prefixModes == null) determinePrefixes() - return _prefixModes!! + return _prefixModes ?: emptyList() } private fun determinePrefixes() { // seems like we have to construct them first val prefix = support("PREFIX") if (prefix.startsWith("(") && prefix.contains(")")) { - val (prefixes, prefixModes) = prefix.substring(1) + val (prefixModes, prefixes) = prefix.substring(1) .split(')', limit = 2) .map(String::toCharArray) - .map(CharArray::toSet) + .map(CharArray::toList) _prefixes = prefixes _prefixModes = prefixModes } else { - val defaultPrefixes = setOf('~', '&', '@', '%', '+') - val defaultPrefixModes = setOf('q', 'a', 'o', 'h', 'v') + val defaultPrefixes = listOf('~', '&', '@', '%', '+') + val defaultPrefixModes = listOf('q', 'a', 'o', 'h', 'v') if (prefix.isBlank()) { _prefixes = defaultPrefixes _prefixModes = defaultPrefixModes @@ -238,8 +246,8 @@ class Network constructor( val (prefixes, prefixModes) = defaultPrefixes.zip(defaultPrefixModes) .filter { prefix.contains(it.second) } .unzip() - _prefixes = prefixes.toSet() - _prefixModes = prefixModes.toSet() + _prefixes = prefixes + _prefixModes = prefixModes // check for success if (prefixes.isNotEmpty()) return @@ -248,8 +256,8 @@ class Network constructor( val (prefixes2, prefixModes2) = defaultPrefixes.zip(defaultPrefixModes) .filter { prefix.contains(it.first) } .unzip() - _prefixes = prefixes2.toSet() - _prefixModes = prefixModes2.toSet() + _prefixes = prefixes2 + _prefixModes = prefixModes2 // now we've done all we've could... } } @@ -876,8 +884,8 @@ class Network constructor( private var _connected: Boolean = false private var _connectionState: ConnectionState = ConnectionState.Disconnected val liveConnectionState = BehaviorSubject.createDefault(ConnectionState.Disconnected) - private var _prefixes: Set<Char>? = null - private var _prefixModes: Set<Char>? = null + private var _prefixes: List<Char>? = null + private var _prefixModes: List<Char>? = null private var _channelModes: Map<ChannelModeType, Set<Char>>? = null // stores all known nicks for the server private var _ircUsers: MutableMap<String, IrcUser> = mutableMapOf() @@ -931,4 +939,4 @@ class Network constructor( companion object { val NULL = Network(-1, SignalProxy.NULL) } -} +} \ No newline at end of file -- GitLab