From 11aa25ad45f4f466251a53c86e6e1eb0402091d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ensar=20Saraj=C4=8Di=C4=87?= Date: Fri, 21 Jul 2023 11:16:24 +0200 Subject: [PATCH 01/13] Make subfolder grouping follow file structure This changes subfolder grouping to follow file hierarchy to prevent unreliable behavior with middle folders missing media. This fixes #1886 --- .../gallery/pro/extensions/Context.kt | 140 ++++++++---------- 1 file changed, 64 insertions(+), 76 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt index fe01f1229..96e83c074 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt @@ -195,90 +195,83 @@ fun Context.getDirsToShow(dirs: ArrayList, allDirs: ArrayList, currentPathPrefix: String): ArrayList { val folders = dirs.map { it.path }.sorted().toMutableSet() as HashSet - val currentPaths = LinkedHashSet() - val foldersWithoutMediaFiles = ArrayList() + // Sort by path length, to ensure that parents get processed first + val foldersByPathLength = dirs.filter { currentPathPrefix.isEmpty() || (it.path.startsWith(currentPathPrefix, true) && it.path != currentPathPrefix) }.sortedBy { it.path.length } var newDirId = 1000L + val groups = mutableMapOf>() - for (path in folders) { - if (path == RECYCLE_BIN || path == FAVORITES) { - continue - } + for (folder in foldersByPathLength) { + val parent = groups.keys.firstOrNull { folder.path.startsWith(it, true) } + if (parent != null) { + // If we have parent in top level groups + // Add this folder to that group, + // but also add all folders in between which may not have media files + groups.getOrPut(parent, ::mutableListOf).apply { + var midParent = File(folder.path).parent + while (midParent != null && none { it.path.equals(midParent, true) }) { + val isSortingAscending = config.sorting.isSortingAscending() + val subDirs = dirs.filter { File(it.path).parent.equals(midParent, true) } as ArrayList + if (subDirs.isNotEmpty()) { + val lastModified = if (isSortingAscending) { + subDirs.minByOrNull { it.modified }?.modified + } else { + subDirs.maxByOrNull { it.modified }?.modified + } ?: 0 - if (currentPathPrefix.isNotEmpty()) { - if (!path.startsWith(currentPathPrefix, true)) { - continue - } + val dateTaken = if (isSortingAscending) { + subDirs.minByOrNull { it.taken }?.taken + } else { + subDirs.maxByOrNull { it.taken }?.taken + } ?: 0 - if (!File(path).parent.equals(currentPathPrefix, true)) { - continue - } - } + var mediaTypes = 0 + subDirs.forEach { + mediaTypes = mediaTypes or it.types + } - if (currentPathPrefix.isNotEmpty() && path.equals(currentPathPrefix, true) || File(path).parent.equals(currentPathPrefix, true)) { - currentPaths.add(path) - } else if (folders.any { !it.equals(path, true) && (File(path).parent.equals(it, true) || File(it).parent.equals(File(path).parent, true)) }) { - // if we have folders like - // /storage/emulated/0/Pictures/Images and - // /storage/emulated/0/Pictures/Screenshots, - // but /storage/emulated/0/Pictures is empty, still Pictures with the first folders thumbnails and proper other info - val parent = File(path).parent - if (parent != null && !folders.contains(parent) && dirs.none { it.path.equals(parent, true) }) { - currentPaths.add(parent) - val isSortingAscending = config.sorting.isSortingAscending() - val subDirs = dirs.filter { File(it.path).parent.equals(File(path).parent, true) } as ArrayList - if (subDirs.isNotEmpty()) { - val lastModified = if (isSortingAscending) { - subDirs.minByOrNull { it.modified }?.modified - } else { - subDirs.maxByOrNull { it.modified }?.modified - } ?: 0 + val directory = Directory( + newDirId++, + midParent, + subDirs.first().tmb, + getFolderNameFromPath(midParent), + subDirs.sumBy { it.mediaCnt }, + lastModified, + dateTaken, + subDirs.sumByLong { it.size }, + getPathLocation(midParent), + mediaTypes, + "" + ) - val dateTaken = if (isSortingAscending) { - subDirs.minByOrNull { it.taken }?.taken - } else { - subDirs.maxByOrNull { it.taken }?.taken - } ?: 0 - - var mediaTypes = 0 - subDirs.forEach { - mediaTypes = mediaTypes or it.types + directory.containsMediaFilesDirectly = false + dirs.add(directory) + add(directory) } - - val directory = Directory( - newDirId++, - parent, - subDirs.first().tmb, - getFolderNameFromPath(parent), - subDirs.sumBy { it.mediaCnt }, - lastModified, - dateTaken, - subDirs.sumByLong { it.size }, - getPathLocation(parent), - mediaTypes, - "" - ) - - directory.containsMediaFilesDirectly = false - dirs.add(directory) - currentPaths.add(parent) - foldersWithoutMediaFiles.add(parent) + midParent = File(midParent).parent } + add(folder) } } else { - currentPaths.add(path) - } - } - - var areDirectSubfoldersAvailable = false - currentPaths.forEach { - val path = it - currentPaths.forEach { - if (!foldersWithoutMediaFiles.contains(it) && !it.equals(path, true) && File(it).parent?.equals(path, true) == true) { - areDirectSubfoldersAvailable = true + // If we have don't have parent in top level groups + // Set this folder as top level group if it is direct child + if (currentPathPrefix.isEmpty() || File(folder.path).parent.equals(currentPathPrefix, true)) { + groups.getOrPut(folder.path, ::mutableListOf).add(folder) + } else { + // Otherwise find its parent which is a direct child of current path prefix + // And create a group for it + var firstVisibleParent = File(folder.path).parent + while (firstVisibleParent != null && !File(firstVisibleParent).parent.equals(currentPathPrefix, true)) { + firstVisibleParent = File(firstVisibleParent).parent + } + if (firstVisibleParent != null) { + groups.getOrPut(firstVisibleParent, ::mutableListOf).add(folder) + } } } } + val currentPaths = groups.keys.toMutableList() + if (currentPathPrefix.isEmpty() && folders.contains(RECYCLE_BIN)) { currentPaths.add(RECYCLE_BIN) } @@ -294,12 +287,7 @@ fun Context.getDirectParentSubfolders(dirs: ArrayList, currentPathPre folders.clear() folders.addAll(currentPaths) - val dirsToShow = dirs.filter { folders.contains(it.path) } as ArrayList - return if (areDirectSubfoldersAvailable) { - getDirectParentSubfolders(dirsToShow, currentPathPrefix) - } else { - dirsToShow - } + return dirs.filter { folders.contains(it.path) } as ArrayList } fun Context.updateSubfolderCounts(children: ArrayList, parentDirs: ArrayList) { From 92ea6d81388b0d187a525dc38166c01ad6ceb10b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ensar=20Saraj=C4=8Di=C4=87?= Date: Fri, 21 Jul 2023 15:27:07 +0200 Subject: [PATCH 02/13] Always use ARGB_8888 to avoid artifacts in images This closes #343 --- .../simplemobiletools/gallery/pro/fragments/PhotoFragment.kt | 2 +- .../gallery/pro/helpers/PicassoRegionDecoder.kt | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/PhotoFragment.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/PhotoFragment.kt index d094d4ba6..84da27361 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/PhotoFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/PhotoFragment.kt @@ -665,7 +665,7 @@ class PhotoFragment : ViewPagerFragment() { } val regionDecoder = object : DecoderFactory { - override fun make() = PicassoRegionDecoder(showHighestQuality, mScreenWidth, mScreenHeight, minTileDpi, mMedium.isHeic()) + override fun make() = PicassoRegionDecoder(showHighestQuality, mScreenWidth, mScreenHeight, minTileDpi) } var newOrientation = (rotation + mCurrentRotationDegrees) % 360 diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/PicassoRegionDecoder.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/PicassoRegionDecoder.kt index b3133327d..35a7c6cfc 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/PicassoRegionDecoder.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/PicassoRegionDecoder.kt @@ -9,8 +9,7 @@ class PicassoRegionDecoder( val showHighestQuality: Boolean, val screenWidth: Int, val screenHeight: Int, - val minTileDpi: Int, - val isHeic: Boolean + val minTileDpi: Int ) : ImageRegionDecoder { private var decoder: BitmapRegionDecoder? = null private val decoderLock = Any() @@ -35,7 +34,7 @@ class PicassoRegionDecoder( val options = BitmapFactory.Options() options.inSampleSize = newSampleSize - options.inPreferredConfig = if (showHighestQuality || isHeic) Bitmap.Config.ARGB_8888 else Bitmap.Config.RGB_565 + options.inPreferredConfig = Bitmap.Config.ARGB_8888 val bitmap = decoder!!.decodeRegion(rect, options) return bitmap ?: throw RuntimeException("Region decoder returned null bitmap - image format may not be supported") } From 762b712246d3d49886e894a5d113fd9b2ea4d287 Mon Sep 17 00:00:00 2001 From: Tibor Kaputa Date: Fri, 21 Jul 2023 21:33:13 +0200 Subject: [PATCH 03/13] minor code style update --- .../gallery/pro/extensions/Context.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt index 96e83c074..7072abedb 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt @@ -23,7 +23,6 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.RequestOptions -import com.bumptech.glide.request.target.Target import com.bumptech.glide.signature.ObjectKey import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.* @@ -136,6 +135,7 @@ fun Context.getSortedDirectories(source: ArrayList): ArrayList { if (o1.sortValue.isEmpty()) { o1.sortValue = o1.path.toLowerCase() @@ -151,6 +151,7 @@ fun Context.getSortedDirectories(source: ArrayList): ArrayList AlphanumericComparator().compare(o1.sortValue.toLowerCase(), o2.sortValue.toLowerCase()) sorting and SORT_BY_SIZE != 0 -> (o1.sortValue.toLongOrNull() ?: 0).compareTo(o2.sortValue.toLongOrNull() ?: 0) sorting and SORT_BY_DATE_MODIFIED != 0 -> (o1.sortValue.toLongOrNull() ?: 0).compareTo(o2.sortValue.toLongOrNull() ?: 0) @@ -196,7 +197,13 @@ fun Context.getDirsToShow(dirs: ArrayList, allDirs: ArrayList, currentPathPrefix: String): ArrayList { val folders = dirs.map { it.path }.sorted().toMutableSet() as HashSet // Sort by path length, to ensure that parents get processed first - val foldersByPathLength = dirs.filter { currentPathPrefix.isEmpty() || (it.path.startsWith(currentPathPrefix, true) && it.path != currentPathPrefix) }.sortedBy { it.path.length } + val foldersByPathLength = dirs.filter { + currentPathPrefix.isEmpty() || + (it.path.startsWith(currentPathPrefix, true) && it.path != currentPathPrefix) + }.sortedBy { + it.path.length + } + var newDirId = 1000L val groups = mutableMapOf>() From 6b847bef167721497c14b7fae1e455f4af18eded Mon Sep 17 00:00:00 2001 From: tibbi Date: Fri, 21 Jul 2023 21:39:40 +0200 Subject: [PATCH 04/13] updating commons --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index e7799fc94..2bb4e79b2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -78,7 +78,7 @@ android { } dependencies { - implementation 'com.github.SimpleMobileTools:Simple-Commons:571e8e3ef2' + implementation 'com.github.SimpleMobileTools:Simple-Commons:ae8713396b' implementation 'com.vanniktech:android-image-cropper:4.5.0' implementation 'it.sephiroth.android.exif:library:1.0.1' implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.25' From a2b1c67fc27f232efba6e949340213722d49527e Mon Sep 17 00:00:00 2001 From: elgratea Date: Fri, 14 Jul 2023 00:57:26 +0000 Subject: [PATCH 05/13] Translated using Weblate (Bulgarian) Currently translated at 100.0% (356 of 356 strings) Translation: Simple Mobile Tools/Simple Gallery Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-gallery/bg/ --- app/src/main/res/values-bg/strings.xml | 50 +++++++++++++------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 29272752d..3e0844c3d 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -5,7 +5,7 @@ Редакция Камера (скрито) - (excluded) + (изключено) Закачете папката Откачете папката Закачете отгоре @@ -54,7 +54,7 @@ Скрити папки Управление на скритите папки Изглежда нямате папки скрити чрез \'.nomedia\' файл. - You have to grant the app All Files access to see hidden files, else it cannot work. + Трябва да предоставите на приложението достъп до всички файлове, за да видите скритите файлове, в противен случай то не може да работи. Включени папки Управление на включените папки @@ -69,19 +69,19 @@ Височина Запазете съотношението на страните Моля въведете валидна резолюция - Resize multiple images - Resize factor - Resize images to the given percentage, value must be within 10 and 90. - Enter a number between 10 and 90 + Преоразмеряване на няколко изображения + Коефициент на преоразмеряване + Преоразмерете изображенията до дадения процент, стойността трябва да е в рамките на 10 и 90. + Въведете число между 10 и 90 - Failed to resize %d image - Failed to resize %d images + Преоразмеряването неуспешно за %d изображение + Преоразмеряването неуспешно за %d изображения - Images resized successfully + Изображенията са преоразмерени успешно Редактор - Basic Editor - Advanced Editor + Базов редактор + Разширен редактор Завъртане Неправилен път до изображението Неправилен път до видеото @@ -101,9 +101,9 @@ Завъртане наляво Завъртане надясно Завъртане на 180º - Transform - Crop - Draw + Трансформирай + Изрежи + Рисувай Oбръщане Хоризонтално обръщане Вертикално обръщане @@ -209,19 +209,19 @@ Ограничаване на заглавията на папките до един ред Квадрат Заоблени ъгли - Експортиране на пътищата на любимите файлове - Import favorites - Paths imported successfully + Експортиране на любимите + Импортиране на любими + Пътищата са импортирани успешно За да работят надеждно всички операции, моля задайте това приложение да управлява медията в настройките на вашето устройство. Защита на изключена папка с парола Нещо се обърка, моля, влезте в Настройки на вашето устройство - Приложения - Достъп до специални приложения - Приложения за управление на медии и разрешете на това приложение да управлява медиите. Ако пренасочването не работи, моля, влезте в Настройки на вашето устройство - Приложения - Достъп до специални приложения - Приложения за управление на медии и разрешете на това приложение да управлява медиите. - If you do not want to do it, you can also go into your device Settings - Apps - Special app access - Media management apps and allow this app to manage media. - Alternatively, you can allow accessing media files only. In that case you will not be able to work with hidden files though. - Media only - All files - Search all files instead of folders on the main screen - Show a menu button for toggling Show All Folders Content quickly + Ако не искате да го направите, можете също да отидете в Настройки на вашето устройство - Приложения - Специален достъп до приложения - Приложения за управление на медии и да разрешите на това приложение да управлява медии. + Като алтернатива можете да разрешите достъп само до медийни файлове. В този случай обаче няма да можете да работите със скрити файлове. + Само медия + Всички файлове + Търсете всички файлове вместо папки на главния екран + Показване на бутон на менюто за бързо превключване на Показване на съдържанието на всички папки Миниатюри Медия на цял екран @@ -374,7 +374,7 @@ Кешът на приложението може да отнеме до 250 MB, което гарантира по-бързо зареждане на изображението. Ако приложението заема още повече място, най-вероятно това е причинено от това, че имате елементи в кошчето. Тези файлове се броят към размера на приложението. Можете да изчистите кошчето, като го отворите и изтриете всички файлове или от настройките на приложението. Всеки файл в кошчето се изтрива автоматично след 30 дни. Какво се случи със скриването на файлове и папки и защо вече не мога да виждам скрити елементи\? Започвайки с Android 11, вече не можете да скривате или показвате файлове или папки, не можете да виждате скритите в приложения за галерия поради системни ограничения. За това ще трябва да използвате някакъв файлов мениджър. - Or you can also grant this gallery access to All Files through your device settings, that will allow us showing hidden items and make file operations more reliable in general. + Или можете също да предоставите на тази галерия достъп до всички файлове през настройките на вашето устройство, което ще ни позволи да показваме скрити елементи и ще направи файловите операции по-надеждни като цяло. Защо вече не мога да добавя липсващи папки\? Това спря да работи поради системните промени, които дойдоха и с Android 11, приложението вече не може да преглежда истински папки, разчита на така наречения MediaStore при извличане на данни. Защо виждам реклами по време на възпроизвеждане на видео\? @@ -383,4 +383,4 @@ Haven't found some strings? There's more at https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res --> - + \ No newline at end of file From bd592e1ca8064b0fb1e8e8ab98143b67b7182a38 Mon Sep 17 00:00:00 2001 From: abc0922001 Date: Mon, 17 Jul 2023 03:16:27 +0000 Subject: [PATCH 06/13] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (356 of 356 strings) Translation: Simple Mobile Tools/Simple Gallery Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-gallery/zh_Hant/ --- app/src/main/res/values-zh-rTW/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 314f5874f..b0f2ba8e5 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -213,7 +213,7 @@ Import favorites Paths imported successfully To make sure that all file operations work reliably, please make this app a Media management app in your device settings. - Password protect excluded folder visibility + 設定密碼保護,隱藏不顯示的資料夾 出錯了,請至裝置的設定 - 應用程式(和通知) - 特殊應用程式存取權 - 媒體管理應用程式,允許本 app 管理媒體。 若重新導向未順利運作,請至裝置的設定 - 應用程式(和通知) - 特殊應用程式存取權 - 媒體管理應用程式,允許本 app 管理媒體。 If you do not want to do it, you can also go into your device Settings - Apps - Special app access - Media management apps and allow this app to manage media. @@ -384,4 +384,4 @@ Haven't found some strings? There's more at https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res --> - + \ No newline at end of file From 6f9ae7f030548986dd27f3dc0508f927163fa2c1 Mon Sep 17 00:00:00 2001 From: spkprs Date: Sat, 22 Jul 2023 12:56:01 +0300 Subject: [PATCH 07/13] Update strings.xml --- app/src/main/res/values-el/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 1840f3e1a..93830fadf 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -74,8 +74,8 @@ Αλλάξτε το μέγεθος των εικόνων στο δεδομένο ποσοστό. Η τιμή πρέπει να είναι μεταξύ 10 και 90. Εισάγετε έναν αριθμό μεταξύ 10 και 90 - Αποτυχία αλλαγής μεγέθους εικόνας %d - Αποτυχία αλλαγής μεγέθους εικόνων %d + Αποτυχία αλλαγής μεγέθους %d εικόνας + Αποτυχία αλλαγής μεγέθους %d εικόνων Το μέγεθος των εικόνων άλλαξε με επιτυχία @@ -384,4 +384,4 @@ Haven't found some strings? There's more at https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res --> - \ No newline at end of file + From a9210c5a1bfebb06b11203258a78aad72121c5bf Mon Sep 17 00:00:00 2001 From: yangfeng <1719957182@qq.com> Date: Sat, 22 Jul 2023 20:02:08 +0800 Subject: [PATCH 08/13] fix: lack of import statement --- .../com/simplemobiletools/gallery/pro/extensions/Context.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt index 7072abedb..4bca91b8c 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt @@ -23,6 +23,7 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.RequestOptions +import com.bumptech.glide.request.target.Target import com.bumptech.glide.signature.ObjectKey import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.* From 8aaab1eed3e9ba8f78fb0b6680f4d6c498e972c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ensar=20Saraj=C4=8Di=C4=87?= Date: Mon, 24 Jul 2023 08:26:34 +0200 Subject: [PATCH 09/13] Migrate to media3-exoplayer --- app/build.gradle | 2 +- .../pro/activities/VideoPlayerActivity.kt | 21 +++++++++-------- .../gallery/pro/fragments/VideoFragment.kt | 23 ++++++++++--------- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index e7799fc94..020cac216 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -83,7 +83,7 @@ dependencies { implementation 'it.sephiroth.android.exif:library:1.0.1' implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.25' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'com.google.android.exoplayer:exoplayer-core:2.18.7' + implementation 'androidx.media3:media3-exoplayer:1.1.0' implementation 'com.google.vr:sdk-panowidget:1.180.0' implementation 'com.google.vr:sdk-videowidget:1.180.0' implementation 'org.apache.sanselan:sanselan:0.97-incubator' diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/VideoPlayerActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/VideoPlayerActivity.kt index efc01f962..af22ede1d 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/VideoPlayerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/VideoPlayerActivity.kt @@ -15,15 +15,16 @@ import android.util.DisplayMetrics import android.view.* import android.widget.RelativeLayout import android.widget.SeekBar -import com.google.android.exoplayer2.* -import com.google.android.exoplayer2.audio.AudioAttributes -import com.google.android.exoplayer2.source.DefaultMediaSourceFactory -import com.google.android.exoplayer2.source.MediaSource -import com.google.android.exoplayer2.source.ProgressiveMediaSource -import com.google.android.exoplayer2.upstream.ContentDataSource -import com.google.android.exoplayer2.upstream.DataSource -import com.google.android.exoplayer2.upstream.DataSpec -import com.google.android.exoplayer2.video.VideoSize +import androidx.media3.common.* +import androidx.media3.common.util.UnstableApi +import androidx.media3.datasource.ContentDataSource +import androidx.media3.datasource.DataSource +import androidx.media3.datasource.DataSpec +import androidx.media3.exoplayer.ExoPlayer +import androidx.media3.exoplayer.SeekParameters +import androidx.media3.exoplayer.source.DefaultMediaSourceFactory +import androidx.media3.exoplayer.source.MediaSource +import androidx.media3.exoplayer.source.ProgressiveMediaSource import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.extensions.* @@ -31,7 +32,7 @@ import com.simplemobiletools.gallery.pro.helpers.* import kotlinx.android.synthetic.main.activity_video_player.* import kotlinx.android.synthetic.main.bottom_video_time_holder.* -open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListener, TextureView.SurfaceTextureListener { +@UnstableApi open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListener, TextureView.SurfaceTextureListener { private val PLAY_WHEN_READY_DRAG_DELAY = 100L private var mIsFullscreen = false diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt index af8deaccf..3a4573dc2 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt @@ -13,17 +13,18 @@ import android.widget.ImageView import android.widget.RelativeLayout import android.widget.SeekBar import android.widget.TextView +import androidx.media3.common.* +import androidx.media3.common.util.UnstableApi import com.bumptech.glide.Glide -import com.google.android.exoplayer2.* -import com.google.android.exoplayer2.audio.AudioAttributes -import com.google.android.exoplayer2.source.DefaultMediaSourceFactory -import com.google.android.exoplayer2.source.MediaSource -import com.google.android.exoplayer2.source.ProgressiveMediaSource -import com.google.android.exoplayer2.upstream.ContentDataSource -import com.google.android.exoplayer2.upstream.DataSource -import com.google.android.exoplayer2.upstream.DataSpec -import com.google.android.exoplayer2.upstream.FileDataSource -import com.google.android.exoplayer2.video.VideoSize +import androidx.media3.datasource.ContentDataSource +import androidx.media3.datasource.DataSource +import androidx.media3.datasource.DataSpec +import androidx.media3.datasource.FileDataSource +import androidx.media3.exoplayer.ExoPlayer +import androidx.media3.exoplayer.SeekParameters +import androidx.media3.exoplayer.source.DefaultMediaSourceFactory +import androidx.media3.exoplayer.source.MediaSource +import androidx.media3.exoplayer.source.ProgressiveMediaSource import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.gallery.pro.R @@ -40,7 +41,7 @@ import kotlinx.android.synthetic.main.pager_video_item.view.* import java.io.File import java.io.FileInputStream -class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, SeekBar.OnSeekBarChangeListener { +@UnstableApi class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, SeekBar.OnSeekBarChangeListener { private val PROGRESS = "progress" private var mIsFullscreen = false From 566cbd87650522c4eb788b8b2bb179b35c2bdda3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ensar=20Saraj=C4=8Di=C4=87?= Date: Mon, 24 Jul 2023 08:39:09 +0200 Subject: [PATCH 10/13] Fix an issue with inaccurate video resume This closes #2750 --- .../com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt index 3a4573dc2..a6baa9369 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt @@ -674,7 +674,6 @@ import java.io.FileInputStream mPlayPauseButton.setImageResource(R.drawable.ic_play_outline_vector) activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) mPositionAtPause = mExoPlayer?.currentPosition ?: 0L - releaseExoPlayer() } private fun videoEnded(): Boolean { From 39b6f4bbafe81126df2fc642d69ee42fe600b353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ensar=20Saraj=C4=8Di=C4=87?= Date: Mon, 24 Jul 2023 09:54:26 +0200 Subject: [PATCH 11/13] Handle password protection when copying/moving folders This changes copy and move handling to work similarly to delete. It will ask for protection if single folder is selected and it will ignore protected folders if multiple are selected. This closes #2901 --- .../gallery/pro/adapters/DirectoryAdapter.kt | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/DirectoryAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/DirectoryAdapter.kt index dab4b2eab..11e60afef 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/DirectoryAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/DirectoryAdapter.kt @@ -52,6 +52,7 @@ import kotlinx.android.synthetic.main.directory_item_list.view.dir_holder import kotlinx.android.synthetic.main.directory_item_list.view.photo_cnt import java.io.File import java.util.* +import kotlin.collections.ArrayList class DirectoryAdapter( activity: BaseSimpleActivity, var dirs: ArrayList, val listener: DirectoryOperationsListener?, recyclerView: MyRecyclerView, @@ -152,7 +153,7 @@ class DirectoryAdapter( R.id.cab_exclude -> tryExcludeFolder() R.id.cab_lock -> tryLockFolder() R.id.cab_unlock -> unlockFolder() - R.id.cab_copy_to -> copyMoveTo(true) + R.id.cab_copy_to -> copyFilesTo() R.id.cab_move_to -> moveFilesTo() R.id.cab_select_all -> selectAll() R.id.cab_create_shortcut -> tryCreateShortcut() @@ -505,16 +506,24 @@ class DirectoryAdapter( } } - private fun moveFilesTo() { - activity.handleDeletePasswordProtection { - copyMoveTo(false) + private fun copyFilesTo() { + handleLockedFolderOpeningForFolders(getSelectedPaths()) { + copyMoveTo(it, true) } } - private fun copyMoveTo(isCopyOperation: Boolean) { + private fun moveFilesTo() { + activity.handleDeletePasswordProtection { + handleLockedFolderOpeningForFolders(getSelectedPaths()) { + copyMoveTo(it, false) + } + } + } + + private fun copyMoveTo(selectedPaths: Collection, isCopyOperation: Boolean) { val paths = ArrayList() val showHidden = config.shouldShowHidden - getSelectedPaths().forEach { + selectedPaths.forEach { val filter = config.filterMedia File(it).listFiles()?.filter { !File(it.absolutePath).isDirectory && @@ -583,6 +592,7 @@ class DirectoryAdapter( config.isDeletePasswordProtectionOn -> activity.handleDeletePasswordProtection { deleteFolders() } + config.skipDeleteConfirmation -> deleteFolders() else -> { val itemsCnt = selectedKeys.size @@ -654,20 +664,26 @@ class DirectoryAdapter( } } - if (foldersToDelete.size == 1) { - activity.handleLockedFolderOpening(foldersToDelete.first().absolutePath) { success -> - if (success) { - listener?.deleteFolders(foldersToDelete) - } - } - } else { - foldersToDelete = foldersToDelete.filter { !config.isFolderProtected(it.absolutePath) }.toMutableList() as ArrayList - listener?.deleteFolders(foldersToDelete) + handleLockedFolderOpeningForFolders(foldersToDelete.map { it.absolutePath }) { + listener?.deleteFolders(it.map { File(it) }.toMutableList() as ArrayList) } } } } + private fun handleLockedFolderOpeningForFolders(folders: Collection, callback: (Collection) -> Unit) { + if (folders.size == 1) { + activity.handleLockedFolderOpening(folders.first()) { success -> + if (success) { + callback(folders) + } + } + } else { + val filtered = folders.filter { !config.isFolderProtected(it) } + callback(filtered) + } + } + private fun tryChangeAlbumCover(useDefault: Boolean) { activity.handleLockedFolderOpening(getFirstSelectedItemPath() ?: "") { success -> if (success) { From 272093f533d4005300d58db34fe10e10f9e12297 Mon Sep 17 00:00:00 2001 From: tibbi Date: Mon, 24 Jul 2023 11:42:09 +0200 Subject: [PATCH 12/13] adding an empty line --- .../simplemobiletools/gallery/pro/dialogs/PickDirectoryDialog.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/PickDirectoryDialog.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/PickDirectoryDialog.kt index f6d7cc5e7..438c005c9 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/PickDirectoryDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/PickDirectoryDialog.kt @@ -105,6 +105,7 @@ class PickDirectoryDialog( onSearchOpenListener = { updateSearchViewLeftIcon(R.drawable.ic_cross_vector) } + onSearchClosedListener = { searchEditText.clearFocus() activity.hideKeyboard(searchEditText) From 19a500f55275e2406f1c5603ee2b5ca0824aed98 Mon Sep 17 00:00:00 2001 From: fatih ergin Date: Tue, 25 Jul 2023 00:59:14 +0300 Subject: [PATCH 13/13] hide skip recycle bin option on delete dialog if file is already in recycle bin --- .../gallery/pro/activities/ViewPagerActivity.kt | 7 +++++-- .../simplemobiletools/gallery/pro/adapters/MediaAdapter.kt | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt index 585fe2df2..eb6e2c94a 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt @@ -1070,15 +1070,18 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View val size = fileDirItem.getProperSize(this, countHidden = true).formatSize() val filename = "\"${getCurrentPath().getFilenameFromPath()}\"" val filenameAndSize = "$filename ($size)" + val isInRecycleBin = getCurrentMedium()!!.getIsInRecycleBin() - val baseString = if (config.useRecycleBin && !config.tempSkipRecycleBin && !getCurrentMedium()!!.getIsInRecycleBin()) { + val baseString = if (config.useRecycleBin && !config.tempSkipRecycleBin && !isInRecycleBin) { R.string.move_to_recycle_bin_confirmation } else { R.string.deletion_confirmation } val message = String.format(resources.getString(baseString), filenameAndSize) - DeleteWithRememberDialog(this, message, config.useRecycleBin) { remember, skipRecycleBin -> + val showSkipRecycleBinOption = config.useRecycleBin && !isInRecycleBin + + DeleteWithRememberDialog(this, message, showSkipRecycleBinOption) { remember, skipRecycleBin -> config.tempSkipDeleteConfirmation = remember if (remember) { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt index 13bf88b8a..027eedf23 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt @@ -508,8 +508,9 @@ class MediaAdapter( val baseString = if (config.useRecycleBin && !config.tempSkipRecycleBin && !isRecycleBin) R.string.move_to_recycle_bin_confirmation else R.string.deletion_confirmation val question = String.format(resources.getString(baseString), itemsAndSize) + val showSkipRecycleBinOption = config.useRecycleBin && !isRecycleBin - DeleteWithRememberDialog(activity, question, config.useRecycleBin) { remember, skipRecycleBin -> + DeleteWithRememberDialog(activity, question, showSkipRecycleBinOption) { remember, skipRecycleBin -> config.tempSkipDeleteConfirmation = remember if (remember) {