Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3419 alt text in any case #3421

Merged
merged 12 commits into from
Apr 24, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -227,13 +227,13 @@ class ComposeActivity :
val mediaAdapter = MediaPreviewAdapter(
this,
onAddCaption = { item ->
CaptionDialog.newInstance(item.localId, item.description, item.uri)
.show(supportFragmentManager, "caption_dialog")
CaptionDialog.newInstance(item.localId, item.description, item.uri).show(supportFragmentManager, "caption_dialog")
},
onAddFocus = { item ->
makeFocusDialog(item.focus, item.uri) { newFocus ->
viewModel.updateFocus(item.localId, newFocus)
}
// TODO this is inconsistent to CaptionDialog (device rotation)?
connyduck marked this conversation as resolved.
Show resolved Hide resolved
},
onEditImage = this::editImageInQueue,
onRemove = this::removeMediaFromQueue
Expand Down Expand Up @@ -1266,11 +1266,7 @@ class ComposeActivity :
}

override fun onUpdateDescription(localId: Int, description: String) {
lifecycleScope.launch {
if (!viewModel.updateDescription(localId, description)) {
Toast.makeText(this@ComposeActivity, R.string.error_failed_set_caption, Toast.LENGTH_SHORT).show()
}
}
viewModel.updateDescription(localId, description)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.flow.updateAndGet
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
Expand Down Expand Up @@ -130,7 +129,7 @@ class ComposeViewModel @Inject constructor(
): QueuedMedia {
var stashMediaItem: QueuedMedia? = null

media.updateAndGet { mediaValue ->
media.update { mediaList ->
val mediaItem = QueuedMedia(
localId = mediaUploader.getNewLocalMediaId(),
uri = uri,
Expand All @@ -144,11 +143,11 @@ class ComposeViewModel @Inject constructor(

if (replaceItem != null) {
mediaUploader.cancelUploadScope(replaceItem.localId)
mediaValue.map {
mediaList.map {
if (it.localId == replaceItem.localId) mediaItem else it
}
} else { // Append
mediaValue + mediaItem
mediaList + mediaItem
}
}
val mediaItem = stashMediaItem!! // stashMediaItem is always non-null and uncaptured at this point, but Kotlin doesn't know that
Expand All @@ -169,13 +168,13 @@ class ComposeViewModel @Inject constructor(
state = if (event.processed) { QueuedMedia.State.PROCESSED } else { QueuedMedia.State.UNPROCESSED }
)
is UploadEvent.ErrorEvent -> {
media.update { mediaValue -> mediaValue.filter { it.localId != mediaItem.localId } }
media.update { mediaList -> mediaList.filter { it.localId != mediaItem.localId } }
uploadError.emit(event.error)
return@collect
}
}
media.update { mediaValue ->
mediaValue.map { mediaItem ->
media.update { mediaList ->
mediaList.map { mediaItem ->
if (mediaItem.localId == newMediaItem.localId) {
newMediaItem
} else {
Expand All @@ -189,7 +188,7 @@ class ComposeViewModel @Inject constructor(
}

private fun addUploadedMedia(id: String, type: QueuedMedia.Type, uri: Uri, description: String?, focus: Attachment.Focus?) {
media.update { mediaValue ->
media.update { mediaList ->
val mediaItem = QueuedMedia(
localId = mediaUploader.getNewLocalMediaId(),
uri = uri,
Expand All @@ -201,13 +200,13 @@ class ComposeViewModel @Inject constructor(
focus = focus,
state = QueuedMedia.State.PUBLISHED
)
mediaValue + mediaItem
mediaList + mediaItem
}
}

fun removeMediaFromQueue(item: QueuedMedia) {
mediaUploader.cancelUploadScope(item.localId)
media.update { mediaValue -> mediaValue.filter { it.localId != item.localId } }
media.update { mediaList -> mediaList.filter { it.localId != item.localId } }
}

fun toggleMarkSensitive() {
Expand Down Expand Up @@ -322,44 +321,26 @@ class ComposeViewModel @Inject constructor(
serviceClient.sendToot(tootToSend)
}

// Updates a QueuedMedia item arbitrarily, then sends description and focus to server
private suspend fun updateMediaItem(localId: Int, mutator: (QueuedMedia) -> QueuedMedia): Boolean {
val newMediaList = media.updateAndGet { mediaValue ->
mediaValue.map { mediaItem ->
private fun updateMediaItem(localId: Int, mutator: (QueuedMedia) -> QueuedMedia) {
media.update { mediaList ->
mediaList.map { mediaItem ->
if (mediaItem.localId == localId) {
mutator(mediaItem)
} else {
mediaItem
}
}
}

if (!editing) {
// Updates to media for already-published statuses need to go through the status edit api
Lakoja marked this conversation as resolved.
Show resolved Hide resolved
val updatedItem = newMediaList.find { it.localId == localId }
if (updatedItem?.id != null) {
val focus = updatedItem.focus
val focusString = if (focus != null) "${focus.x},${focus.y}" else null
return api.updateMedia(updatedItem.id, updatedItem.description, focusString)
.fold({
true
}, { throwable ->
Log.w(TAG, "failed to update media", throwable)
false
})
}
}
return true
}

suspend fun updateDescription(localId: Int, description: String): Boolean {
return updateMediaItem(localId) { mediaItem ->
fun updateDescription(localId: Int, description: String) {
updateMediaItem(localId) { mediaItem ->
mediaItem.copy(description = description)
}
}

suspend fun updateFocus(localId: Int, focus: Attachment.Focus): Boolean {
return updateMediaItem(localId) { mediaItem ->
fun updateFocus(localId: Int, focus: Attachment.Focus) {
updateMediaItem(localId) { mediaItem ->
mediaItem.copy(focus = focus)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import android.graphics.drawable.Drawable
import android.net.Uri
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
Expand All @@ -31,15 +30,14 @@ import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.DialogFocusBinding
import com.keylesspalace.tusky.entity.Attachment.Focus
import kotlinx.coroutines.launch

fun <T> T.makeFocusDialog(
existingFocus: Focus?,
previewUri: Uri,
onUpdateFocus: suspend (Focus) -> Boolean
onUpdateFocus: suspend (Focus) -> Unit
) where T : Activity, T : LifecycleOwner {
val focus = existingFocus ?: Focus(0.0f, 0.0f) // Default to center

Expand Down Expand Up @@ -79,9 +77,7 @@ fun <T> T.makeFocusDialog(

val okListener = { dialog: DialogInterface, _: Int ->
lifecycleScope.launch {
if (!onUpdateFocus(dialogBinding.focusIndicator.getFocus())) {
showFailedFocusMessage()
}
onUpdateFocus(dialogBinding.focusIndicator.getFocus())
}
dialog.dismiss()
}
Expand All @@ -99,7 +95,3 @@ fun <T> T.makeFocusDialog(

dialog.show()
}

private fun Activity.showFailedFocusMessage() {
Toast.makeText(this, R.string.error_failed_set_focus, Toast.LENGTH_SHORT).show()
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ public void writeTo(@NonNull BufferedSink sink) throws IOException {
uploaded += read;
sink.write(buffer, 0, read);
}

uploadListener.onProgressUpdate((int)(100 * uploaded / contentLength));
Lakoja marked this conversation as resolved.
Show resolved Hide resolved
} finally {
content.close();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,23 @@ class SendStatusService : Service(), Injectable {
return@launch
}

val isNew = statusToSend.statusId == null

if (isNew) {
media.forEach { mediaItem ->
if (mediaItem.processed && (mediaItem.description != null || mediaItem.focus != null)) {
mastodonApi.updateMedia(mediaItem.id!!, mediaItem.description, mediaItem.focus?.toMastodonApiString())
.fold({
}, { throwable ->
Log.w(TAG, "failed to update media on status send", throwable)
failOrRetry(throwable, statusId)

return@launch
})
}
}
}

// finally, send the new status
val newStatus = NewStatus(
status = statusToSend.text,
Expand All @@ -204,17 +221,16 @@ class SendStatusService : Service(), Injectable {
}
)

val editing = (statusToSend.statusId != null)
val sendResult = if (editing) {
mastodonApi.editStatus(
statusToSend.statusId!!,
val sendResult = if (isNew) {
mastodonApi.createStatus(
"Bearer " + account.accessToken,
account.domain,
statusToSend.idempotencyKey,
newStatus
)
} else {
mastodonApi.createStatus(
mastodonApi.editStatus(
statusToSend.statusId!!,
"Bearer " + account.accessToken,
account.domain,
statusToSend.idempotencyKey,
Expand All @@ -235,7 +251,7 @@ class SendStatusService : Service(), Injectable {

if (scheduled) {
eventHub.dispatch(StatusScheduledEvent(sentStatus))
} else if (editing) {
} else if (!isNew) {
eventHub.dispatch(StatusEditedEvent(statusToSend.statusId!!, sentStatus))
} else {
eventHub.dispatch(StatusComposedEvent(sentStatus))
Expand All @@ -244,18 +260,22 @@ class SendStatusService : Service(), Injectable {
notificationManager.cancel(statusId)
}, { throwable ->
Log.w(TAG, "failed sending status", throwable)
if (throwable is HttpException) {
// the server refused to accept the status, save status & show error message
failSending(statusId)
} else {
// a network problem occurred, let's retry sending the status
retrySending(statusId)
}
failOrRetry(throwable, statusId)
})
stopSelfWhenDone()
}
}

private suspend fun failOrRetry(throwable: Throwable, statusId: Int) {
if (throwable is HttpException) {
// the server refused to accept, save status & show error message
failSending(statusId)
} else {
// a network problem occurred, let's retry sending the status
retrySending(statusId)
Lakoja marked this conversation as resolved.
Show resolved Hide resolved
}
}

private suspend fun retrySending(statusId: Int) {
// when statusToSend == null, sending has been canceled
val statusToSend = statusesToSend[statusId] ?: return
Expand Down Expand Up @@ -290,6 +310,9 @@ class SendStatusService : Service(), Injectable {
notificationManager.cancel(statusId)
notificationManager.notify(errorNotificationId++, notification)
}

// NOTE only this removes the "Sending..." notification (added with startForeground() above)
Lakoja marked this conversation as resolved.
Show resolved Hide resolved
stopSelfWhenDone()
}

private fun cancelSending(statusId: Int) = serviceScope.launch {
Expand Down
14 changes: 6 additions & 8 deletions app/src/main/res/values-ar/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,12 @@
<string name="label_header">صورة رأس الصفحة</string>
<string name="link_whats_an_instance">ماذا نعني بمثيل الخادم؟</string>
<string name="login_connection">الإتصال جارٍ…</string>
<string name="dialog_whats_an_instance">بإمكانك إدخال عنوان أي مثيل خادوم ماستدون هنا. على سبيل المثال mastodon.social أو icosahedron.website أو social.tchncs.de أوالإطلاع على <a href="https://instances.social">لاكتشاف المزيد !</a>
\n
<string name="dialog_whats_an_instance">بإمكانك إدخال عنوان أي مثيل خادوم ماستدون هنا. على سبيل المثال mastodon.social أو icosahedron.website أو social.tchncs.de أوالإطلاع على <a href="https://instances.social">لاكتشاف المزيد !</a>
\n
\n إن كنت لا تملك حسابا بإمكانك إدخال اسم مثيل خادوم تريد الانضمام إليه قصد إنشاء حسابك عليه.
\n
\n نعني بمثيل الخادوم المكان الذي استُضِيف فيه حسابك و يمكنك التواصل مع أصدقائك و متابعيك و كأنكم على موقع واحد و ذلك حتى و إن كانت حساباتهم مُستضافة على مثيلات خوادم أخرى.
\n
\n
\n نعني بمثيل الخادوم المكان الذي استُضِيف فيه حسابك و يمكنك التواصل مع أصدقائك و متابعيك و كأنكم على موقع واحد و ذلك حتى و إن كانت حساباتهم مُستضافة على مثيلات خوادم أخرى.
\n
\n للمزيد مِن التفاصيل إطّلع على <a href="https://joinmastodon.org">joinmastodon.org</a>. </string>
<string name="dialog_title_finishing_media_upload">تتمة رفع الوسائط</string>
<string name="dialog_message_uploading_media">الإرسال جارٍ…</string>
Expand Down Expand Up @@ -278,7 +278,6 @@
<string name="action_add_to_list">إضافة الحساب إلى القائمة</string>
<string name="action_remove_from_list">إزالة الحساب مِن القائمة</string>
<string name="compose_active_account_description">النشر بإسم %1$s</string>
<string name="error_failed_set_caption">تعذرت عملية إضافة الشرح</string>
<plurals name="hint_describe_for_visually_impaired">
<item quantity="zero">وصف لضعاف البصر
\n(%d أحرف على أقصى تقدير)</item>
Expand Down Expand Up @@ -631,7 +630,6 @@
<string name="url_domain_notifier">%s (🔗 %s)</string>
<string name="action_set_focus">ضبط نقطة التركيز</string>
<string name="action_edit_image">تعديل الصورة</string>
<string name="error_failed_set_focus">فشل في تعيين نقطة التركيز</string>
<string name="action_add_reaction">إضافة رد فعل</string>
<string name="action_share_account_link">مشاركة رابط الحساب</string>
<string name="action_share_account_username">مشاركة اسم مستخدم الحساب</string>
Expand Down Expand Up @@ -671,4 +669,4 @@
<string name="ui_error_unknown">سبب مجهول</string>
<string name="socket_timeout_exception">طال الاتصال بخادمك كثيرًا</string>
<string name="action_add">إضافة</string>
</resources>
</resources>
4 changes: 1 addition & 3 deletions app/src/main/res/values-be/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,6 @@
<string name="add_account_name">Дадаць уліковы запіс</string>
<string name="action_remove_from_list">Выдаліць уліковы запіс са спіса</string>
<string name="compose_active_account_description">Публікаваць як %1$s</string>
<string name="error_failed_set_caption">Не атрымалася дадаць подпіс</string>
<string name="set_focus_description">Націсніце або перацягніце кола каб абраць пункт фокусу, які будзе заўсёды бачны на паменшаных выявах.</string>
<string name="action_set_caption">Задаць подпіс</string>
<string name="action_set_focus">Задаць пункт фокуса</string>
Expand All @@ -413,7 +412,6 @@
<string name="action_rename_list">Перайменаваць спіс</string>
<string name="action_delete_list">Выдаліць спіс</string>
<string name="filter_add_description">Фільтраваць фразу</string>
<string name="error_failed_set_focus">Не атрымалася задаць пункт фокуса</string>
<string name="action_remove">Выдаліць</string>
<string name="lock_account_label">Заблакаваць уліковы запіс</string>
<string name="compose_save_draft">Захаваць чарнавік\?</string>
Expand Down Expand Up @@ -648,4 +646,4 @@
<string name="status_filter_placeholder_label_format">Адфільтрована: %s</string>
<string name="pref_title_account_filter_keywords">Профілі</string>
<string name="title_public_trending_hashtags">Папулярныя хэштэгі</string>
</resources>
</resources>
3 changes: 1 addition & 2 deletions app/src/main/res/values-bg/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@
<item quantity="other">Опишете за хора със зрителни увреждания
\n(%d ограничение на знаците)</item>
</plurals>
<string name="error_failed_set_caption">Неуспешно задаване на надпис</string>
<string name="compose_active_account_description">Публикуване с акаунт %1$s</string>
<string name="action_remove_from_list">Премахване на акаунт от списъка</string>
<string name="action_add_to_list">Добавяне на акаунт към списъка</string>
Expand Down Expand Up @@ -503,4 +502,4 @@
<string name="pref_title_show_boosts">Показване на споделяния</string>
<string name="error_multimedia_size_limit">Видео и аудио файловете не може да превишават %s МБ в размер.</string>
<string name="error_image_edit_failed">Тази снимка не може да абъде редактирана.</string>
</resources>
</resources>
Loading