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 6f99a1c98199..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
@@ -94,6 +97,16 @@ class SyncMediaWorker(
setContentTitle(CollectionManager.TR.syncMediaFailed())
throwable.localizedMessage?.let { message ->
setContentText(message)
+ setStyle(
+ NotificationCompat
+ .BigTextStyle()
+ .bigText(message),
+ )
+ addAction(
+ R.drawable.baseline_content_copy_24,
+ CollectionManager.TR.qtMiscCopyToClipboard(),
+ getCopyToClipboardIntent(message),
+ )
}
}
Timber.d("SyncMediaWorker: showing failure notification")
@@ -145,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) {