From c9e6ad09daf44b368228cae3de9fb977deb54cda Mon Sep 17 00:00:00 2001 From: Mildrette Date: Wed, 3 Jun 2026 15:09:36 +0100 Subject: [PATCH 1/9] changed the + button into a small menu with 3 choices: pick image, share contact, and share file. when you press +, the menu opens. when you choose something, the menu closes first so the screen does not overlap --- .gradle/8.13/checksums/checksums.lock | Bin 17 -> 17 bytes .gradle/8.13/checksums/sha1-checksums.bin | Bin 158615 -> 158777 bytes .../executionHistory/executionHistory.lock | Bin 17 -> 17 bytes .gradle/8.13/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../buildOutputCleanup.lock | Bin 17 -> 17 bytes .../ui/components/ConversationsComponents.kt | 140 +++++++++++++++--- 6 files changed, 119 insertions(+), 21 deletions(-) diff --git a/.gradle/8.13/checksums/checksums.lock b/.gradle/8.13/checksums/checksums.lock index ec79cb9d4cd0e4b5c6221e4d24cdd1cb7f3741cd..246094c6d5e8053c3364969a598909debc7e958c 100644 GIT binary patch literal 17 VcmZQx_|JWVaK6wT1~A~%001;w1Umo# literal 17 VcmZQx_|JWVaK6wT1~A}M1^_fx1U3Kw diff --git a/.gradle/8.13/checksums/sha1-checksums.bin b/.gradle/8.13/checksums/sha1-checksums.bin index 99e989e991ee4a2d010d6b4a5d3a511ce60b18f0..9782346bf20a238c2a41b1c5e74f7914786dcbe8 100644 GIT binary patch delta 190 zcmbP!opa|6&J89KjPo{|N(A!qTV4C6HI2uK0R)(`r*E!Rt(IhbxLMG?c`4(b%~PLz zWaj6VZs=dR(FLmH?B?1Rt5q2{Zg=EkJd(?}WIJ08BcmMughZAKMTtO&q8#S!|7J2q zb21igR9wI@{pB-8zU>NY7|Zuhe{IdgH{IKgNt}0H@7dFJVC9URho_&lWzu8?3r+uR Z%Oo}ZvICR2Adr9V1y~7-Zwin$0sw9sKs^8e delta 89 zcmV-f0H*)B*a?@{39vL60iClo7*P$go+WY_0m+x)%>h-jPCrJa0lTx6nytO0kwkuxMK diff --git a/.gradle/8.13/executionHistory/executionHistory.lock b/.gradle/8.13/executionHistory/executionHistory.lock index 63e8cda83712100a6d9ba363fa838cc236edcebf..9d96c515cfbefd055543a428e90f8479176a5b90 100644 GIT binary patch literal 17 VcmZQx{wrl+`X+l81~A}m1pqd#1eO2* literal 17 VcmZQx{wrl+`X+l81~A|@1^_l(1VjJ; diff --git a/.gradle/8.13/fileHashes/fileHashes.lock b/.gradle/8.13/fileHashes/fileHashes.lock index 86241505435b93bb1b87fcb52a7b8541c7450afc..66128755ca28cc6b77a0a42bb9a26b00a7d7fc15 100644 GIT binary patch literal 17 VcmZSfktz3|{>FbZ0~jFbZ0~l271OP2>1n2+& diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index bbe6ed4667a26efef49df9a32b30ba7a1239e4b4..724b68f6fe7d3557909a8e4c67efe238d81eb3e3 100644 GIT binary patch literal 17 VcmZR!e!D6BMc%y&3}E2d002Oy1_A&8 literal 17 VcmZR!e!D6BMc%y&3}E1~2LM3e20Z`( diff --git a/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt b/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt index 2f062d1..949ac19 100644 --- a/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt +++ b/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt @@ -19,14 +19,10 @@ import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.aspectRatio -import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentSize @@ -48,7 +44,10 @@ import androidx.compose.material.icons.filled.FilePresent import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.filled.PlayCircle import androidx.compose.material.icons.filled.Share +import androidx.compose.material.icons.outlined.AccountCircle import androidx.compose.material.icons.outlined.AddCircleOutline +import androidx.compose.material.icons.outlined.Description +import androidx.compose.material.icons.outlined.Image import androidx.compose.material.icons.outlined.SimCard import androidx.compose.material3.BottomAppBar import androidx.compose.material3.Card @@ -90,7 +89,6 @@ import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontStyle -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextDecoration @@ -109,7 +107,6 @@ import com.afkanerd.smswithoutborders_libsmsmms.data.entities.Conversations import com.afkanerd.smswithoutborders_libsmsmms.extensions.context.copyItemToClipboard import com.afkanerd.smswithoutborders_libsmsmms.extensions.context.getSimCardInformation import com.afkanerd.smswithoutborders_libsmsmms.extensions.context.getSubscriptionBitmap -import com.afkanerd.smswithoutborders_libsmsmms.extensions.context.getSubscriptionName import com.afkanerd.smswithoutborders_libsmsmms.extensions.context.getUriForDrawable import com.afkanerd.smswithoutborders_libsmsmms.extensions.context.isDualSim import com.afkanerd.smswithoutborders_libsmsmms.extensions.context.shareItem @@ -257,16 +254,86 @@ fun ChatCompose( imageUri = uri } + val coroutineScope = rememberCoroutineScope() + val contactPickerLauncher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.PickContact() + ) { contactUri: Uri? -> + contactUri?.let { uri -> + coroutineScope.launch(Dispatchers.IO) { + var displayName = "" + var phoneNumber = "" + + context.contentResolver.query(uri, null, null, null, null)?.use { cursor -> + if (cursor.moveToFirst()) { + val nameIndex = cursor.getColumnIndex(android.provider.ContactsContract.Contacts.DISPLAY_NAME) + val idIndex = cursor.getColumnIndex(android.provider.ContactsContract.Contacts._ID) + + if (nameIndex >= 0) displayName = cursor.getString(nameIndex) + + val hasPhoneIndex = cursor.getColumnIndex(android.provider.ContactsContract.Contacts.HAS_PHONE_NUMBER) + val hasPhone = if (hasPhoneIndex >= 0) cursor.getString(hasPhoneIndex) else "0" + + if (hasPhone == "1" && idIndex >= 0) { + val contactId = cursor.getString(idIndex) + context.contentResolver.query( + android.provider.ContactsContract.CommonDataKinds.Phone.CONTENT_URI, + null, + "${android.provider.ContactsContract.CommonDataKinds.Phone.CONTACT_ID} = ?", + arrayOf(contactId), + null + )?.use { phoneCursor -> + if (phoneCursor.moveToFirst()) { + val numberIndex = phoneCursor.getColumnIndex(android.provider.ContactsContract.CommonDataKinds.Phone.NUMBER) + if (numberIndex >= 0) { + phoneNumber = phoneCursor.getString(numberIndex) + } + } + } + } + } + } + + if (displayName.isNotEmpty() || phoneNumber.isNotEmpty()) { + val contactTextString = buildString { + if (displayName.isNotEmpty()) append("Name: $displayName") + if (phoneNumber.isNotEmpty()) { + if (displayName.isNotEmpty()) append("\n") + append("Phone: $phoneNumber") + } + } + + launch(Dispatchers.Main) { + val currentText = value + val updatedText = if (currentText.isEmpty()) contactTextString else "$currentText\n$contactTextString" + valueChanged?.invoke(updatedText) + } + } + } + } + } + + val filePickerLauncher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.GetContent() + ) { fileUri: Uri? -> + fileUri?.let { uri -> + val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION + context.contentResolver.takePersistableUriPermission(uri, flag) + mmsValueChanged?.invoke(uri) + imageUri = uri + } + } + var messagingType by remember { mutableStateOf("SMS") } + var isMenuExpanded by remember { mutableStateOf(false) } LaunchedEffect(imageUri) { messagingType = if(imageUri != null) "MMS" else "SMS" } var length: String by remember{ - mutableStateOf( - if(inPreviewMode) "10/140" else - getSMSCount(context, value, subscriptionId) + mutableStateOf( + if(inPreviewMode) "10/140" else + getSMSCount(context, value, subscriptionId) ) } LaunchedEffect(value) { @@ -319,19 +386,52 @@ fun ChatCompose( .fillMaxWidth(), verticalAlignment = Alignment.Bottom, ) { + Column( - Modifier.padding(bottom=20.dp), + Modifier.padding(bottom = 20.dp), verticalArrangement = Arrangement.Bottom, ) { - IconButton(onClick = { - imagePicker.launch(arrayOf("image/png", "image/jpg", "image/jpeg")) - }) { - Icon( - Icons.Outlined.AddCircleOutline, - stringResource(R.string.send_mms_photo), - tint = MaterialTheme.colorScheme.onBackground, - modifier = Modifier.size(30.dp) - ) + Box { + IconButton(onClick = { isMenuExpanded = !isMenuExpanded }) { + Icon( + Icons.Outlined.AddCircleOutline, + contentDescription = "Attachment Options", + tint = MaterialTheme.colorScheme.onBackground, + modifier = Modifier.size(30.dp) + ) + } + + DropdownMenu( + expanded = isMenuExpanded, + onDismissRequest = { isMenuExpanded = false } + ) { + DropdownMenuItem( + text = { Text(stringResource(R.string.send_mms_photo)) }, + leadingIcon = { Icon(Icons.Outlined.Image, contentDescription = null) }, + onClick = { + isMenuExpanded = false + imagePicker.launch(arrayOf("image/png", "image/jpg", "image/jpeg")) + } + ) + + DropdownMenuItem( + text = { Text("Attach Contact") }, + leadingIcon = { Icon(Icons.Outlined.AccountCircle, contentDescription = null) }, + onClick = { + isMenuExpanded = false + contactPickerLauncher.launch(null) + } + ) + + DropdownMenuItem( + text = { Text("Attach File") }, + leadingIcon = { Icon(Icons.Outlined.Description, contentDescription = null) }, + onClick = { + isMenuExpanded = false + filePickerLauncher.launch("*/*") + } + ) + } } } @@ -449,10 +549,8 @@ fun ChatCompose( } } } - } } - } fun getSMSCount( From 004cc5ad011ecf17142e05541258777de7446f5e Mon Sep 17 00:00:00 2001 From: Mildrette Date: Thu, 4 Jun 2026 10:29:38 +0100 Subject: [PATCH 2/9] Removed coroutineScope and the files picker and contactpicker from chatcompose to seperate composables --- .gradle/8.13/checksums/checksums.lock | Bin 17 -> 17 bytes .gradle/8.13/checksums/sha1-checksums.bin | Bin 158777 -> 159101 bytes .../executionHistory/executionHistory.lock | Bin 17 -> 17 bytes .gradle/8.13/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../buildOutputCleanup.lock | Bin 17 -> 17 bytes .../ConversationsComponentsTest.kt | 205 ++++++++++++++++ .../ui/ContactDetailsMain.kt | 1 - .../ui/components/ConversationsComponents.kt | 232 ++++++++++++------ 8 files changed, 367 insertions(+), 71 deletions(-) create mode 100644 lib_smsmms_android/src/androidTest/java/com/afkanerd/smswithoutborders_libsmsmms/ConversationsComponentsTest.kt diff --git a/.gradle/8.13/checksums/checksums.lock b/.gradle/8.13/checksums/checksums.lock index 246094c6d5e8053c3364969a598909debc7e958c..0d1800dc5ecb5bcc0b9c336759ec14ebcd21e51e 100644 GIT binary patch literal 17 VcmZQx_|JWVaK6wT1~A|>001;&1VaD- literal 17 VcmZQx_|JWVaK6wT1~A~%001;w1Umo# diff --git a/.gradle/8.13/checksums/sha1-checksums.bin b/.gradle/8.13/checksums/sha1-checksums.bin index 9782346bf20a238c2a41b1c5e74f7914786dcbe8..163e60da42257412dc7543d24f5afd0fcb93dca5 100644 GIT binary patch delta 319 zcmdmagY)k#&J89Kj0-lKN?hdT-+RVXQg20fyI-YJ7gz=0X)M-Td^~PiFpz_V=6Oc1?r|T5i7j zDp7?0`OA={#d>xS!Cd#vy8ngwS${Gxns!bDZ6 z)9vk<40(afd+HFK3boT;+B0c_gdSf43o&T*O>RsPo^Is8BnHy-eE)P`2PUcM4;>+f bdBJ+n?fMx_C~vz6pn z0<#6@@dL9C>sS=Ce*X#&1+f4DX#tlenE@e}cbNegm%o_-7q^uT0dQ>rq_+lq0T~Rp ZH;4gJ8v${#A)pAC>E;0rw;-$m8Nf^NEyMr- diff --git a/.gradle/8.13/executionHistory/executionHistory.lock b/.gradle/8.13/executionHistory/executionHistory.lock index 9d96c515cfbefd055543a428e90f8479176a5b90..4ac8ab308b83b158a82b4b99ab743a2ac6a7654d 100644 GIT binary patch literal 17 VcmZQx{wrl+`X+l81~A}$1^_n?1or>{ literal 17 VcmZQx{wrl+`X+l81~A}m1pqd#1eO2* diff --git a/.gradle/8.13/fileHashes/fileHashes.lock b/.gradle/8.13/fileHashes/fileHashes.lock index 66128755ca28cc6b77a0a42bb9a26b00a7d7fc15..5dd3ce78c20bfc5ae60fe5600dffe1dabe69d27f 100644 GIT binary patch literal 17 VcmZSfktz3|{>FbZ0~oYC0st+r1swnY literal 17 VcmZSfktz3|{>FbZ0~j Unit, - valueChanged: ((String) -> Unit)? = null, - mmsValueChanged: ((Uri) -> Unit)? = null, - mmsCancelledCallback: (() -> Unit)? = null, - simCardChooserCallback: (() -> Unit)? = null, - imageUri: Uri? = null, - smsSendCallback: () -> Unit, -) { +fun FilePickerLauncher( + mmsValueChanged: ((Uri) -> Unit)?, + onFileSelected: (Uri) -> Unit +): ManagedActivityResultLauncher { val context = LocalContext.current - val inPreviewMode = LocalInspectionMode.current - val interactionsSource = remember { MutableInteractionSource() } - - var subscriptionInformation: SubscriptionInfo? by remember { mutableStateOf(null) } - LaunchedEffect(subscriptionId) { - subscriptionInformation = context.getSimCardInformation(subscriptionId.toInt()) - } - var imageUri: Uri? by remember { mutableStateOf(imageUri) } - val imagePicker = mmsImagePicker { uri -> - val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION - context.contentResolver.takePersistableUriPermission(uri, flag) - mmsValueChanged?.invoke(uri) - imageUri = uri + return rememberLauncherForActivityResult( + contract = ActivityResultContracts.GetContent() + ) { fileUri: Uri? -> + fileUri?.let { uri -> + val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION + context.contentResolver.takePersistableUriPermission(uri, flag) + mmsValueChanged?.invoke(uri) + onFileSelected(uri) + } } +} +@Composable +fun ContactPickerLauncher( + value: String, + valueChanged: ((String) -> Unit)? +): ManagedActivityResultLauncher { + val context = LocalContext.current val coroutineScope = rememberCoroutineScope() - val contactPickerLauncher = rememberLauncherForActivityResult( + + return rememberLauncherForActivityResult( contract = ActivityResultContracts.PickContact() ) { contactUri: Uri? -> contactUri?.let { uri -> @@ -265,13 +261,17 @@ fun ChatCompose( context.contentResolver.query(uri, null, null, null, null)?.use { cursor -> if (cursor.moveToFirst()) { - val nameIndex = cursor.getColumnIndex(android.provider.ContactsContract.Contacts.DISPLAY_NAME) - val idIndex = cursor.getColumnIndex(android.provider.ContactsContract.Contacts._ID) + val nameIndex = cursor.getColumnIndex( + android.provider.ContactsContract.Contacts.DISPLAY_NAME) + val idIndex = cursor.getColumnIndex( + android.provider.ContactsContract.Contacts._ID) if (nameIndex >= 0) displayName = cursor.getString(nameIndex) - val hasPhoneIndex = cursor.getColumnIndex(android.provider.ContactsContract.Contacts.HAS_PHONE_NUMBER) - val hasPhone = if (hasPhoneIndex >= 0) cursor.getString(hasPhoneIndex) else "0" + val hasPhoneIndex = cursor.getColumnIndex( + android.provider.ContactsContract.Contacts.HAS_PHONE_NUMBER) + val hasPhone = if (hasPhoneIndex >= 0) + cursor.getString(hasPhoneIndex) else "0" if (hasPhone == "1" && idIndex >= 0) { val contactId = cursor.getString(idIndex) @@ -283,7 +283,8 @@ fun ChatCompose( null )?.use { phoneCursor -> if (phoneCursor.moveToFirst()) { - val numberIndex = phoneCursor.getColumnIndex(android.provider.ContactsContract.CommonDataKinds.Phone.NUMBER) + val numberIndex = phoneCursor.getColumnIndex( + android.provider.ContactsContract.CommonDataKinds.Phone.NUMBER) if (numberIndex >= 0) { phoneNumber = phoneCursor.getString(numberIndex) } @@ -301,28 +302,57 @@ fun ChatCompose( append("Phone: $phoneNumber") } } - launch(Dispatchers.Main) { - val currentText = value - val updatedText = if (currentText.isEmpty()) contactTextString else "$currentText\n$contactTextString" + val updatedText = if (value.isEmpty()) contactTextString + else "$value\n$contactTextString" valueChanged?.invoke(updatedText) } } } } } +} - val filePickerLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.GetContent() - ) { fileUri: Uri? -> - fileUri?.let { uri -> - val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION - context.contentResolver.takePersistableUriPermission(uri, flag) - mmsValueChanged?.invoke(uri) - imageUri = uri - } +@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class) +@Composable +fun ChatCompose( + value: String, + subscriptionId: Long, + sendMmsCallback: (Uri) -> Unit, + valueChanged: ((String) -> Unit)? = null, + mmsValueChanged: ((Uri) -> Unit)? = null, + mmsCancelledCallback: (() -> Unit)? = null, + simCardChooserCallback: (() -> Unit)? = null, + imageUri: Uri? = null, + smsSendCallback: () -> Unit, +) { + val context = LocalContext.current + val inPreviewMode = LocalInspectionMode.current + val interactionsSource = remember { MutableInteractionSource() } + + var subscriptionInformation: SubscriptionInfo? by remember { mutableStateOf(null) } + LaunchedEffect(subscriptionId) { + subscriptionInformation = context.getSimCardInformation(subscriptionId.toInt()) } + var imageUri: Uri? by remember { mutableStateOf(imageUri) } + val imagePicker = mmsImagePicker { uri -> + val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION + context.contentResolver.takePersistableUriPermission(uri, flag) + mmsValueChanged?.invoke(uri) + imageUri = uri + } + + val contactPickerLauncher = ContactPickerLauncher( + value = value, + valueChanged = valueChanged + ) + + val filePickerLauncher = FilePickerLauncher( + mmsValueChanged = mmsValueChanged, + onFileSelected = { uri -> imageUri = uri } + ) + var messagingType by remember { mutableStateOf("SMS") } var isMenuExpanded by remember { mutableStateOf(false) } @@ -401,36 +431,98 @@ fun ChatCompose( ) } - DropdownMenu( - expanded = isMenuExpanded, - onDismissRequest = { isMenuExpanded = false } - ) { - DropdownMenuItem( - text = { Text(stringResource(R.string.send_mms_photo)) }, - leadingIcon = { Icon(Icons.Outlined.Image, contentDescription = null) }, - onClick = { - isMenuExpanded = false - imagePicker.launch(arrayOf("image/png", "image/jpg", "image/jpeg")) - } - ) + if (isMenuExpanded) { + ModalBottomSheet( + onDismissRequest = { isMenuExpanded = false } + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally + ) { + IconButton( + onClick = { + isMenuExpanded = false + imagePicker.launch(arrayOf( + "image/png", "image/jpg", "image/jpeg" + )) + }, + modifier = Modifier + .size(64.dp) + .clip(CircleShape) + .background(MaterialTheme.colorScheme.surfaceVariant) + ) { + Icon( + Icons.Outlined.Image, + contentDescription = "Photo", + modifier = Modifier.size(28.dp) + ) + } + Spacer(modifier = Modifier.padding(4.dp)) + Text( + "Photo", + style = MaterialTheme.typography.labelMedium + ) + } - DropdownMenuItem( - text = { Text("Attach Contact") }, - leadingIcon = { Icon(Icons.Outlined.AccountCircle, contentDescription = null) }, - onClick = { - isMenuExpanded = false - contactPickerLauncher.launch(null) - } - ) + Column( + horizontalAlignment = Alignment.CenterHorizontally + ) { + IconButton( + onClick = { + isMenuExpanded = false + contactPickerLauncher.launch(null) + }, + modifier = Modifier + .size(64.dp) + .clip(CircleShape) + .background(MaterialTheme.colorScheme.surfaceVariant) + ) { + Icon( + Icons.Outlined.AccountCircle, + contentDescription = "Attach Contact", + modifier = Modifier.size(28.dp) + ) + } + Spacer(modifier = Modifier.padding(4.dp)) + Text( + "Contact", + style = MaterialTheme.typography.labelMedium + ) + } - DropdownMenuItem( - text = { Text("Attach File") }, - leadingIcon = { Icon(Icons.Outlined.Description, contentDescription = null) }, - onClick = { - isMenuExpanded = false - filePickerLauncher.launch("*/*") + Column( + horizontalAlignment = Alignment.CenterHorizontally + ) { + IconButton( + onClick = { + isMenuExpanded = false + filePickerLauncher.launch("*/*") + }, + modifier = Modifier + .size(64.dp) + .clip(CircleShape) + .background(MaterialTheme.colorScheme.surfaceVariant) + ) { + Icon( + Icons.Outlined.Description, + contentDescription = "Attach File", + modifier = Modifier.size(28.dp) + ) + } + Spacer(modifier = Modifier.padding(4.dp)) + Text( + "File", + style = MaterialTheme.typography.labelMedium + ) + } } - ) + Spacer(modifier = Modifier.padding(16.dp)) + } } } } From a4c8d5aa7ea8d99e29642cb4e3c0bcbab59c4954 Mon Sep 17 00:00:00 2001 From: Mildrette Date: Thu, 4 Jun 2026 10:57:53 +0100 Subject: [PATCH 3/9] Removed coroutineScope and the files picker and contactpicker from chatcompose to seperate composables, other changes include a updated dropdown to buttomSheet and a test file for conversationsComponents testing for the following checks that index and total number shows on the screen, check that placeholder text shows when search is empty, check that the + button is visible, tapping + button sheet show up with photo contact and file, that each button in the bottom shows, send button shows when you type something, send button hides when text field is empty, checks that tapping the send button actually triger the send action, check that the resend options shows up, and delete also shows and all test passed --- .../executionHistory/executionHistory.lock | Bin 17 -> 17 bytes .gradle/8.13/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../buildOutputCleanup.lock | Bin 17 -> 17 bytes .../ConversationsComponentsTest.kt | 95 +++++++++++------- .../ui/components/ConversationsComponents.kt | 2 + 5 files changed, 62 insertions(+), 35 deletions(-) diff --git a/.gradle/8.13/executionHistory/executionHistory.lock b/.gradle/8.13/executionHistory/executionHistory.lock index 4ac8ab308b83b158a82b4b99ab743a2ac6a7654d..16a2cfcd4f478c67df2c8d55e8b6a8500ac19264 100644 GIT binary patch literal 17 VcmZQx{wrl+`X+l81~B0M4*)kP1rPuL literal 17 VcmZQx{wrl+`X+l81~A}$1^_n?1or>{ diff --git a/.gradle/8.13/fileHashes/fileHashes.lock b/.gradle/8.13/fileHashes/fileHashes.lock index 5dd3ce78c20bfc5ae60fe5600dffe1dabe69d27f..525dee7c0be2ddc9ad6bb213e5c01cfad785f94a 100644 GIT binary patch literal 17 VcmZSfktz3|{>FbZ0~oZ{0st*d1i1hJ literal 17 VcmZSfktz3|{>FbZ0~oYC0st+r1swnY diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 38e5f02e718e9991f9491f2469d08002ad952bbc..606c571093177bf9790a3d3cdbad7be2fe172cf6 100644 GIT binary patch literal 17 VcmZR!e!D6BMc%y&3}E2H2>?Jf1&#m! literal 17 VcmZR!e!D6BMc%y&3}E1$1OPyc1?B(% diff --git a/lib_smsmms_android/src/androidTest/java/com/afkanerd/smswithoutborders_libsmsmms/ConversationsComponentsTest.kt b/lib_smsmms_android/src/androidTest/java/com/afkanerd/smswithoutborders_libsmsmms/ConversationsComponentsTest.kt index 57e9a8f..cbf3648 100644 --- a/lib_smsmms_android/src/androidTest/java/com/afkanerd/smswithoutborders_libsmsmms/ConversationsComponentsTest.kt +++ b/lib_smsmms_android/src/androidTest/java/com/afkanerd/smswithoutborders_libsmsmms/ConversationsComponentsTest.kt @@ -31,64 +31,71 @@ class ConversationsComponentsTest { } @Test - fun searchCounter_forwardButtonClick_triggersCallback() { - var clicked = false + fun searchTopAppBar_displaysPlaceholder_whenEmpty() { composeTestRule.setContent { - SearchCounterCompose( - index = "1", - total = "5", - forwardClick = { clicked = true } - ) + SearchTopAppBarText(searchQuery = "") } composeTestRule - .onNodeWithContentDescription("move_search_backwards") - .performClick() - - assert(clicked) { "Forward button did not trigger callback" } + .onNodeWithText("Text message", substring = true) + .assertIsDisplayed() } @Test - fun searchCounter_backwardButtonClick_triggersCallback() { - var clicked = false + fun searchTopAppBar_closeButton_isDisplayed() { composeTestRule.setContent { - SearchCounterCompose( - index = "1", - total = "5", - backwardClick = { clicked = true } - ) + SearchTopAppBarText(searchQuery = "hello") } composeTestRule - .onNodeWithContentDescription("move search forwards") - .performClick() - - assert(clicked) { "Backward button did not trigger callback" } + .onNodeWithContentDescription("cancel search", ignoreCase = true) + .assertIsDisplayed() } @Test - fun searchTopAppBar_displaysPlaceholder_whenEmpty() { + fun chatCompose_plusButton_isDisplayed() { composeTestRule.setContent { - SearchTopAppBarText(searchQuery = "") + ChatCompose( + value = "", + subscriptionId = -1L, + sendMmsCallback = {}, + smsSendCallback = {} + ) } - composeTestRule - .onNodeWithText("Text message", substring = true) + .onNodeWithContentDescription("Attachment Options") .assertIsDisplayed() } @Test - fun searchTopAppBar_closeButton_isDisplayed() { + fun chatCompose_plusButton_click_opensBottomSheet() { composeTestRule.setContent { - SearchTopAppBarText(searchQuery = "hello") + ChatCompose( + value = "", + subscriptionId = -1L, + sendMmsCallback = {}, + smsSendCallback = {} + ) } + composeTestRule - .onNodeWithContentDescription("cancel search", ignoreCase = true) + .onNodeWithContentDescription("Attachment Options") + .performClick() + + composeTestRule + .onNodeWithText("Photo") .assertIsDisplayed() - } + composeTestRule + .onNodeWithText("Contact") + .assertIsDisplayed() + + composeTestRule + .onNodeWithText("File") + .assertIsDisplayed() + } @Test - fun chatCompose_plusButton_isDisplayed() { + fun chatCompose_bottomSheet_photoOption_isDisplayed() { composeTestRule.setContent { ChatCompose( value = "", @@ -99,11 +106,15 @@ class ConversationsComponentsTest { } composeTestRule .onNodeWithContentDescription("Attachment Options") + .performClick() + + composeTestRule + .onNodeWithContentDescription("Photo") .assertIsDisplayed() } @Test - fun chatCompose_plusButton_click_opensDropdownMenu() { + fun chatCompose_bottomSheet_contactOption_isDisplayed() { composeTestRule.setContent { ChatCompose( value = "", @@ -117,11 +128,26 @@ class ConversationsComponentsTest { .performClick() composeTestRule - .onNodeWithText("Attach Contact") + .onNodeWithContentDescription("Attach Contact") .assertIsDisplayed() + } + + @Test + fun chatCompose_bottomSheet_fileOption_isDisplayed() { + composeTestRule.setContent { + ChatCompose( + value = "", + subscriptionId = -1L, + sendMmsCallback = {}, + smsSendCallback = {} + ) + } + composeTestRule + .onNodeWithContentDescription("Attachment Options") + .performClick() composeTestRule - .onNodeWithText("Attach File") + .onNodeWithContentDescription("Attach File") .assertIsDisplayed() } @@ -135,7 +161,6 @@ class ConversationsComponentsTest { smsSendCallback = {} ) } - composeTestRule .onNodeWithContentDescription("send message", ignoreCase = true) .assertDoesNotExist() diff --git a/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt b/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt index 8b7fcbc..24c1cb6 100644 --- a/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt +++ b/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt @@ -348,11 +348,13 @@ fun ChatCompose( valueChanged = valueChanged ) + val filePickerLauncher = FilePickerLauncher( mmsValueChanged = mmsValueChanged, onFileSelected = { uri -> imageUri = uri } ) + var messagingType by remember { mutableStateOf("SMS") } var isMenuExpanded by remember { mutableStateOf(false) } From 14b92ac85c660b4ef00d4ae40e3a02dca87078b4 Mon Sep 17 00:00:00 2001 From: Mildrette Date: Wed, 10 Jun 2026 10:31:15 +0100 Subject: [PATCH 4/9] test:-> add instrumented tests for makeE164PhoneNumber - checks that a number already in international format comes back unchanged - checks that spaces and dashes are stripped from a phone number --- .../executionHistory/executionHistory.lock | Bin 17 -> 17 bytes .gradle/8.13/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../buildOutputCleanup.lock | Bin 17 -> 17 bytes .../TelephonyTest.kt | 33 ++++++++++++++++++ 4 files changed, 33 insertions(+) create mode 100644 lib_smsmms_android/src/androidTest/java/com/afkanerd/smswithoutborders_libsmsmms/TelephonyTest.kt diff --git a/.gradle/8.13/executionHistory/executionHistory.lock b/.gradle/8.13/executionHistory/executionHistory.lock index 16a2cfcd4f478c67df2c8d55e8b6a8500ac19264..8b9354ba63c273375d7bc5573b5f5d2c953e62c7 100644 GIT binary patch literal 17 VcmZQx{wrl+`X+l81~A|e2LLug1StRj literal 17 VcmZQx{wrl+`X+l81~B0M4*)kP1rPuL diff --git a/.gradle/8.13/fileHashes/fileHashes.lock b/.gradle/8.13/fileHashes/fileHashes.lock index 525dee7c0be2ddc9ad6bb213e5c01cfad785f94a..0c5f3ab5529d1381a49479d05452d3aa331b92d6 100644 GIT binary patch literal 17 VcmZSfktz3|{>FbZ0~oZ~001ox1bF}e literal 17 VcmZSfktz3|{>FbZ0~oZ{0st*d1i1hJ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 606c571093177bf9790a3d3cdbad7be2fe172cf6..d7589003af02306aa43f6f2ba7eed37dbb214554 100644 GIT binary patch literal 17 VcmZR!e!D6BMc%y&3}E1M6aYZ+21)<` literal 17 VcmZR!e!D6BMc%y&3}E2H2>?Jf1&#m! diff --git a/lib_smsmms_android/src/androidTest/java/com/afkanerd/smswithoutborders_libsmsmms/TelephonyTest.kt b/lib_smsmms_android/src/androidTest/java/com/afkanerd/smswithoutborders_libsmsmms/TelephonyTest.kt new file mode 100644 index 0000000..91bb16d --- /dev/null +++ b/lib_smsmms_android/src/androidTest/java/com/afkanerd/smswithoutborders_libsmsmms/TelephonyTest.kt @@ -0,0 +1,33 @@ +package com.afkanerd.smswithoutborders_libsmsmms + +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.afkanerd.smswithoutborders_libsmsmms.extensions.context.makeE16PhoneNumber +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class PhoneNumberInstrumentationTest { + + private lateinit var context: Context + + @Before + fun setUp() { + context = ApplicationProvider.getApplicationContext() + } + + @Test + fun formatsInternationalNumber() { + val result = context.makeE16PhoneNumber("+237671234567") + assertEquals("+237671234567", result) + } + + @Test + fun removesSpacesAndDashes() { + val result = context.makeE16PhoneNumber("+237 671-234-567") + assertEquals("+237671234567", result) + } +} \ No newline at end of file From d3c173b8d0349e6255cf64dd8164176ffc71b5cd Mon Sep 17 00:00:00 2001 From: Mildrette Date: Wed, 10 Jun 2026 11:17:14 +0100 Subject: [PATCH 5/9] removed fileshare --- .../executionHistory/executionHistory.lock | Bin 17 -> 17 bytes .gradle/8.13/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../buildOutputCleanup.lock | Bin 17 -> 17 bytes .../ui/components/ConversationsComponents.kt | 34 ------------------ 4 files changed, 34 deletions(-) diff --git a/.gradle/8.13/executionHistory/executionHistory.lock b/.gradle/8.13/executionHistory/executionHistory.lock index 8b9354ba63c273375d7bc5573b5f5d2c953e62c7..63d432a14bfee9d8cf2b2ac29c35fb74692ac346 100644 GIT binary patch literal 17 VcmZQx{wrl+`X+l81~A|;001^y1VR7+ literal 17 VcmZQx{wrl+`X+l81~A|e2LLug1StRj diff --git a/.gradle/8.13/fileHashes/fileHashes.lock b/.gradle/8.13/fileHashes/fileHashes.lock index 0c5f3ab5529d1381a49479d05452d3aa331b92d6..cc50ad574ebe8d5b6c302ada38a594f1ecf09419 100644 GIT binary patch literal 17 VcmZSfktz3|{>FbZ0~oZ;2LLT`1l#}s literal 17 VcmZSfktz3|{>FbZ0~oZ~001ox1bF}e diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index d7589003af02306aa43f6f2ba7eed37dbb214554..bc044369f1ea20934372e0093d755b1cb8cd0917 100644 GIT binary patch literal 17 VcmZR!e!D6BMc%y&3}E2f3IIT}1`7ZH literal 17 VcmZR!e!D6BMc%y&3}E1M6aYZ+21)<` diff --git a/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt b/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt index 24c1cb6..224f911 100644 --- a/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt +++ b/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt @@ -46,7 +46,6 @@ import androidx.compose.material.icons.filled.PlayCircle import androidx.compose.material.icons.filled.Share import androidx.compose.material.icons.outlined.AccountCircle import androidx.compose.material.icons.outlined.AddCircleOutline -import androidx.compose.material.icons.outlined.Description import androidx.compose.material.icons.outlined.Image import androidx.compose.material.icons.outlined.SimCard import androidx.compose.material3.BottomAppBar @@ -348,13 +347,6 @@ fun ChatCompose( valueChanged = valueChanged ) - - val filePickerLauncher = FilePickerLauncher( - mmsValueChanged = mmsValueChanged, - onFileSelected = { uri -> imageUri = uri } - ) - - var messagingType by remember { mutableStateOf("SMS") } var isMenuExpanded by remember { mutableStateOf(false) } @@ -496,32 +488,6 @@ fun ChatCompose( style = MaterialTheme.typography.labelMedium ) } - - Column( - horizontalAlignment = Alignment.CenterHorizontally - ) { - IconButton( - onClick = { - isMenuExpanded = false - filePickerLauncher.launch("*/*") - }, - modifier = Modifier - .size(64.dp) - .clip(CircleShape) - .background(MaterialTheme.colorScheme.surfaceVariant) - ) { - Icon( - Icons.Outlined.Description, - contentDescription = "Attach File", - modifier = Modifier.size(28.dp) - ) - } - Spacer(modifier = Modifier.padding(4.dp)) - Text( - "File", - style = MaterialTheme.typography.labelMedium - ) - } } Spacer(modifier = Modifier.padding(16.dp)) } From 80341b9de0f6e3f89d8a068155e6929925405023 Mon Sep 17 00:00:00 2001 From: Mildrette Date: Wed, 10 Jun 2026 11:28:23 +0100 Subject: [PATCH 6/9] removed fileshare --- .../executionHistory/executionHistory.lock | Bin 17 -> 17 bytes .gradle/8.13/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../buildOutputCleanup.lock | Bin 17 -> 17 bytes .../ui/components/ConversationsComponents.kt | 36 +----------------- 4 files changed, 1 insertion(+), 35 deletions(-) diff --git a/.gradle/8.13/executionHistory/executionHistory.lock b/.gradle/8.13/executionHistory/executionHistory.lock index 63d432a14bfee9d8cf2b2ac29c35fb74692ac346..77dd29590e86589b5e83eb4e3ee9b6bce96ab786 100644 GIT binary patch literal 17 VcmZQx{wrl+`X+l81~A|W0RT3C1ZDsL literal 17 VcmZQx{wrl+`X+l81~A|;001^y1VR7+ diff --git a/.gradle/8.13/fileHashes/fileHashes.lock b/.gradle/8.13/fileHashes/fileHashes.lock index cc50ad574ebe8d5b6c302ada38a594f1ecf09419..c1cd6e58e74e0aa6494dd24992e43fa64565cf39 100644 GIT binary patch literal 17 VcmZSfktz3|{>FbZ0~oY@0st+<1up;q literal 17 VcmZSfktz3|{>FbZ0~oZ;2LLT`1l#}s diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index bc044369f1ea20934372e0093d755b1cb8cd0917..fe070df52962444928678dff39434e6149053a21 100644 GIT binary patch literal 17 VcmZR!e!D6BMc%y&3}E252LM3q215V< literal 17 VcmZR!e!D6BMc%y&3}E2f3IIT}1`7ZH diff --git a/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt b/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt index 224f911..bca7911 100644 --- a/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt +++ b/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt @@ -46,6 +46,7 @@ import androidx.compose.material.icons.filled.PlayCircle import androidx.compose.material.icons.filled.Share import androidx.compose.material.icons.outlined.AccountCircle import androidx.compose.material.icons.outlined.AddCircleOutline +import androidx.compose.material.icons.outlined.Description import androidx.compose.material.icons.outlined.Image import androidx.compose.material.icons.outlined.SimCard import androidx.compose.material3.BottomAppBar @@ -335,18 +336,11 @@ fun ChatCompose( } var imageUri: Uri? by remember { mutableStateOf(imageUri) } - val imagePicker = mmsImagePicker { uri -> - val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION - context.contentResolver.takePersistableUriPermission(uri, flag) - mmsValueChanged?.invoke(uri) - imageUri = uri - } val contactPickerLauncher = ContactPickerLauncher( value = value, valueChanged = valueChanged ) - var messagingType by remember { mutableStateOf("SMS") } var isMenuExpanded by remember { mutableStateOf(false) } @@ -435,34 +429,6 @@ fun ChatCompose( .padding(16.dp), horizontalArrangement = Arrangement.SpaceEvenly ) { - Column( - horizontalAlignment = Alignment.CenterHorizontally - ) { - IconButton( - onClick = { - isMenuExpanded = false - imagePicker.launch(arrayOf( - "image/png", "image/jpg", "image/jpeg" - )) - }, - modifier = Modifier - .size(64.dp) - .clip(CircleShape) - .background(MaterialTheme.colorScheme.surfaceVariant) - ) { - Icon( - Icons.Outlined.Image, - contentDescription = "Photo", - modifier = Modifier.size(28.dp) - ) - } - Spacer(modifier = Modifier.padding(4.dp)) - Text( - "Photo", - style = MaterialTheme.typography.labelMedium - ) - } - Column( horizontalAlignment = Alignment.CenterHorizontally ) { From c3586958af99d18afe87ea01a803ed576cd12b8e Mon Sep 17 00:00:00 2001 From: Mildrette Date: Wed, 10 Jun 2026 11:28:45 +0100 Subject: [PATCH 7/9] removed fileshare and image share --- .../ui/components/ConversationsComponents.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt b/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt index bca7911..2d46632 100644 --- a/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt +++ b/lib_smsmms_android/src/main/java/com/afkanerd/smswithoutborders_libsmsmms/ui/components/ConversationsComponents.kt @@ -461,6 +461,7 @@ fun ChatCompose( } } + Column( Modifier .fillMaxWidth() From ff591627dda53b57a0036dfc471c26b5f429f140 Mon Sep 17 00:00:00 2001 From: Mildrette Date: Wed, 10 Jun 2026 11:55:36 +0100 Subject: [PATCH 8/9] simplify attachment to contact only --- .../executionHistory/executionHistory.lock | Bin 17 -> 17 bytes .gradle/8.13/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../buildOutputCleanup.lock | Bin 17 -> 17 bytes .../ui/components/ConversationsComponents.kt | 58 +++--------------- 4 files changed, 7 insertions(+), 51 deletions(-) diff --git a/.gradle/8.13/executionHistory/executionHistory.lock b/.gradle/8.13/executionHistory/executionHistory.lock index 77dd29590e86589b5e83eb4e3ee9b6bce96ab786..a3698bb2cf5ec4b9e4d5d0400ee1fcb5cdde306c 100644 GIT binary patch literal 17 VcmZQx{wrl+`X+l81~B011OPU)1e*W= literal 17 VcmZQx{wrl+`X+l81~A|W0RT3C1ZDsL diff --git a/.gradle/8.13/fileHashes/fileHashes.lock b/.gradle/8.13/fileHashes/fileHashes.lock index c1cd6e58e74e0aa6494dd24992e43fa64565cf39..6892107fcb92deceabccdac82b607860f565e61a 100644 GIT binary patch literal 17 VcmZSfktz3|{>FbZ0~oa51^_Lu1sMPU literal 17 VcmZSfktz3|{>FbZ0~oY@0st+<1up;q diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index fe070df52962444928678dff39434e6149053a21..96d48cc958fe1987721360c1d311afc2a50fddd2 100644 GIT binary patch literal 17 VcmZR!e!D6BMc%y&3}6u80sugG1 Date: Fri, 12 Jun 2026 10:36:13 +0100 Subject: [PATCH 9/9] the added test test When the ShortCodeAlert popup appears on screen, does the dismiss button show up --- .../executionHistory/executionHistory.lock | Bin 17 -> 17 bytes .gradle/8.13/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../buildOutputCleanup.lock | Bin 17 -> 17 bytes .../ConversationsComponentsTest.kt | 165 ++---------------- 4 files changed, 14 insertions(+), 151 deletions(-) diff --git a/.gradle/8.13/executionHistory/executionHistory.lock b/.gradle/8.13/executionHistory/executionHistory.lock index a3698bb2cf5ec4b9e4d5d0400ee1fcb5cdde306c..4206e678972fa0bce57799ca93e2213afc5bda41 100644 GIT binary patch literal 17 VcmZQx{wrl+`X+l81~A}R2LLwN1i%0Q literal 17 VcmZQx{wrl+`X+l81~B011OPU)1e*W= diff --git a/.gradle/8.13/fileHashes/fileHashes.lock b/.gradle/8.13/fileHashes/fileHashes.lock index 6892107fcb92deceabccdac82b607860f565e61a..fe9f7f719d8a2ca8079cabfcf9250660ae5d8438 100644 GIT binary patch literal 17 VcmZSfktz3|{>FbZ0~mC)0{|^u1jYaW literal 17 VcmZSfktz3|{>FbZ0~oa51^_Lu1sMPU diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 96d48cc958fe1987721360c1d311afc2a50fddd2..eeb3e27a345f7bd567c8e123e5dec6b0574370c2 100644 GIT binary patch literal 17 VcmZR!e!D6BMc%y&3}6sA2>?LI1{?qY literal 17 VcmZR!e!D6BMc%y&3}6u80sugG1