From c33cb587a0e004bed9c9076a856967991074f151 Mon Sep 17 00:00:00 2001 From: LUwUcifer Date: Sat, 25 Apr 2026 10:31:03 +0530 Subject: [PATCH 1/2] make media sync fail notification expandable --- .../src/main/java/com/ichi2/anki/worker/SyncMediaWorker.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/worker/SyncMediaWorker.kt b/AnkiDroid/src/main/java/com/ichi2/anki/worker/SyncMediaWorker.kt index 6f99a1c98199..25d0a320087e 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/worker/SyncMediaWorker.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/worker/SyncMediaWorker.kt @@ -94,6 +94,11 @@ class SyncMediaWorker( setContentTitle(CollectionManager.TR.syncMediaFailed()) throwable.localizedMessage?.let { message -> setContentText(message) + setStyle( + NotificationCompat + .BigTextStyle() + .bigText(message), + ) } } Timber.d("SyncMediaWorker: showing failure notification") From aacfdcb3689cfbdb43f5dee159e4f5ceb4d61449 Mon Sep 17 00:00:00 2001 From: LUwUcifer Date: Thu, 7 May 2026 19:11:58 +0530 Subject: [PATCH 2/2] make media sync fail notification copyable --- AnkiDroid/src/main/AndroidManifest.xml | 5 +++ .../anki/receiver/CopyToClipboardReceiver.kt | 43 +++++++++++++++++++ .../com/ichi2/anki/worker/SyncMediaWorker.kt | 21 +++++++++ 3 files changed, 69 insertions(+) create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/receiver/CopyToClipboardReceiver.kt diff --git a/AnkiDroid/src/main/AndroidManifest.xml b/AnkiDroid/src/main/AndroidManifest.xml index 6ad593fb36b8..bd2e03a209c2 100644 --- a/AnkiDroid/src/main/AndroidManifest.xml +++ b/AnkiDroid/src/main/AndroidManifest.xml @@ -536,6 +536,11 @@ /> + + + + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 3 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ +package com.ichi2.anki.receiver + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import androidx.core.app.NotificationManagerCompat +import com.ichi2.anki.notifications.NotificationId +import com.ichi2.utils.copyToClipboard +import timber.log.Timber + +class CopyToClipboardReceiver : BroadcastReceiver() { + override fun onReceive( + context: Context, + intent: Intent, + ) { + val text = + intent.getStringExtra(SYNC_ERROR_LOG) ?: run { + Timber.w("CopyToClipboardReceiver: no error log found") + return + } + NotificationManagerCompat.from(context).cancel(NotificationId.SYNC_MEDIA) + context.copyToClipboard(text) + } + + companion object { + const val SYNC_ERROR_LOG = "COPY ERROR" + } +} diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/worker/SyncMediaWorker.kt b/AnkiDroid/src/main/java/com/ichi2/anki/worker/SyncMediaWorker.kt index 25d0a320087e..1b18bfd8252d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/worker/SyncMediaWorker.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/worker/SyncMediaWorker.kt @@ -16,7 +16,9 @@ package com.ichi2.anki.worker import android.app.Notification +import android.app.PendingIntent import android.content.Context +import android.content.Intent import android.content.pm.ServiceInfo import android.os.Build import androidx.core.app.NotificationCompat @@ -40,6 +42,7 @@ import com.ichi2.anki.CollectionManager import com.ichi2.anki.R import com.ichi2.anki.cancelMediaSync import com.ichi2.anki.notifications.NotificationId +import com.ichi2.anki.receiver.CopyToClipboardReceiver import com.ichi2.anki.utils.ext.trySetForeground import com.ichi2.utils.Permissions import kotlinx.coroutines.CancellationException @@ -99,6 +102,11 @@ class SyncMediaWorker( .BigTextStyle() .bigText(message), ) + addAction( + R.drawable.baseline_content_copy_24, + CollectionManager.TR.qtMiscCopyToClipboard(), + getCopyToClipboardIntent(message), + ) } } Timber.d("SyncMediaWorker: showing failure notification") @@ -150,6 +158,19 @@ class SyncMediaWorker( } } + private fun getCopyToClipboardIntent(text: String): PendingIntent { + val intent = Intent(applicationContext, CopyToClipboardReceiver::class.java) + intent.apply { + putExtra(CopyToClipboardReceiver.SYNC_ERROR_LOG, text) + } + return PendingIntent.getBroadcast( + applicationContext, + 0, + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, + ) + } + private fun notify(notification: Notification) = notificationManager?.notify(NotificationId.SYNC_MEDIA, notification) private fun notify(builder: NotificationCompat.Builder.() -> Unit) {