Skip to content

Commit

Permalink
[i110] control options icon for each channel (#4928)
Browse files Browse the repository at this point in the history
* [i110] control options icon for each channel

(cherry picked from commit 5d79022)

# Conflicts:
#	stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/channel/list/adapter/viewholder/ChannelListIconProviderContainer.kt
#	stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/channel/list/adapter/viewholder/ChannelListIconProviderContainerImpl.kt
#	stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/channel/list/internal/SimpleChannelListView.kt

* [i110] fix api-dump & detekt

* [i110] add CHANGELOG

---------

Co-authored-by: kanat <>
  • Loading branch information
kanat authored Aug 18, 2023
1 parent 789dfe3 commit be7bb99
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@

### ✅ Added
- Added `MessageListView.setCustomItemAnimator` to allow customizing the item animator used by the `MessageListView`. [#4926](https://github.com/GetStream/stream-chat-android/pull/4926)
- Added `ChannelListView.setMoreOptionsIconProvider` and `ChannelListView.setDeleteOptionIconProvider` to allow customizing the options icons used by the `ChannelListView`. [#4928](https://github.com/GetStream/stream-chat-android/pull/4928)

### ⚠️ Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,7 @@ public final class io/getstream/chat/android/ui/channel/list/ChannelListView : a
public final fun setChannelListUpdateListener (Lio/getstream/chat/android/ui/channel/list/ChannelListView$ChannelListUpdateListener;)V
public final fun setChannelLongClickListener (Lio/getstream/chat/android/ui/channel/list/ChannelListView$ChannelLongClickListener;)V
public final fun setChannels (Ljava/util/List;)V
public final fun setDeleteOptionIconProvider (Lkotlin/jvm/functions/Function1;)V
public final fun setEmptyStateView (Landroid/view/View;)V
public final fun setEmptyStateView (Landroid/view/View;Landroid/widget/FrameLayout$LayoutParams;)V
public static synthetic fun setEmptyStateView$default (Lio/getstream/chat/android/ui/channel/list/ChannelListView;Landroid/view/View;Landroid/widget/FrameLayout$LayoutParams;ILjava/lang/Object;)V
Expand All @@ -1000,6 +1001,7 @@ public final class io/getstream/chat/android/ui/channel/list/ChannelListView : a
public final fun setLoadingView (Landroid/view/View;Landroid/widget/FrameLayout$LayoutParams;)V
public static synthetic fun setLoadingView$default (Lio/getstream/chat/android/ui/channel/list/ChannelListView;Landroid/view/View;Landroid/widget/FrameLayout$LayoutParams;ILjava/lang/Object;)V
public final fun setMoreOptionsClickListener (Lio/getstream/chat/android/ui/channel/list/ChannelListView$ChannelClickListener;)V
public final fun setMoreOptionsIconProvider (Lkotlin/jvm/functions/Function1;)V
public final fun setOnEndReachedListener (Lio/getstream/chat/android/ui/channel/list/ChannelListView$EndReachedListener;)V
public final fun setPaginationEnabled (Z)V
public final fun setShouldDrawItemSeparatorOnLastItem (Z)V
Expand Down Expand Up @@ -1037,6 +1039,15 @@ public abstract interface class io/getstream/chat/android/ui/channel/list/Channe
public final class io/getstream/chat/android/ui/channel/list/ChannelListView$ChannelLongClickListener$Companion {
}

public abstract interface class io/getstream/chat/android/ui/channel/list/ChannelListView$ChannelOptionIconProvider : kotlin/jvm/functions/Function1 {
public static final field Companion Lio/getstream/chat/android/ui/channel/list/ChannelListView$ChannelOptionIconProvider$Companion;
public static final field DEFAULT Lio/getstream/chat/android/ui/channel/list/ChannelListView$ChannelOptionIconProvider;
public abstract fun invoke (Lio/getstream/chat/android/client/models/Channel;)Landroid/graphics/drawable/Drawable;
}

public final class io/getstream/chat/android/ui/channel/list/ChannelListView$ChannelOptionIconProvider$Companion {
}

public abstract interface class io/getstream/chat/android/ui/channel/list/ChannelListView$ChannelOptionVisibilityPredicate : kotlin/jvm/functions/Function1 {
public static final field Companion Lio/getstream/chat/android/ui/channel/list/ChannelListView$ChannelOptionVisibilityPredicate$Companion;
public static final field DEFAULT Lio/getstream/chat/android/ui/channel/list/ChannelListView$ChannelOptionVisibilityPredicate;
Expand Down Expand Up @@ -1197,11 +1208,17 @@ public abstract class io/getstream/chat/android/ui/channel/list/adapter/viewhold
public fun bind (Lio/getstream/chat/android/ui/channel/list/adapter/ChannelListItem$ChannelItem;Lio/getstream/chat/android/ui/channel/list/adapter/ChannelListPayloadDiff;)V
}

public abstract interface class io/getstream/chat/android/ui/channel/list/adapter/viewholder/ChannelListIconProviderContainer {
public abstract fun getGetDeleteOptionIcon ()Lio/getstream/chat/android/ui/channel/list/ChannelListView$ChannelOptionIconProvider;
public abstract fun getGetMoreOptionsIcon ()Lio/getstream/chat/android/ui/channel/list/ChannelListView$ChannelOptionIconProvider;
}

public class io/getstream/chat/android/ui/channel/list/adapter/viewholder/ChannelListItemViewHolderFactory {
public fun <init> ()V
protected fun createChannelViewHolder (Landroid/view/ViewGroup;)Lio/getstream/chat/android/ui/channel/list/adapter/viewholder/BaseChannelListItemViewHolder;
protected fun createLoadingMoreViewHolder (Landroid/view/ViewGroup;)Lio/getstream/chat/android/ui/channel/list/adapter/viewholder/BaseChannelListItemViewHolder;
public fun createViewHolder (Landroid/view/ViewGroup;I)Lio/getstream/chat/android/ui/channel/list/adapter/viewholder/BaseChannelListItemViewHolder;
protected final fun getIconProviderContainer ()Lio/getstream/chat/android/ui/channel/list/adapter/viewholder/ChannelListIconProviderContainer;
public fun getItemViewType (Lio/getstream/chat/android/ui/channel/list/adapter/ChannelListItem;)I
protected final fun getListenerContainer ()Lio/getstream/chat/android/ui/channel/list/adapter/viewholder/ChannelListListenerContainer;
protected final fun getStyle ()Lio/getstream/chat/android/ui/channel/list/ChannelListViewStyle;
Expand Down
1 change: 1 addition & 0 deletions stream-chat-android-ui-components/detekt-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
<ID>MaxLineLength:AutoLinkableTextTransformer.kt$AutoLinkableTextTransformer$*</ID>
<ID>MaxLineLength:AvatarView.kt$AvatarView$*</ID>
<ID>MaxLineLength:ChannelActionsDialogViewStyle.kt$ChannelActionsDialogViewStyle$*</ID>
<ID>MaxLineLength:ChannelListIconProviderContainerImpl.kt$ChannelListIconProviderContainerImpl$override</ID>
<ID>MaxLineLength:ChannelListView.kt$ChannelListView$is ChannelListViewModel.ErrorEvent.DeleteChannelError -> R.string.stream_ui_channel_list_error_delete_channel</ID>
<ID>MaxLineLength:ChannelListViewModel.kt$ChannelListViewModel$*</ID>
<ID>MaxLineLength:ChannelListViewModelFactory.kt$ChannelListViewModelFactory$*</ID>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import kotlin.reflect.KProperty
* wrapped can be referenced by calling the realListener() method. This
* function always returns the current listener, even if it changes.
*/
// TODO Needs to be renamed to something like WrapDelegate. It is no longer used for listeners only.
@InternalStreamChatApi
public class ListenerDelegate<L : Any>(
initialValue: L,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package io.getstream.chat.android.ui.channel.list

import android.content.Context
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.os.Parcelable
import android.util.AttributeSet
Expand Down Expand Up @@ -314,6 +315,24 @@ public class ChannelListView : FrameLayout {
simpleChannelListView.setIsDeleteOptionVisible(isDeleteOptionVisible)
}

/**
* Allows clients to override a "more options" icon in ViewHolder items.
*
* @param getMoreOptionsIcon Provides icon for a "more options".
*/
public fun setMoreOptionsIconProvider(getMoreOptionsIcon: (Channel) -> Drawable?) {
simpleChannelListView.setMoreOptionsIconProvider(getMoreOptionsIcon)
}

/**
* Allows clients to override a "delete option" icon in ViewHolder items.
*
* @param getDeleteOptionIcon Provides icon for delete option.
*/
public fun setDeleteOptionIconProvider(getDeleteOptionIcon: (Channel) -> Drawable?) {
simpleChannelListView.setDeleteOptionIconProvider(getDeleteOptionIcon)
}

/**
* Allows a client to set a click listener to be notified of "channel info" clicks in the "more options" menu.
*
Expand Down Expand Up @@ -533,7 +552,25 @@ public class ChannelListView : FrameLayout {
*
* @return True if the option is visible.
*/
override fun invoke(p1: Channel): Boolean
override fun invoke(channel: Channel): Boolean
}

public fun interface ChannelOptionIconProvider : Function1<Channel, Drawable?> {

public companion object {
@JvmField
public val DEFAULT: ChannelOptionIconProvider = ChannelOptionIconProvider {
// option has no customized icon by default
null
}
}

/**
* Called to provide option's icon for the specified [channel].
*
* @return Drawable which overrides ChannelListViewStyle values.
*/
override fun invoke(channel: Channel): Drawable?
}

public fun interface EndReachedListener {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2014-2022 Stream.io Inc. All rights reserved.
*
* Licensed under the Stream License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://github.com/GetStream/stream-chat-android/blob/main/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.getstream.chat.android.ui.channel.list.adapter.viewholder

import io.getstream.chat.android.ui.channel.list.ChannelListView.ChannelOptionIconProvider

public sealed interface ChannelListIconProviderContainer {
public val getMoreOptionsIcon: ChannelOptionIconProvider
public val getDeleteOptionIcon: ChannelOptionIconProvider
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2014-2022 Stream.io Inc. All rights reserved.
*
* Licensed under the Stream License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://github.com/GetStream/stream-chat-android/blob/main/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.getstream.chat.android.ui.channel.list.adapter.viewholder

import com.getstream.sdk.chat.utils.ListenerDelegate
import io.getstream.chat.android.ui.channel.list.ChannelListView.ChannelOptionIconProvider

internal class ChannelListIconProviderContainerImpl(
getMoreOptionsIcon: ChannelOptionIconProvider = ChannelOptionIconProvider.DEFAULT,
getDeleteOptionIcon: ChannelOptionIconProvider = ChannelOptionIconProvider.DEFAULT,
) : ChannelListIconProviderContainer {

override var getMoreOptionsIcon: ChannelOptionIconProvider by ListenerDelegate(getMoreOptionsIcon) { realPredicate ->
ChannelOptionIconProvider { channel ->
realPredicate().invoke(channel)
}
}

override var getDeleteOptionIcon: ChannelOptionIconProvider by ListenerDelegate(getDeleteOptionIcon) { realPredicate ->
ChannelOptionIconProvider { channel ->
realPredicate().invoke(channel)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public open class ChannelListItemViewHolderFactory {
protected lateinit var visibilityContainer: ChannelListVisibilityContainer
private set

protected lateinit var iconProviderContainer: ChannelListIconProviderContainer
private set

protected lateinit var style: ChannelListViewStyle
private set

Expand All @@ -43,6 +46,10 @@ public open class ChannelListItemViewHolderFactory {
this.visibilityContainer = visibilityContainer
}

internal fun setIconProviderContainer(iconProviderContainer: ChannelListIconProviderContainer) {
this.iconProviderContainer = iconProviderContainer
}

internal fun setStyle(style: ChannelListViewStyle) {
this.style = style
}
Expand Down Expand Up @@ -89,6 +96,8 @@ public open class ChannelListItemViewHolderFactory {
style,
visibilityContainer.isMoreOptionsVisible,
visibilityContainer.isDeleteOptionVisible,
iconProviderContainer.getMoreOptionsIcon,
iconProviderContainer.getDeleteOptionIcon,
)
}

Expand All @@ -106,6 +115,9 @@ public open class ChannelListItemViewHolderFactory {
if (!::visibilityContainer.isInitialized) {
visibilityContainer = ChannelListVisibilityContainerImpl()
}
if (!::iconProviderContainer.isInitialized) {
iconProviderContainer = ChannelListIconProviderContainerImpl()
}
if (!::style.isInitialized) {
style = ChannelListViewStyle(context, null)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ internal class ChannelViewHolder @JvmOverloads constructor(
private val swipeListener: ChannelListView.SwipeListener,
private val style: ChannelListViewStyle,
private val isMoreOptionsVisible: ChannelListView.ChannelOptionVisibilityPredicate,
private val isDeleteOptionsVisible: ChannelListView.ChannelOptionVisibilityPredicate,
private val isDeleteOptionVisible: ChannelListView.ChannelOptionVisibilityPredicate,
private val getMoreOptionsIcon: ChannelListView.ChannelOptionIconProvider,
private val getDeleteOptionIcon: ChannelListView.ChannelOptionIconProvider,
private val binding: StreamUiChannelListItemViewBinding = StreamUiChannelListItemViewBinding.inflate(
parent.streamThemeInflater,
parent,
Expand Down Expand Up @@ -188,15 +190,17 @@ internal class ChannelViewHolder @JvmOverloads constructor(
binding.itemBackgroundView.moreOptionsImageView.apply {
if (style.optionsEnabled && isMoreOptionsVisible(channel)) {
isVisible = true
getMoreOptionsIcon.invoke(channel)?.also { setImageDrawable(it) }
optionsCount++
} else {
isVisible = false
}
}
binding.itemBackgroundView.deleteImageView.apply {
val canDeleteChannel = channel.ownCapabilities.contains(ChannelCapabilities.DELETE_CHANNEL)
if (style.deleteEnabled && canDeleteChannel && isDeleteOptionsVisible(channel)) {
if (style.deleteEnabled && canDeleteChannel && isDeleteOptionVisible(channel)) {
isVisible = true
getDeleteOptionIcon.invoke(channel)?.also { setImageDrawable(it) }
optionsCount++
} else {
isVisible = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import io.getstream.chat.android.ui.channel.list.ChannelListView
import io.getstream.chat.android.ui.channel.list.ChannelListViewStyle
import io.getstream.chat.android.ui.channel.list.adapter.ChannelListItem
import io.getstream.chat.android.ui.channel.list.adapter.internal.ChannelListItemAdapter
import io.getstream.chat.android.ui.channel.list.adapter.viewholder.ChannelListIconProviderContainerImpl
import io.getstream.chat.android.ui.channel.list.adapter.viewholder.ChannelListItemViewHolderFactory
import io.getstream.chat.android.ui.channel.list.adapter.viewholder.ChannelListListenerContainerImpl
import io.getstream.chat.android.ui.channel.list.adapter.viewholder.ChannelListVisibilityContainerImpl
Expand Down Expand Up @@ -57,6 +58,8 @@ internal class SimpleChannelListView @JvmOverloads constructor(

internal val visibilityContainer = ChannelListVisibilityContainerImpl()

internal val iconProviderContainer = ChannelListIconProviderContainerImpl()

private lateinit var style: ChannelListViewStyle

init {
Expand Down Expand Up @@ -100,6 +103,7 @@ internal class SimpleChannelListView @JvmOverloads constructor(

viewHolderFactory.setListenerContainer(this.listenerContainer)
viewHolderFactory.setVisibilityContainer(this.visibilityContainer)
viewHolderFactory.setIconProviderContainer(this.iconProviderContainer)
viewHolderFactory.setStyle(style)

adapter = ChannelListItemAdapter(viewHolderFactory)
Expand Down Expand Up @@ -146,6 +150,14 @@ internal class SimpleChannelListView @JvmOverloads constructor(
visibilityContainer.isDeleteOptionVisible = isDeleteOptionVisible
}

fun setMoreOptionsIconProvider(getMoreOptionsIcon: ChannelListView.ChannelOptionIconProvider) {
iconProviderContainer.getMoreOptionsIcon = getMoreOptionsIcon
}

fun setDeleteOptionIconProvider(getDeleteOptionIcon: ChannelListView.ChannelOptionIconProvider) {
iconProviderContainer.getDeleteOptionIcon = getDeleteOptionIcon
}

fun setSwipeListener(listener: ChannelListView.SwipeListener?) {
listenerContainer.swipeListener = listener ?: ChannelListView.SwipeListener.DEFAULT
}
Expand Down

0 comments on commit be7bb99

Please sign in to comment.