Add conversation settings pager in toolbar
parent
29efd41939
commit
290e646679
@ -0,0 +1,179 @@
|
|||||||
|
package org.thoughtcrime.securesms.conversation
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import androidx.annotation.DimenRes
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import network.loki.messenger.databinding.ViewConversationActionBarBinding
|
||||||
|
import network.loki.messenger.databinding.ViewConversationSettingBinding
|
||||||
|
import org.session.libsession.messaging.open_groups.OpenGroup
|
||||||
|
import org.session.libsession.utilities.ExpirationUtil
|
||||||
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
|
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities
|
||||||
|
import org.thoughtcrime.securesms.database.GroupDatabase
|
||||||
|
import org.thoughtcrime.securesms.database.LokiAPIDatabase
|
||||||
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
|
import org.thoughtcrime.securesms.util.DateUtils
|
||||||
|
import java.util.Locale
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class ConversationActionBarView : LinearLayout {
|
||||||
|
|
||||||
|
private lateinit var binding: ViewConversationActionBarBinding
|
||||||
|
|
||||||
|
@Inject lateinit var lokiApiDb: LokiAPIDatabase
|
||||||
|
@Inject lateinit var groupDb: GroupDatabase
|
||||||
|
|
||||||
|
var delegate: ConversationActionBarDelegate? = null
|
||||||
|
|
||||||
|
private val settingsAdapter = ConversationSettingsAdapter { setting ->
|
||||||
|
if (setting.settingType == ConversationSettingType.EXPIRATION) {
|
||||||
|
delegate?.onExpirationSettingClicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(context: Context) : super(context) { initialize() }
|
||||||
|
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { initialize() }
|
||||||
|
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { initialize() }
|
||||||
|
|
||||||
|
private fun initialize() {
|
||||||
|
binding = ViewConversationActionBarBinding.inflate(LayoutInflater.from(context), this, true)
|
||||||
|
binding.settingsPager.adapter = settingsAdapter
|
||||||
|
val mediator = TabLayoutMediator(binding.settingsTabLayout, binding.settingsPager) { _, _ -> }
|
||||||
|
mediator.attach()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bind(threadId: Long, recipient: Recipient, glide: GlideRequests) {
|
||||||
|
binding.conversationTitleView.text = when {
|
||||||
|
recipient.isLocalNumber -> context.getString(R.string.note_to_self)
|
||||||
|
else -> recipient.toShortString()
|
||||||
|
}
|
||||||
|
@DimenRes val sizeID: Int = if (recipient.isClosedGroupRecipient) {
|
||||||
|
R.dimen.medium_profile_picture_size
|
||||||
|
} else {
|
||||||
|
R.dimen.small_profile_picture_size
|
||||||
|
}
|
||||||
|
val size = resources.getDimension(sizeID).roundToInt()
|
||||||
|
binding.profilePictureView.root.layoutParams = LayoutParams(size, size)
|
||||||
|
binding.profilePictureView.root.glide = glide
|
||||||
|
MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded(threadId, context)
|
||||||
|
binding.profilePictureView.root.update(recipient)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(recipient: Recipient) {
|
||||||
|
binding.profilePictureView.root.update(recipient)
|
||||||
|
binding.conversationTitleView.text = when {
|
||||||
|
recipient.isLocalNumber -> context.getString(R.string.note_to_self)
|
||||||
|
else -> recipient.toShortString()
|
||||||
|
}
|
||||||
|
updateSubtitle(recipient)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateSubtitle(recipient: Recipient, openGroup: OpenGroup? = null) {
|
||||||
|
val settings = mutableListOf<ConversationSetting>()
|
||||||
|
if (recipient.expireMessages > 0) {
|
||||||
|
settings.add(
|
||||||
|
ConversationSetting(
|
||||||
|
"${context.getString(R.string.expiration_type_disappear_after_read)} - ${ExpirationUtil.getExpirationAbbreviatedDisplayValue(context, recipient.expireMessages)}" ,
|
||||||
|
ConversationSettingType.EXPIRATION,
|
||||||
|
R.drawable.ic_timer
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (recipient.isMuted) {
|
||||||
|
settings.add(
|
||||||
|
ConversationSetting(
|
||||||
|
if (recipient.mutedUntil != Long.MAX_VALUE) {
|
||||||
|
context.getString(R.string.ConversationActivity_muted_until_date, DateUtils.getFormattedDateTime(recipient.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault()))
|
||||||
|
} else {
|
||||||
|
context.getString(R.string.ConversationActivity_muted_forever)
|
||||||
|
},
|
||||||
|
ConversationSettingType.NOTIFICATION,
|
||||||
|
R.drawable.ic_outline_notifications_off_24
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (recipient.isGroupRecipient) {
|
||||||
|
settings.add(
|
||||||
|
ConversationSetting(
|
||||||
|
openGroup?.let {
|
||||||
|
val userCount = lokiApiDb.getUserCount(it.room, it.server) ?: 0
|
||||||
|
context.getString(R.string.ConversationActivity_active_member_count, userCount)
|
||||||
|
} ?: run {
|
||||||
|
val userCount = groupDb.getGroupMemberAddresses(recipient.address.toGroupString(), true).size
|
||||||
|
context.getString(R.string.ConversationActivity_member_count, userCount)
|
||||||
|
},
|
||||||
|
ConversationSettingType.MEMBER_COUNT,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
settingsAdapter.submitList(settings)
|
||||||
|
binding.settingsTabLayout.isVisible = settings.size > 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConversationSettingsAdapter(
|
||||||
|
private val settingsListener: (ConversationSetting) -> Unit
|
||||||
|
) : ListAdapter<ConversationSetting, ConversationSettingsAdapter.SettingViewHolder>(SettingsDiffer()) {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SettingViewHolder {
|
||||||
|
val layoutInflater = LayoutInflater.from(parent.context)
|
||||||
|
return SettingViewHolder(ViewConversationSettingBinding.inflate(layoutInflater, parent, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: SettingViewHolder, position: Int) {
|
||||||
|
holder.bind(getItem(position), itemCount) {
|
||||||
|
settingsListener.invoke(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SettingViewHolder(
|
||||||
|
private val binding: ViewConversationSettingBinding
|
||||||
|
): RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
|
fun bind(setting: ConversationSetting, itemCount: Int, listener: (ConversationSetting) -> Unit) {
|
||||||
|
binding.root.setOnClickListener { listener.invoke(setting) }
|
||||||
|
binding.iconImageView.setImageResource(setting.iconResId)
|
||||||
|
binding.iconImageView.isVisible = setting.iconResId > 0
|
||||||
|
binding.titleView.text = setting.title
|
||||||
|
binding.leftArrowImageView.isVisible = itemCount > 1
|
||||||
|
binding.rightArrowImageView.isVisible = itemCount > 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class SettingsDiffer: DiffUtil.ItemCallback<ConversationSetting>() {
|
||||||
|
override fun areItemsTheSame(oldItem: ConversationSetting, newItem: ConversationSetting) = oldItem === newItem
|
||||||
|
override fun areContentsTheSame(oldItem: ConversationSetting, newItem: ConversationSetting) = oldItem == newItem
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun interface ConversationActionBarDelegate {
|
||||||
|
fun onExpirationSettingClicked()
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ConversationSetting(
|
||||||
|
val title: String,
|
||||||
|
val settingType: ConversationSettingType,
|
||||||
|
val iconResId: Int = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
enum class ConversationSettingType {
|
||||||
|
EXPIRATION,
|
||||||
|
MEMBER_COUNT,
|
||||||
|
NOTIFICATION
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#000000"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M15.41,16.59L10.83,12l4.58,-4.59L14,6l-6,6 6,6 1.41,-1.41z"/>
|
||||||
|
</vector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#000000"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M8.59,16.59L13.17,12 8.59,7.41 10,6l6,6 -6,6 -1.41,-1.41z"/>
|
||||||
|
</vector>
|
@ -0,0 +1,21 @@
|
|||||||
|
<?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="ring"
|
||||||
|
android:innerRadius="0dp"
|
||||||
|
android:thickness="2dp"
|
||||||
|
android:useLevel="false">
|
||||||
|
<solid android:color="?android:textColorPrimary"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape
|
||||||
|
android:shape="ring"
|
||||||
|
android:innerRadius="0dp"
|
||||||
|
android:thickness="2dp"
|
||||||
|
android:useLevel="false">
|
||||||
|
<solid android:color="?android:textColorTertiary"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
@ -1,67 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?attr/actionBarSize"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:gravity="center_vertical">
|
|
||||||
|
|
||||||
<include layout="@layout/view_profile_picture"
|
|
||||||
android:id="@+id/profilePictureView"
|
|
||||||
android:layout_width="@dimen/medium_profile_picture_size"
|
|
||||||
android:layout_height="@dimen/medium_profile_picture_size" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/conversationTitleView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="12dp"
|
|
||||||
tools:text="@tools:sample/full_names"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="@dimen/very_large_font_size"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:ellipsize="end" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="12dp"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:gravity="center_vertical">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/muteIconImageView"
|
|
||||||
android:layout_width="14dp"
|
|
||||||
android:layout_height="14dp"
|
|
||||||
android:layout_marginEnd="4dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:src="@drawable/ic_outline_notifications_off_24"
|
|
||||||
app:tint="?android:textColorPrimary"
|
|
||||||
android:alpha="0.6"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/conversationSubtitleView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Muted"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:alpha="0.6"
|
|
||||||
android:textSize="@dimen/very_small_font_size"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:ellipsize="end" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<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="?attr/actionBarSize"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/conversationTitleView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="@tools:sample/full_names"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="@dimen/large_font_size"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end" />
|
||||||
|
|
||||||
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
|
android:id="@+id/settings_pager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/very_small_spacing"/>
|
||||||
|
|
||||||
|
<com.google.android.material.tabs.TabLayout
|
||||||
|
android:id="@+id/settings_tab_layout"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="@dimen/very_small_spacing"
|
||||||
|
app:tabBackground="@drawable/tab_indicator_dot"
|
||||||
|
app:tabGravity="center"
|
||||||
|
app:tabIndicator="@null"
|
||||||
|
app:tabPaddingStart="@dimen/very_small_spacing"
|
||||||
|
app:tabPaddingEnd="@dimen/very_small_spacing"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<include layout="@layout/view_profile_picture"
|
||||||
|
android:id="@+id/profilePictureView"
|
||||||
|
android:layout_width="@dimen/medium_profile_picture_size"
|
||||||
|
android:layout_height="@dimen/medium_profile_picture_size" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<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="match_parent"
|
||||||
|
android:gravity="center_horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/leftArrowImageView"
|
||||||
|
android:layout_width="14dp"
|
||||||
|
android:layout_height="14dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:alpha="0.6"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:src="@drawable/ic_baseline_keyboard_arrow_left_24dp"
|
||||||
|
app:tint="?android:textColorPrimary"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iconImageView"
|
||||||
|
android:layout_width="14dp"
|
||||||
|
android:layout_height="14dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginEnd="4dp"
|
||||||
|
android:alpha="0.6"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:tint="?android:textColorPrimary"
|
||||||
|
tools:src="@drawable/ic_outline_notifications_off_24"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/titleView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:alpha="0.6"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
android:textSize="@dimen/very_small_font_size"
|
||||||
|
tools:text="Muted" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/rightArrowImageView"
|
||||||
|
android:layout_width="14dp"
|
||||||
|
android:layout_height="14dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:alpha="0.6"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:src="@drawable/ic_baseline_keyboard_arrow_right_24dp"
|
||||||
|
app:tint="?android:textColorPrimary"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:title="@string/conversation_expiring_off__disappearing_messages"
|
|
||||||
android:id="@+id/menu_expiring_messages_off"
|
|
||||||
android:icon="@drawable/ic_baseline_timer_off_24" />
|
|
||||||
|
|
||||||
</menu>
|
|
@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/menu_expiring_messages"
|
|
||||||
app:actionLayout="@layout/expiration_timer_menu"
|
|
||||||
app:showAsAction="always"
|
|
||||||
android:title="@string/menu_conversation_expiring_on__messages_expiring" />
|
|
||||||
|
|
||||||
</menu>
|
|
Loading…
Reference in New Issue