Add conversation settings pager in toolbar

pull/1014/head
charles 3 years ago
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
}

@ -28,11 +28,9 @@ import android.view.MenuItem
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
import android.widget.LinearLayout
import android.widget.RelativeLayout import android.widget.RelativeLayout
import android.widget.Toast import android.widget.Toast
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.annotation.DimenRes
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.view.drawToBitmap import androidx.core.view.drawToBitmap
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -88,6 +86,8 @@ import org.thoughtcrime.securesms.attachments.ScreenshotObserver
import org.thoughtcrime.securesms.audio.AudioRecorder import org.thoughtcrime.securesms.audio.AudioRecorder
import org.thoughtcrime.securesms.contacts.SelectContactsActivity.Companion.selectedContactsKey import org.thoughtcrime.securesms.contacts.SelectContactsActivity.Companion.selectedContactsKey
import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher
import org.thoughtcrime.securesms.conversation.ConversationActionBarDelegate
import org.thoughtcrime.securesms.conversation.ConversationSetting
import org.thoughtcrime.securesms.conversation.expiration.ExpirationSettingsActivity import org.thoughtcrime.securesms.conversation.expiration.ExpirationSettingsActivity
import org.thoughtcrime.securesms.conversation.v2.ConversationReactionOverlay.OnActionSelectedListener import org.thoughtcrime.securesms.conversation.v2.ConversationReactionOverlay.OnActionSelectedListener
import org.thoughtcrime.securesms.conversation.v2.ConversationReactionOverlay.OnReactionSelectedListener import org.thoughtcrime.securesms.conversation.v2.ConversationReactionOverlay.OnReactionSelectedListener
@ -107,19 +107,16 @@ import org.thoughtcrime.securesms.conversation.v2.search.SearchBottomBar
import org.thoughtcrime.securesms.conversation.v2.search.SearchViewModel import org.thoughtcrime.securesms.conversation.v2.search.SearchViewModel
import org.thoughtcrime.securesms.conversation.v2.utilities.AttachmentManager import org.thoughtcrime.securesms.conversation.v2.utilities.AttachmentManager
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities
import org.thoughtcrime.securesms.conversation.v2.utilities.ResendMessageUtilities import org.thoughtcrime.securesms.conversation.v2.utilities.ResendMessageUtilities
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.crypto.MnemonicUtilities import org.thoughtcrime.securesms.crypto.MnemonicUtilities
import org.thoughtcrime.securesms.database.GroupDatabase import org.thoughtcrime.securesms.database.GroupDatabase
import org.thoughtcrime.securesms.database.LokiAPIDatabase
import org.thoughtcrime.securesms.database.LokiMessageDatabase import org.thoughtcrime.securesms.database.LokiMessageDatabase
import org.thoughtcrime.securesms.database.LokiThreadDatabase import org.thoughtcrime.securesms.database.LokiThreadDatabase
import org.thoughtcrime.securesms.database.MmsDatabase import org.thoughtcrime.securesms.database.MmsDatabase
import org.thoughtcrime.securesms.database.MmsSmsDatabase import org.thoughtcrime.securesms.database.MmsSmsDatabase
import org.thoughtcrime.securesms.database.ReactionDatabase import org.thoughtcrime.securesms.database.ReactionDatabase
import org.thoughtcrime.securesms.database.RecipientDatabase
import org.thoughtcrime.securesms.database.SessionContactDatabase import org.thoughtcrime.securesms.database.SessionContactDatabase
import org.thoughtcrime.securesms.database.SmsDatabase import org.thoughtcrime.securesms.database.SmsDatabase
import org.thoughtcrime.securesms.database.Storage import org.thoughtcrime.securesms.database.Storage
@ -172,7 +169,7 @@ import kotlin.math.sqrt
class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDelegate, class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDelegate,
InputBarRecordingViewDelegate, AttachmentManager.AttachmentListener, ActivityDispatcher, InputBarRecordingViewDelegate, AttachmentManager.AttachmentListener, ActivityDispatcher,
ConversationActionModeCallbackDelegate, VisibleMessageViewDelegate, RecipientModifiedListener, ConversationActionModeCallbackDelegate, VisibleMessageViewDelegate, RecipientModifiedListener,
SearchBottomBar.EventListener, LoaderManager.LoaderCallbacks<Cursor>, SearchBottomBar.EventListener, LoaderManager.LoaderCallbacks<Cursor>, ConversationActionBarDelegate,
OnReactionSelectedListener, ReactWithAnyEmojiDialogFragment.Callback, ReactionsDialogFragment.Callback, OnReactionSelectedListener, ReactWithAnyEmojiDialogFragment.Callback, ReactionsDialogFragment.Callback,
ConversationMenuHelper.ConversationMenuListener { ConversationMenuHelper.ConversationMenuListener {
@ -184,8 +181,6 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
@Inject lateinit var lokiThreadDb: LokiThreadDatabase @Inject lateinit var lokiThreadDb: LokiThreadDatabase
@Inject lateinit var sessionContactDb: SessionContactDatabase @Inject lateinit var sessionContactDb: SessionContactDatabase
@Inject lateinit var groupDb: GroupDatabase @Inject lateinit var groupDb: GroupDatabase
@Inject lateinit var recipientDb: RecipientDatabase
@Inject lateinit var lokiApiDb: LokiAPIDatabase
@Inject lateinit var smsDb: SmsDatabase @Inject lateinit var smsDb: SmsDatabase
@Inject lateinit var mmsDb: MmsDatabase @Inject lateinit var mmsDb: MmsDatabase
@Inject lateinit var lokiMessageDb: LokiMessageDatabase @Inject lateinit var lokiMessageDb: LokiMessageDatabase
@ -363,7 +358,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
updateUnreadCountIndicator() updateUnreadCountIndicator()
setUpTypingObserver() setUpTypingObserver()
setUpRecipientObserver() setUpRecipientObserver()
updateSubtitle() binding?.toolbarContent?.updateSubtitle(viewModel.recipient!!)
getLatestOpenGroupInfoIfNeeded() getLatestOpenGroupInfoIfNeeded()
setUpBlockedBanner() setUpBlockedBanner()
binding!!.searchBottomBar.setEventListener(this) binding!!.searchBottomBar.setEventListener(this)
@ -460,23 +455,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
actionBar.title = "" actionBar.title = ""
actionBar.setDisplayHomeAsUpEnabled(true) actionBar.setDisplayHomeAsUpEnabled(true)
actionBar.setHomeButtonEnabled(true) actionBar.setHomeButtonEnabled(true)
binding!!.toolbarContent.conversationTitleView.text = when { binding!!.toolbarContent.bind(viewModel.threadId, recipient, glide)
recipient.isLocalNumber -> getString(R.string.note_to_self)
else -> recipient.toShortString()
}
@DimenRes val sizeID: Int = if (viewModel.recipient?.isClosedGroupRecipient == true) {
R.dimen.medium_profile_picture_size
} else {
R.dimen.small_profile_picture_size
}
val size = resources.getDimension(sizeID).roundToInt()
binding!!.toolbarContent.profilePictureView.root.layoutParams = LinearLayout.LayoutParams(size, size)
binding!!.toolbarContent.profilePictureView.root.glide = glide
MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded(viewModel.threadId, this)
val profilePictureView = binding!!.toolbarContent.profilePictureView.root
viewModel.recipient?.let { recipient ->
profilePictureView.update(recipient)
}
} }
// called from onCreate // called from onCreate
@ -566,8 +545,10 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
} }
private fun getLatestOpenGroupInfoIfNeeded() { private fun getLatestOpenGroupInfoIfNeeded() {
viewModel.openGroup?.let { viewModel.openGroup?.let { openGroup ->
OpenGroupApi.getMemberCount(it.room, it.server).successUi { updateSubtitle() } OpenGroupApi.getMemberCount(openGroup.room, openGroup.server).successUi {
binding?.toolbarContent?.updateSubtitle(viewModel.recipient!!, openGroup)
}
} }
} }
@ -631,9 +612,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
menu, menu,
menuInflater, menuInflater,
recipient, recipient,
viewModel.threadId,
this this
) { onOptionsItemSelected(it) } )
} }
super.onPrepareOptionsMenu(menu) super.onPrepareOptionsMenu(menu)
return true return true
@ -657,13 +637,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
} }
setUpMessageRequestsBar() setUpMessageRequestsBar()
invalidateOptionsMenu() invalidateOptionsMenu()
updateSubtitle()
showOrHideInputIfNeeded() showOrHideInputIfNeeded()
binding?.toolbarContent?.profilePictureView?.root?.update(threadRecipient) binding?.toolbarContent?.update(threadRecipient)
binding!!.toolbarContent.conversationTitleView.text = when {
threadRecipient.isLocalNumber -> getString(R.string.note_to_self)
else -> threadRecipient.toShortString()
}
} }
} }
@ -924,33 +899,13 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
binding.unreadCountIndicator.isVisible = (unreadCount != 0) binding.unreadCountIndicator.isVisible = (unreadCount != 0)
} }
private fun updateSubtitle() {
val actionBarBinding = binding?.toolbarContent ?: return
val recipient = viewModel.recipient ?: return
actionBarBinding.muteIconImageView.isVisible = recipient.isMuted
actionBarBinding.conversationSubtitleView.isVisible = true
if (recipient.isMuted) {
if (recipient.mutedUntil != Long.MAX_VALUE) {
actionBarBinding.conversationSubtitleView.text = getString(R.string.ConversationActivity_muted_until_date, DateUtils.getFormattedDateTime(recipient.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault()))
} else {
actionBarBinding.conversationSubtitleView.text = getString(R.string.ConversationActivity_muted_forever)
}
} else if (recipient.isGroupRecipient) {
viewModel.openGroup?.let { openGroup ->
val userCount = lokiApiDb.getUserCount(openGroup.room, openGroup.server) ?: 0
actionBarBinding.conversationSubtitleView.text = getString(R.string.ConversationActivity_active_member_count, userCount)
} ?: run {
val userCount = groupDb.getGroupMemberAddresses(recipient.address.toGroupString(), true).size
actionBarBinding.conversationSubtitleView.text = getString(R.string.ConversationActivity_member_count, userCount)
}
viewModel
} else {
actionBarBinding.conversationSubtitleView.isVisible = false
}
}
// endregion // endregion
// region Interaction // region Interaction
override fun onExpirationSettingClicked() {
viewModel.recipient?.let { showExpirationSettings(it) }
}
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) { if (item.itemId == android.R.id.home) {
return false return false
@ -983,7 +938,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
} }
override fun showExpiringMessagesDialog(thread: Recipient) { override fun showExpirationSettings(thread: Recipient) {
if (thread.isClosedGroupRecipient) { if (thread.isClosedGroupRecipient) {
val group = groupDb.getGroup(thread.address.toGroupString()).orNull() val group = groupDb.getGroup(thread.address.toGroupString()).orNull()
if (group?.isActive == false) { return } if (group?.isActive == false) { return }

@ -4,16 +4,11 @@ import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.os.AsyncTask import android.os.AsyncTask
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.annotation.ColorInt
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ContextThemeWrapper import androidx.appcompat.view.ContextThemeWrapper
@ -25,10 +20,8 @@ import androidx.core.graphics.drawable.IconCompat
import network.loki.messenger.R import network.loki.messenger.R
import org.session.libsession.messaging.sending_receiving.MessageSender import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.messaging.sending_receiving.leave import org.session.libsession.messaging.sending_receiving.leave
import org.session.libsession.utilities.ExpirationUtil
import org.session.libsession.utilities.GroupUtil.doubleDecodeGroupID import org.session.libsession.utilities.GroupUtil.doubleDecodeGroupID
import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.getColorFromAttr
import org.session.libsession.utilities.recipients.Recipient import org.session.libsession.utilities.recipients.Recipient
import org.session.libsignal.utilities.guava.Optional import org.session.libsignal.utilities.guava.Optional
import org.session.libsignal.utilities.toHexString import org.session.libsignal.utilities.toHexString
@ -53,31 +46,13 @@ object ConversationMenuHelper {
menu: Menu, menu: Menu,
inflater: MenuInflater, inflater: MenuInflater,
thread: Recipient, thread: Recipient,
threadId: Long, context: Context
context: Context,
onOptionsItemSelected: (MenuItem) -> Unit
) { ) {
// Prepare // Prepare
menu.clear() menu.clear()
val isOpenGroup = thread.isOpenGroupRecipient val isOpenGroup = thread.isOpenGroupRecipient
// Base menu (options that should always be present) // Base menu (options that should always be present)
inflater.inflate(R.menu.menu_conversation, menu) inflater.inflate(R.menu.menu_conversation, menu)
// Expiring messages
if (!isOpenGroup && (thread.hasApprovedMe() || thread.isClosedGroupRecipient || thread.isLocalNumber)) {
if (thread.expireMessages > 0) {
inflater.inflate(R.menu.menu_conversation_expiration_on, menu)
val item = menu.findItem(R.id.menu_expiring_messages)
val actionView = item.actionView
val iconView = actionView.findViewById<ImageView>(R.id.menu_badge_icon)
val badgeView = actionView.findViewById<TextView>(R.id.expiration_badge)
@ColorInt val color = context.getColorFromAttr(android.R.attr.textColorPrimary)
iconView.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)
badgeView.text = ExpirationUtil.getExpirationAbbreviatedDisplayValue(context, thread.expireMessages)
actionView.setOnClickListener { onOptionsItemSelected(item) }
} else {
inflater.inflate(R.menu.menu_conversation_expiration_off, menu)
}
}
// One-on-one chat menu (options that should only be present for one-on-one chats) // One-on-one chat menu (options that should only be present for one-on-one chats)
if (thread.isContactRecipient) { if (thread.isContactRecipient) {
if (thread.isBlocked) { if (thread.isBlocked) {
@ -148,8 +123,6 @@ object ConversationMenuHelper {
R.id.menu_view_all_media -> { showAllMedia(context, thread) } R.id.menu_view_all_media -> { showAllMedia(context, thread) }
R.id.menu_search -> { search(context) } R.id.menu_search -> { search(context) }
R.id.menu_add_shortcut -> { addShortcut(context, thread) } R.id.menu_add_shortcut -> { addShortcut(context, thread) }
R.id.menu_expiring_messages -> { showExpiringMessagesDialog(context, thread) }
R.id.menu_expiring_messages_off -> { showExpiringMessagesDialog(context, thread) }
R.id.menu_unblock -> { unblock(context, thread) } R.id.menu_unblock -> { unblock(context, thread) }
R.id.menu_block -> { block(context, thread, deleteThread = false) } R.id.menu_block -> { block(context, thread, deleteThread = false) }
R.id.menu_block_delete -> { blockAndDelete(context, thread) } R.id.menu_block_delete -> { blockAndDelete(context, thread) }
@ -241,9 +214,9 @@ object ConversationMenuHelper {
}.execute() }.execute()
} }
private fun showExpiringMessagesDialog(context: Context, thread: Recipient) { private fun showExpirationSettings(context: Context, thread: Recipient) {
val listener = context as? ConversationMenuListener ?: return val listener = context as? ConversationMenuListener ?: return
listener.showExpiringMessagesDialog(thread) listener.showExpirationSettings(thread)
} }
private fun unblock(context: Context, thread: Recipient) { private fun unblock(context: Context, thread: Recipient) {
@ -344,7 +317,7 @@ object ConversationMenuHelper {
fun block(deleteThread: Boolean = false) fun block(deleteThread: Boolean = false)
fun unblock() fun unblock()
fun copySessionID(sessionId: String) fun copySessionID(sessionId: String)
fun showExpiringMessagesDialog(thread: Recipient) fun showExpirationSettings(thread: Recipient)
} }
} }

@ -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>

@ -16,8 +16,10 @@
android:background="?colorPrimary" android:background="?colorPrimary"
app:contentInsetStart="0dp"> app:contentInsetStart="0dp">
<include android:id="@+id/toolbarContent" <org.thoughtcrime.securesms.conversation.ConversationActionBarView
layout="@layout/activity_conversation_v2_action_bar" /> android:id="@+id/toolbarContent"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.appcompat.widget.Toolbar> </androidx.appcompat.widget.Toolbar>

@ -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…
Cancel
Save