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 onContactSelected(address: String)
fun onDialogBackPressed() fun onDialogBackPressed()
fun onDialogClosePressed() fun onDialogClosePressed()
fun onInviteFriend()
} }

View File

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

View File

@ -4,67 +4,69 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup 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.Fragment
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.RecyclerView
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import network.loki.messenger.R 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.libsession.utilities.TextSecurePreferences
import org.session.libsignal.utilities.PublicKeyValidation import org.thoughtcrime.securesms.ui.AppTheme
import org.thoughtcrime.securesms.dependencies.DatabaseComponent import org.thoughtcrime.securesms.ui.ItemButton
import org.thoughtcrime.securesms.mms.GlideApp 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 import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class NewConversationHomeFragment : Fragment() { class NewConversationHomeFragment : Fragment() {
private lateinit var binding: FragmentNewConversationHomeBinding
private val viewModel: NewConversationHomeViewModel by viewModels()
@Inject @Inject
lateinit var textSecurePreferences: TextSecurePreferences lateinit var textSecurePreferences: TextSecurePreferences
lateinit var delegate: NewConversationDelegate lateinit var delegate: NewConversationDelegate
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View = ComposeView(requireContext()).apply {
binding = FragmentNewConversationHomeBinding.inflate(inflater) setContent {
return binding.root AppTheme {
} NewConversationScreen()
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)
} }
} }
binding.contactsRecyclerView.addItemDecoration(divider)
} }
}
@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")
}
}
}
}

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, onClick = onClick,
shape = RectangleShape, shape = RectangleShape,
) { ) {
Box(modifier = Modifier Box(
.width(80.dp) modifier = Modifier
.fillMaxHeight()) { .width(80.dp)
.fillMaxHeight()
) {
icon() icon()
} }
Text(text, modifier = Modifier.fillMaxWidth(), style = MaterialTheme.typography.h8) Text(text, modifier = Modifier.fillMaxWidth(), style = MaterialTheme.typography.h8)

View File

@ -112,6 +112,7 @@ val sessionTypography = Typography(
h6 = boldStyle(20.sp), h6 = boldStyle(20.sp),
) )
val Typography.medium get() = defaultStyle(18.sp)
val Typography.base get() = defaultStyle(14.sp) val Typography.base get() = defaultStyle(14.sp)
val Typography.baseBold get() = boldStyle(14.sp) val Typography.baseBold get() = boldStyle(14.sp)
val Typography.small get() = defaultStyle(12.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.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import network.loki.messenger.R import network.loki.messenger.R
@Preview
@Composable
fun AppBarPreview() {
AppBar(title = "Title", {}, {})
}
@Composable @Composable
fun AppBar(title: String, onClose: () -> Unit = {}, onBack: (() -> Unit)? = null) { fun AppBar(title: String, onClose: () -> Unit = {}, onBack: (() -> Unit)? = null) {
Row(modifier = Modifier.height(64.dp), verticalAlignment = Alignment.CenterVertically) { 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>