Skip to content

Commit d6446d2

Browse files
jeffrey-signalgreyson-signal
authored andcommitted
Add split-pane UI for create group screen.
1 parent d763baa commit d6446d2

File tree

9 files changed

+607
-68
lines changed

9 files changed

+607
-68
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,6 +1059,11 @@
10591059
android:theme="@style/Theme.Signal.DayNight.NoActionBar"
10601060
android:exported="false"/>
10611061

1062+
<activity
1063+
android:name=".groups.ui.creategroup.CreateGroupActivityV2"
1064+
android:exported="false"
1065+
android:theme="@style/Signal.DayNight.NoActionBar" />
1066+
10621067
<activity android:name=".groups.ui.addtogroup.AddToGroupsActivity"
10631068
android:theme="@style/Theme.Signal.DayNight.NoActionBar"
10641069
android:exported="false"/>

app/src/main/java/org/thoughtcrime/securesms/components/ContactFilterView.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ public void focusAndShowKeyboard() {
147147
ViewUtil.focusAndShowKeyboard(searchText);
148148
}
149149

150+
public void setText(String text) {
151+
searchText.setText(text);
152+
searchText.setSelection(text.length());
153+
}
154+
150155
public void clear() {
151156
searchText.setText("");
152157
notifyListener();

app/src/main/java/org/thoughtcrime/securesms/contacts/selection/ContactSelectionArguments.kt

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -86,21 +86,21 @@ data class ContactSelectionArguments(
8686
)
8787
}
8888
}
89-
}
9089

91-
private object Defaults {
92-
const val DISPLAY_MODE = ContactSelectionDisplayMode.FLAG_ALL
93-
const val IS_REFRESHABLE = true
94-
const val ENABLE_CREATE_NEW_GROUP = false
95-
const val ENABLE_FIND_BY_USERNAME = false
96-
const val ENABLE_FIND_BY_PHONE_NUMBER = false
97-
const val INCLUDE_RECENTS = false
98-
const val INCLUDE_CHAT_TYPES = false
99-
val SELECTION_LIMITS: SelectionLimits? = null
100-
val CURRENT_SELECTION: Set<RecipientId> = emptySet()
101-
const val DISPLAY_CHIPS = true
102-
const val RECYCLER_PADDING_BOTTOM = -1
103-
const val RECYCLER_CHILD_CLIPPING = true
90+
object Defaults {
91+
const val DISPLAY_MODE = ContactSelectionDisplayMode.FLAG_ALL
92+
const val IS_REFRESHABLE = true
93+
const val ENABLE_CREATE_NEW_GROUP = false
94+
const val ENABLE_FIND_BY_USERNAME = false
95+
const val ENABLE_FIND_BY_PHONE_NUMBER = false
96+
const val INCLUDE_RECENTS = false
97+
const val INCLUDE_CHAT_TYPES = false
98+
val SELECTION_LIMITS: SelectionLimits? = null
99+
val CURRENT_SELECTION: Set<RecipientId> = emptySet()
100+
const val DISPLAY_CHIPS = true
101+
const val RECYCLER_PADDING_BOTTOM = -1
102+
const val RECYCLER_CHILD_CLIPPING = true
104103

105-
fun canSelectSelf(selectionLimits: SelectionLimits?): Boolean = selectionLimits == null
104+
fun canSelectSelf(selectionLimits: SelectionLimits?): Boolean = selectionLimits == null
105+
}
106106
}

app/src/main/java/org/thoughtcrime/securesms/conversation/NewConversationActivity.kt

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,22 +117,24 @@ private fun NewConversationScreen(
117117
contract = FindByActivity.Contract(),
118118
onResult = { recipientId ->
119119
if (recipientId != null) {
120-
viewModel.onMessage(recipientId)
120+
viewModel.openConversation(recipientId)
121121
}
122122
}
123123
)
124124

125125
val coroutineScope = rememberCoroutineScope()
126126
val callbacks = remember {
127127
object : UiCallbacks {
128+
override fun onSearchQueryChanged(query: String) = viewModel.onSearchQueryChanged(query)
128129
override fun onCreateNewGroup() = createGroupLauncher.launch(CreateGroupActivity.newIntent(context))
129130
override fun onFindByUsername() = findByLauncher.launch(FindByMode.USERNAME)
130131
override fun onFindByPhoneNumber() = findByLauncher.launch(FindByMode.PHONE_NUMBER)
131-
override fun shouldAllowSelection(id: RecipientId): Boolean = true
132-
override fun onRecipientSelected(id: RecipientId?, phone: PhoneNumber?) = viewModel.onRecipientSelected(id, phone)
133-
override fun onMessage(id: RecipientId) = viewModel.onMessage(id)
134-
override fun onVoiceCall(recipient: Recipient) = CommunicationActions.startVoiceCall(context, recipient, viewModel::onUserAlreadyInACall)
135-
override fun onVideoCall(recipient: Recipient) = CommunicationActions.startVideoCall(context, recipient, viewModel::onUserAlreadyInACall)
132+
override suspend fun shouldAllowSelection(id: RecipientId?, phone: PhoneNumber?): Boolean = true
133+
override fun onRecipientSelected(id: RecipientId?, phone: PhoneNumber?) = viewModel.openConversation(id, phone)
134+
override fun onPendingRecipientSelectionsConsumed() = Unit
135+
override fun onMessage(id: RecipientId) = viewModel.openConversation(id)
136+
override fun onVoiceCall(recipient: Recipient) = CommunicationActions.startVoiceCall(context, recipient, viewModel::showUserAlreadyInACall)
137+
override fun onVideoCall(recipient: Recipient) = CommunicationActions.startVideoCall(context, recipient, viewModel::showUserAlreadyInACall)
136138

137139
override fun onRemove(recipient: Recipient) = viewModel.showRemoveConfirmation(recipient)
138140
override fun onRemoveConfirmed(recipient: Recipient) {
@@ -146,8 +148,8 @@ private fun NewConversationScreen(
146148

147149
override fun onInviteToSignal() = context.startActivity(AppSettingsActivity.invite(context))
148150
override fun onRefresh() = viewModel.refresh()
149-
override fun onUserMessageDismissed(userMessage: UserMessage) = viewModel.onUserMessageDismissed()
150-
override fun onContactsListReset() = viewModel.onContactsListReset()
151+
override fun onUserMessageDismissed(userMessage: UserMessage) = viewModel.clearUserMessage()
152+
override fun onContactsListReset() = viewModel.clearShouldResetContactsList()
151153
override fun onBackPressed() = closeScreen()
152154
}
153155
}
@@ -256,7 +258,7 @@ private fun NewConversationScreenUi(
256258
snackbarHostState = snackbarHostState
257259
)
258260

259-
if (uiState.isRefreshingRecipient) {
261+
if (uiState.isLookingUpRecipient) {
260262
Dialogs.IndeterminateProgressDialog()
261263
}
262264
}
@@ -320,11 +322,13 @@ private interface UiCallbacks :
320322
fun onBackPressed()
321323

322324
object Empty : UiCallbacks {
325+
override fun onSearchQueryChanged(query: String) = Unit
323326
override fun onCreateNewGroup() = Unit
324327
override fun onFindByUsername() = Unit
325328
override fun onFindByPhoneNumber() = Unit
326-
override fun shouldAllowSelection(id: RecipientId): Boolean = true
329+
override suspend fun shouldAllowSelection(id: RecipientId?, phone: PhoneNumber?): Boolean = true
327330
override fun onRecipientSelected(id: RecipientId?, phone: PhoneNumber?) = Unit
331+
override fun onPendingRecipientSelectionsConsumed() = Unit
328332
override fun onMessage(id: RecipientId) = Unit
329333
override fun onVoiceCall(recipient: Recipient) = Unit
330334
override fun onVideoCall(recipient: Recipient) = Unit
@@ -347,6 +351,7 @@ private fun NewConversationRecipientPicker(
347351
modifier: Modifier = Modifier
348352
) {
349353
RecipientPicker(
354+
searchQuery = uiState.searchQuery,
350355
isRefreshing = uiState.isRefreshingContacts,
351356
shouldResetContactsList = uiState.shouldResetContactsList,
352357
callbacks = RecipientPickerCallbacks(

app/src/main/java/org/thoughtcrime/securesms/conversation/NewConversationViewModel.kt

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,41 +37,39 @@ class NewConversationViewModel : ViewModel() {
3737

3838
private val contactsManagementRepo = ContactsManagementRepository(AppDependencies.application)
3939

40-
fun onMessage(id: RecipientId): Unit = openConversation(recipientId = id)
40+
fun onSearchQueryChanged(query: String) {
41+
internalUiState.update { it.copy(searchQuery = query) }
42+
}
43+
44+
fun openConversation(recipientId: RecipientId) {
45+
internalUiState.update { it.copy(pendingDestination = recipientId) }
46+
}
4147

42-
fun onRecipientSelected(id: RecipientId?, phone: PhoneNumber?) {
48+
fun openConversation(id: RecipientId?, phone: PhoneNumber?) {
4349
when {
4450
id != null -> openConversation(recipientId = id)
4551

4652
SignalStore.account.isRegistered -> {
47-
Log.d(TAG, "[onRecipientSelected] Missing recipientId: attempting to look up.")
48-
resolveAndOpenConversation(phone)
53+
Log.d(TAG, "[openConversation] Missing recipientId: attempting to look up.")
54+
resolveAndOpenConversation(phone!!)
4955
}
5056

51-
else -> Log.w(TAG, "[onRecipientSelected] Cannot look up recipient: account not registered.")
57+
else -> Log.w(TAG, "[openConversation] Cannot look up recipient: account not registered.")
5258
}
5359
}
5460

55-
private fun openConversation(recipientId: RecipientId) {
56-
internalUiState.update { it.copy(pendingDestination = recipientId) }
57-
}
58-
59-
private fun resolveAndOpenConversation(phone: PhoneNumber?) {
61+
private fun resolveAndOpenConversation(phone: PhoneNumber) {
6062
viewModelScope.launch {
61-
internalUiState.update { it.copy(isRefreshingRecipient = true) }
63+
internalUiState.update { it.copy(isLookingUpRecipient = true) }
6264

6365
val lookupResult = withContext(Dispatchers.IO) {
64-
if (phone != null) {
65-
RecipientRepository.lookupNewE164(inputE164 = phone.value)
66-
} else {
67-
RecipientRepository.LookupResult.InvalidEntry
68-
}
66+
RecipientRepository.lookupNewE164(inputE164 = phone.value)
6967
}
7068

7169
when (lookupResult) {
7270
is RecipientRepository.LookupResult.Success -> {
7371
val recipient = Recipient.resolved(lookupResult.recipientId)
74-
internalUiState.update { it.copy(isRefreshingRecipient = false) }
72+
internalUiState.update { it.copy(isLookingUpRecipient = false) }
7573

7674
if (recipient.isRegistered && recipient.hasServiceId) {
7775
openConversation(recipient.id)
@@ -83,7 +81,7 @@ class NewConversationViewModel : ViewModel() {
8381
is RecipientRepository.LookupResult.NotFound, is RecipientRepository.LookupResult.InvalidEntry -> {
8482
internalUiState.update {
8583
it.copy(
86-
isRefreshingRecipient = false,
84+
isLookingUpRecipient = false,
8785
userMessage = Info.RecipientNotSignalUser(phone)
8886
)
8987
}
@@ -92,7 +90,7 @@ class NewConversationViewModel : ViewModel() {
9290
is RecipientRepository.LookupResult.NetworkError -> {
9391
internalUiState.update {
9492
it.copy(
95-
isRefreshingRecipient = false,
93+
isLookingUpRecipient = false,
9694
userMessage = Info.NetworkError
9795
)
9896
}
@@ -137,11 +135,11 @@ class NewConversationViewModel : ViewModel() {
137135
}
138136
}
139137

140-
fun onUserAlreadyInACall() {
138+
fun showUserAlreadyInACall() {
141139
internalUiState.update { it.copy(userMessage = Info.UserAlreadyInAnotherCall) }
142140
}
143141

144-
fun onContactsListReset() {
142+
fun clearShouldResetContactsList() {
145143
internalUiState.update { it.copy(shouldResetContactsList = false) }
146144
}
147145

@@ -157,14 +155,15 @@ class NewConversationViewModel : ViewModel() {
157155
}
158156
}
159157

160-
fun onUserMessageDismissed() {
158+
fun clearUserMessage() {
161159
internalUiState.update { it.copy(userMessage = null) }
162160
}
163161
}
164162

165163
data class NewConversationUiState(
166164
val forceSplitPaneOnCompactLandscape: Boolean = SignalStore.internal.forceSplitPaneOnCompactLandscape,
167-
val isRefreshingRecipient: Boolean = false,
165+
val searchQuery: String = "",
166+
val isLookingUpRecipient: Boolean = false,
168167
val isRefreshingContacts: Boolean = false,
169168
val shouldResetContactsList: Boolean = false,
170169
val pendingDestination: RecipientId? = null,
@@ -174,7 +173,7 @@ data class NewConversationUiState(
174173
sealed interface Info : UserMessage {
175174
data class RecipientRemoved(val recipient: Recipient) : Info
176175
data class RecipientBlocked(val recipient: Recipient) : Info
177-
data class RecipientNotSignalUser(val phone: PhoneNumber?) : Info
176+
data class RecipientNotSignalUser(val phone: PhoneNumber) : Info
178177
data object UserAlreadyInAnotherCall : Info
179178
data object NetworkError : Info
180179
}

0 commit comments

Comments
 (0)