Update NewConversationHomeFragment

This commit is contained in:
Andrew 2024-05-03 23:37:42 +09:30
parent 18a4bcdbd9
commit ddf0b027d7
8 changed files with 65 additions and 253 deletions

View File

@ -7,4 +7,5 @@ interface NewConversationDelegate {
fun onContactSelected(address: String)
fun onDialogBackPressed()
fun onDialogClosePressed()
fun onInviteFriend()
}

View File

@ -80,6 +80,10 @@ class NewConversationFragment : BottomSheetDialogFragment(), NewConversationDele
childFragmentManager.popBackStack()
}
override fun onInviteFriend() {
}
override fun onDialogClosePressed() {
dismiss()
}

View File

@ -4,67 +4,69 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Divider
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.RecyclerView
import dagger.hilt.android.AndroidEntryPoint
import network.loki.messenger.R
import network.loki.messenger.databinding.FragmentNewConversationHomeBinding
import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.utilities.PublicKeyValidation
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.mms.GlideApp
import org.thoughtcrime.securesms.ui.AppTheme
import org.thoughtcrime.securesms.ui.ItemButton
import org.thoughtcrime.securesms.ui.classicDarkColors
import org.thoughtcrime.securesms.ui.components.AppBar
import org.thoughtcrime.securesms.ui.components.QrImage
import org.thoughtcrime.securesms.ui.medium
import org.thoughtcrime.securesms.ui.small
import javax.inject.Inject
@AndroidEntryPoint
class NewConversationHomeFragment : Fragment() {
private lateinit var binding: FragmentNewConversationHomeBinding
private val viewModel: NewConversationHomeViewModel by viewModels()
@Inject
lateinit var textSecurePreferences: TextSecurePreferences
lateinit var delegate: NewConversationDelegate
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentNewConversationHomeBinding.inflate(inflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.closeButton.setOnClickListener { delegate.onDialogClosePressed() }
binding.createPrivateChatButton.setOnClickListener { delegate.onNewMessageSelected() }
binding.createClosedGroupButton.setOnClickListener { delegate.onCreateGroupSelected() }
binding.joinCommunityButton.setOnClickListener { delegate.onJoinCommunitySelected() }
val adapter = ContactListAdapter(requireContext(), GlideApp.with(requireContext())) {
delegate.onContactSelected(it.address.serialize())
}
val unknownSectionTitle = getString(R.string.new_conversation_unknown_contacts_section_title)
val recipients = viewModel.recipients.value?.filter { !it.isGroupRecipient && it.address.serialize() != textSecurePreferences.getLocalNumber()!! } ?: emptyList()
val contactGroups = recipients.map {
val sessionId = it.address.serialize()
val contact = DatabaseComponent.get(requireContext()).sessionContactDatabase().getContactWithSessionID(sessionId)
val displayName = contact?.displayName(Contact.ContactContext.REGULAR) ?: sessionId
ContactListItem.Contact(it, displayName)
}.sortedBy { it.displayName }
.groupBy { if (PublicKeyValidation.isValid(it.displayName)) unknownSectionTitle else it.displayName.firstOrNull()?.uppercase() ?: unknownSectionTitle }
.toMutableMap()
contactGroups.remove(unknownSectionTitle)?.let { contactGroups.put(unknownSectionTitle, it) }
adapter.items = contactGroups.flatMap { entry -> listOf(ContactListItem.Header(entry.key)) + entry.value }
binding.contactsRecyclerView.adapter = adapter
val divider = ContextCompat.getDrawable(requireActivity(), R.drawable.conversation_menu_divider)!!.let {
DividerItemDecoration(requireActivity(), RecyclerView.VERTICAL).apply {
setDrawable(it)
): View = ComposeView(requireContext()).apply {
setContent {
AppTheme {
NewConversationScreen()
}
}
}
@Composable
fun NewConversationScreen() {
Column {
AppBar(stringResource(R.string.dialog_new_conversation_title), onClose = { delegate.onDialogClosePressed() })
ItemButton(textId = R.string.messageNew, icon = R.drawable.ic_message) { delegate.onNewMessageSelected() }
Divider(modifier = Modifier.padding(start = 80.dp))
ItemButton(textId = R.string.activity_create_group_title, icon = R.drawable.ic_group) { delegate.onCreateGroupSelected() }
Divider(modifier = Modifier.padding(start = 80.dp))
ItemButton(textId = R.string.dialog_join_community_title, icon = R.drawable.ic_globe) { delegate.onJoinCommunitySelected() }
Divider(modifier = Modifier.padding(start = 80.dp))
ItemButton(textId = R.string.activity_settings_invite_button_title, icon = R.drawable.ic_invite_friend) { delegate.onInviteFriend() }
Column(modifier = Modifier.padding(horizontal = 32.dp).padding(top = 20.dp)) {
Text(text = "Your Account ID", style = MaterialTheme.typography.medium)
Spacer(modifier = Modifier.height(4.dp))
Text(text = "Friends can message you by scanning your QR code.", color = classicDarkColors[5], style = MaterialTheme.typography.small)
Spacer(modifier = Modifier.height(20.dp))
QrImage(string = TextSecurePreferences.getLocalNumber(requireContext())!!, contentDescription = "Your session id")
}
}
binding.contactsRecyclerView.addItemDecoration(divider)
}
}

View File

@ -1,35 +0,0 @@
package org.thoughtcrime.securesms.conversation.start
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.database.ThreadDatabase
import javax.inject.Inject
@HiltViewModel
class NewConversationHomeViewModel @Inject constructor(private val threadDb: ThreadDatabase): ViewModel() {
private val _recipients = MutableLiveData<List<Recipient>>()
val recipients: LiveData<List<Recipient>> = _recipients
init {
viewModelScope.launch {
threadDb.approvedConversationList.use { openCursor ->
val reader = threadDb.readerFor(openCursor)
val threads = mutableListOf<Recipient>()
while (true) {
threads += reader.next?.recipient ?: break
}
withContext(Dispatchers.Main) {
_recipients.value = threads
}
}
}
}
}

View File

@ -193,9 +193,11 @@ fun ItemButton(
onClick = onClick,
shape = RectangleShape,
) {
Box(modifier = Modifier
.width(80.dp)
.fillMaxHeight()) {
Box(
modifier = Modifier
.width(80.dp)
.fillMaxHeight()
) {
icon()
}
Text(text, modifier = Modifier.fillMaxWidth(), style = MaterialTheme.typography.h8)

View File

@ -112,6 +112,7 @@ val sessionTypography = Typography(
h6 = boldStyle(20.sp),
)
val Typography.medium get() = defaultStyle(18.sp)
val Typography.base get() = defaultStyle(14.sp)
val Typography.baseBold get() = boldStyle(14.sp)
val Typography.small get() = defaultStyle(12.sp)

View File

@ -13,9 +13,16 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import network.loki.messenger.R
@Preview
@Composable
fun AppBarPreview() {
AppBar(title = "Title", {}, {})
}
@Composable
fun AppBar(title: String, onClose: () -> Unit = {}, onBack: (() -> Unit)? = null) {
Row(modifier = Modifier.height(64.dp), verticalAlignment = Alignment.CenterVertically) {

View File

@ -1,170 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView 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:background="?conversation_menu_background_color">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/medium_spacing">
<TextView
android:id="@+id/titleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal|center_vertical"
android:paddingTop="@dimen/large_spacing"
android:paddingBottom="@dimen/very_large_spacing"
android:text="@string/dialog_new_conversation_title"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/very_large_font_size"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/closeButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/small_spacing"
android:layout_marginStart="@dimen/large_spacing"
android:clickable="true"
android:contentDescription="@string/new_conversation_dialog_close_button_content_description"
android:focusable="true"
android:src="@drawable/ic_baseline_close_24"
android:background="?selectableItemBackgroundBorderless"
app:layout_constraintBottom_toTopOf="@id/title_divider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/title_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginBottom="1dp"
android:background="?conversation_menu_border_color"
app:layout_constraintStart_toStartOf="@+id/titleText"
app:layout_constraintTop_toBottomOf="@+id/titleText" />
<View
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="@+id/createPrivateChatButton"
app:layout_constraintBottom_toBottomOf="@+id/joinCommunityButton"
android:background="?conversation_menu_cell_color"/>
<TextView
android:id="@+id/createPrivateChatButton"
android:contentDescription="@string/AccessibilityId_new_direct_message"
android:layout_width="match_parent"
android:layout_height="@dimen/setting_button_height"
android:drawablePadding="@dimen/large_spacing"
android:gravity="center_vertical"
android:paddingHorizontal="@dimen/large_spacing"
android:text="@string/dialog_new_message_title"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/medium_font_size"
android:background="?selectableItemBackground"
app:drawableStartCompat="@drawable/ic_message"
app:layout_constraintBottom_toTopOf="@+id/new_message_divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title_divider" />
<View
android:id="@+id/new_message_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="@dimen/massive_spacing"
android:background="?conversation_menu_border_color"
app:layout_constraintStart_toStartOf="@+id/createPrivateChatButton"
app:layout_constraintTop_toBottomOf="@+id/createPrivateChatButton" />
<TextView
android:id="@+id/createClosedGroupButton"
android:contentDescription="@string/AccessibilityId_create_group"
android:layout_width="match_parent"
android:layout_height="@dimen/setting_button_height"
android:drawablePadding="@dimen/large_spacing"
android:gravity="center_vertical"
android:paddingHorizontal="@dimen/large_spacing"
android:text="@string/activity_create_group_title"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/medium_font_size"
android:background="?selectableItemBackground"
app:drawableStartCompat="@drawable/ic_group"
app:layout_constraintBottom_toTopOf="@+id/create_group_divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/new_message_divider" />
<View
android:id="@+id/create_group_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="@dimen/massive_spacing"
android:background="?conversation_menu_border_color"
app:layout_constraintStart_toStartOf="@+id/createClosedGroupButton"
app:layout_constraintTop_toBottomOf="@+id/createClosedGroupButton" />
<TextView
android:id="@+id/joinCommunityButton"
android:contentDescription="@string/AccessibilityId_join_community"
android:layout_width="match_parent"
android:layout_height="@dimen/setting_button_height"
android:drawablePadding="@dimen/large_spacing"
android:gravity="center_vertical"
android:paddingHorizontal="@dimen/large_spacing"
android:text="@string/dialog_join_community_title"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/medium_font_size"
android:background="?selectableItemBackground"
app:drawableStartCompat="@drawable/ic_globe"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/create_group_divider" />
<View
android:id="@+id/join_community_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginBottom="1dp"
android:background="?conversation_menu_border_color"
app:layout_constraintStart_toStartOf="@+id/joinCommunityButton"
app:layout_constraintTop_toBottomOf="@+id/joinCommunityButton" />
<TextView
android:id="@+id/contactsText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingHorizontal="@dimen/large_spacing"
android:paddingTop="@dimen/medium_spacing"
android:paddingBottom="@dimen/small_spacing"
android:text="@string/new_conversation_contacts_title"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/medium_font_size"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/join_community_divider" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/contactsRecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/contactsText"
tools:itemCount="6"
tools:listitem="@layout/view_contact" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>