@@ -73,6 +73,7 @@ import com.keylesspalace.tusky.adapter.EmojiAdapter
73
73
import com.keylesspalace.tusky.adapter.LocaleAdapter
74
74
import com.keylesspalace.tusky.adapter.OnEmojiSelectedListener
75
75
import com.keylesspalace.tusky.components.compose.ComposeViewModel.ConfirmationKind
76
+ import com.keylesspalace.tusky.components.compose.ComposeViewModel.QueuedMedia
76
77
import com.keylesspalace.tusky.components.compose.dialog.CaptionDialog
77
78
import com.keylesspalace.tusky.components.compose.dialog.makeFocusDialog
78
79
import com.keylesspalace.tusky.components.compose.dialog.showAddPollDialog
@@ -102,6 +103,7 @@ import com.keylesspalace.tusky.util.getSerializableCompat
102
103
import com.keylesspalace.tusky.util.hide
103
104
import com.keylesspalace.tusky.util.highlightSpans
104
105
import com.keylesspalace.tusky.util.loadAvatar
106
+ import com.keylesspalace.tusky.util.map
105
107
import com.keylesspalace.tusky.util.modernLanguageCode
106
108
import com.keylesspalace.tusky.util.setDrawableTint
107
109
import com.keylesspalace.tusky.util.show
@@ -162,7 +164,7 @@ class ComposeActivity :
162
164
private val takePictureLauncher =
163
165
registerForActivityResult(ActivityResultContracts .TakePicture ()) { success ->
164
166
if (success) {
165
- pickMedia(photoUploadUri!! )
167
+ viewModel. pickMedia(photoUploadUri!! )
166
168
}
167
169
}
168
170
private val pickMediaFilePermissionLauncher =
@@ -194,9 +196,11 @@ class ComposeActivity :
194
196
Toast .LENGTH_SHORT
195
197
).show()
196
198
} else {
197
- uris.forEach { uri ->
198
- pickMedia(uri)
199
- }
199
+ viewModel.pickMedia(
200
+ uris.map { uri ->
201
+ ComposeViewModel .MediaData (uri)
202
+ }
203
+ )
200
204
}
201
205
}
202
206
@@ -207,17 +211,15 @@ class ComposeActivity :
207
211
viewModel.cropImageItemOld?.let { itemOld ->
208
212
val size = getMediaSize(contentResolver, uriNew)
209
213
210
- lifecycleScope.launch {
211
- viewModel.addMediaToQueue(
212
- itemOld.type,
213
- uriNew,
214
- size,
215
- itemOld.description,
216
- // Intentionally reset focus when cropping
217
- null ,
218
- itemOld
219
- )
220
- }
214
+ viewModel.addMediaToQueue(
215
+ type = itemOld.type,
216
+ uri = uriNew,
217
+ mediaSize = size,
218
+ description = itemOld.description,
219
+ // Intentionally reset focus when cropping
220
+ focus = null ,
221
+ replaceItem = itemOld
222
+ )
221
223
}
222
224
} else if (result == CropImage .CancelledResult ) {
223
225
Log .w(TAG , " Edit image cancelled by user" )
@@ -308,7 +310,7 @@ class ComposeActivity :
308
310
}
309
311
310
312
if (! composeOptions?.scheduledAt.isNullOrEmpty()) {
311
- binding.composeScheduleView.setDateTime(composeOptions? .scheduledAt)
313
+ binding.composeScheduleView.setDateTime(composeOptions.scheduledAt)
312
314
}
313
315
314
316
setupLanguageSpinner(getInitialLanguages(composeOptions?.language, activeAccount))
@@ -347,14 +349,14 @@ class ComposeActivity :
347
349
when (intent.action) {
348
350
Intent .ACTION_SEND -> {
349
351
intent.getParcelableExtraCompat<Uri >(Intent .EXTRA_STREAM )?.let { uri ->
350
- pickMedia(uri)
352
+ viewModel. pickMedia(uri)
351
353
}
352
354
}
353
355
Intent .ACTION_SEND_MULTIPLE -> {
354
356
intent.getParcelableArrayListExtraCompat<Uri >(Intent .EXTRA_STREAM )
355
- ?.forEach { uri ->
356
- pickMedia (uri)
357
- }
357
+ ?.map { uri ->
358
+ ComposeViewModel . MediaData (uri)
359
+ }?. let (viewModel::pickMedia)
358
360
}
359
361
}
360
362
}
@@ -557,16 +559,25 @@ class ComposeActivity :
557
559
558
560
lifecycleScope.launch {
559
561
viewModel.uploadError.collect { throwable ->
560
- if (throwable is UploadServerError ) {
561
- displayTransientMessage(throwable.errorMessage)
562
- } else {
563
- displayTransientMessage(
564
- getString(
565
- R .string.error_media_upload_sending_fmt,
566
- throwable.message
567
- )
562
+ val errorString = when (throwable) {
563
+ is UploadServerError -> throwable.errorMessage
564
+ is FileSizeException -> {
565
+ val decimalFormat = DecimalFormat (" 0.##" )
566
+ val allowedSizeInMb = throwable.allowedSizeInBytes.toDouble() / (1024 * 1024 )
567
+ val formattedSize = decimalFormat.format(allowedSizeInMb)
568
+ getString(R .string.error_multimedia_size_limit, formattedSize)
569
+ }
570
+ is VideoOrImageException -> getString(
571
+ R .string.error_media_upload_image_or_video
572
+ )
573
+ is CouldNotOpenFileException -> getString(R .string.error_media_upload_opening)
574
+ is MediaTypeException -> getString(R .string.error_media_upload_opening)
575
+ else -> getString(
576
+ R .string.error_media_upload_sending_fmt,
577
+ throwable.message
568
578
)
569
579
}
580
+ displayTransientMessage(errorString)
570
581
}
571
582
}
572
583
@@ -1090,12 +1101,27 @@ class ComposeActivity :
1090
1101
if (contentInfo.clip.description.hasMimeType(" image/*" )) {
1091
1102
val split = contentInfo.partition { item: ClipData .Item -> item.uri != null }
1092
1103
split.first?.let { content ->
1093
- for (i in 0 until content.clip.itemCount) {
1094
- pickMedia(
1095
- content.clip.getItemAt(i).uri,
1096
- contentInfo.clip.description.label as String?
1097
- )
1104
+ val description = (contentInfo.clip.description.label as String? )?.let {
1105
+ // The Gboard android keyboard attaches this text whenever the user
1106
+ // pastes something from the keyboard's suggestion bar.
1107
+ // Due to different end user locales, the exact text may vary, but at
1108
+ // least in version 13.4.08, all of the translations contained the
1109
+ // string "Gboard".
1110
+ if (" Gboard" in it) {
1111
+ null
1112
+ } else {
1113
+ it
1114
+ }
1098
1115
}
1116
+
1117
+ viewModel.pickMedia(
1118
+ content.clip.map { clipItem ->
1119
+ ComposeViewModel .MediaData (
1120
+ uri = clipItem.uri,
1121
+ description = description
1122
+ )
1123
+ }
1124
+ )
1099
1125
}
1100
1126
return split.second
1101
1127
}
@@ -1199,45 +1225,6 @@ class ComposeActivity :
1199
1225
viewModel.removeMediaFromQueue(item)
1200
1226
}
1201
1227
1202
- private fun sanitizePickMediaDescription (description : String? ): String? {
1203
- if (description == null ) {
1204
- return null
1205
- }
1206
-
1207
- // The Gboard android keyboard attaches this text whenever the user
1208
- // pastes something from the keyboard's suggestion bar.
1209
- // Due to different end user locales, the exact text may vary, but at
1210
- // least in version 13.4.08, all of the translations contained the
1211
- // string "Gboard".
1212
- if (" Gboard" in description) {
1213
- return null
1214
- }
1215
-
1216
- return description
1217
- }
1218
-
1219
- private fun pickMedia (uri : Uri , description : String? = null) {
1220
- val sanitizedDescription = sanitizePickMediaDescription(description)
1221
-
1222
- lifecycleScope.launch {
1223
- viewModel.pickMedia(uri, sanitizedDescription).onFailure { throwable ->
1224
- val errorString = when (throwable) {
1225
- is FileSizeException -> {
1226
- val decimalFormat = DecimalFormat (" 0.##" )
1227
- val allowedSizeInMb = throwable.allowedSizeInBytes.toDouble() / (1024 * 1024 )
1228
- val formattedSize = decimalFormat.format(allowedSizeInMb)
1229
- getString(R .string.error_multimedia_size_limit, formattedSize)
1230
- }
1231
- is VideoOrImageException -> getString(
1232
- R .string.error_media_upload_image_or_video
1233
- )
1234
- else -> getString(R .string.error_media_upload_opening)
1235
- }
1236
- displayTransientMessage(errorString)
1237
- }
1238
- }
1239
- }
1240
-
1241
1228
private fun showContentWarning (show : Boolean ) {
1242
1229
TransitionManager .beginDelayedTransition(
1243
1230
binding.composeContentWarningBar.parent as ViewGroup
@@ -1420,30 +1407,6 @@ class ComposeActivity :
1420
1407
}
1421
1408
}
1422
1409
1423
- data class QueuedMedia (
1424
- val localId : Int ,
1425
- val uri : Uri ,
1426
- val type : Type ,
1427
- val mediaSize : Long ,
1428
- val uploadPercent : Int = 0 ,
1429
- val id : String? = null ,
1430
- val description : String? = null ,
1431
- val focus : Attachment .Focus ? = null ,
1432
- val state : State
1433
- ) {
1434
- enum class Type {
1435
- IMAGE ,
1436
- VIDEO ,
1437
- AUDIO
1438
- }
1439
- enum class State {
1440
- UPLOADING ,
1441
- UNPROCESSED ,
1442
- PROCESSED ,
1443
- PUBLISHED
1444
- }
1445
- }
1446
-
1447
1410
override fun onTimeSet (time : String? ) {
1448
1411
viewModel.updateScheduledAt(time)
1449
1412
if (verifyScheduledTime()) {
0 commit comments