From 7d3715d8b9f1e8be3bff9c6a44c8007e11c7b122 Mon Sep 17 00:00:00 2001 From: tateisu Date: Wed, 12 Jul 2023 09:54:09 +0900 Subject: [PATCH] =?UTF-8?q?=E5=A4=96=E9=83=A8=E3=82=A2=E3=83=97=E3=83=AA?= =?UTF-8?q?=E3=81=8B=E3=82=89=E3=82=B7=E3=82=A7=E3=82=A2=E3=81=97=E3=81=9F?= =?UTF-8?q?=E9=9A=9B=E3=81=AB=E9=80=81=E4=BF=A1=E5=85=88=E3=82=A4=E3=83=B3?= =?UTF-8?q?=E3=82=B9=E3=82=BF=E3=83=B3=E3=82=B9=E3=81=AE=E3=82=B5=E3=83=BC?= =?UTF-8?q?=E3=83=90=E6=83=85=E5=A0=B1=E3=82=92=E3=81=BE=E3=81=A0=E3=82=AD?= =?UTF-8?q?=E3=83=A3=E3=83=83=E3=82=B7=E3=83=A5=E3=81=A7=E3=81=8D=E3=81=A6?= =?UTF-8?q?=E3=81=84=E3=81=AA=E3=81=84=E5=A0=B4=E5=90=88=E3=81=AB=E5=AF=BE?= =?UTF-8?q?=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/jp/juggler/subwaytooter/ActPost.kt | 11 +++ .../subwaytooter/actpost/ActPostAttachment.kt | 98 ++++++++++++++++--- 2 files changed, 97 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActPost.kt b/app/src/main/java/jp/juggler/subwaytooter/ActPost.kt index 0ff88556..cb1840f2 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActPost.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActPost.kt @@ -22,6 +22,7 @@ import jp.juggler.subwaytooter.actpost.CompletionHelper import jp.juggler.subwaytooter.actpost.FeaturedTagCache import jp.juggler.subwaytooter.actpost.addAttachment import jp.juggler.subwaytooter.actpost.applyMushroomText +import jp.juggler.subwaytooter.actpost.launchAddAttachmentChannelReader import jp.juggler.subwaytooter.actpost.onPickCustomThumbnailImpl import jp.juggler.subwaytooter.actpost.onPostAttachmentCompleteImpl import jp.juggler.subwaytooter.actpost.openAttachment @@ -197,6 +198,13 @@ class ActPost : AppCompatActivity(), } } + class AddAttachmentChannelItem( + val uri: Uri, + val mimeTypeArg: String?, + ) + + val addAttachmentChannel = Channel(capacity = Channel.BUFFERED) + //////////////////////////////////////////////////////////////// override fun onCreate(savedInstanceState: Bundle?) { @@ -220,6 +228,8 @@ class ActPost : AppCompatActivity(), progressChannel = Channel(capacity = Channel.CONFLATED) + launchAddAttachmentChannelReader() + initUI() // 進捗表示チャネルの回収コルーチン @@ -255,6 +265,7 @@ class ActPost : AppCompatActivity(), } completionHelper.onDestroy() attachmentUploader.onActivityDestroy() + addAttachmentChannel.close() super.onDestroy() } diff --git a/app/src/main/java/jp/juggler/subwaytooter/actpost/ActPostAttachment.kt b/app/src/main/java/jp/juggler/subwaytooter/actpost/ActPostAttachment.kt index 5a048eb8..e30cbba5 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/actpost/ActPostAttachment.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/actpost/ActPostAttachment.kt @@ -8,6 +8,8 @@ import androidx.appcompat.app.AlertDialog import jp.juggler.subwaytooter.ActPost import jp.juggler.subwaytooter.R import jp.juggler.subwaytooter.api.ApiTask +import jp.juggler.subwaytooter.api.TootApiCallback +import jp.juggler.subwaytooter.api.TootApiClient import jp.juggler.subwaytooter.api.TootApiResult import jp.juggler.subwaytooter.api.entity.InstanceType import jp.juggler.subwaytooter.api.entity.ServiceType @@ -44,6 +46,9 @@ import jp.juggler.util.log.withCaption import jp.juggler.util.network.toPutRequestBuilder import jp.juggler.util.ui.isLiveActivity import jp.juggler.util.ui.vg +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.channels.ClosedReceiveChannelException +import java.nio.channels.ClosedChannelException import kotlin.math.min private val log = LogCategory("ActPostAttachment") @@ -126,34 +131,77 @@ fun ActPost.openAttachment() { fun ActPost.addAttachment( uri: Uri, mimeTypeArg: String? = null, -// onUploadEnd: () -> Unit = {}, ) { + val item = ActPost.AddAttachmentChannelItem(uri = uri, mimeTypeArg = mimeTypeArg) + for (nTry in 1..10) { + try { + val channelResult = addAttachmentChannel.trySend(item) + when { + channelResult.isSuccess -> return + channelResult.isClosed -> return + channelResult.isFailure -> continue + } + } catch (ex: Throwable) { + log.e(ex, "addAttachmentChannel.trySend failed.") + continue + } + } +} + +suspend fun ActPost.getInstance(): TootInstance { + val client = TootApiClient( + context = applicationContext, + callback = object : TootApiCallback { + override suspend fun isApiCancelled() = isFinishing || isDestroyed + } + ).apply { + this.account = this@getInstance.account + } + val (instance, ri) = TootInstance.get(client = client) + if (instance != null) return instance + when (ri) { + null -> throw CancellationException() + else -> error("missing instance information. ${ri.error}") + } +} + +suspend fun ActPost.addAttachmentSuspend( + uri: Uri, + mimeTypeArg: String? = null, +) { + val actPost = this val account = this.account - if (account == null) { - dialogOrToast(R.string.account_select_please) - return - } - val instance = TootInstance.getCached(account) - if (instance == null) { - dialogOrToast("missing instance imformation.") - return - } + val mimeType = uri.resolveMimeType(mimeTypeArg, this) ?.notEmpty() val isReply = states.inReplyToId != null when { + actPost.isFinishing || actPost.isDestroyed -> { + dialogOrToast("actPost is finishing or destroyed.") + return + } + attachmentList.size >= 4 -> { dialogOrToast(R.string.attachment_too_many) return } + account == null -> { + dialogOrToast(R.string.account_select_please) + return + } + mimeType == null -> { dialogOrToast(R.string.mime_type_missing) return } + } + val instance = getInstance() + + when { instance.instanceType == InstanceType.Pixelfed && isReply -> { AttachmentUploader.log.e("pixelfed_does_not_allow_reply_with_media") dialogOrToast(R.string.pixelfed_does_not_allow_reply_with_media) @@ -169,10 +217,10 @@ fun ActPost.addAttachment( attachmentUploader.addRequest( AttachmentRequest( context = applicationContext, - account = account, + account = account!!, pa = pa, uri = uri, - mimeType = mimeType, + mimeType = mimeType!!, instance = instance, mediaConfig = mediaConfig, serverMaxSqPixel = mediaConfig?.int("image_matrix_limit")?.takeIf { it > 0 }, @@ -194,6 +242,32 @@ fun ActPost.addAttachment( } } +fun ActPost.launchAddAttachmentChannelReader() { + launchMain { + while (true) { + try { + val item = addAttachmentChannel.receive() + addAttachmentSuspend(item.uri, item.mimeTypeArg) + } catch (ex: Throwable) { + when (ex) { + is CancellationException -> { + log.i("launchAddAttachmentChannelReader: cancelled.") + break + } + + is ClosedChannelException, is ClosedReceiveChannelException -> { + log.i("launchAddAttachmentChannelReader: channel closed.") + break + } + + else -> + log.e(ex,"launchAddAttachmentChannelReader: addAttachmentSuspend raise error. retry…") + } + } + } + } +} + fun ActPost.onPostAttachmentCompleteImpl(pa: PostAttachment) { // この添付メディアはリストにない if (!attachmentList.contains(pa)) {