diff --git a/README.MD b/README.MD index ab37e4bf..a8b834ef 100644 --- a/README.MD +++ b/README.MD @@ -73,6 +73,10 @@ Join our [Telegram Channel](https://t.me/ytdlnis) or [Discord](https://discord.g The App's package name is com.deniscerri.ytdl ## 📝 Help Translate on Weblate + +Translation status + + Translation status diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e5339e17..7ab0e1fe 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -173,6 +173,8 @@ + + dialogInterface.cancel() } deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int -> - historyViewModel.delete(item, deleteFile[0]) + historyViewModel.delete(item, deleteFile[0]) } deleteDialog.show() } @@ -491,7 +499,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{ redownload.setOnLongClickListener { bottomSheet!!.cancel() - val sheet = DownloadBottomSheetDialog(downloadViewModel.createResultItemFromHistory(item), item.type, null) + val sheet = DownloadBottomSheetDialog(downloadViewModel.createResultItemFromHistory(item), item.type, downloadViewModel.createDownloadItemFromHistory(item)) sheet.show(parentFragmentManager, "downloadSingleSheet") true } @@ -614,6 +622,72 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{ selectedObjects?.clear() } + private var simpleCallback: ItemTouchHelper.SimpleCallback = + object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) { + override fun onMove(recyclerView: RecyclerView,viewHolder: RecyclerView.ViewHolder,target: RecyclerView.ViewHolder + ): Boolean { + return false + } + + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { + val position = viewHolder.bindingAdapterPosition + when (direction) { + ItemTouchHelper.LEFT -> { + val deletedItem = historyList!![position] + historyAdapter!!.notifyItemChanged(position) + removeItem(deletedItem!!) + } + ItemTouchHelper.RIGHT -> { + val item = historyList!![position]!! + historyAdapter!!.notifyItemChanged(position) + val sheet = DownloadBottomSheetDialog(downloadViewModel.createResultItemFromHistory(item), item.type, downloadViewModel.createDownloadItemFromHistory(item)) + sheet.show(parentFragmentManager, "downloadSingleSheet") + } + } + } + + override fun onChildDraw( + c: Canvas, + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder, + dX: Float, + dY: Float, + actionState: Int, + isCurrentlyActive: Boolean + ) { + RecyclerViewSwipeDecorator.Builder( + requireContext(), + c, + recyclerView, + viewHolder, + dX, + dY, + actionState, + isCurrentlyActive + ) + .addSwipeLeftBackgroundColor(Color.RED) + .addSwipeLeftActionIcon(R.drawable.baseline_delete_24) + .addSwipeRightBackgroundColor( + MaterialColors.getColor( + requireContext(), + R.attr.colorOnSurfaceInverse, Color.TRANSPARENT + ) + ) + .addSwipeRightActionIcon(R.drawable.ic_refresh) + .create() + .decorate() + super.onChildDraw( + c, + recyclerView, + viewHolder!!, + dX, + dY, + actionState, + isCurrentlyActive + ) + } + } + companion object { private const val TAG = "historyFragment" } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt index 3fa5a486..916c46c2 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt @@ -11,10 +11,14 @@ import android.os.Build import androidx.core.app.NotificationCompat import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.receiver.CancelDownloadNotificationReceiver +import com.deniscerri.ytdlnis.receiver.OpenDownloadNotificationReceiver +import com.deniscerri.ytdlnis.receiver.SharedDownloadNotificationReceiver +import com.deniscerri.ytdlnis.ui.more.downloadLogs.DownloadLogActivity class NotificationUtil(var context: Context) { private val downloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, DOWNLOAD_SERVICE_CHANNEL_ID) private val commandDownloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID) + private val finishedDownloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, DOWNLOAD_FINISHED_CHANNEL_ID) private val notificationManager: NotificationManager = context.getSystemService(NotificationManager::class.java) fun createNotificationChannel() { @@ -38,6 +42,14 @@ class NotificationUtil(var context: Context) { channel = NotificationChannel(COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID, name, importance) channel.description = description notificationManager.createNotificationChannel(channel) + + //finished or errored downloads + name = context.getString(R.string.finished_download_notification_channel_name) + description = + context.getString(R.string.finished_download_notification_channel_description) + channel = NotificationChannel(DOWNLOAD_FINISHED_CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH) + channel.description = description + notificationManager.createNotificationChannel(channel) } } @@ -45,6 +57,7 @@ class NotificationUtil(var context: Context) { when(channel) { DOWNLOAD_SERVICE_CHANNEL_ID -> { return downloadNotificationBuilder} COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID -> { return commandDownloadNotificationBuilder } + DOWNLOAD_FINISHED_CHANNEL_ID -> { return finishedDownloadNotificationBuilder } } return downloadNotificationBuilder } @@ -89,6 +102,84 @@ class NotificationUtil(var context: Context) { .build() } + fun createDownloadFinished(title: String?, + filepath: String?, + channel: String + ) { + val notificationBuilder = getBuilder(channel) + + val openIntent = Intent(context, OpenDownloadNotificationReceiver::class.java) + openIntent.putExtra("open", "") + openIntent.putExtra("path", filepath) + openIntent.putExtra("notificationID", DOWNLOAD_FINISHED_NOTIFICATION_ID) + val openNotificationPendingIntent = PendingIntent.getBroadcast( + context, + 1, + openIntent, + PendingIntent.FLAG_IMMUTABLE + ) + + val shareIntent = Intent(context, SharedDownloadNotificationReceiver::class.java) + shareIntent.putExtra("share", "") + shareIntent.putExtra("path", filepath) + openIntent.putExtra("notificationID", DOWNLOAD_FINISHED_NOTIFICATION_ID) + val shareNotificationPendingIntent = PendingIntent.getBroadcast( + context, + 1, + shareIntent, + PendingIntent.FLAG_IMMUTABLE + ) + + notificationBuilder + .setContentTitle("${context.getString(R.string.downloaded)} $title") + .setSmallIcon(R.drawable.ic_app_icon) + .setLargeIcon( + BitmapFactory.decodeResource( + context.resources, + R.drawable.ic_app_icon + ) + ) + .setPriority(NotificationCompat.PRIORITY_MAX) + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + .clearActions() + if (filepath != null){ + notificationBuilder.addAction(0, context.getString(R.string.Open_File), openNotificationPendingIntent) + notificationBuilder.addAction(0, context.getString(R.string.share), shareNotificationPendingIntent) + } + notificationManager.notify(DOWNLOAD_FINISHED_NOTIFICATION_ID, notificationBuilder.build()) + } + + fun createDownloadErrored(title: String?, + error: String?, + logFilePath: String?, + channel: String + ) { + val notificationBuilder = getBuilder(channel) + + val intent = Intent(context, DownloadLogActivity::class.java) + intent.putExtra("path", logFilePath) + intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + val errorPendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE) + + notificationBuilder + .setContentTitle("${context.getString(R.string.errored)}: $title") + .setContentText(error) + .setSmallIcon(R.drawable.ic_app_icon) + .setLargeIcon( + BitmapFactory.decodeResource( + context.resources, + R.drawable.ic_app_icon + ) + ) + .setPriority(NotificationCompat.PRIORITY_MAX) + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + .clearActions() + if (logFilePath != null){ + notificationBuilder.addAction(0, context.getString(R.string.logs), errorPendingIntent) + } + notificationManager.notify(DOWNLOAD_FINISHED_NOTIFICATION_ID, notificationBuilder.build()) + } + fun updateDownloadNotification( id: Int, desc: String, @@ -118,9 +209,9 @@ class NotificationUtil(var context: Context) { companion object { const val DOWNLOAD_SERVICE_CHANNEL_ID = "1" - const val DOWNLOAD_NOTIFICATION_ID = 1 const val COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID = "2" - const val COMMAND_DOWNLOAD_NOTIFICATION_ID = 2 + const val DOWNLOAD_FINISHED_CHANNEL_ID = "3" + const val DOWNLOAD_FINISHED_NOTIFICATION_ID = 3 const val FILE_TRANSFER_CHANNEL_ID = "3" private const val PROGRESS_MAX = 100 private const val PROGRESS_CURR = 0 diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt index 9df9ff3f..e98f8845 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt @@ -228,7 +228,12 @@ class UiUtil(private val fileUtil: FileUtil) { val i = Intent(Intent.ACTION_VIEW) i.setDataAndType(uri, mime) i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - fragmentContext.startActivity(i) + try { + fragmentContext.startActivity(i) + }catch (e: Exception){ + i.flags = Intent.FLAG_ACTIVITY_NEW_TASK + fragmentContext.startActivity(i) + } } fun shareFileIntent(fragmentContext: Context, paths: List){ @@ -251,7 +256,13 @@ class UiUtil(private val fileUtil: FileUtil) { type = "*/*" putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true) } - fragmentContext.startActivity(Intent.createChooser(shareIntent, null)) + try { + fragmentContext.startActivity(Intent.createChooser(shareIntent, null)) + }catch (e: Exception){ + val intent = Intent.createChooser(shareIntent, null) + intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + fragmentContext.startActivity(intent) + } } fun showDatePicker(fragmentManager: FragmentManager , onSubmit : (chosenDate: Calendar) -> Unit ){ diff --git a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt index 40dab72b..95737a2b 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt @@ -16,6 +16,7 @@ import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdlnis.database.models.HistoryItem import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel +import com.deniscerri.ytdlnis.ui.more.downloadLogs.DownloadLogActivity import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdlnis.util.NotificationUtil import com.yausername.youtubedl_android.YoutubeDL @@ -309,6 +310,11 @@ class DownloadWorker( historyDao.insert(historyItem) } } + notificationUtil.createDownloadFinished( + downloadItem.title, if (finalPath.equals(context.getString(R.string.unfound_file))) null else finalPath, + NotificationUtil.DOWNLOAD_FINISHED_CHANNEL_ID + ) + runBlocking { dao.delete(downloadItem.id) } @@ -342,6 +348,13 @@ class DownloadWorker( runBlocking { dao.update(downloadItem) } + + notificationUtil.createDownloadErrored( + downloadItem.title, it.message, + if (logDownloads) logFile.absolutePath else null, + NotificationUtil.DOWNLOAD_FINISHED_CHANNEL_ID + ) + return Result.failure( Data.Builder().putString("output", it.toString()).build() ) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6e8f3493..3a74d730 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -238,4 +238,7 @@ Purple Yellow Monochrome + "Downloaded: " + Finished Downloads + Notification showing when the download has succesfully finished or errored out \ No newline at end of file