Fix saving failed status to drafts (#2410)
* fix saving failed statuses to drafts * use coroutine delay instead of timer
This commit is contained in:
parent
3d2ae4dcbb
commit
59b627664f
1 changed files with 56 additions and 69 deletions
|
@ -30,13 +30,12 @@ import dagger.android.AndroidInjection
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.Callback
|
import retrofit2.Callback
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
import java.util.Timer
|
|
||||||
import java.util.TimerTask
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -58,8 +57,6 @@ class SendStatusService : Service(), Injectable {
|
||||||
private val statusesToSend = ConcurrentHashMap<Int, StatusToSend>()
|
private val statusesToSend = ConcurrentHashMap<Int, StatusToSend>()
|
||||||
private val sendCalls = ConcurrentHashMap<Int, Call<Status>>()
|
private val sendCalls = ConcurrentHashMap<Int, Call<Status>>()
|
||||||
|
|
||||||
private val timer = Timer()
|
|
||||||
|
|
||||||
private val notificationManager by lazy { getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager }
|
private val notificationManager by lazy { getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager }
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
|
@ -154,56 +151,56 @@ class SendStatusService : Service(), Injectable {
|
||||||
|
|
||||||
val callback = object : Callback<Status> {
|
val callback = object : Callback<Status> {
|
||||||
override fun onResponse(call: Call<Status>, response: Response<Status>) {
|
override fun onResponse(call: Call<Status>, response: Response<Status>) {
|
||||||
|
serviceScope.launch {
|
||||||
|
|
||||||
val scheduled = !statusToSend.scheduledAt.isNullOrEmpty()
|
val scheduled = !statusToSend.scheduledAt.isNullOrEmpty()
|
||||||
statusesToSend.remove(statusId)
|
statusesToSend.remove(statusId)
|
||||||
|
|
||||||
if (response.isSuccessful) {
|
if (response.isSuccessful) {
|
||||||
// If the status was loaded from a draft, delete the draft and associated media files.
|
// If the status was loaded from a draft, delete the draft and associated media files.
|
||||||
if (statusToSend.draftId != 0) {
|
if (statusToSend.draftId != 0) {
|
||||||
serviceScope.launch {
|
|
||||||
draftHelper.deleteDraftAndAttachments(statusToSend.draftId)
|
draftHelper.deleteDraftAndAttachments(statusToSend.draftId)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (scheduled) {
|
if (scheduled) {
|
||||||
response.body()?.let(::StatusScheduledEvent)?.let(eventHub::dispatch)
|
response.body()?.let(::StatusScheduledEvent)?.let(eventHub::dispatch)
|
||||||
|
} else {
|
||||||
|
response.body()?.let(::StatusComposedEvent)?.let(eventHub::dispatch)
|
||||||
|
}
|
||||||
|
|
||||||
|
notificationManager.cancel(statusId)
|
||||||
} else {
|
} else {
|
||||||
response.body()?.let(::StatusComposedEvent)?.let(eventHub::dispatch)
|
// the server refused to accept the status, save status & show error message
|
||||||
|
saveStatusToDrafts(statusToSend)
|
||||||
|
|
||||||
|
val builder = NotificationCompat.Builder(this@SendStatusService, CHANNEL_ID)
|
||||||
|
.setSmallIcon(R.drawable.ic_notify)
|
||||||
|
.setContentTitle(getString(R.string.send_post_notification_error_title))
|
||||||
|
.setContentText(getString(R.string.send_post_notification_saved_content))
|
||||||
|
.setColor(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
this@SendStatusService,
|
||||||
|
R.color.notification_color
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
notificationManager.cancel(statusId)
|
||||||
|
notificationManager.notify(errorNotificationId--, builder.build())
|
||||||
}
|
}
|
||||||
|
stopSelfWhenDone()
|
||||||
notificationManager.cancel(statusId)
|
|
||||||
} else {
|
|
||||||
// the server refused to accept the status, save status & show error message
|
|
||||||
saveStatusToDrafts(statusToSend)
|
|
||||||
|
|
||||||
val builder = NotificationCompat.Builder(this@SendStatusService, CHANNEL_ID)
|
|
||||||
.setSmallIcon(R.drawable.ic_notify)
|
|
||||||
.setContentTitle(getString(R.string.send_post_notification_error_title))
|
|
||||||
.setContentText(getString(R.string.send_post_notification_saved_content))
|
|
||||||
.setColor(ContextCompat.getColor(this@SendStatusService, R.color.notification_color))
|
|
||||||
|
|
||||||
notificationManager.cancel(statusId)
|
|
||||||
notificationManager.notify(errorNotificationId--, builder.build())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stopSelfWhenDone()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<Status>, t: Throwable) {
|
override fun onFailure(call: Call<Status>, t: Throwable) {
|
||||||
var backoff = TimeUnit.SECONDS.toMillis(statusToSend.retries.toLong())
|
serviceScope.launch {
|
||||||
if (backoff > MAX_RETRY_INTERVAL) {
|
var backoff = TimeUnit.SECONDS.toMillis(statusToSend.retries.toLong())
|
||||||
backoff = MAX_RETRY_INTERVAL
|
if (backoff > MAX_RETRY_INTERVAL) {
|
||||||
}
|
backoff = MAX_RETRY_INTERVAL
|
||||||
|
}
|
||||||
|
|
||||||
timer.schedule(
|
delay(backoff)
|
||||||
object : TimerTask() {
|
sendStatus(statusId)
|
||||||
override fun run() {
|
}
|
||||||
sendStatus(statusId)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
backoff
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +215,7 @@ class SendStatusService : Service(), Injectable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cancelSending(statusId: Int) {
|
private fun cancelSending(statusId: Int) = serviceScope.launch {
|
||||||
val statusToCancel = statusesToSend.remove(statusId)
|
val statusToCancel = statusesToSend.remove(statusId)
|
||||||
if (statusToCancel != null) {
|
if (statusToCancel != null) {
|
||||||
val sendCall = sendCalls.remove(statusId)
|
val sendCall = sendCalls.remove(statusId)
|
||||||
|
@ -230,38 +227,28 @@ class SendStatusService : Service(), Injectable {
|
||||||
.setSmallIcon(R.drawable.ic_notify)
|
.setSmallIcon(R.drawable.ic_notify)
|
||||||
.setContentTitle(getString(R.string.send_post_notification_cancel_title))
|
.setContentTitle(getString(R.string.send_post_notification_cancel_title))
|
||||||
.setContentText(getString(R.string.send_post_notification_saved_content))
|
.setContentText(getString(R.string.send_post_notification_saved_content))
|
||||||
.setColor(ContextCompat.getColor(this, R.color.notification_color))
|
.setColor(ContextCompat.getColor(this@SendStatusService, R.color.notification_color))
|
||||||
|
|
||||||
notificationManager.notify(statusId, builder.build())
|
notificationManager.notify(statusId, builder.build())
|
||||||
|
|
||||||
timer.schedule(
|
delay(5000)
|
||||||
object : TimerTask() {
|
|
||||||
override fun run() {
|
|
||||||
notificationManager.cancel(statusId)
|
|
||||||
stopSelfWhenDone()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
5000
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveStatusToDrafts(status: StatusToSend) {
|
private suspend fun saveStatusToDrafts(status: StatusToSend) {
|
||||||
serviceScope.launch {
|
draftHelper.saveDraft(
|
||||||
draftHelper.saveDraft(
|
draftId = status.draftId,
|
||||||
draftId = status.draftId,
|
accountId = status.accountId,
|
||||||
accountId = status.accountId,
|
inReplyToId = status.inReplyToId,
|
||||||
inReplyToId = status.inReplyToId,
|
content = status.text,
|
||||||
content = status.text,
|
contentWarning = status.warningText,
|
||||||
contentWarning = status.warningText,
|
sensitive = status.sensitive,
|
||||||
sensitive = status.sensitive,
|
visibility = Status.Visibility.byString(status.visibility),
|
||||||
visibility = Status.Visibility.byString(status.visibility),
|
mediaUris = status.mediaUris,
|
||||||
mediaUris = status.mediaUris,
|
mediaDescriptions = status.mediaDescriptions,
|
||||||
mediaDescriptions = status.mediaDescriptions,
|
poll = status.poll,
|
||||||
poll = status.poll,
|
failedToSend = true
|
||||||
failedToSend = true
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cancelSendingIntent(statusId: Int): PendingIntent {
|
private fun cancelSendingIntent(statusId: Int): PendingIntent {
|
||||||
|
|
Loading…
Reference in a new issue