Skip to content
Snippets Groups Projects
Commit 4d94af26 authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Allow selecting buffers

parent f3c489de
No related branches found
No related tags found
No related merge requests found
Showing with 199 additions and 20 deletions
......@@ -30,11 +30,14 @@ class BufferListAdapter(
liveData: LiveData<List<BufferProps>?>,
runInBackground: (() -> Unit) -> Any,
runOnUiThread: (Runnable) -> Any,
private val clickListener: ((BufferId) -> Unit)? = null
private val clickListener: ((BufferId) -> Unit)? = null,
private val longClickListener: ((BufferId) -> Unit)? = null
) : RecyclerView.Adapter<BufferListAdapter.BufferViewHolder>() {
var data = mutableListOf<BufferListItem>()
var collapsedNetworks = MutableLiveData<Set<NetworkId>>()
private val collapsedNetworks = MutableLiveData<Set<NetworkId>>()
val selectedBuffers = MutableLiveData<Set<BufferId>>()
fun expandListener(networkId: NetworkId) {
if (collapsedNetworks.value.orEmpty().contains(networkId))
......@@ -43,14 +46,29 @@ class BufferListAdapter(
collapsedNetworks.postValue(collapsedNetworks.value.orEmpty() + networkId)
}
fun toggleSelection(buffer: BufferId) {
val value = selectedBuffers.value.orEmpty()
if (value.contains(buffer)) {
selectedBuffers.value = value - buffer
} else {
selectedBuffers.value = value + buffer
}
}
fun unselectAll() {
selectedBuffers.value = emptySet()
}
init {
collapsedNetworks.value = emptySet()
selectedBuffers.value = emptySet()
liveData.zip(collapsedNetworks).observe(
lifecycleOwner, Observer { it: Pair<List<BufferProps>?, Set<NetworkId>>? ->
liveData.zip(collapsedNetworks, selectedBuffers).observe(
lifecycleOwner, Observer { it: Triple<List<BufferProps>?, Set<NetworkId>, Set<BufferId>>? ->
runInBackground {
val list = it?.first ?: emptyList()
val collapsedNetworks = it?.second ?: emptySet()
val selected = it?.third ?: emptySet()
val old: List<BufferListItem> = data
val new: List<BufferListItem> = list.sortedBy { props ->
......@@ -61,7 +79,8 @@ class BufferListAdapter(
BufferListItem(
props,
BufferState(
networkExpanded = !collapsedNetworks.contains(props.network.networkId)
networkExpanded = !collapsedNetworks.contains(props.network.networkId),
selected = selected.contains(props.info.bufferId)
)
)
}.filter { (props, state) ->
......@@ -97,25 +116,29 @@ class BufferListAdapter(
LayoutInflater.from(parent.context).inflate(
R.layout.widget_buffer, parent, false
),
clickListener = clickListener
clickListener = clickListener,
longClickListener = longClickListener
)
BufferInfo.Type.QueryBuffer.toInt() -> BufferViewHolder.QueryBuffer(
LayoutInflater.from(parent.context).inflate(
R.layout.widget_buffer, parent, false
),
clickListener = clickListener
clickListener = clickListener,
longClickListener = longClickListener
)
BufferInfo.Type.GroupBuffer.toInt() -> BufferViewHolder.GroupBuffer(
LayoutInflater.from(parent.context).inflate(
R.layout.widget_buffer, parent, false
),
clickListener = clickListener
clickListener = clickListener,
longClickListener = longClickListener
)
BufferInfo.Type.StatusBuffer.toInt() -> BufferViewHolder.StatusBuffer(
LayoutInflater.from(parent.context).inflate(
R.layout.widget_network, parent, false
),
clickListener = clickListener,
longClickListener = longClickListener,
expansionListener = ::expandListener
)
else -> throw IllegalArgumentException(
......@@ -146,7 +169,8 @@ class BufferListAdapter(
)
data class BufferState(
val networkExpanded: Boolean
val networkExpanded: Boolean,
val selected: Boolean
)
abstract class BufferViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
......@@ -155,6 +179,7 @@ class BufferListAdapter(
class StatusBuffer(
itemView: View,
private val clickListener: ((BufferId) -> Unit)? = null,
private val longClickListener: ((BufferId) -> Unit)? = null,
private val expansionListener: ((NetworkId) -> Unit)? = null
) : BufferViewHolder(itemView) {
@BindView(R.id.status)
......@@ -179,6 +204,16 @@ class BufferListAdapter(
clickListener?.invoke(buffer)
}
itemView.setOnLongClickListener {
val buffer = bufferId
if (buffer != null) {
longClickListener?.invoke(buffer)
true
} else {
false
}
}
status.setOnClickListener {
val network = networkId
if (network != null)
......@@ -210,6 +245,8 @@ class BufferListAdapter(
}
)
itemView.isSelected = state.selected
if (state.networkExpanded) {
status.setImageDrawable(itemView.context.getCompatDrawable(R.drawable.ic_chevron_up))
} else {
......@@ -220,7 +257,8 @@ class BufferListAdapter(
class GroupBuffer(
itemView: View,
private val clickListener: ((BufferId) -> Unit)? = null
private val clickListener: ((BufferId) -> Unit)? = null,
private val longClickListener: ((BufferId) -> Unit)? = null
) : BufferViewHolder(itemView) {
@BindView(R.id.status)
lateinit var status: ImageView
......@@ -249,6 +287,16 @@ class BufferListAdapter(
clickListener?.invoke(buffer)
}
itemView.setOnLongClickListener {
val buffer = bufferId
if (buffer != null) {
longClickListener?.invoke(buffer)
true
} else {
false
}
}
online = itemView.context.getCompatDrawable(R.drawable.ic_status).mutate()
offline = itemView.context.getCompatDrawable(R.drawable.ic_status_offline).mutate()
......@@ -282,6 +330,8 @@ class BufferListAdapter(
}
)
itemView.isSelected = state.selected
description.visibleIf(props.description.isNotBlank())
status.setImageDrawable(
......@@ -295,7 +345,8 @@ class BufferListAdapter(
class ChannelBuffer(
itemView: View,
private val clickListener: ((BufferId) -> Unit)? = null
private val clickListener: ((BufferId) -> Unit)? = null,
private val longClickListener: ((BufferId) -> Unit)? = null
) : BufferViewHolder(itemView) {
@BindView(R.id.status)
lateinit var status: ImageView
......@@ -324,6 +375,16 @@ class BufferListAdapter(
clickListener?.invoke(buffer)
}
itemView.setOnLongClickListener {
val buffer = bufferId
if (buffer != null) {
longClickListener?.invoke(buffer)
true
} else {
false
}
}
online = itemView.context.getCompatDrawable(R.drawable.ic_status_channel).mutate()
offline = itemView.context.getCompatDrawable(R.drawable.ic_status_channel_offline).mutate()
......@@ -357,6 +418,8 @@ class BufferListAdapter(
}
)
itemView.isSelected = state.selected
description.visibleIf(props.description.isNotBlank())
status.setImageDrawable(
......@@ -370,7 +433,8 @@ class BufferListAdapter(
class QueryBuffer(
itemView: View,
private val clickListener: ((BufferId) -> Unit)? = null
private val clickListener: ((BufferId) -> Unit)? = null,
private val longClickListener: ((BufferId) -> Unit)? = null
) : BufferViewHolder(itemView) {
@BindView(R.id.status)
lateinit var status: ImageView
......@@ -400,6 +464,16 @@ class BufferListAdapter(
clickListener?.invoke(buffer)
}
itemView.setOnLongClickListener {
val buffer = bufferId
if (buffer != null) {
longClickListener?.invoke(buffer)
true
} else {
false
}
}
online = itemView.context.getCompatDrawable(R.drawable.ic_status).mutate()
away = itemView.context.getCompatDrawable(R.drawable.ic_status).mutate()
offline = itemView.context.getCompatDrawable(R.drawable.ic_status_offline).mutate()
......@@ -435,6 +509,8 @@ class BufferListAdapter(
}
)
itemView.isSelected = state.selected
description.visibleIf(props.description.isNotBlank())
status.setImageDrawable(
......
......@@ -3,9 +3,7 @@ package de.kuschku.quasseldroid_ng.ui.chat.buffers
import android.arch.lifecycle.ViewModelProviders
import android.os.Bundle
import android.support.v7.widget.*
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.*
import android.widget.AdapterView
import butterknife.BindView
import butterknife.ButterKnife
......@@ -44,6 +42,30 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
private var ircFormatDeserializer: IrcFormatDeserializer? = null
private lateinit var appearanceSettings: AppearanceSettings
private var isInActionMode = false
private val actionModeCallback = object : ActionMode.Callback {
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
return true
}
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
isInActionMode = true
return true
}
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
return false
}
override fun onDestroyActionMode(mode: ActionMode?) {
isInActionMode = false
listAdapter.unselectAll()
}
}
private lateinit var listAdapter: BufferListAdapter
override fun onCreate(savedInstanceState: Bundle?) {
handlerThread.onCreate()
super.onCreate(savedInstanceState)
......@@ -75,7 +97,7 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
}
}
chatList.adapter = BufferListAdapter(
listAdapter = BufferListAdapter(
this,
viewModel.bufferList.zip(database.filtered().listen(accountId)).map {
val (data, activityList) = it
......@@ -107,8 +129,12 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
},
handlerThread::post,
activity!!::runOnUiThread,
clickListener
clickListener,
longClickListener
)
chatList.adapter = listAdapter
chatListToolbar.startActionMode(actionModeCallback)
chatList.layoutManager = LinearLayoutManager(context)
chatList.itemAnimator = DefaultItemAnimator()
chatList.setItemViewCacheSize(10)
......@@ -121,6 +147,17 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
}
private val clickListener: ((BufferId) -> Unit)? = {
viewModel.setBuffer(it)
if (isInActionMode) {
longClickListener?.invoke(it)
} else {
viewModel.setBuffer(it)
}
}
private val longClickListener: ((BufferId) -> Unit)? = {
if (!isInActionMode) {
chatListToolbar.startActionMode(actionModeCallback)
}
listAdapter.toggleSelection(it)
}
}
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<shape android:shape="rectangle">
<solid android:color="@color/ripple_dark" />
</shape>
</item>
<item>
<ripple android:color="@color/ripple_dark" />
</item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<shape android:shape="rectangle">
<solid android:color="@color/ripple_light" />
</shape>
</item>
<item>
<ripple android:color="@color/ripple_light" />
</item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<shape android:shape="rectangle">
<solid android:color="@color/ripple_dark" />
</shape>
</item>
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="@color/ripple_dark" />
</shape>
</item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<shape android:shape="rectangle">
<solid android:color="@color/ripple_light" />
</shape>
</item>
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="@color/ripple_light" />
</shape>
</item>
</selector>
\ No newline at end of file
......@@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?attr/selectableItemBackgroundBorderless"
android:background="?attr/backgroundMenuItem"
android:minHeight="48dp"
android:paddingBottom="8dp"
android:paddingLeft="16dp"
......
......@@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:background="?attr/backgroundMenuItem"
android:orientation="vertical">
<View
......
......@@ -71,4 +71,7 @@
<attr name="buttonTheme" format="reference" />
<attr name="buttonThemeColored" format="reference" />
<attr name="cardStyle" format="reference" />
<!-- Menu Items -->
<attr name="backgroundMenuItem" format="reference" />
</resources>
......@@ -12,4 +12,7 @@
<color name="colorAwayLight">#959595</color>
<color name="colorAwayDark">#939393</color>
<color name="ripple_dark">#33ffffff</color>
<color name="ripple_light">#1f000000</color>
</resources>
......@@ -4,22 +4,30 @@
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="backgroundMenuItem">@drawable/bg_menuitem_dark</item>
</style>
<style name="Theme.AppTheme.Light" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="backgroundMenuItem">@drawable/bg_menuitem_light</item>
</style>
<style name="Theme.AppTheme.NoActionBar" parent="Theme.AppTheme">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="backgroundMenuItem">@drawable/bg_menuitem_dark</item>
</style>
<style name="Theme.AppTheme.Light.NoActionBar" parent="Theme.AppTheme.Light">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="backgroundMenuItem">@drawable/bg_menuitem_light</item>
</style>
<style name="Theme.Base.ChatTheme" parent="Theme.AppTheme.NoActionBar" />
......@@ -38,6 +46,8 @@
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
<item name="actionBarPopupTheme">@style/Widget.PopupOverlay</item>
<item name="backgroundMenuItem">@drawable/bg_menuitem_dark</item>
<item name="windowActionModeOverlay">true</item>
<item name="colorTextPrimary">#dedede</item>
......@@ -85,6 +95,8 @@
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
<item name="actionBarPopupTheme">@style/Widget.PopupOverlay.Light</item>
<item name="backgroundMenuItem">@drawable/bg_menuitem_light</item>
<item name="windowActionModeOverlay">true</item>
<item name="colorTextPrimary">#212121</item>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment