Skip to content

Commit 82ae2ff

Browse files
jbsessionThomasSessiondependabot[bot]
authored
MediaSend update 1 : Moved fragment UI to compose (#4)
* Initial MediaPickerFolder and MediaPickerItem compose * Initial fragment changes, ComposeViews and minor VM updates * Fixed wrong flag set * SelectionOverflow error * Updated hardcoded dimensions, other compose changes * Moved most logic to viewmodel * Dimensions file and compose cleanups * initial update to checking permission * Updated paddings and color values * Removed old code, use innerShadow for Box * Selection index text set to white * Removed unused dimensions, updated padding for Grid * Cleanup * UI tweaks * SES-4433 : Handle landscape mode (session-foundation#1527) * removed portrait lock for most activities, retained for WebRtcCallActivity * Initial landscape, compact, and flip compatibility * Landing screen initial landscape compat with flip, tablet and phone * QR code activity landscape * Initial layout for Start Conversation sheet * Added Adaptive layout helper * Revert "Initial landscape, compact, and flip compatibility" This reverts commit 20a5fa9. * Use adaptive layout * made sholdUseTwoPane private * removed padding for back button * GiphyActivity initial compose * GiphyFragment compose * GiphyFragment initial kotlin * cleanup * GiphyFragment to kotlin * Cleanup * Converted async task to coroutine * Giphy fragment and sticket to kotlin * Separate compose fun * Start conversation cleanup * cleanup * Cleanup * notif landscape fix * Revert "notif landscape fix" This reverts commit 3cc3ec0. * initial scaling for QR in recovery password * Updated usage of twopane into landscape check only. * Share component for qrPanel * Fixed overlap for 3 button navigation * camera inset in conversation * apply safe inset camera inset * remove portrait mode for webrtccall * cleanup * Media preview insets * Use state for giph loading * Use state for giphyLoading * themed content for tabs * Removed two pane * GiphyActivity converted to kotlin, updated compose usage * Cleanup * A bit of optimization for session netowork's node image * inset for settings screen * token page and conversation settings * App bar search bar insets * WebRtc rotation fix, Landscape xml * contactAvatar webRtc adaptive * refactor adaptiveInfo name * State list drawable landscape * rtc call landscape update * Added insets and updated overlay stub * Serializable data for bottom sheet. Fixed crashes * Fixed landscape scroll for conversation bottomsheet * insets for cameraXfragment * Initial workaround for giphytabs * cleanup * Let activity handle the orientation change * Fixed how web rtc looks on landscape * allow recreation of layout for fragment. Add saveInstance check to prevent duplicate framgnet * Simplified logic * Added to LocalDimensions * cleanups * Filter thread record instead of db call * Cleanup * Removed auto scroll flag from setDeviceOrientation function * Search contact action bottomsheet landscape state expanded * convert calculation into anchor * Narrow width use anchor, helper function to get anchor * Safe insets for start conversation sheet * Dynamic insets if sheet does not fill the width * Update minimum size, fixed box constraints * cleanup * draw on image fix layout * spacing fixes for editing images * fixed constraints for color slider * initial configuration change handling * Revert "initial configuration change handling" This reverts commit 8c9891d. * Made some QR areas scrollable but fit area * conversationv2 landscape layout * Remove landscape hiding the rail * Refactored dimen name * added comments * Fixed rotation value * Removed landscape layout, added rotation to back arrow * Handle onConfigureChanged for WebrtcActivity * Cleanups * Updated inset margine helper to fix home FAB * Initial orientation handling for CameraXFragment * Added CameraXActivity to replace old fragment * Fixed insets for CameraXActivity * Added tiny helper for bottom margin insets * Fixed missing dimen * SDK 36 bump * Updated back handling for activity with fragment * Updated back handling * Video camera landscape adjustment * Updated avatar sizes for portrait and landscape * Navigator to survive config changes, collapsible footer inset * replaced vm with retain * Used retain for navigations, updated insets for debug and pro screens * Fixed leftoever condition * Updated landscape screen for manage group stuff * ManageMembersScreen cleanup and improvements * More cleanups * Updated some remembers to retain * Minor cleanup --------- Co-authored-by: ThomasSession <thomas.r@getsession.org> * Bump androidx.activity:activity-compose from 1.10.1 to 1.12.2 (session-foundation#1825) Bumps androidx.activity:activity-compose from 1.10.1 to 1.12.2. --- updated-dependencies: - dependency-name: androidx.activity:activity-compose dependency-version: 1.12.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix : Manage members QA pt.4 (session-foundation#1881) * Send control message before exception * Add sorting by accountId when showing new dialogs * cleanup * cleanup for readability * Cleanups * SES-1971 : Enable minification (session-foundation#1566) * Initial proguard and minify * Initial proguard rules, App doesnt crash on start * Conversation and emoji * Some JNI rules * cleanup * Kryo proguard * Cleanup * more rules * added to proguard * added rules to proguard * proguard file cleanup * gradle and proguard cleanup * Cleanup * Gradle cleanup * Huawei warnings * Compile only for huawei * HMS analytics * Fix build error * Updated rules * Added rules, cleanups * Removed misplaced flag * Some rules cleanup * gradle update --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: ThomasSession <thomas.r@getsession.org> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1 parent 4f1ab96 commit 82ae2ff

33 files changed

Lines changed: 1214 additions & 1007 deletions

app/build.gradle.kts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,12 @@ android {
151151

152152
buildTypes {
153153
getByName("release") {
154-
isMinifyEnabled = false
155-
154+
isMinifyEnabled = true
155+
isShrinkResources = true
156+
proguardFiles(
157+
getDefaultProguardFile("proguard-android-optimize.txt"),
158+
file("proguard-rules.pro")
159+
)
156160
devNetDefaultOn(false)
157161
enablePermissiveNetworkSecurityConfig(false)
158162
setAlternativeAppName(null)
@@ -188,7 +192,6 @@ android {
188192

189193
getByName("debug") {
190194
isDefault = true
191-
isMinifyEnabled = false
192195
enableUnitTestCoverage = false
193196
signingConfig = signingConfigs.getByName("debug")
194197

@@ -373,6 +376,11 @@ dependencies {
373376
if (huaweiEnabled) {
374377
val huaweiImplementation = configurations.maybeCreate("huaweiImplementation")
375378
huaweiImplementation(libs.huawei.push)
379+
380+
// These are compileOnly on the Huawei flavor so R8 can resolve optional HMS classes
381+
// referenced by HMS Push during minification.
382+
compileOnly(libs.huawei.hianalytics)
383+
compileOnly(libs.huawei.availableupdate)
376384
}
377385

378386
implementation(libs.androidx.media3.exoplayer)

app/proguard-rules.pro

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
########## BASELINE / ATTRIBUTES ##########
2+
# Core attrs (serialization/DI/reflective access often rely on these)
3+
-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod,MethodParameters,Record
4+
5+
# Honor @Keep if present
6+
-keep @androidx.annotation.Keep class * { *; }
7+
-keepclasseswithmembers class * { @androidx.annotation.Keep *; }
8+
9+
########## OPTIONAL GOOGLE BITS (SUPPRESSED WARNINGS) ##########
10+
-dontwarn com.google.android.gms.common.annotation.**
11+
-dontwarn com.google.firebase.analytics.connector.**
12+
13+
########## ANDROID / DI ##########
14+
# Workers constructed by class name
15+
-keep class ** extends androidx.work.ListenableWorker
16+
17+
########## KOTLINX SERIALIZATION ##########
18+
-keepclassmembers class ** {
19+
@kotlinx.serialization.Serializable *;
20+
*** Companion;
21+
kotlinx.serialization.KSerializer serializer(...);
22+
}
23+
24+
########## JACKSON (CORE + ANNOTATIONS + DTOs) ##########
25+
# Keep Jackson packages and common annotated members
26+
-keep class com.fasterxml.jackson.** { *; }
27+
-keepclassmembers class ** {
28+
@com.fasterxml.jackson.annotation.JsonCreator <init>(...);
29+
@com.fasterxml.jackson.annotation.JsonProperty *;
30+
}
31+
32+
-keep class ** extends com.fasterxml.jackson.core.type.TypeReference { *; }
33+
-keep class * implements com.fasterxml.jackson.databind.util.Converter { public <init>(); public *; }
34+
-keep class * extends com.fasterxml.jackson.databind.JsonDeserializer { public <init>(); public *; }
35+
36+
-dontwarn com.fasterxml.jackson.databind.**
37+
38+
# Jackson DTO used by OpenGroupApi (reactions map values)
39+
-keep class org.session.libsession.messaging.open_groups.OpenGroupApi$Reaction { *; }
40+
-keepnames class org.session.libsession.messaging.open_groups.OpenGroupApi$Reaction
41+
-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Reaction {
42+
<fields>;
43+
*** get*();
44+
void set*(***);
45+
46+
# keep the default constructor too:
47+
public <init>(***, int, kotlin.jvm.internal.DefaultConstructorMarker);
48+
# and a bare no-arg constructor if it exists
49+
public <init>();
50+
}
51+
52+
# DTO used by OpenGroupApi
53+
-keep class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities { *; }
54+
-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities { <init>(); }
55+
-keepnames class org.session.libsession.messaging.open_groups.OpenGroupApi$Capabilities
56+
57+
# Project models referenced via Jackson (from crashes)
58+
-keep class org.thoughtcrime.securesms.crypto.KeyStoreHelper$SealedData { *; }
59+
-keep class org.thoughtcrime.securesms.crypto.KeyStoreHelper$SealedData$* { *; }
60+
-keep class org.thoughtcrime.securesms.crypto.AttachmentSecret { *; }
61+
-keep class org.thoughtcrime.securesms.crypto.AttachmentSecret$* { *; }
62+
63+
# Keep names + bean-style accessors for OpenGroupApi models
64+
-keepnames class org.session.libsession.messaging.open_groups.**
65+
-keepclassmembers class org.session.libsession.messaging.open_groups.** {
66+
<fields>;
67+
*** get*();
68+
void set*(***);
69+
}
70+
71+
# Keep names + bean-style accessors for snode models
72+
-keepnames class org.session.libsession.snode.**
73+
-keepclassmembers class org.session.libsession.snode.** {
74+
<fields>;
75+
*** get*();
76+
void set*(***);
77+
}
78+
79+
# Converters / Deserializers
80+
-keep class org.session.libsession.snode.model.RetrieveMessageConverter { public <init>(); public *; }
81+
82+
########## JNI LOGGER / NATIVE ENTRYPOINTS ##########
83+
# Logging interface & implementations (JNI looks up log(String,String,int))
84+
-keep interface network.loki.messenger.libsession_util.util.Logger { *; }
85+
-keepnames class * implements network.loki.messenger.libsession_util.util.Logger
86+
-keepclassmembers class * implements network.loki.messenger.libsession_util.util.Logger {
87+
public void log(java.lang.String, java.lang.String, int);
88+
}
89+
90+
# JNI: ConfigPush constructors (exact signatures preserved)
91+
-keepnames class network.loki.messenger.libsession_util.util.ConfigPush
92+
-keepclassmembers class network.loki.messenger.libsession_util.util.ConfigPush {
93+
public <init>(java.util.List, long, java.util.List);
94+
public <init>(java.util.List, long, java.util.List, int, kotlin.jvm.internal.DefaultConstructorMarker);
95+
}
96+
97+
# JNI: specific getter used from native
98+
-keepnames class network.loki.messenger.libsession_util.util.UserPic
99+
-keepclassmembers class network.loki.messenger.libsession_util.util.UserPic {
100+
public byte[] getKeyAsByteArray();
101+
}
102+
103+
-keep class network.loki.messenger.libsession_util.util.GroupInfo$ClosedGroupInfo { *; }
104+
-keepnames class network.loki.messenger.libsession_util.util.GroupInfo$ClosedGroupInfo
105+
-keepclassmembers class network.loki.messenger.libsession_util.util.GroupInfo$ClosedGroupInfo {
106+
public byte[] getAdminKeyAsByteArray();
107+
public byte[] getAuthDataAsByteArray();
108+
}
109+
110+
########## WEBRTC / CHROMIUM JNI ##########
111+
# WebRTC public Java APIs (kept for JNI_OnLoad registration)
112+
-keep class org.webrtc.** { *; }
113+
114+
# Chromium-based bits
115+
-keep class org.chromium.base.** { *; }
116+
-keep class org.chromium.net.** { *; }
117+
118+
# Keep all native bridges everywhere
119+
-keepclasseswithmembers,includedescriptorclasses class * {
120+
native <methods>;
121+
}
122+
123+
########## WEBRTC / CHROMIUM jni_zero ##########
124+
# Ensure jni_zero Java side is discoverable by native
125+
-keep class org.jni_zero.** { *; }
126+
-keepnames class org.jni_zero.**
127+
128+
########## CONVERSATION / MODELS (JNI + REFLECTION) ##########
129+
# Conversation.* types constructed via JNI with (String,long,boolean)
130+
-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$* {
131+
public <init>(java.lang.String, long, boolean);
132+
}
133+
134+
# Keep names and members of Conversation/Community models (JNI searches by name)
135+
-keep class network.loki.messenger.libsession_util.util.Conversation$Community { *; }
136+
-keep class network.loki.messenger.libsession_util.util.Conversation$OneToOne { *; }
137+
-keep class network.loki.messenger.libsession_util.util.Conversation$ClosedGroup { *; }
138+
-keep class network.loki.messenger.libsession_util.util.BaseCommunityInfo { *; }
139+
140+
-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$Community { public <init>(...); }
141+
-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$OneToOne { public <init>(...); }
142+
-keepclassmembers class network.loki.messenger.libsession_util.util.Conversation$ClosedGroup { public <init>(...); }
143+
144+
-keepnames class network.loki.messenger.libsession_util.util.Conversation$Community
145+
-keepnames class network.loki.messenger.libsession_util.util.Conversation$OneToOne
146+
-keepnames class network.loki.messenger.libsession_util.util.Conversation$ClosedGroup
147+
-keepnames class network.loki.messenger.libsession_util.util.BaseCommunityInfo
148+
149+
# Group members (JNI constructor with long)
150+
-keep class network.loki.messenger.libsession_util.GroupMembersConfig { *; }
151+
-keep class network.loki.messenger.libsession_util.util.GroupMember { *; }
152+
-keepclassmembers class network.loki.messenger.libsession_util.util.GroupMember { public <init>(long); }
153+
-keepnames class network.loki.messenger.libsession_util.util.GroupMember
154+
155+
# Broad safety net for long-arg ctors in util package
156+
-keepclassmembers class network.loki.messenger.libsession_util.util.** { public <init>(long); }
157+
158+
########## EMOJI SEARCH (JACKSON / POLYMORPHIC) ##########
159+
# Keep names if @JsonTypeInfo uses CLASS/MINIMAL_CLASS
160+
-keepnames class org.thoughtcrime.securesms.database.model.**
161+
# Preserve abstract base + nested types for property/creator names
162+
-keep class org.thoughtcrime.securesms.database.model.EmojiSearchData { *; }
163+
-keep class org.thoughtcrime.securesms.database.model.EmojiSearchData$* { *; }
164+
165+
########## KRYO (SERIALIZATION OF DESTINATIONS) ##########
166+
# No-arg contructors required at runtime for these sealed subclasses
167+
-keepclassmembers class org.session.libsession.messaging.messages.Destination$ClosedGroup { <init>(); }
168+
-keepclassmembers class org.session.libsession.messaging.messages.Destination$Contact { <init>(); }
169+
-keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyClosedGroup { <init>(); }
170+
-keepclassmembers class org.session.libsession.messaging.messages.Destination$LegacyOpenGroup { <init>(); }
171+
-keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroup { <init>(); }
172+
-keepclassmembers class org.session.libsession.messaging.messages.Destination$OpenGroupInbox { <init>(); }
173+
174+
# Keep the Enum serializer contructor Kryo reflects on
175+
-keepclassmembers class com.esotericsoftware.kryo.serializers.** {
176+
public <init>(...);
177+
}
178+
179+
# Prevent enum unboxing/renaming for the enum field being serialized
180+
-keep class org.session.libsession.messaging.messages.control.TypingIndicator$Kind { *; }
181+
182+
# Preserve class names for Kryo
183+
-keepnames class org.session.libsession.messaging.messages.Destination$**
184+
185+
########## OPEN GROUP API (MESSAGES) ##########
186+
-keep class org.session.libsession.messaging.open_groups.OpenGroupApi$Message { *; }
187+
-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Message { <init>(); }
188+
-keepnames class org.session.libsession.messaging.open_groups.OpenGroupApi$Message
189+
-keepclassmembers class org.session.libsession.messaging.open_groups.OpenGroupApi$Message {
190+
*** get*();
191+
void set*(***);
192+
}
193+
194+
-keep class org.session.libsession.messaging.utilities.UpdateMessageData { *; }
195+
-keep class org.session.libsession.messaging.utilities.UpdateMessageData$* { *; }
196+
-keepnames class org.session.libsession.messaging.utilities.UpdateMessageData$*
197+
198+
########## HUAWEI / HMS (minified builds) ##########
199+
# Device-only classes referenced by HMS internals — not present on Maven.
200+
-dontwarn android.telephony.HwTelephonyManager
201+
-dontwarn com.huawei.android.os.BuildEx$VERSION
202+
-dontwarn com.huawei.libcore.io.**
203+
-dontwarn com.huawei.hianalytics.**
204+
-dontwarn com.huawei.hms.availableupdate.**
205+
206+
# Misc suppressed warnings
207+
-dontwarn java.beans.BeanInfo
208+
-dontwarn java.beans.IntrospectionException
209+
-dontwarn java.beans.Introspector
210+
-dontwarn java.beans.PropertyDescriptor
211+
-dontwarn java.lang.management.ManagementFactory
212+
-dontwarn java.lang.management.RuntimeMXBean
213+
-dontwarn sun.nio.ch.DirectBuffer

app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/AttachmentManager.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import android.content.ActivityNotFoundException;
2525
import android.content.Context;
2626
import android.content.Intent;
27-
import android.content.pm.PackageManager;
2827
import android.database.Cursor;
2928
import android.net.Uri;
3029
import android.os.AsyncTask;
@@ -35,8 +34,6 @@
3534
import android.widget.Toast;
3635
import androidx.annotation.NonNull;
3736
import androidx.annotation.Nullable;
38-
import androidx.core.app.ActivityCompat;
39-
import androidx.core.content.ContextCompat;
4037

4138
import com.bumptech.glide.RequestManager;
4239
import com.squareup.phrase.Phrase;
@@ -349,13 +346,13 @@ public static void selectGallery(Activity activity, int requestCode, @NonNull Ad
349346
.execute();
350347
}
351348

352-
public static boolean hasFullAccess(Activity activity) {
349+
public static boolean hasFullAccess(Context c) {
353350
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
354-
return Permissions.hasAll(activity,
351+
return Permissions.hasAll(c,
355352
Manifest.permission.READ_MEDIA_IMAGES,
356353
Manifest.permission.READ_MEDIA_VIDEO);
357354
} else {
358-
return Permissions.hasAll(activity, android.Manifest.permission.READ_EXTERNAL_STORAGE);
355+
return Permissions.hasAll(c, android.Manifest.permission.READ_EXTERNAL_STORAGE);
359356
}
360357
}
361358

@@ -386,9 +383,9 @@ public static void managePhotoAccess(@NonNull Activity activity, @Nullable Runna
386383
}
387384
}
388385

389-
public static boolean shouldShowManagePhoto(@NonNull Activity activity){
386+
public static boolean shouldShowManagePhoto(@NonNull Context c){
390387
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE){
391-
return !hasFullAccess(activity) && hasPartialAccess(activity);
388+
return !hasFullAccess(c) && hasPartialAccess(c);
392389
}else{
393390
// No partial access for <= API 33
394391
return false;

app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2Impl.kt

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -622,39 +622,35 @@ class GroupManagerV2Impl @Inject constructor(
622622
.mapNotNull { (member, result) ->
623623
configs.groupMembers.get(member.hexString)?.apply {
624624
if (result.isFailure) {
625-
configs.groupMembers.get(member.hexString)?.let { member ->
626-
member.setPromotionFailed()
627-
configs.groupMembers.set(member)
628-
}
625+
setPromotionFailed()
629626
}
630627
}
631628
}
632629
.forEach(configs.groupMembers::set)
633630
}
634631

632+
if (!isRepromote) {
633+
messageSender.sendAndAwait(message, Address.fromSerialized(group.hexString))
634+
}
635+
635636
val failedMembers = promotedByMemberIDs
636637
.filterValues { it.isFailure }
637638
.keys
638-
.toList()
639+
.map { it.hexString }
639640

640641
if (failedMembers.isNotEmpty()) {
641642
val cause = promotedByMemberIDs.values
642-
.firstOrNull { it.isFailure }
643-
?.exceptionOrNull()
643+
.firstOrNull { it.isFailure }?.exceptionOrNull()
644644
?: RuntimeException("Failed to promote ${failedMembers.size} member(s)")
645645

646646
throw GroupInviteException(
647647
isPromotion = true,
648-
inviteeAccountIds = failedMembers.map { it.hexString },
648+
inviteeAccountIds = failedMembers,
649649
groupName = groupName ?: "",
650650
isReinvite = isRepromote,
651651
underlying = cause
652652
)
653653
}
654-
655-
if (!isRepromote) {
656-
messageSender.sendAndAwait(message, Address.fromSerialized(group.hexString))
657-
}
658654
}
659655
}
660656

app/src/main/java/org/thoughtcrime/securesms/groups/InviteMembersViewModel.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ class InviteMembersViewModel @AssistedInject constructor(
9090
selected: Set<SelectedContact>,
9191
): InviteContactsDialogState {
9292
val count = selected.size
93-
val firstMember = selected.firstOrNull()
93+
val sortedMembers = selected.sortedBy { it.address }
94+
val firstMember = sortedMembers.firstOrNull()
9495

9596
val body: CharSequence = when (count) {
9697
1 -> {
@@ -103,7 +104,7 @@ class InviteMembersViewModel @AssistedInject constructor(
103104
}
104105
}
105106
2 -> {
106-
val secondMember = selected.elementAtOrNull(1)?.name
107+
val secondMember = sortedMembers.elementAtOrNull(1)?.name
107108
Phrase.from(context, R.string.membersInviteShareDescriptionTwo)
108109
.put(NAME_KEY, firstMember?.name)
109110
.put(OTHER_NAME_KEY, secondMember)

app/src/main/java/org/thoughtcrime/securesms/groups/ManageGroupMembersViewModel.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,8 @@ class ManageGroupMembersViewModel @AssistedInject constructor(
303303
group: String
304304
): RemoveMembersDialogState {
305305
val count = selected.size
306-
val firstMember = selected.firstOrNull()
306+
val sortedMembers = selected.sortedBy { it.accountId }
307+
val firstMember = sortedMembers.firstOrNull()
307308

308309
val body: CharSequence = when (count) {
309310
1 -> Phrase.from(context, R.string.groupRemoveDescription)
@@ -312,7 +313,7 @@ class ManageGroupMembersViewModel @AssistedInject constructor(
312313
.format()
313314

314315
2 -> {
315-
val secondMember = selected.elementAtOrNull(1)?.name
316+
val secondMember = sortedMembers.elementAtOrNull(1)?.name
316317
Phrase.from(context, R.string.groupRemoveDescriptionTwo)
317318
.put(NAME_KEY, firstMember?.name)
318319
.put(OTHER_NAME_KEY, secondMember)

0 commit comments

Comments
 (0)