mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 04:58:45 +00:00
Add call tab info screen.
This commit is contained in:
committed by
Greyson Parrelli
parent
49a814abef
commit
545f1fa5a4
@@ -70,7 +70,7 @@ class CallLogContextMenu(
|
||||
iconRes = R.drawable.symbol_info_24,
|
||||
title = fragment.getString(R.string.CallContextMenu__info)
|
||||
) {
|
||||
val intent = ConversationSettingsActivity.forCall(fragment.requireContext(), call.peer)
|
||||
val intent = ConversationSettingsActivity.forCall(fragment.requireContext(), call.peer, longArrayOf(call.call.messageId))
|
||||
fragment.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ class ConversationSettingsActivity : DSLSettingsActivity(), ConversationSettings
|
||||
|
||||
@JvmStatic
|
||||
fun forGroup(context: Context, groupId: GroupId): Intent {
|
||||
val startBundle = ConversationSettingsFragmentArgs.Builder(null, ParcelableGroupId.from(groupId))
|
||||
val startBundle = ConversationSettingsFragmentArgs.Builder(null, ParcelableGroupId.from(groupId), null)
|
||||
.build()
|
||||
.toBundle()
|
||||
|
||||
@@ -77,7 +77,7 @@ class ConversationSettingsActivity : DSLSettingsActivity(), ConversationSettings
|
||||
|
||||
@JvmStatic
|
||||
fun forRecipient(context: Context, recipientId: RecipientId): Intent {
|
||||
val startBundle = ConversationSettingsFragmentArgs.Builder(recipientId, null)
|
||||
val startBundle = ConversationSettingsFragmentArgs.Builder(recipientId, null, null)
|
||||
.build()
|
||||
.toBundle()
|
||||
|
||||
@@ -86,17 +86,14 @@ class ConversationSettingsActivity : DSLSettingsActivity(), ConversationSettings
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun forCall(context: Context, callPeer: Recipient): Intent {
|
||||
fun forCall(context: Context, callPeer: Recipient, callMessageIds: LongArray): Intent {
|
||||
val startBundleBuilder = if (callPeer.isGroup) {
|
||||
ConversationSettingsFragmentArgs.Builder(null, ParcelableGroupId.from(callPeer.requireGroupId()))
|
||||
ConversationSettingsFragmentArgs.Builder(null, ParcelableGroupId.from(callPeer.requireGroupId()), callMessageIds)
|
||||
} else {
|
||||
ConversationSettingsFragmentArgs.Builder(callPeer.id, null)
|
||||
ConversationSettingsFragmentArgs.Builder(callPeer.id, null, callMessageIds)
|
||||
}
|
||||
|
||||
val startBundle = startBundleBuilder
|
||||
.setIsCallInfo(true)
|
||||
.build()
|
||||
.toBundle()
|
||||
val startBundle = startBundleBuilder.build().toBundle()
|
||||
|
||||
return getIntent(context)
|
||||
.putExtra(ARG_START_BUNDLE, startBundle)
|
||||
|
||||
@@ -19,6 +19,7 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.Navigation
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import app.cash.exhaustive.Exhaustive
|
||||
@@ -49,6 +50,7 @@ import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.AvatarPreference
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.BioTextPreference
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.ButtonStripPreference
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.CallPreference
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.GroupDescriptionPreference
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.InternalPreference
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.LargeIconClickPreference
|
||||
@@ -83,6 +85,7 @@ import org.thoughtcrime.securesms.stories.viewer.AddToGroupStoryDelegate
|
||||
import org.thoughtcrime.securesms.stories.viewer.StoryViewerActivity
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions
|
||||
import org.thoughtcrime.securesms.util.ContextUtil
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import org.thoughtcrime.securesms.util.ExpirationUtil
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.Material3OnScrollHelper
|
||||
@@ -92,6 +95,7 @@ import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog
|
||||
import org.thoughtcrime.securesms.verify.VerifyIdentityActivity
|
||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaperActivity
|
||||
import java.util.Locale
|
||||
|
||||
private const val REQUEST_CODE_VIEW_CONTACT = 1
|
||||
private const val REQUEST_CODE_ADD_CONTACT = 2
|
||||
@@ -103,6 +107,7 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||
menuId = R.menu.conversation_settings
|
||||
) {
|
||||
|
||||
private val args: ConversationSettingsFragmentArgs by navArgs()
|
||||
private val alertTint by lazy { ContextCompat.getColor(requireContext(), R.color.signal_alert_primary) }
|
||||
private val blockIcon by lazy {
|
||||
ContextUtil.requireDrawable(requireContext(), R.drawable.ic_block_tinted_24).apply {
|
||||
@@ -122,13 +127,12 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||
|
||||
private val viewModel by viewModels<ConversationSettingsViewModel>(
|
||||
factoryProducer = {
|
||||
val args = ConversationSettingsFragmentArgs.fromBundle(requireArguments())
|
||||
val groupId = args.groupId as? ParcelableGroupId
|
||||
|
||||
ConversationSettingsViewModel.Factory(
|
||||
recipientId = args.recipientId,
|
||||
groupId = ParcelableGroupId.get(groupId),
|
||||
isCallInfo = args.isCallInfo,
|
||||
callMessageIds = args.callMessageIds ?: longArrayOf(),
|
||||
repository = ConversationSettingsRepository(requireContext())
|
||||
)
|
||||
}
|
||||
@@ -221,6 +225,7 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||
InternalPreference.register(adapter)
|
||||
GroupDescriptionPreference.register(adapter)
|
||||
LegacyGroupPreference.register(adapter)
|
||||
CallPreference.register(adapter)
|
||||
|
||||
val recipientId = args.recipientId
|
||||
if (recipientId != null) {
|
||||
@@ -437,6 +442,17 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||
|
||||
dividerPref()
|
||||
|
||||
if (state.calls.isNotEmpty()) {
|
||||
val firstCall = state.calls.first()
|
||||
sectionHeaderPref(DSLSettingsText.from(DateUtils.formatDate(Locale.getDefault(), firstCall.record.timestamp)))
|
||||
|
||||
for (call in state.calls) {
|
||||
customPref(call)
|
||||
}
|
||||
|
||||
dividerPref()
|
||||
}
|
||||
|
||||
val summary = DSLSettingsText.from(formatDisappearingMessagesLifespan(state.disappearingMessagesLifespan))
|
||||
val icon = if (state.disappearingMessagesLifespan <= 0 || state.recipient.isBlocked) {
|
||||
R.drawable.ic_update_timer_disabled_16
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.database.Cursor
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.LiveData
|
||||
import io.reactivex.rxjava3.core.Observable
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.signal.core.util.logging.Log
|
||||
@@ -15,6 +16,7 @@ import org.thoughtcrime.securesms.database.MediaTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord
|
||||
import org.thoughtcrime.securesms.database.model.IdentityRecord
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.StoryViewState
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
@@ -37,6 +39,16 @@ class ConversationSettingsRepository(
|
||||
private val groupManagementRepository: GroupManagementRepository = GroupManagementRepository(context)
|
||||
) {
|
||||
|
||||
fun getCallEvents(callMessageIds: LongArray): Single<List<MessageRecord>> {
|
||||
return if (callMessageIds.isEmpty()) {
|
||||
Single.just(emptyList())
|
||||
} else {
|
||||
Single.fromCallable {
|
||||
SignalDatabase.messages.getMessages(callMessageIds.toList()).iterator().asSequence().toList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getThreadMedia(threadId: Long): Optional<Cursor> {
|
||||
return if (threadId <= 0) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.components.settings.conversation
|
||||
|
||||
import android.database.Cursor
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.ButtonStripPreference
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.CallPreference
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.LegacyGroupPreference
|
||||
import org.thoughtcrime.securesms.database.model.IdentityRecord
|
||||
import org.thoughtcrime.securesms.database.model.StoryViewState
|
||||
@@ -19,6 +20,7 @@ data class ConversationSettingsState(
|
||||
val sharedMedia: Cursor? = null,
|
||||
val sharedMediaIds: List<Long> = listOf(),
|
||||
val displayInternalRecipientDetails: Boolean = false,
|
||||
val calls: List<CallPreference.Model> = emptyList(),
|
||||
private val sharedMediaLoaded: Boolean = false,
|
||||
private val specificSettingsState: SpecificSettingsState
|
||||
) {
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.signal.core.util.CursorUtil
|
||||
import org.signal.core.util.ThreadUtil
|
||||
import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.ButtonStripPreference
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.CallPreference
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.LegacyGroupPreference
|
||||
import org.thoughtcrime.securesms.database.AttachmentTable
|
||||
import org.thoughtcrime.securesms.database.RecipientTable
|
||||
@@ -33,6 +34,7 @@ import org.thoughtcrime.securesms.util.livedata.Store
|
||||
import java.util.Optional
|
||||
|
||||
sealed class ConversationSettingsViewModel(
|
||||
private val callMessageIds: LongArray,
|
||||
private val repository: ConversationSettingsRepository,
|
||||
specificSettingsState: SpecificSettingsState
|
||||
) : ViewModel() {
|
||||
@@ -64,6 +66,10 @@ sealed class ConversationSettingsViewModel(
|
||||
repository.getThreadMedia(tId)
|
||||
}
|
||||
|
||||
store.update(repository.getCallEvents(callMessageIds).toObservable()) { callRecords, state ->
|
||||
state.copy(calls = callRecords.map { CallPreference.Model(it) })
|
||||
}
|
||||
|
||||
store.update(sharedMedia) { cursor, state ->
|
||||
if (!cleared) {
|
||||
if (cursor.isPresent) {
|
||||
@@ -128,9 +134,10 @@ sealed class ConversationSettingsViewModel(
|
||||
|
||||
private class RecipientSettingsViewModel(
|
||||
private val recipientId: RecipientId,
|
||||
private val isCallInfo: Boolean,
|
||||
private val callMessageIds: LongArray,
|
||||
private val repository: ConversationSettingsRepository
|
||||
) : ConversationSettingsViewModel(
|
||||
callMessageIds,
|
||||
repository,
|
||||
SpecificSettingsState.RecipientSettingsState()
|
||||
) {
|
||||
@@ -152,13 +159,13 @@ sealed class ConversationSettingsViewModel(
|
||||
state.copy(
|
||||
recipient = recipient,
|
||||
buttonStripState = ButtonStripPreference.State(
|
||||
isMessageAvailable = isCallInfo,
|
||||
isMessageAvailable = callMessageIds.isNotEmpty(),
|
||||
isVideoAvailable = recipient.registered == RecipientTable.RegisteredState.REGISTERED && !recipient.isSelf && !recipient.isBlocked && !recipient.isReleaseNotes,
|
||||
isAudioAvailable = isAudioAvailable,
|
||||
isAudioSecure = recipient.registered == RecipientTable.RegisteredState.REGISTERED,
|
||||
isMuted = recipient.isMuted,
|
||||
isMuteAvailable = !recipient.isSelf,
|
||||
isSearchAvailable = !isCallInfo
|
||||
isSearchAvailable = callMessageIds.isEmpty()
|
||||
),
|
||||
disappearingMessagesLifespan = recipient.expiresInSeconds,
|
||||
canModifyBlockedState = !recipient.isSelf && RecipientUtil.isBlockable(recipient),
|
||||
@@ -258,9 +265,9 @@ sealed class ConversationSettingsViewModel(
|
||||
|
||||
private class GroupSettingsViewModel(
|
||||
private val groupId: GroupId,
|
||||
private val isCallInfo: Boolean,
|
||||
private val callMessageIds: LongArray,
|
||||
private val repository: ConversationSettingsRepository
|
||||
) : ConversationSettingsViewModel(repository, SpecificSettingsState.GroupSettingsState(groupId)) {
|
||||
) : ConversationSettingsViewModel(callMessageIds, repository, SpecificSettingsState.GroupSettingsState(groupId)) {
|
||||
|
||||
private val liveGroup = LiveGroup(groupId)
|
||||
|
||||
@@ -274,13 +281,13 @@ sealed class ConversationSettingsViewModel(
|
||||
state.copy(
|
||||
recipient = recipient,
|
||||
buttonStripState = ButtonStripPreference.State(
|
||||
isMessageAvailable = isCallInfo,
|
||||
isMessageAvailable = callMessageIds.isNotEmpty(),
|
||||
isVideoAvailable = recipient.isPushV2Group && !recipient.isBlocked && isActive,
|
||||
isAudioAvailable = false,
|
||||
isAudioSecure = recipient.isPushV2Group,
|
||||
isMuted = recipient.isMuted,
|
||||
isMuteAvailable = true,
|
||||
isSearchAvailable = !isCallInfo,
|
||||
isSearchAvailable = callMessageIds.isEmpty(),
|
||||
isAddToStoryAvailable = recipient.isPushV2Group && !recipient.isBlocked && isActive && !SignalStore.storyValues().isFeatureDisabled
|
||||
),
|
||||
canModifyBlockedState = RecipientUtil.isBlockable(recipient),
|
||||
@@ -483,7 +490,7 @@ sealed class ConversationSettingsViewModel(
|
||||
class Factory(
|
||||
private val recipientId: RecipientId? = null,
|
||||
private val groupId: GroupId? = null,
|
||||
private val isCallInfo: Boolean,
|
||||
private val callMessageIds: LongArray,
|
||||
private val repository: ConversationSettingsRepository
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@@ -491,8 +498,8 @@ sealed class ConversationSettingsViewModel(
|
||||
return requireNotNull(
|
||||
modelClass.cast(
|
||||
when {
|
||||
recipientId != null -> RecipientSettingsViewModel(recipientId, isCallInfo, repository)
|
||||
groupId != null -> GroupSettingsViewModel(groupId, isCallInfo, repository)
|
||||
recipientId != null -> RecipientSettingsViewModel(recipientId, callMessageIds, repository)
|
||||
groupId != null -> GroupSettingsViewModel(groupId, callMessageIds, repository)
|
||||
else -> error("One of RecipientId or GroupId required.")
|
||||
}
|
||||
)
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.thoughtcrime.securesms.components.settings.conversation.preferences
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.database.MessageTypes
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.databinding.ConversationSettingsCallPreferenceItemBinding
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.BindingFactory
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.BindingViewHolder
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* Renders a single call preference row when displaying call info.
|
||||
*/
|
||||
object CallPreference {
|
||||
fun register(mappingAdapter: MappingAdapter) {
|
||||
mappingAdapter.registerFactory(Model::class.java, BindingFactory(::ViewHolder, ConversationSettingsCallPreferenceItemBinding::inflate))
|
||||
}
|
||||
|
||||
class Model(
|
||||
val record: MessageRecord
|
||||
) : MappingModel<Model> {
|
||||
override fun areItemsTheSame(newItem: Model): Boolean = record.id == newItem.record.id
|
||||
|
||||
override fun areContentsTheSame(newItem: Model): Boolean {
|
||||
return record.type == newItem.record.type &&
|
||||
record.isOutgoing == newItem.record.isOutgoing &&
|
||||
record.timestamp == newItem.record.timestamp &&
|
||||
record.id == newItem.record.id
|
||||
}
|
||||
}
|
||||
|
||||
private class ViewHolder(binding: ConversationSettingsCallPreferenceItemBinding) : BindingViewHolder<Model, ConversationSettingsCallPreferenceItemBinding>(binding) {
|
||||
override fun bind(model: Model) {
|
||||
binding.callIcon.setImageResource(getCallIcon(model.record))
|
||||
binding.callType.text = getCallType(model.record)
|
||||
binding.callTime.text = getCallTime(model.record)
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
private fun getCallIcon(messageRecord: MessageRecord): Int {
|
||||
return when (messageRecord.type) {
|
||||
MessageTypes.MISSED_VIDEO_CALL_TYPE, MessageTypes.MISSED_AUDIO_CALL_TYPE -> R.drawable.symbol_missed_incoming_24
|
||||
MessageTypes.INCOMING_AUDIO_CALL_TYPE, MessageTypes.INCOMING_VIDEO_CALL_TYPE -> R.drawable.symbol_arrow_downleft_24
|
||||
MessageTypes.OUTGOING_AUDIO_CALL_TYPE, MessageTypes.OUTGOING_VIDEO_CALL_TYPE -> R.drawable.symbol_arrow_upright_24
|
||||
else -> error("Unexpected type ${messageRecord.type}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCallType(messageRecord: MessageRecord): String {
|
||||
val id = when (messageRecord.type) {
|
||||
MessageTypes.MISSED_VIDEO_CALL_TYPE -> R.string.MessageRecord_missed_voice_call
|
||||
MessageTypes.MISSED_AUDIO_CALL_TYPE -> R.string.MessageRecord_missed_video_call
|
||||
MessageTypes.INCOMING_AUDIO_CALL_TYPE -> R.string.MessageRecord_incoming_voice_call
|
||||
MessageTypes.INCOMING_VIDEO_CALL_TYPE -> R.string.MessageRecord_incoming_video_call
|
||||
MessageTypes.OUTGOING_AUDIO_CALL_TYPE -> R.string.MessageRecord_outgoing_voice_call
|
||||
MessageTypes.OUTGOING_VIDEO_CALL_TYPE -> R.string.MessageRecord_outgoing_video_call
|
||||
else -> error("Unexpected type ${messageRecord.type}")
|
||||
}
|
||||
|
||||
return context.getString(id)
|
||||
}
|
||||
|
||||
private fun getCallTime(messageRecord: MessageRecord): String {
|
||||
return DateUtils.getOnlyTimeString(context, Locale.getDefault(), messageRecord.timestamp)
|
||||
}
|
||||
}
|
||||
}
|
||||
9
app/src/main/res/drawable/symbol_arrow_downleft_24.xml
Normal file
9
app/src/main/res/drawable/symbol_arrow_downleft_24.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M18.37 6.87l-8.25 8.25-1.5 1.26h7.63c0.48 0 0.88 0.39 0.88 0.87s-0.4 0.88-0.88 0.88h-9.5c-0.48 0-0.88-0.4-0.88-0.88v-9.5c0-0.48 0.4-0.88 0.88-0.88s0.88 0.4 0.88 0.88v7.64l1.25-1.5 8.25-8.26c0.34-0.34 0.9-0.34 1.24 0 0.34 0.34 0.34 0.9 0 1.24Z"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/symbol_arrow_upright_24.xml
Normal file
9
app/src/main/res/drawable/symbol_arrow_upright_24.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M16.38 8.61v7.64c0 0.48 0.39 0.88 0.87 0.88s0.88-0.4 0.88-0.88v-9.5c0-0.48-0.4-0.88-0.88-0.88h-9.5c-0.48 0-0.88 0.4-0.88 0.88s0.4 0.88 0.88 0.88h7.64l-1.5 1.25-8.26 8.25c-0.34 0.34-0.34 0.9 0 1.24 0.34 0.34 0.9 0.34 1.24 0l8.25-8.25 1.26-1.5Z"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/symbol_missed_incoming_24.xml
Normal file
9
app/src/main/res/drawable/symbol_missed_incoming_24.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M4.13 9.61v6.14c0 0.48-0.4 0.88-0.88 0.88s-0.88-0.4-0.88-0.88v-8c0-0.48 0.4-0.88 0.88-0.88h8c0.48 0 0.88 0.4 0.88 0.88s-0.4 0.88-0.88 0.88H5.11l1.5 1.25 6.14 6.13 8.63-8.63c0.34-0.34 0.9-0.34 1.24 0 0.34 0.34 0.34 0.9 0 1.24l-8.72 8.72c-0.64 0.63-1.66 0.63-2.3 0l-6.22-6.22-1.25-1.5Z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content"
|
||||
android:minHeight="72dp"
|
||||
android:paddingHorizontal="@dimen/dsl_settings_gutter"
|
||||
android:paddingVertical="14dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/call_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:srcCompat="@drawable/ic_update_video_call_missed_16" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/call_type"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:textAppearance="@style/Signal.Text.BodyLarge"
|
||||
app:layout_constraintBottom_toTopOf="@id/call_time"
|
||||
app:layout_constraintStart_toEndOf="@id/call_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Incoming video call" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/call_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:textAppearance="@style/Signal.Text.BodyMedium"
|
||||
android:textColor="@color/signal_colorOnSurfaceVariant"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/call_icon"
|
||||
app:layout_constraintTop_toBottomOf="@id/call_type"
|
||||
tools:text="10:00 AM" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -48,9 +48,9 @@
|
||||
app:nullable="true" />
|
||||
|
||||
<argument
|
||||
android:name="is_call_info"
|
||||
app:argType="boolean"
|
||||
android:defaultValue="false" />
|
||||
android:name="call_message_ids"
|
||||
app:argType="long[]"
|
||||
app:nullable="true" />
|
||||
|
||||
<action
|
||||
android:id="@+id/action_conversationSettingsFragment_to_soundsAndNotificationsSettingsFragment"
|
||||
|
||||
Reference in New Issue
Block a user