From 81767ccd4a576990b0848017b36418d04f236824 Mon Sep 17 00:00:00 2001 From: Vishal Nehra Date: Thu, 23 Nov 2023 16:32:52 +0530 Subject: [PATCH 1/5] Fix transaction too large exception in audio player service --- .../audio_player/AudioPlayerService.kt | 3 +- .../audio_player/playlist/M3UWriter.java | 6 ++-- .../amaze/fileutilities/utilis/Extensions.kt | 32 +++++++++++++++++++ app/src/main/res/layout/adapter_donation.xml | 8 +++-- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/amaze/fileutilities/audio_player/AudioPlayerService.kt b/app/src/main/java/com/amaze/fileutilities/audio_player/AudioPlayerService.kt index 07de4e1a..a8cb47f4 100644 --- a/app/src/main/java/com/amaze/fileutilities/audio_player/AudioPlayerService.kt +++ b/app/src/main/java/com/amaze/fileutilities/audio_player/AudioPlayerService.kt @@ -49,6 +49,7 @@ import com.amaze.fileutilities.utilis.ObtainableServiceBinder import com.amaze.fileutilities.utilis.PreferencesConstants import com.amaze.fileutilities.utilis.Utils import com.amaze.fileutilities.utilis.getAppCommonSharedPreferences +import com.amaze.fileutilities.utilis.startServiceSafely import com.google.android.exoplayer2.C import com.google.android.exoplayer2.ExoPlayer import com.google.android.exoplayer2.MediaItem @@ -89,7 +90,7 @@ class AudioPlayerService : Service(), ServiceOperationCallback, OnPlayerRepeatin intent.putParcelableArrayListExtra(ARG_URI_LIST, ArrayList(uriList)) } intent.action = action - context.startService(intent) + context.startServiceSafely(intent, ARG_URI_LIST) } fun sendCancelBroadcast(context: Context) { diff --git a/app/src/main/java/com/amaze/fileutilities/audio_player/playlist/M3UWriter.java b/app/src/main/java/com/amaze/fileutilities/audio_player/playlist/M3UWriter.java index a26863f5..483a5be2 100644 --- a/app/src/main/java/com/amaze/fileutilities/audio_player/playlist/M3UWriter.java +++ b/app/src/main/java/com/amaze/fileutilities/audio_player/playlist/M3UWriter.java @@ -37,8 +37,10 @@ public class M3UWriter { public static File write(File dir, MediaFileInfo.Playlist playlist, List songs) throws IOException { - if (!dir.exists()) // noinspection ResultOfMethodCallIgnored - dir.mkdirs(); + if (!dir.exists()) { + // noinspection ResultOfMethodCallIgnored + dir.mkdirs(); + } File file = new File(dir, playlist.getName().concat("." + EXTENSION)); if (songs.size() > 0) { diff --git a/app/src/main/java/com/amaze/fileutilities/utilis/Extensions.kt b/app/src/main/java/com/amaze/fileutilities/utilis/Extensions.kt index fad43e47..18c57c89 100644 --- a/app/src/main/java/com/amaze/fileutilities/utilis/Extensions.kt +++ b/app/src/main/java/com/amaze/fileutilities/utilis/Extensions.kt @@ -22,6 +22,7 @@ package com.amaze.fileutilities.utilis import android.content.ContentResolver import android.content.Context +import android.content.Intent import android.content.SharedPreferences import android.content.res.Resources import android.database.Cursor @@ -30,6 +31,7 @@ import android.net.Uri import android.os.Build import android.os.Environment import android.os.ParcelFileDescriptor +import android.os.TransactionTooLargeException import android.provider.MediaStore import android.util.DisplayMetrics import android.view.Gravity @@ -45,6 +47,7 @@ import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.files.FileFilter import com.afollestad.materialdialogs.files.fileChooser import com.afollestad.materialdialogs.files.folderChooser +import com.amaze.fileutilities.audio_player.AudioPlayerService import com.amaze.fileutilities.home_page.database.BlurAnalysis import com.amaze.fileutilities.home_page.database.BlurAnalysisDao import com.amaze.fileutilities.home_page.database.ImageAnalysis @@ -451,6 +454,35 @@ fun Context.getAppCommonSharedPreferences(): SharedPreferences { ) } +fun Context.startServiceSafely(intent: Intent, extraName: String) { + try { + this.startService(intent) + } catch (ttle: TransactionTooLargeException) { + // decrease by 10% and try recursively + val intentUriList: ArrayList? = intent.getParcelableArrayListExtra(extraName) + intentUriList?.let { + if (intentUriList.isNotEmpty()) { + log.warn("failed to start service with extras size ${intentUriList.size}", ttle) + val uri = it.take(intentUriList.size - (intentUriList.size / 10)) + if (uri.isNotEmpty()) { + log.warn("trying to start with new size ${uri.size}") + intent.putParcelableArrayListExtra( + AudioPlayerService.ARG_URI_LIST, + ArrayList(uri) + ) + startServiceSafely(intent, extraName) + } else { + log.error("couldn't start service safely, returning...", ttle) + return + } + } else { + log.error("couldn't start service safely, returning...", ttle) + return + } + } + } +} + fun ImageAnalysis.invalidate(dao: ImageAnalysisDao): Boolean { val file = File(filePath) return if (!file.exists()) { diff --git a/app/src/main/res/layout/adapter_donation.xml b/app/src/main/res/layout/adapter_donation.xml index 2a9b5ead..316b300c 100644 --- a/app/src/main/res/layout/adapter_donation.xml +++ b/app/src/main/res/layout/adapter_donation.xml @@ -1,7 +1,8 @@ - + Date: Thu, 23 Nov 2023 16:37:53 +0530 Subject: [PATCH 2/5] Update translations --- app/src/main/res/values-af-rZA/strings.xml | 8 ++++++++ app/src/main/res/values-ar-rSA/strings.xml | 8 ++++++++ app/src/main/res/values-ca-rES/strings.xml | 8 ++++++++ app/src/main/res/values-cs-rCZ/strings.xml | 8 ++++++++ app/src/main/res/values-da-rDK/strings.xml | 8 ++++++++ app/src/main/res/values-de-rDE/strings.xml | 8 ++++++++ app/src/main/res/values-el-rGR/strings.xml | 8 ++++++++ app/src/main/res/values-en-rUS/strings.xml | 12 ++++++++++-- app/src/main/res/values-es-rES/strings.xml | 12 ++++++++++-- app/src/main/res/values-fi-rFI/strings.xml | 8 ++++++++ app/src/main/res/values-fr-rFR/strings.xml | 8 ++++++++ app/src/main/res/values-hi-rIN/strings.xml | 8 ++++++++ app/src/main/res/values-hu-rHU/strings.xml | 8 ++++++++ app/src/main/res/values-it-rIT/strings.xml | 8 ++++++++ app/src/main/res/values-iw-rIL/strings.xml | 8 ++++++++ app/src/main/res/values-ja-rJP/strings.xml | 8 ++++++++ app/src/main/res/values-ko-rKR/strings.xml | 8 ++++++++ app/src/main/res/values-ml-rIN/strings.xml | 8 ++++++++ app/src/main/res/values-nl-rNL/strings.xml | 8 ++++++++ app/src/main/res/values-no-rNO/strings.xml | 8 ++++++++ app/src/main/res/values-pl-rPL/strings.xml | 8 ++++++++ app/src/main/res/values-pt-rBR/strings.xml | 8 ++++++++ app/src/main/res/values-pt-rPT/strings.xml | 8 ++++++++ app/src/main/res/values-ro-rRO/strings.xml | 8 ++++++++ app/src/main/res/values-ru-rRU/strings.xml | 12 ++++++++++-- app/src/main/res/values-sr-rSP/strings.xml | 8 ++++++++ app/src/main/res/values-sv-rSE/strings.xml | 8 ++++++++ app/src/main/res/values-tr-rTR/strings.xml | 8 ++++++++ app/src/main/res/values-uk-rUA/strings.xml | 8 ++++++++ app/src/main/res/values-vi-rVN/strings.xml | 8 ++++++++ app/src/main/res/values-zh-rHK/strings.xml | 8 ++++++++ app/src/main/res/values-zh-rTW/strings.xml | 8 ++++++++ 32 files changed, 262 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/values-af-rZA/strings.xml b/app/src/main/res/values-af-rZA/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-af-rZA/strings.xml +++ b/app/src/main/res/values-af-rZA/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-ar-rSA/strings.xml b/app/src/main/res/values-ar-rSA/strings.xml index 86dd0426..b1ddc05c 100644 --- a/app/src/main/res/values-ar-rSA/strings.xml +++ b/app/src/main/res/values-ar-rSA/strings.xml @@ -35,6 +35,8 @@ يحتاج التطبيق لأذونات قراءة الذاكرة لتحقيق الأداء الأمثل. + App needs notification permissions for optimal performance. + منح الأذن منح @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-ca-rES/strings.xml b/app/src/main/res/values-ca-rES/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-ca-rES/strings.xml +++ b/app/src/main/res/values-ca-rES/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-da-rDK/strings.xml b/app/src/main/res/values-da-rDK/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-da-rDK/strings.xml +++ b/app/src/main/res/values-da-rDK/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml index 0848e15c..1313fe1d 100644 --- a/app/src/main/res/values-de-rDE/strings.xml +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -35,6 +35,8 @@ Die App benötigt Leserechte für eine optimale Performance. + App needs notification permissions for optimal performance. + Zugriff gewähren Erlauben @@ -681,6 +683,8 @@ Wir sind ein Team von Open-Source-Entwicklern, die hart daran arbeiten, ein werb Datenübertragung zwischen Geräten über WLAN\nHohe Übertragungsgeschwindigkeiten mit Android WiFi-Direct Wir benötigen Speicherrechte, um Zugriff auf Mediendateien zu erhalten + + We need notification permissions to show app operations Bevor wir beginnen… @@ -960,6 +964,10 @@ Wir sind ein Team von Open-Source-Entwicklern, die hart daran arbeiten, ein werb Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-el-rGR/strings.xml b/app/src/main/res/values-el-rGR/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-el-rGR/strings.xml +++ b/app/src/main/res/values-el-rGR/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-en-rUS/strings.xml b/app/src/main/res/values-en-rUS/strings.xml index eacef777..4cdb019e 100644 --- a/app/src/main/res/values-en-rUS/strings.xml +++ b/app/src/main/res/values-en-rUS/strings.xml @@ -5,7 +5,7 @@ Amaze Utilities - File Utility app with inbuilt media players for all your needs. + File. Utility app with inbuilt media players for all your needs. Amaze Image Viewer @@ -15,7 +15,7 @@ Amaze Video Player (Dialog) - Amaze Video Player (Full Screen) + Amaze Music Player @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index 1f436b89..14646e0f 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -35,6 +35,8 @@ La aplicación necesita permisos de lectura de almacenamiento para un rendimiento óptimo. + App needs notification permissions for optimal performance. + Otorgar permiso Otorgar @@ -75,7 +77,7 @@ Audios - Videos + Video Documentos @@ -220,7 +222,7 @@ Luz Baja - Memes + Español Entrecejo @@ -682,6 +684,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -961,6 +965,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-fi-rFI/strings.xml b/app/src/main/res/values-fi-rFI/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-fi-rFI/strings.xml +++ b/app/src/main/res/values-fi-rFI/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-fr-rFR/strings.xml b/app/src/main/res/values-fr-rFR/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-fr-rFR/strings.xml +++ b/app/src/main/res/values-fr-rFR/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-hi-rIN/strings.xml b/app/src/main/res/values-hi-rIN/strings.xml index 1619894b..7a0430f6 100644 --- a/app/src/main/res/values-hi-rIN/strings.xml +++ b/app/src/main/res/values-hi-rIN/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-hu-rHU/strings.xml +++ b/app/src/main/res/values-hu-rHU/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it-rIT/strings.xml index ec67a04e..7eaa45ec 100644 --- a/app/src/main/res/values-it-rIT/strings.xml +++ b/app/src/main/res/values-it-rIT/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-iw-rIL/strings.xml b/app/src/main/res/values-iw-rIL/strings.xml index 99e6a89e..0d2977d0 100644 --- a/app/src/main/res/values-iw-rIL/strings.xml +++ b/app/src/main/res/values-iw-rIL/strings.xml @@ -35,6 +35,8 @@ ליישומון דרושה גישה לקרוא מהאחסון לביצועים מיטביים. + App needs notification permissions for optimal performance. + הענקת הרשאה הענקה @@ -679,6 +681,8 @@ העברת נתונים בין מכשירים דרך רשת אלחוטית\nמהירויות במהירות גבוהה עם Android Wi-Fi Direct אנחנו צריכים הרשאות לאחסון כדי לגשת לקובצי המדיה שלך + + We need notification permissions to show app operations לפני שנתחיל… @@ -958,6 +962,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index c0626769..e9b71b2c 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + アクセス許可を付与する 付与 @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations 始める前に… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index 9f36902a..2b4f7e33 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-ml-rIN/strings.xml b/app/src/main/res/values-ml-rIN/strings.xml index 3d60489e..0ddefe36 100644 --- a/app/src/main/res/values-ml-rIN/strings.xml +++ b/app/src/main/res/values-ml-rIN/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + അനുമതി നൽകുക നല്‍കുക @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-nl-rNL/strings.xml b/app/src/main/res/values-nl-rNL/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-nl-rNL/strings.xml +++ b/app/src/main/res/values-nl-rNL/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-no-rNO/strings.xml b/app/src/main/res/values-no-rNO/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-no-rNO/strings.xml +++ b/app/src/main/res/values-no-rNO/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-pl-rPL/strings.xml b/app/src/main/res/values-pl-rPL/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-pl-rPL/strings.xml +++ b/app/src/main/res/values-pl-rPL/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 5b93b3c9..64866fd7 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -35,6 +35,8 @@ O aplicativo precisa de acesso ao armazenamento para ter um desempenho ideal. + App needs notification permissions for optimal performance. + Conceder permissão Conceder @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 60232df9..d179c527 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -35,6 +35,8 @@ A necessidade de aplicação de permissões de leitura de armazenamento para um ótimo desempenho. + App needs notification permissions for optimal performance. + Conceder permissão concedente @@ -643,6 +645,8 @@ Transfira dados entre dispositivos por wifi\nAltas velocidades de transferência usando o android wifi direct Precisamos de permissões de armazenamento para acessar seus arquivos de mídia + + We need notification permissions to show app operations Antes de começarmos… @@ -917,6 +921,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-ro-rRO/strings.xml b/app/src/main/res/values-ro-rRO/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-ro-rRO/strings.xml +++ b/app/src/main/res/values-ro-rRO/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-ru-rRU/strings.xml b/app/src/main/res/values-ru-rRU/strings.xml index 5475cfc5..1e43e300 100644 --- a/app/src/main/res/values-ru-rRU/strings.xml +++ b/app/src/main/res/values-ru-rRU/strings.xml @@ -35,6 +35,8 @@ Приложению требуется разрешение для чтения хранилища для оптимальной производительности. + App needs notification permissions for optimal performance. + Предоставьте доступ Предоставить @@ -476,7 +478,7 @@ Рейтинг - CD + КД Загрузчик @@ -681,6 +683,8 @@ Передавайте данные между устройствами через Wi-Fi\nВысокая скорость передачи данных с помощью android Wi-Fi Direct Нам нужно разрешение к хранилищу для доступа к вашим медиа-файлам + + We need notification permissions to show app operations До начала… @@ -918,7 +922,7 @@ Apps newly installed (in days) - Recently updated apps + Apps recently updated (in days) @@ -959,6 +963,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-sr-rSP/strings.xml b/app/src/main/res/values-sr-rSP/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-sr-rSP/strings.xml +++ b/app/src/main/res/values-sr-rSP/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-tr-rTR/strings.xml b/app/src/main/res/values-tr-rTR/strings.xml index be7e1e47..56968918 100644 --- a/app/src/main/res/values-tr-rTR/strings.xml +++ b/app/src/main/res/values-tr-rTR/strings.xml @@ -35,6 +35,8 @@ Uygulamanın optimum performans için depolama okuma izinlerine ihtiyacı vardır. + App needs notification permissions for optimal performance. + İzin ver Ver @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-uk-rUA/strings.xml b/app/src/main/res/values-uk-rUA/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-uk-rUA/strings.xml +++ b/app/src/main/res/values-uk-rUA/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-vi-rVN/strings.xml b/app/src/main/res/values-vi-rVN/strings.xml index 944e6162..31b28db2 100644 --- a/app/src/main/res/values-vi-rVN/strings.xml +++ b/app/src/main/res/values-vi-rVN/strings.xml @@ -35,6 +35,8 @@ App needs storage read permissions for optimal performance. + App needs notification permissions for optimal performance. + Grant permission Grant @@ -681,6 +683,8 @@ Transfer data between devices through wifi\nHigh transfer speeds using android wifi direct We need storage permissions to access your media files + + We need notification permissions to show app operations Before we start… @@ -960,6 +964,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index f0e5c654..c35233c7 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -35,6 +35,8 @@ 為提供最佳效能,App需要授予儲存空間存取權限。 + App needs notification permissions for optimal performance. + 授予權限 授權 @@ -683,6 +685,8 @@ 在裝置之間以 wifi傳送資料\n利用 Android wifi direct嘅高速傳輸 我們需要授予儲存空間存取權限以讀取你嘅媒體檔案 + + We need notification permissions to show app operations 喺開始之前… @@ -962,6 +966,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index e7c2bdab..8d0d3a52 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -35,6 +35,8 @@ 為提供最佳效能,App需要授予儲存空間存取權限。 + App needs notification permissions for optimal performance. + 授予權限 授權 @@ -682,6 +684,8 @@ 在裝置之間以 wifi傳送資料\n利用 Android wifi direct的高速傳輸 我們需要授予儲存空間存取權限以讀取你的媒體檔案 + + We need notification permissions to show app operations 在開始之前… @@ -961,6 +965,10 @@ Retention by data size Maximum data (in MBs) trash bin can store + + Cleanup interval + + Trigger auto-cleanup interval (hours) Retention by days From 4f4dc16f7790ab6a0b2c48e7d94de3aba4b6a8e2 Mon Sep 17 00:00:00 2001 From: Vishal Nehra Date: Thu, 7 Dec 2023 17:38:57 +0530 Subject: [PATCH 3/5] Fix filter crash in image editor activity --- .../image_viewer/editor/EditImageActivity.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/amaze/fileutilities/image_viewer/editor/EditImageActivity.kt b/app/src/main/java/com/amaze/fileutilities/image_viewer/editor/EditImageActivity.kt index 125aef85..91a6347c 100644 --- a/app/src/main/java/com/amaze/fileutilities/image_viewer/editor/EditImageActivity.kt +++ b/app/src/main/java/com/amaze/fileutilities/image_viewer/editor/EditImageActivity.kt @@ -65,6 +65,7 @@ import com.amaze.fileutilities.utilis.share.getShareIntents import com.amaze.fileutilities.utilis.share.showEditImageDialog import com.amaze.fileutilities.utilis.share.showShareDialog import com.amaze.fileutilities.utilis.showFade +import com.amaze.fileutilities.utilis.showToastOnBottom import com.bumptech.glide.Glide import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.engine.GlideException @@ -314,13 +315,14 @@ class EditImageActivity : private fun addFilterViews() { loadedBitmap?.let { + val resizedBitmap = Bitmap.createScaledBitmap(loadedBitmap!!, 100, 100, false) supportedFilters.forEach { photoFilter -> val filterItem = layoutInflater.inflate(R.layout.row_filter_view, null) val photoEditorView = filterItem.findViewById(R.id.imgFilterView) val txtFilterName = filterItem.findViewById(R.id.txtFilterName) txtFilterName.text = photoFilter.name.replace("_", " ") - photoEditorView.source.setImageBitmap(loadedBitmap) + photoEditorView.source.setImageBitmap(resizedBitmap) try { photoEditorView.setFilterEffect(photoFilter) } catch (e: Exception) { @@ -620,7 +622,12 @@ class EditImageActivity : } override fun onFilterSelected(photoFilter: PhotoFilter?) { - mPhotoEditor?.setFilterEffect(photoFilter) + try { + mPhotoEditor?.setFilterEffect(photoFilter) + } catch (e: Exception) { + log.error("failed to apply filter on bitmap") + this.showToastOnBottom(getString(R.string.operation_failed)) + } } override fun onToolSelected(toolType: ToolType?) { From 1218864cc1877148fff5836c62ffccbd65f519ae Mon Sep 17 00:00:00 2001 From: Vishal Nehra Date: Thu, 7 Dec 2023 21:16:29 +0530 Subject: [PATCH 4/5] Fix subtitles dialog picker in video player --- .../amaze/fileutilities/utilis/Extensions.kt | 6 +- .../utilis/dialog_picker/ContextExt.kt | 44 +++ .../dialog_picker/DialogFileChooserExt.kt | 184 +++++++++++ .../dialog_picker/DialogFolderChooserExt.kt | 145 +++++++++ .../dialog_picker/FileChooserAdapter.kt | 285 ++++++++++++++++++ .../utilis/dialog_picker/FilesUtilExt.kt | 117 +++++++ .../utilis/dialog_picker/ViewExt.kt | 43 +++ .../video_player/BaseVideoPlayerActivity.kt | 2 +- gradle.properties | 2 +- 9 files changed, 823 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/ContextExt.kt create mode 100644 app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/DialogFileChooserExt.kt create mode 100644 app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/DialogFolderChooserExt.kt create mode 100644 app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/FileChooserAdapter.kt create mode 100644 app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/FilesUtilExt.kt create mode 100644 app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/ViewExt.kt diff --git a/app/src/main/java/com/amaze/fileutilities/utilis/Extensions.kt b/app/src/main/java/com/amaze/fileutilities/utilis/Extensions.kt index 18c57c89..e4b792d3 100644 --- a/app/src/main/java/com/amaze/fileutilities/utilis/Extensions.kt +++ b/app/src/main/java/com/amaze/fileutilities/utilis/Extensions.kt @@ -44,9 +44,6 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.content.FileProvider import androidx.documentfile.provider.DocumentFile import com.afollestad.materialdialogs.MaterialDialog -import com.afollestad.materialdialogs.files.FileFilter -import com.afollestad.materialdialogs.files.fileChooser -import com.afollestad.materialdialogs.files.folderChooser import com.amaze.fileutilities.audio_player.AudioPlayerService import com.amaze.fileutilities.home_page.database.BlurAnalysis import com.amaze.fileutilities.home_page.database.BlurAnalysisDao @@ -62,6 +59,9 @@ import com.amaze.fileutilities.home_page.database.SimilarImagesAnalysis import com.amaze.fileutilities.home_page.database.SimilarImagesAnalysisDao import com.amaze.fileutilities.home_page.database.SimilarImagesAnalysisMetadata import com.amaze.fileutilities.home_page.database.SimilarImagesAnalysisMetadataDao +import com.amaze.fileutilities.utilis.dialog_picker.FileFilter +import com.amaze.fileutilities.utilis.dialog_picker.fileChooser +import com.amaze.fileutilities.utilis.dialog_picker.folderChooser import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/ContextExt.kt b/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/ContextExt.kt new file mode 100644 index 00000000..fc1115e9 --- /dev/null +++ b/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/ContextExt.kt @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2021-2023 Arpit Khurana , Vishal Nehra , + * Emmanuel Messulam, Raymond Lai and Contributors. + * + * This file is part of Amaze File Utilities. + * + * Amaze File Utilities 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 . + */ + +/** + * Designed and developed by Aidan Follestad (@afollestad) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.amaze.fileutilities.utilis.dialog_picker + +import android.content.Context +import java.io.File + +internal fun Context.getExternalFilesDir(): File? { + return this.getExternalFilesDir(null) +} diff --git a/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/DialogFileChooserExt.kt b/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/DialogFileChooserExt.kt new file mode 100644 index 00000000..65c992a6 --- /dev/null +++ b/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/DialogFileChooserExt.kt @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2021-2023 Arpit Khurana , Vishal Nehra , + * Emmanuel Messulam, Raymond Lai and Contributors. + * + * This file is part of Amaze File Utilities. + * + * Amaze File Utilities 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 . + */ + +/** + * Designed and developed by Aidan Follestad (@afollestad) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("unused") + +package com.amaze.fileutilities.utilis.dialog_picker + +import android.annotation.SuppressLint +import android.content.Context +import android.text.InputFilter +import android.widget.EditText +import android.widget.TextView +import androidx.annotation.CheckResult +import androidx.annotation.StringRes +import androidx.recyclerview.widget.LinearLayoutManager +import com.afollestad.materialdialogs.MaterialDialog +import com.afollestad.materialdialogs.WhichButton.POSITIVE +import com.afollestad.materialdialogs.actions.setActionButtonEnabled +import com.afollestad.materialdialogs.customview.customView +import com.afollestad.materialdialogs.customview.getCustomView +import com.afollestad.materialdialogs.files.R +import com.afollestad.materialdialogs.input.getInputField +import com.afollestad.materialdialogs.input.input +import com.afollestad.materialdialogs.internal.list.DialogRecyclerView +import com.afollestad.materialdialogs.utils.MDUtil.maybeSetTextColor +import java.io.File + +typealias FileFilter = ((File) -> Boolean)? +typealias FileCallback = ((dialog: MaterialDialog, file: File) -> Unit)? + +/** Gets the selected file for the current file chooser dialog. */ +@CheckResult +fun MaterialDialog.selectedFile(): File? { + val customView = getCustomView() + val list: DialogRecyclerView = customView.findViewById(R.id.list) + return (list.adapter as? FileChooserAdapter)?.selectedFile +} + +/** + * Shows a dialog that lets the user select a local file. + * + * @param initialDirectory The directory that is listed initially, defaults to external storage. + * @param filter A filter to apply when listing files, defaults to only show non-hidden files. + * @param waitForPositiveButton When true, the callback isn't invoked until the user selects a + * file and taps on the positive action button. Defaults to true if the dialog has buttons. + * @param emptyTextRes A string resource displayed on the empty view shown when a directory is + * empty. Defaults to "This folder's empty!". + * @param selection A callback invoked when a file is selected. + */ +@SuppressLint("CheckResult") +fun MaterialDialog.fileChooser( + context: Context, + initialDirectory: File? = context.getExternalFilesDir(), + filter: FileFilter = null, + waitForPositiveButton: Boolean = true, + emptyTextRes: Int = R.string.files_default_empty_text, + allowFolderCreation: Boolean = false, + @StringRes folderCreationLabel: Int? = null, + selection: FileCallback = null +): MaterialDialog { + var actualFilter: FileFilter = filter + + if (allowFolderCreation) { + // we already have permissions at app startup +// check(hasWriteStoragePermission()) { +// "You must have the WRITE_EXTERNAL_STORAGE permission first." +// } + if (filter == null) { + actualFilter = { !it.isHidden && it.canWrite() } + } + } else { + // we already have permissions at app startup +// check(hasWriteStoragePermission()) { +// "You must have the WRITE_EXTERNAL_STORAGE permission first." +// } + if (filter == null) { + actualFilter = { !it.isHidden && it.canRead() } + } + } + + check(initialDirectory != null) { + "The initial directory is null." + } + + customView(R.layout.md_file_chooser_base, noVerticalPadding = true) + setActionButtonEnabled(POSITIVE, false) + + val customView = getCustomView() + val list: DialogRecyclerView = customView.findViewById(R.id.list) + val emptyText: TextView = customView.findViewById(R.id.empty_text) + emptyText.setText(emptyTextRes) + emptyText.maybeSetTextColor(windowContext, R.attr.md_color_content) + + list.attach(this) + list.layoutManager = LinearLayoutManager(windowContext) + val adapter = FileChooserAdapter( + dialog = this, + initialFolder = initialDirectory, + waitForPositiveButton = waitForPositiveButton, + emptyView = emptyText, + onlyFolders = false, + filter = actualFilter, + allowFolderCreation = allowFolderCreation, + folderCreationLabel = folderCreationLabel, + callback = selection + ) + list.adapter = adapter + + if (waitForPositiveButton && selection != null) { + setActionButtonEnabled(POSITIVE, false) + positiveButton { + val selectedFile = adapter.selectedFile + if (selectedFile != null) { + selection.invoke(this, selectedFile) + } + } + } + + return this +} + +internal fun MaterialDialog.showNewFolderCreator( + parent: File, + @StringRes folderCreationLabel: Int?, + onCreation: () -> Unit +) { + val dialog = MaterialDialog(windowContext).show { + title(folderCreationLabel ?: R.string.files_new_folder) + input(hintRes = R.string.files_new_folder_hint) { _, input -> + File(parent, input.toString().trim()).mkdir() + onCreation() + } + } + dialog.getInputField() + .blockReservedCharacters() +} + +private fun EditText.blockReservedCharacters() { + filters += InputFilter { source, _, _, _, _, _ -> + if (source.isEmpty()) { + return@InputFilter null + } + val last = source[source.length - 1] + val reservedChars = "?:\"*|/\\<>" + if (reservedChars.indexOf(last) > -1) { + source.subSequence(0, source.length - 1) + } else { + null + } + } +} diff --git a/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/DialogFolderChooserExt.kt b/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/DialogFolderChooserExt.kt new file mode 100644 index 00000000..086a826b --- /dev/null +++ b/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/DialogFolderChooserExt.kt @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2021-2023 Arpit Khurana , Vishal Nehra , + * Emmanuel Messulam, Raymond Lai and Contributors. + * + * This file is part of Amaze File Utilities. + * + * Amaze File Utilities 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 . + */ + +/** + * Designed and developed by Aidan Follestad (@afollestad) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("unused") + +package com.amaze.fileutilities.utilis.dialog_picker + +import android.annotation.SuppressLint +import android.content.Context +import android.widget.TextView +import androidx.annotation.CheckResult +import androidx.annotation.StringRes +import androidx.recyclerview.widget.LinearLayoutManager +import com.afollestad.materialdialogs.MaterialDialog +import com.afollestad.materialdialogs.WhichButton.POSITIVE +import com.afollestad.materialdialogs.actions.setActionButtonEnabled +import com.afollestad.materialdialogs.customview.customView +import com.afollestad.materialdialogs.customview.getCustomView +import com.afollestad.materialdialogs.files.R +import com.afollestad.materialdialogs.internal.list.DialogRecyclerView +import com.afollestad.materialdialogs.utils.MDUtil.maybeSetTextColor +import java.io.File + +/** Gets the selected folder for the current folder chooser dialog. */ +@CheckResult +fun MaterialDialog.selectedFolder(): File? { + val list: DialogRecyclerView = getCustomView().findViewById(R.id.list) + return (list.adapter as? FileChooserAdapter)?.selectedFile +} + +/** + * Shows a dialog that lets the user select a local folder. + * + * @param initialDirectory The directory that is listed initially, defaults to external storage. + * @param filter A filter to apply when listing folders, defaults to only show non-hidden folders. + * @param waitForPositiveButton When true, the callback isn't invoked until the user selects a + * folder and taps on the positive action button. Defaults to true if the dialog has buttons. + * @param emptyTextRes A string resource displayed on the empty view shown when a directory is + * empty. Defaults to "This folder's empty!". + * @param selection A callback invoked when a folder is selected. + */ +@SuppressLint("CheckResult") +fun MaterialDialog.folderChooser( + context: Context, + initialDirectory: File? = context.getExternalFilesDir(), + filter: FileFilter = null, + waitForPositiveButton: Boolean = true, + emptyTextRes: Int = R.string.files_default_empty_text, + allowFolderCreation: Boolean = false, + @StringRes folderCreationLabel: Int? = null, + selection: FileCallback = null +): MaterialDialog { + var actualFilter: FileFilter = filter + + if (allowFolderCreation) { + // we already have permissions at app startup +// check(hasWriteStoragePermission()) { +// "You must have the WRITE_EXTERNAL_STORAGE permission first." +// } + if (filter == null) { + actualFilter = { !it.isHidden && it.canWrite() } + } + } else { + // we already have permissions at app startup +// check(hasWriteStoragePermission()) { +// "You must have the READ_EXTERNAL_STORAGE permission first." +// } + if (filter == null) { + actualFilter = { !it.isHidden && it.canRead() } + } + } + + check(initialDirectory != null) { + "The initial directory is null." + } + + customView(R.layout.md_file_chooser_base, noVerticalPadding = true) + setActionButtonEnabled(POSITIVE, false) + + val customView = getCustomView() + val list: DialogRecyclerView = customView.findViewById(R.id.list) + val emptyText: TextView = customView.findViewById(R.id.empty_text) + emptyText.setText(emptyTextRes) + emptyText.maybeSetTextColor(windowContext, R.attr.md_color_content) + + list.attach(this) + list.layoutManager = LinearLayoutManager(windowContext) + + val adapter = FileChooserAdapter( + dialog = this, + initialFolder = initialDirectory, + waitForPositiveButton = waitForPositiveButton, + emptyView = emptyText, + onlyFolders = true, + filter = actualFilter, + allowFolderCreation = allowFolderCreation, + folderCreationLabel = folderCreationLabel, + callback = selection + ) + list.adapter = adapter + + if (waitForPositiveButton && selection != null) { + positiveButton { + val selectedFile = adapter.selectedFile + if (selectedFile != null) { + selection.invoke(this, selectedFile) + } + } + } + + return this +} diff --git a/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/FileChooserAdapter.kt b/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/FileChooserAdapter.kt new file mode 100644 index 00000000..61786563 --- /dev/null +++ b/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/FileChooserAdapter.kt @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2021-2023 Arpit Khurana , Vishal Nehra , + * Emmanuel Messulam, Raymond Lai and Contributors. + * + * This file is part of Amaze File Utilities. + * + * Amaze File Utilities 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 . + */ + +/** + * Designed and developed by Aidan Follestad (@afollestad) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.amaze.fileutilities.utilis.dialog_picker + +import android.view.LayoutInflater +import android.view.View +import android.view.View.OnClickListener +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.StringRes +import androidx.recyclerview.widget.RecyclerView +import com.afollestad.materialdialogs.MaterialDialog +import com.afollestad.materialdialogs.WhichButton.POSITIVE +import com.afollestad.materialdialogs.actions.hasActionButtons +import com.afollestad.materialdialogs.actions.setActionButtonEnabled +import com.afollestad.materialdialogs.callbacks.onDismiss +import com.afollestad.materialdialogs.files.R +import com.afollestad.materialdialogs.list.getItemSelector +import com.afollestad.materialdialogs.utils.MDUtil.isColorDark +import com.afollestad.materialdialogs.utils.MDUtil.maybeSetTextColor +import com.afollestad.materialdialogs.utils.MDUtil.resolveColor +import kotlinx.coroutines.Dispatchers.IO +import kotlinx.coroutines.Dispatchers.Main +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import java.io.File +import java.util.Locale + +internal class FileChooserViewHolder( + itemView: View, + private val adapter: FileChooserAdapter +) : RecyclerView.ViewHolder(itemView), OnClickListener { + + init { + itemView.setOnClickListener(this) + } + + val iconView: ImageView = itemView.findViewById(R.id.icon) + val nameView: TextView = itemView.findViewById(R.id.name) + + override fun onClick(view: View) = adapter.itemClicked(adapterPosition) +} + +/** @author Aidan Follestad (afollestad */ +internal class FileChooserAdapter( + private val dialog: MaterialDialog, + initialFolder: File, + private val waitForPositiveButton: Boolean, + private val emptyView: TextView, + private val onlyFolders: Boolean, + private val filter: FileFilter, + private val allowFolderCreation: Boolean, + @StringRes private val folderCreationLabel: Int?, + private val callback: FileCallback +) : RecyclerView.Adapter() { + + var selectedFile: File? = null + + private var currentFolder = initialFolder + private var listingJob: Job? = null + private var contents: List? = null + + private val isLightTheme = + resolveColor(dialog.windowContext, attr = android.R.attr.textColorPrimary).isColorDark() + + init { + dialog.onDismiss { listingJob?.cancel() } + switchDirectory(initialFolder) + } + + fun itemClicked(index: Int) { + val parent = currentFolder.betterParent(dialog.context, allowFolderCreation, filter) + if (parent != null && index == goUpIndex()) { + // go up + switchDirectory(parent) + return + } else if (currentFolder.canWrite() && allowFolderCreation && index == newFolderIndex()) { + // New folder + dialog.showNewFolderCreator( + parent = currentFolder, + folderCreationLabel = folderCreationLabel + ) { + // Refresh view + switchDirectory(currentFolder) + } + return + } + + val actualIndex = actualIndex(index) + val selected = contents!![actualIndex].jumpOverEmulated(dialog.context) + + if (selected.isDirectory) { + switchDirectory(selected) + } else { + val previousSelectedIndex = getSelectedIndex() + this.selectedFile = selected + val actualWaitForPositive = waitForPositiveButton && dialog.hasActionButtons() + + if (actualWaitForPositive) { + dialog.setActionButtonEnabled(POSITIVE, true) + notifyItemChanged(index) + notifyItemChanged(previousSelectedIndex) + } else { + callback?.invoke(dialog, selected) + dialog.dismiss() + } + } + } + + private fun switchDirectory(directory: File) { + listingJob?.cancel() + listingJob = GlobalScope.launch(Main) { + if (onlyFolders) { + selectedFile = directory + dialog.setActionButtonEnabled(POSITIVE, true) + } + + currentFolder = directory + dialog.title(text = directory.friendlyName(dialog.context)) + + val result = withContext(IO) { + val rawContents = directory.listFiles() ?: emptyArray() + if (onlyFolders) { + rawContents + .filter { it.isDirectory && filter?.invoke(it) ?: true } + .sortedBy { it.name.toLowerCase(Locale.getDefault()) } + } else { + rawContents + .filter { filter?.invoke(it) ?: true } + .sortedWith( + compareBy({ !it.isDirectory }, { + it.nameWithoutExtension.toLowerCase(Locale.getDefault()) + }) + ) + } + } + + contents = result.apply { + emptyView.setVisible(isEmpty()) + } + notifyDataSetChanged() + } + } + + override fun getItemCount(): Int { + var count = contents?.size ?: 0 + if (currentFolder.hasParent(dialog.context, allowFolderCreation, filter)) { + count += 1 + } + if (allowFolderCreation && currentFolder.canWrite()) { + count += 1 + } + return count + } + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ): FileChooserViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.md_file_chooser_item, parent, false) + view.background = dialog.getItemSelector() + + val viewHolder = FileChooserViewHolder(view, this) + viewHolder.nameView.maybeSetTextColor(dialog.windowContext, R.attr.md_color_content) + return viewHolder + } + + override fun onBindViewHolder( + holder: FileChooserViewHolder, + position: Int + ) { + val currentParent = currentFolder.betterParent(dialog.context, allowFolderCreation, filter) + if (currentParent != null && position == goUpIndex()) { + // Go up + holder.iconView.setImageResource( + if (isLightTheme) R.drawable.icon_return_dark + else R.drawable.icon_return_light + ) + holder.nameView.text = currentParent.name + holder.itemView.isActivated = false + return + } + + if (allowFolderCreation && currentFolder.canWrite() && position == newFolderIndex()) { + // New folder + holder.iconView.setImageResource( + if (isLightTheme) R.drawable.icon_new_folder_dark + else R.drawable.icon_new_folder_light + ) + holder.nameView.text = dialog.windowContext.getString( + folderCreationLabel ?: R.string.files_new_folder + ) + holder.itemView.isActivated = false + return + } + + val actualIndex = actualIndex(position) + val item = contents!![actualIndex] + holder.iconView.setImageResource(item.iconRes()) + holder.nameView.text = item.name + holder.itemView.isActivated = selectedFile?.absolutePath == item.absolutePath ?: false + } + + private fun goUpIndex() = if (currentFolder.hasParent( + dialog.context, allowFolderCreation, + filter + ) + ) 0 else -1 + + private fun newFolderIndex() = if (currentFolder.hasParent( + dialog.context, allowFolderCreation, + filter + ) + ) 1 else 0 + + private fun actualIndex(position: Int): Int { + var actualIndex = position + if (currentFolder.hasParent(dialog.context, allowFolderCreation, filter)) { + actualIndex -= 1 + } + if (currentFolder.canWrite() && allowFolderCreation) { + actualIndex -= 1 + } + return actualIndex + } + + private fun File.iconRes(): Int { + return if (isLightTheme) { + if (this.isDirectory) R.drawable.icon_folder_dark + else R.drawable.icon_file_dark + } else { + if (this.isDirectory) R.drawable.icon_folder_light + else R.drawable.icon_file_light + } + } + + private fun getSelectedIndex(): Int { + if (selectedFile == null) return -1 + else if (contents?.isEmpty() == true) return -1 + val index = contents?.indexOfFirst { it.absolutePath == selectedFile?.absolutePath } ?: -1 + return if (index > -1 && currentFolder.hasParent( + dialog.context, allowFolderCreation, + filter + ) + ) index + 1 else index + } +} diff --git a/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/FilesUtilExt.kt b/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/FilesUtilExt.kt new file mode 100644 index 00000000..ec6ea53e --- /dev/null +++ b/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/FilesUtilExt.kt @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2021-2023 Arpit Khurana , Vishal Nehra , + * Emmanuel Messulam, Raymond Lai and Contributors. + * + * This file is part of Amaze File Utilities. + * + * Amaze File Utilities 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 . + */ + +/** + * Designed and developed by Aidan Follestad (@afollestad) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("SpellCheckingInspection") + +package com.amaze.fileutilities.utilis.dialog_picker + +import android.Manifest.permission +import android.content.Context +import android.content.pm.PackageManager +import androidx.core.content.ContextCompat +import com.afollestad.materialdialogs.MaterialDialog +import com.afollestad.materialdialogs.files.FileFilter +import java.io.File + +internal fun File.hasParent( + context: Context, + writeable: Boolean, + filter: FileFilter +) = betterParent(context, writeable, filter) != null + +internal fun File.isExternalStorage(context: Context) = + absolutePath == context.getExternalFilesDir()?.absolutePath + +internal fun File.isRoot() = absolutePath == "/" + +internal fun File.betterParent( + context: Context, + writeable: Boolean, + filter: FileFilter +): File? { + val parentToUse = ( + if (isExternalStorage(context)) { + // Emulated external storage's parent is empty so jump over it + context.getExternalFilesDir()?.parentFile?.parentFile + } else { + parentFile + } + ) ?: return null + + if ((writeable && !parentToUse.canWrite()) || !parentToUse.canRead()) { + // We can't access this folder + return null + } + + val folderContent = + parentToUse.listFiles()?.filter { filter?.invoke(it) ?: true } ?: emptyList() + if (folderContent.isEmpty()) { + // There is nothing in this folder most likely because we can't access files inside of it. + // We don't want to get stuck here. + return null + } + + return parentToUse +} + +internal fun File.jumpOverEmulated(context: Context): File { + val externalFileDir = context.getExternalFilesDir() + externalFileDir?.parentFile?.let { externalParentFile -> + if (absolutePath == externalParentFile.absolutePath) { + return externalFileDir + } + } + return this +} + +internal fun File.friendlyName(context: Context) = when { + isExternalStorage(context) -> "External Storage" + isRoot() -> "Root" + else -> name +} + +internal fun Context.hasPermission(permission: String): Boolean { + return ContextCompat.checkSelfPermission(this, permission) == + PackageManager.PERMISSION_GRANTED +} + +internal fun MaterialDialog.hasReadStoragePermission(): Boolean { + return windowContext.hasPermission(permission.READ_EXTERNAL_STORAGE) +} + +internal fun MaterialDialog.hasWriteStoragePermission(): Boolean { + return windowContext.hasPermission(permission.WRITE_EXTERNAL_STORAGE) +} diff --git a/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/ViewExt.kt b/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/ViewExt.kt new file mode 100644 index 00000000..56443fd1 --- /dev/null +++ b/app/src/main/java/com/amaze/fileutilities/utilis/dialog_picker/ViewExt.kt @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021-2023 Arpit Khurana , Vishal Nehra , + * Emmanuel Messulam, Raymond Lai and Contributors. + * + * This file is part of Amaze File Utilities. + * + * Amaze File Utilities 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 . + */ + +/** + * Designed and developed by Aidan Follestad (@afollestad) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.amaze.fileutilities.utilis.dialog_picker + +import android.view.View + +internal fun T.setVisible(visible: Boolean) { + visibility = if (visible) View.VISIBLE else View.INVISIBLE +} diff --git a/app/src/main/java/com/amaze/fileutilities/video_player/BaseVideoPlayerActivity.kt b/app/src/main/java/com/amaze/fileutilities/video_player/BaseVideoPlayerActivity.kt index a5498727..4ad39931 100644 --- a/app/src/main/java/com/amaze/fileutilities/video_player/BaseVideoPlayerActivity.kt +++ b/app/src/main/java/com/amaze/fileutilities/video_player/BaseVideoPlayerActivity.kt @@ -62,7 +62,6 @@ import androidx.core.view.updateLayoutParams import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.afollestad.materialdialogs.files.FileFilter import com.amaze.fileutilities.PermissionsActivity import com.amaze.fileutilities.R import com.amaze.fileutilities.audio_player.AudioPlayerService @@ -75,6 +74,7 @@ import com.amaze.fileutilities.home_page.ui.transfer.TransferFragment import com.amaze.fileutilities.utilis.PreferencesConstants import com.amaze.fileutilities.utilis.Utils import com.amaze.fileutilities.utilis.Utils.Companion.showProcessingDialog +import com.amaze.fileutilities.utilis.dialog_picker.FileFilter import com.amaze.fileutilities.utilis.getAppCommonSharedPreferences import com.amaze.fileutilities.utilis.getExternalStorageDirectory import com.amaze.fileutilities.utilis.getFileFromUri diff --git a/gradle.properties b/gradle.properties index b54dc1e4..40378899 100644 --- a/gradle.properties +++ b/gradle.properties @@ -25,7 +25,7 @@ kotlin.code.style=official org.gradle.parallel=true abiFilters=x86;x86_64;armeabi-v7a;arm64-v8a # for macs, omit for other operating systems -#org.gradle.java.home=/Applications/Android Studio.app/Contents/jbr/Contents/Home +org.gradle.java.home=/Applications/Android Studio.app/Contents/jbr/Contents/Home # https://github.com/usefulness/easylauncher-gradle-plugin/issues/408 android.disableResourceValidation=true \ No newline at end of file From 1675a3e4919a18cbb25f11fbbd5710586d6b9cc1 Mon Sep 17 00:00:00 2001 From: Vishal Nehra Date: Sun, 10 Dec 2023 17:36:34 +0530 Subject: [PATCH 5/5] Add support for jpeg xl --- app/build.gradle | 16 ++++-- app/src/main/AndroidManifest.xml | 3 +- .../IAudioPlayerInterfaceHandler.kt | 10 ++-- .../home_page/ui/files/FilesViewModel.kt | 57 +++++++++++++++++-- .../ui/files/MediaAdapterPreloader.kt | 10 ++-- .../home_page/ui/files/MediaFileAdapter.kt | 4 -- .../fileutilities/image_viewer/GlideModule.kt | 4 -- .../image_viewer/ImageViewerFragment.kt | 14 ++--- .../image_viewer/editor/EditImageActivity.kt | 24 ++++---- .../main/res/menu/generic_list_overflow.xml | 4 -- build.gradle | 2 + settings.gradle | 1 + 12 files changed, 95 insertions(+), 54 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b61da4d4..a83d0033 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,8 +1,8 @@ buildscript { ext { jacocoVersion = "0.8.7" - androidXLifecycleVersion = "2.3.1" - glideVersion = '4.11.0' + androidXLifecycleVersion = "2.6.1" + glideVersion = '4.16.0' fragment_version = "1.3.6" roomVersion = "2.4.0" billing_version = "6.0.1" @@ -39,6 +39,7 @@ plugins { id 'com.starter.easylauncher' id 'com.mikepenz.aboutlibraries.plugin' id 'org.jetbrains.kotlin.android' + id("com.google.devtools.ksp") } android { @@ -47,12 +48,12 @@ android { release } - compileSdk 33 + compileSdk 34 defaultConfig { applicationId "com.amaze.fileutilities" minSdk 21 - targetSdk 33 + targetSdk 34 Integer sudoVersionCode = 31 String versionNameText = "1.91" @@ -220,7 +221,7 @@ android { } dependencies { - implementation 'androidx.core:core:1.7.0' + implementation 'androidx.core:core:1.9.0' implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'com.google.android.material:material:1.6.1' @@ -231,12 +232,15 @@ dependencies { implementation 'androidx.palette:palette:1.0.0' //Glide: loads icons seemlessly implementation "com.github.bumptech.glide:glide:$glideVersion" + ksp("com.github.bumptech.glide:ksp:$glideVersion") implementation ("com.github.bumptech.glide:recyclerview-integration:$glideVersion") { // Excludes the support library because it's already included by Glide. transitive = false } + implementation("com.github.bumptech.glide:compose:1.0.0-alpha.5") playImplementation 'com.google.android.play:core-ktx:1.8.1' - kapt "com.github.bumptech.glide:compiler:$glideVersion" + implementation 'com.github.awxkee:avif-coder-glide:1.5.7' +// kapt "com.github.bumptech.glide:compiler:$glideVersion" implementation 'androidx.webkit:webkit:1.4.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.2' implementation 'androidx.vectordrawable:vectordrawable:1.1.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c43662cd..56e110dd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,7 +3,8 @@ xmlns:tools="http://schemas.android.com/tools"> + org.opencv, com.mikepenz.aboutlibraries, com.abedelazizshe.lightcompressorlibrary, + com.awxkee.avif.glide, com.github.awxkee.avifcoil, com.github.awxkee.avifcoder, androidx.emoji2" /> ?, + target: Target, isFirstResource: Boolean ): Boolean { // do nothing @@ -274,15 +274,15 @@ interface IAudioPlayerInterfaceHandler : OnPlaybackInfoUpdate, LifecycleOwner { } override fun onResourceReady( - resource: Drawable?, - model: Any?, + resource: Drawable, + model: Any, target: Target?, - dataSource: DataSource?, + dataSource: DataSource, isFirstResource: Boolean ): Boolean { getContextWeakRef().get()?.let { context -> - resource?.let { + resource.let { getAudioPlayerHandlerViewModel().getPaletteColor( it, context.getColor(R.color.navy_blue_alt_3) diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/FilesViewModel.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/FilesViewModel.kt index df694c43..5d26f08c 100644 --- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/FilesViewModel.kt +++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/FilesViewModel.kt @@ -39,8 +39,8 @@ import androidx.core.graphics.drawable.toBitmap import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.Transformations import androidx.lifecycle.liveData +import androidx.lifecycle.switchMap import androidx.lifecycle.viewModelScope import com.abedelazizshe.lightcompressorlibrary.CompressionListener import com.abedelazizshe.lightcompressorlibrary.VideoCompressor @@ -305,7 +305,7 @@ class FilesViewModel(val applicationContext: Application) : fun usedImagesSummaryTransformations(): LiveData>?> { if (usedImagesSummaryTransformations == null) { - usedImagesSummaryTransformations = Transformations.switchMap(internalStorageStats()) { + usedImagesSummaryTransformations = internalStorageStats().switchMap { input -> getImagesSummaryLiveData(input) } @@ -316,7 +316,7 @@ class FilesViewModel(val applicationContext: Application) : fun usedAudiosSummaryTransformations(): LiveData>?> { if (usedAudiosSummaryTransformations == null) { - usedAudiosSummaryTransformations = Transformations.switchMap(internalStorageStats()) { + usedAudiosSummaryTransformations = internalStorageStats().switchMap { input -> getAudiosSummaryLiveData(input) } @@ -328,7 +328,7 @@ class FilesViewModel(val applicationContext: Application) : LiveData>?> { if (usedPlaylistsSummaryTransformations == null) { usedPlaylistsSummaryTransformations = - Transformations.switchMap(internalStorageStats()) { + internalStorageStats().switchMap { input -> getPlaylistsSummaryLiveData(input) } @@ -339,7 +339,7 @@ class FilesViewModel(val applicationContext: Application) : fun usedVideosSummaryTransformations(): LiveData>?> { if (usedVideosSummaryTransformations == null) { - usedVideosSummaryTransformations = Transformations.switchMap(internalStorageStats()) { + usedVideosSummaryTransformations = internalStorageStats().switchMap { input -> getVideosSummaryLiveData(input) } @@ -350,7 +350,7 @@ class FilesViewModel(val applicationContext: Application) : fun usedDocsSummaryTransformations(): LiveData>?> { if (usedDocsSummaryTransformations == null) { - usedDocsSummaryTransformations = Transformations.switchMap(internalStorageStats()) { + usedDocsSummaryTransformations = internalStorageStats().switchMap { input -> getDocumentsSummaryLiveData(input) } @@ -2688,6 +2688,15 @@ class FilesViewModel(val applicationContext: Application) : } val metaInfoAndSummaryPair = CursorUtils .listImages(applicationContext.applicationContext) + val sortingPref = MediaFileListSorter.SortingPreference.newInstance( + applicationContext + .getAppCommonSharedPreferences(), + MediaFileAdapter.MEDIA_TYPE_IMAGES + ) + MediaFileListSorter.generateMediaFileListHeadersAndSort( + applicationContext, + metaInfoAndSummaryPair.second, sortingPref + ) setMediaInfoSummary(metaInfoAndSummaryPair.first, storageSummary) emit(metaInfoAndSummaryPair) } @@ -2727,6 +2736,15 @@ class FilesViewModel(val applicationContext: Application) : it.path } ) + val sortingPref = MediaFileListSorter.SortingPreference.newInstance( + applicationContext + .getAppCommonSharedPreferences(), + MediaFileAdapter.MEDIA_TYPE_AUDIO + ) + MediaFileListSorter.generateMediaFileListHeadersAndSort( + applicationContext, + metaInfoAndSummaryPair.second, sortingPref + ) setMediaInfoSummary(metaInfoAndSummaryPair.first, storageSummary) emit(metaInfoAndSummaryPair) metaInfoAndSummaryPair.second.forEach { @@ -2778,6 +2796,15 @@ class FilesViewModel(val applicationContext: Application) : } mediaStorageSummary?.let { setMediaInfoSummary(it, storageSummary) + val sortingPref = MediaFileListSorter.SortingPreference.newInstance( + applicationContext + .getAppCommonSharedPreferences(), + MediaFileAdapter.MEDIA_TYPE_AUDIO + ) + MediaFileListSorter.generateMediaFileListHeadersAndSort( + applicationContext, + playlistFiles, sortingPref + ) emit(Pair(it, playlistFiles)) playlistFiles.forEach { mediaFileInfo -> @@ -2803,6 +2830,15 @@ class FilesViewModel(val applicationContext: Application) : } val metaInfoAndSummaryPair = CursorUtils .listVideos(applicationContext.applicationContext) + val sortingPref = MediaFileListSorter.SortingPreference.newInstance( + applicationContext + .getAppCommonSharedPreferences(), + MediaFileAdapter.MEDIA_TYPE_VIDEO + ) + MediaFileListSorter.generateMediaFileListHeadersAndSort( + applicationContext, + metaInfoAndSummaryPair.second, sortingPref + ) setMediaInfoSummary(metaInfoAndSummaryPair.first, storageSummary) emit(metaInfoAndSummaryPair) } @@ -2839,6 +2875,15 @@ class FilesViewModel(val applicationContext: Application) : mediaFiles.add(mediaFileInfo) } val docsSummary = StorageSummary(size, 0, longSize) + val sortingPref = MediaFileListSorter.SortingPreference.newInstance( + applicationContext + .getAppCommonSharedPreferences(), + MediaFileAdapter.MEDIA_TYPE_DOCS + ) + MediaFileListSorter.generateMediaFileListHeadersAndSort( + applicationContext, + mediaFiles, sortingPref + ) emit(Pair(docsSummary, mediaFiles)) setMediaInfoSummary(docsSummary, storageSummary) } diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaAdapterPreloader.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaAdapterPreloader.kt index f4169228..f55eb4b1 100644 --- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaAdapterPreloader.kt +++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaAdapterPreloader.kt @@ -91,7 +91,7 @@ class MediaAdapterPreloader(private val context: Context, private val loadingDra override fun onLoadFailed( e: GlideException?, model: Any?, - target: Target?, + target: Target, isFirstResource: Boolean ): Boolean { if (isGrid) { @@ -101,10 +101,10 @@ class MediaAdapterPreloader(private val context: Context, private val loadingDra } override fun onResourceReady( - resource: Drawable?, - model: Any?, - target: Target?, - dataSource: DataSource?, + resource: Drawable, + model: Any, + target: Target, + dataSource: DataSource, isFirstResource: Boolean ): Boolean { // do nothing diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaFileAdapter.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaFileAdapter.kt index 748f5dac..029bc4ed 100644 --- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaFileAdapter.kt +++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaFileAdapter.kt @@ -83,10 +83,6 @@ class MediaFileAdapter( preloader.clear() onlyItemsCounts = 0 headerListItems.clear() - MediaFileListSorter.generateMediaFileListHeadersAndSort( - context, - mediaFileInfoList, sortingPreference - ) var lastHeader: String? = null value.add(ListItem(TYPE_BANNER)) preloader.addItem("") diff --git a/app/src/main/java/com/amaze/fileutilities/image_viewer/GlideModule.kt b/app/src/main/java/com/amaze/fileutilities/image_viewer/GlideModule.kt index 707822b0..ad56b06f 100644 --- a/app/src/main/java/com/amaze/fileutilities/image_viewer/GlideModule.kt +++ b/app/src/main/java/com/amaze/fileutilities/image_viewer/GlideModule.kt @@ -28,9 +28,5 @@ import com.bumptech.glide.module.AppGlideModule @GlideModule class GlideModule : AppGlideModule() { - override fun isManifestParsingEnabled() = false - override fun applyOptions(context: Context, builder: GlideBuilder) { - builder.setLogLevel(Log.ERROR) - } } diff --git a/app/src/main/java/com/amaze/fileutilities/image_viewer/ImageViewerFragment.kt b/app/src/main/java/com/amaze/fileutilities/image_viewer/ImageViewerFragment.kt index 312acfdc..1a62d9a3 100644 --- a/app/src/main/java/com/amaze/fileutilities/image_viewer/ImageViewerFragment.kt +++ b/app/src/main/java/com/amaze/fileutilities/image_viewer/ImageViewerFragment.kt @@ -658,7 +658,7 @@ class ImageViewerFragment : AbstractMediaFragment() { } _binding?.let { glide.into(it.imageView) - Glide.with(this).load(localTypeModel.uri.toString()) + Glide.with(this).load("https://wh.aimuse.online/preset/jxl_icc_12.bit.jxl") .thumbnail( Glide.with(this).load( resources.getDrawable(R.drawable.ic_outline_image_32) @@ -678,7 +678,7 @@ class ImageViewerFragment : AbstractMediaFragment() { override fun onLoadFailed( e: GlideException?, model: Any?, - target: Target?, + target: Target, isFirstResource: Boolean ): Boolean { // do nothing @@ -714,13 +714,13 @@ class ImageViewerFragment : AbstractMediaFragment() { } override fun onResourceReady( - resource: Drawable?, - model: Any?, - target: Target?, - dataSource: DataSource?, + resource: Drawable, + model: Any, + target: Target, + dataSource: DataSource, isFirstResource: Boolean ): Boolean { - resource?.let { + resource.let { filesViewModel.getPaletteColors(it) .observe(this@ImageViewerFragment) { colorPair -> diff --git a/app/src/main/java/com/amaze/fileutilities/image_viewer/editor/EditImageActivity.kt b/app/src/main/java/com/amaze/fileutilities/image_viewer/editor/EditImageActivity.kt index 91a6347c..ce79fd8a 100644 --- a/app/src/main/java/com/amaze/fileutilities/image_viewer/editor/EditImageActivity.kt +++ b/app/src/main/java/com/amaze/fileutilities/image_viewer/editor/EditImageActivity.kt @@ -202,7 +202,7 @@ class EditImageActivity : override fun onLoadFailed( e: GlideException?, model: Any?, - target: Target?, + target: Target, isFirstResource: Boolean ): Boolean { // do nothing @@ -211,13 +211,13 @@ class EditImageActivity : } override fun onResourceReady( - resource: Drawable?, - model: Any?, - target: Target?, - dataSource: DataSource?, + resource: Drawable, + model: Any, + target: Target, + dataSource: DataSource, isFirstResource: Boolean ): Boolean { - loadedBitmap = resource?.toBitmap() + loadedBitmap = resource.toBitmap() addFilterViews() return false } @@ -242,7 +242,7 @@ class EditImageActivity : override fun onLoadFailed( e: GlideException?, model: Any?, - target: Target?, + target: Target, isFirstResource: Boolean ): Boolean { // do nothing @@ -251,13 +251,13 @@ class EditImageActivity : } override fun onResourceReady( - resource: Drawable?, - model: Any?, - target: Target?, - dataSource: DataSource?, + resource: Drawable, + model: Any, + target: Target, + dataSource: DataSource, isFirstResource: Boolean ): Boolean { - loadedBitmap = resource?.toBitmap() + loadedBitmap = resource.toBitmap() addFilterViews() return false } diff --git a/app/src/main/res/menu/generic_list_overflow.xml b/app/src/main/res/menu/generic_list_overflow.xml index ac06b1ec..040c1622 100644 --- a/app/src/main/res/menu/generic_list_overflow.xml +++ b/app/src/main/res/menu/generic_list_overflow.xml @@ -12,8 +12,4 @@ android:id="@+id/delete" android:title="@string/delete" /> - \ No newline at end of file diff --git a/build.gradle b/build.gradle index 3dfb816a..69e53081 100644 --- a/build.gradle +++ b/build.gradle @@ -3,6 +3,7 @@ buildscript { repositories { google() mavenCentral() + gradlePluginPortal() } dependencies { classpath "com.android.tools.build:gradle:7.3.1" @@ -18,6 +19,7 @@ buildscript { plugins { id "com.diffplug.spotless" version "5.14.2" + id("com.google.devtools.ksp") version "1.8.10-1.0.9" apply false } allprojects { diff --git a/settings.gradle b/settings.gradle index 15e2be75..da886ee2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,6 +3,7 @@ dependencyResolutionManagement { repositories { google() mavenCentral() + gradlePluginPortal() jcenter() // Warning: this repository is going to shut down soon maven { url "https://jitpack.io" } maven { url "https://jcenter.bintray.com" }