Merge branch 'master' into fix/hiding-ux

This commit is contained in:
Tibor Kaputa 2023-07-25 09:30:40 +02:00 committed by GitHub
commit b9f762e1e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 167 additions and 151 deletions

View file

@ -78,12 +78,12 @@ android {
} }
dependencies { 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 'com.vanniktech:android-image-cropper:4.5.0'
implementation 'it.sephiroth.android.exif:library:1.0.1' implementation 'it.sephiroth.android.exif:library:1.0.1'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.25' implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.25'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 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-panowidget:1.180.0'
implementation 'com.google.vr:sdk-videowidget:1.180.0' implementation 'com.google.vr:sdk-videowidget:1.180.0'
implementation 'org.apache.sanselan:sanselan:0.97-incubator' implementation 'org.apache.sanselan:sanselan:0.97-incubator'

View file

@ -15,15 +15,16 @@ import android.util.DisplayMetrics
import android.view.* import android.view.*
import android.widget.RelativeLayout import android.widget.RelativeLayout
import android.widget.SeekBar import android.widget.SeekBar
import com.google.android.exoplayer2.* import androidx.media3.common.*
import com.google.android.exoplayer2.audio.AudioAttributes import androidx.media3.common.util.UnstableApi
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory import androidx.media3.datasource.ContentDataSource
import com.google.android.exoplayer2.source.MediaSource import androidx.media3.datasource.DataSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource import androidx.media3.datasource.DataSpec
import com.google.android.exoplayer2.upstream.ContentDataSource import androidx.media3.exoplayer.ExoPlayer
import com.google.android.exoplayer2.upstream.DataSource import androidx.media3.exoplayer.SeekParameters
import com.google.android.exoplayer2.upstream.DataSpec import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
import com.google.android.exoplayer2.video.VideoSize import androidx.media3.exoplayer.source.MediaSource
import androidx.media3.exoplayer.source.ProgressiveMediaSource
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.R
import com.simplemobiletools.gallery.pro.extensions.* 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.activity_video_player.*
import kotlinx.android.synthetic.main.bottom_video_time_holder.* 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 val PLAY_WHEN_READY_DRAG_DELAY = 100L
private var mIsFullscreen = false private var mIsFullscreen = false

View file

@ -1070,15 +1070,18 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
val size = fileDirItem.getProperSize(this, countHidden = true).formatSize() val size = fileDirItem.getProperSize(this, countHidden = true).formatSize()
val filename = "\"${getCurrentPath().getFilenameFromPath()}\"" val filename = "\"${getCurrentPath().getFilenameFromPath()}\""
val filenameAndSize = "$filename ($size)" 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 R.string.move_to_recycle_bin_confirmation
} else { } else {
R.string.deletion_confirmation R.string.deletion_confirmation
} }
val message = String.format(resources.getString(baseString), filenameAndSize) 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 config.tempSkipDeleteConfirmation = remember
if (remember) { if (remember) {

View file

@ -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 kotlinx.android.synthetic.main.directory_item_list.view.photo_cnt
import java.io.File import java.io.File
import java.util.* import java.util.*
import kotlin.collections.ArrayList
class DirectoryAdapter( class DirectoryAdapter(
activity: BaseSimpleActivity, var dirs: ArrayList<Directory>, val listener: DirectoryOperationsListener?, recyclerView: MyRecyclerView, activity: BaseSimpleActivity, var dirs: ArrayList<Directory>, val listener: DirectoryOperationsListener?, recyclerView: MyRecyclerView,
@ -152,7 +153,7 @@ class DirectoryAdapter(
R.id.cab_exclude -> tryExcludeFolder() R.id.cab_exclude -> tryExcludeFolder()
R.id.cab_lock -> tryLockFolder() R.id.cab_lock -> tryLockFolder()
R.id.cab_unlock -> unlockFolder() 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_move_to -> moveFilesTo()
R.id.cab_select_all -> selectAll() R.id.cab_select_all -> selectAll()
R.id.cab_create_shortcut -> tryCreateShortcut() R.id.cab_create_shortcut -> tryCreateShortcut()
@ -510,16 +511,24 @@ class DirectoryAdapter(
} }
} }
private fun moveFilesTo() { private fun copyFilesTo() {
activity.handleDeletePasswordProtection { handleLockedFolderOpeningForFolders(getSelectedPaths()) {
copyMoveTo(false) copyMoveTo(it, true)
} }
} }
private fun copyMoveTo(isCopyOperation: Boolean) { private fun moveFilesTo() {
activity.handleDeletePasswordProtection {
handleLockedFolderOpeningForFolders(getSelectedPaths()) {
copyMoveTo(it, false)
}
}
}
private fun copyMoveTo(selectedPaths: Collection<String>, isCopyOperation: Boolean) {
val paths = ArrayList<String>() val paths = ArrayList<String>()
val showHidden = config.shouldShowHidden val showHidden = config.shouldShowHidden
getSelectedPaths().forEach { selectedPaths.forEach {
val filter = config.filterMedia val filter = config.filterMedia
File(it).listFiles()?.filter { File(it).listFiles()?.filter {
!File(it.absolutePath).isDirectory && !File(it.absolutePath).isDirectory &&
@ -660,17 +669,23 @@ class DirectoryAdapter(
} }
} }
if (foldersToDelete.size == 1) { handleLockedFolderOpeningForFolders(foldersToDelete.map { it.absolutePath }) {
activity.handleLockedFolderOpening(foldersToDelete.first().absolutePath) { success -> listener?.deleteFolders(it.map { File(it) }.toMutableList() as ArrayList<File>)
}
}
}
}
private fun handleLockedFolderOpeningForFolders(folders: Collection<String>, callback: (Collection<String>) -> Unit) {
if (folders.size == 1) {
activity.handleLockedFolderOpening(folders.first()) { success ->
if (success) { if (success) {
listener?.deleteFolders(foldersToDelete) callback(folders)
} }
} }
} else { } else {
foldersToDelete = foldersToDelete.filter { !config.isFolderProtected(it.absolutePath) }.toMutableList() as ArrayList<File> val filtered = folders.filter { !config.isFolderProtected(it) }
listener?.deleteFolders(foldersToDelete) callback(filtered)
}
}
} }
} }

View file

@ -508,8 +508,9 @@ class MediaAdapter(
val baseString = val baseString =
if (config.useRecycleBin && !config.tempSkipRecycleBin && !isRecycleBin) R.string.move_to_recycle_bin_confirmation else R.string.deletion_confirmation 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 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 config.tempSkipDeleteConfirmation = remember
if (remember) { if (remember) {

View file

@ -105,6 +105,7 @@ class PickDirectoryDialog(
onSearchOpenListener = { onSearchOpenListener = {
updateSearchViewLeftIcon(R.drawable.ic_cross_vector) updateSearchViewLeftIcon(R.drawable.ic_cross_vector)
} }
onSearchClosedListener = { onSearchClosedListener = {
searchEditText.clearFocus() searchEditText.clearFocus()
activity.hideKeyboard(searchEditText) activity.hideKeyboard(searchEditText)

View file

@ -136,6 +136,7 @@ fun Context.getSortedDirectories(source: ArrayList<Directory>): ArrayList<Direct
o1.sortValue.normalizeString().toLowerCase().compareTo(o2.sortValue.normalizeString().toLowerCase()) o1.sortValue.normalizeString().toLowerCase().compareTo(o2.sortValue.normalizeString().toLowerCase())
} }
} }
sorting and SORT_BY_PATH != 0 -> { sorting and SORT_BY_PATH != 0 -> {
if (o1.sortValue.isEmpty()) { if (o1.sortValue.isEmpty()) {
o1.sortValue = o1.path.toLowerCase() o1.sortValue = o1.path.toLowerCase()
@ -151,6 +152,7 @@ fun Context.getSortedDirectories(source: ArrayList<Directory>): ArrayList<Direct
o1.sortValue.toLowerCase().compareTo(o2.sortValue.toLowerCase()) o1.sortValue.toLowerCase().compareTo(o2.sortValue.toLowerCase())
} }
} }
sorting and SORT_BY_PATH != 0 -> AlphanumericComparator().compare(o1.sortValue.toLowerCase(), o2.sortValue.toLowerCase()) sorting and SORT_BY_PATH != 0 -> 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_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) sorting and SORT_BY_DATE_MODIFIED != 0 -> (o1.sortValue.toLongOrNull() ?: 0).compareTo(o2.sortValue.toLongOrNull() ?: 0)
@ -195,37 +197,28 @@ fun Context.getDirsToShow(dirs: ArrayList<Directory>, allDirs: ArrayList<Directo
fun Context.getDirectParentSubfolders(dirs: ArrayList<Directory>, currentPathPrefix: String): ArrayList<Directory> { fun Context.getDirectParentSubfolders(dirs: ArrayList<Directory>, currentPathPrefix: String): ArrayList<Directory> {
val folders = dirs.map { it.path }.sorted().toMutableSet() as HashSet<String> val folders = dirs.map { it.path }.sorted().toMutableSet() as HashSet<String>
val currentPaths = LinkedHashSet<String>() // Sort by path length, to ensure that parents get processed first
val foldersWithoutMediaFiles = ArrayList<String>() val foldersByPathLength = dirs.filter {
currentPathPrefix.isEmpty() ||
(it.path.startsWith(currentPathPrefix, true) && it.path != currentPathPrefix)
}.sortedBy {
it.path.length
}
var newDirId = 1000L var newDirId = 1000L
val groups = mutableMapOf<String, MutableList<Directory>>()
for (path in folders) { for (folder in foldersByPathLength) {
if (path == RECYCLE_BIN || path == FAVORITES) { val parent = groups.keys.firstOrNull { folder.path.startsWith(it, true) }
continue if (parent != null) {
} // If we have parent in top level groups
// Add this folder to that group,
if (currentPathPrefix.isNotEmpty()) { // but also add all folders in between which may not have media files
if (!path.startsWith(currentPathPrefix, true)) { groups.getOrPut(parent, ::mutableListOf).apply {
continue var midParent = File(folder.path).parent
} while (midParent != null && none { it.path.equals(midParent, true) }) {
if (!File(path).parent.equals(currentPathPrefix, true)) {
continue
}
}
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 isSortingAscending = config.sorting.isSortingAscending()
val subDirs = dirs.filter { File(it.path).parent.equals(File(path).parent, true) } as ArrayList<Directory> val subDirs = dirs.filter { File(it.path).parent.equals(midParent, true) } as ArrayList<Directory>
if (subDirs.isNotEmpty()) { if (subDirs.isNotEmpty()) {
val lastModified = if (isSortingAscending) { val lastModified = if (isSortingAscending) {
subDirs.minByOrNull { it.modified }?.modified subDirs.minByOrNull { it.modified }?.modified
@ -246,38 +239,46 @@ fun Context.getDirectParentSubfolders(dirs: ArrayList<Directory>, currentPathPre
val directory = Directory( val directory = Directory(
newDirId++, newDirId++,
parent, midParent,
subDirs.first().tmb, subDirs.first().tmb,
getFolderNameFromPath(parent), getFolderNameFromPath(midParent),
subDirs.sumBy { it.mediaCnt }, subDirs.sumBy { it.mediaCnt },
lastModified, lastModified,
dateTaken, dateTaken,
subDirs.sumByLong { it.size }, subDirs.sumByLong { it.size },
getPathLocation(parent), getPathLocation(midParent),
mediaTypes, mediaTypes,
"" ""
) )
directory.containsMediaFilesDirectly = false directory.containsMediaFilesDirectly = false
dirs.add(directory) dirs.add(directory)
currentPaths.add(parent) add(directory)
foldersWithoutMediaFiles.add(parent)
} }
midParent = File(midParent).parent
}
add(folder)
} }
} else { } else {
currentPaths.add(path) // 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)
}
}
} }
} }
var areDirectSubfoldersAvailable = false val currentPaths = groups.keys.toMutableList()
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 (currentPathPrefix.isEmpty() && folders.contains(RECYCLE_BIN)) { if (currentPathPrefix.isEmpty() && folders.contains(RECYCLE_BIN)) {
currentPaths.add(RECYCLE_BIN) currentPaths.add(RECYCLE_BIN)
@ -294,12 +295,7 @@ fun Context.getDirectParentSubfolders(dirs: ArrayList<Directory>, currentPathPre
folders.clear() folders.clear()
folders.addAll(currentPaths) folders.addAll(currentPaths)
val dirsToShow = dirs.filter { folders.contains(it.path) } as ArrayList<Directory> return dirs.filter { folders.contains(it.path) } as ArrayList<Directory>
return if (areDirectSubfoldersAvailable) {
getDirectParentSubfolders(dirsToShow, currentPathPrefix)
} else {
dirsToShow
}
} }
fun Context.updateSubfolderCounts(children: ArrayList<Directory>, parentDirs: ArrayList<Directory>) { fun Context.updateSubfolderCounts(children: ArrayList<Directory>, parentDirs: ArrayList<Directory>) {

View file

@ -665,7 +665,7 @@ class PhotoFragment : ViewPagerFragment() {
} }
val regionDecoder = object : DecoderFactory<ImageRegionDecoder> { val regionDecoder = object : DecoderFactory<ImageRegionDecoder> {
override fun make() = PicassoRegionDecoder(showHighestQuality, mScreenWidth, mScreenHeight, minTileDpi, mMedium.isHeic()) override fun make() = PicassoRegionDecoder(showHighestQuality, mScreenWidth, mScreenHeight, minTileDpi)
} }
var newOrientation = (rotation + mCurrentRotationDegrees) % 360 var newOrientation = (rotation + mCurrentRotationDegrees) % 360

View file

@ -13,17 +13,18 @@ import android.widget.ImageView
import android.widget.RelativeLayout import android.widget.RelativeLayout
import android.widget.SeekBar import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import androidx.media3.common.*
import androidx.media3.common.util.UnstableApi
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.google.android.exoplayer2.* import androidx.media3.datasource.ContentDataSource
import com.google.android.exoplayer2.audio.AudioAttributes import androidx.media3.datasource.DataSource
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory import androidx.media3.datasource.DataSpec
import com.google.android.exoplayer2.source.MediaSource import androidx.media3.datasource.FileDataSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource import androidx.media3.exoplayer.ExoPlayer
import com.google.android.exoplayer2.upstream.ContentDataSource import androidx.media3.exoplayer.SeekParameters
import com.google.android.exoplayer2.upstream.DataSource import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
import com.google.android.exoplayer2.upstream.DataSpec import androidx.media3.exoplayer.source.MediaSource
import com.google.android.exoplayer2.upstream.FileDataSource import androidx.media3.exoplayer.source.ProgressiveMediaSource
import com.google.android.exoplayer2.video.VideoSize
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.gallery.pro.R 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.File
import java.io.FileInputStream import java.io.FileInputStream
class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, SeekBar.OnSeekBarChangeListener { @UnstableApi class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, SeekBar.OnSeekBarChangeListener {
private val PROGRESS = "progress" private val PROGRESS = "progress"
private var mIsFullscreen = false private var mIsFullscreen = false
@ -673,7 +674,6 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
mPlayPauseButton.setImageResource(R.drawable.ic_play_outline_vector) mPlayPauseButton.setImageResource(R.drawable.ic_play_outline_vector)
activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
mPositionAtPause = mExoPlayer?.currentPosition ?: 0L mPositionAtPause = mExoPlayer?.currentPosition ?: 0L
releaseExoPlayer()
} }
private fun videoEnded(): Boolean { private fun videoEnded(): Boolean {

View file

@ -9,8 +9,7 @@ class PicassoRegionDecoder(
val showHighestQuality: Boolean, val showHighestQuality: Boolean,
val screenWidth: Int, val screenWidth: Int,
val screenHeight: Int, val screenHeight: Int,
val minTileDpi: Int, val minTileDpi: Int
val isHeic: Boolean
) : ImageRegionDecoder { ) : ImageRegionDecoder {
private var decoder: BitmapRegionDecoder? = null private var decoder: BitmapRegionDecoder? = null
private val decoderLock = Any() private val decoderLock = Any()
@ -35,7 +34,7 @@ class PicassoRegionDecoder(
val options = BitmapFactory.Options() val options = BitmapFactory.Options()
options.inSampleSize = newSampleSize 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) val bitmap = decoder!!.decodeRegion(rect, options)
return bitmap ?: throw RuntimeException("Region decoder returned null bitmap - image format may not be supported") return bitmap ?: throw RuntimeException("Region decoder returned null bitmap - image format may not be supported")
} }

View file

@ -5,7 +5,7 @@
<string name="edit">Редакция</string> <string name="edit">Редакция</string>
<string name="open_camera">Камера</string> <string name="open_camera">Камера</string>
<string name="hidden">(скрито)</string> <string name="hidden">(скрито)</string>
<string name="excluded">(excluded)</string> <string name="excluded">(изключено)</string>
<string name="pin_folder">Закачете папката</string> <string name="pin_folder">Закачете папката</string>
<string name="unpin_folder">Откачете папката</string> <string name="unpin_folder">Откачете папката</string>
<string name="pin_to_the_top">Закачете отгоре</string> <string name="pin_to_the_top">Закачете отгоре</string>
@ -54,7 +54,7 @@
<string name="hidden_folders">Скрити папки</string> <string name="hidden_folders">Скрити папки</string>
<string name="manage_hidden_folders">Управление на скритите папки</string> <string name="manage_hidden_folders">Управление на скритите папки</string>
<string name="hidden_folders_placeholder">Изглежда нямате папки скрити чрез \'.nomedia\' файл.</string> <string name="hidden_folders_placeholder">Изглежда нямате папки скрити чрез \'.nomedia\' файл.</string>
<string name="hidden_all_files">You have to grant the app All Files access to see hidden files, else it cannot work.</string> <string name="hidden_all_files">Трябва да предоставите на приложението достъп до всички файлове, за да видите скритите файлове, в противен случай то не може да работи.</string>
<string name="cant_unhide_folder">If a folder or one of its parent folders has a dot before its name, it is hidden and cannot be unhidden like this. You have to remove the dot by renaming it.</string> <string name="cant_unhide_folder">If a folder or one of its parent folders has a dot before its name, it is hidden and cannot be unhidden like this. You have to remove the dot by renaming it.</string>
<!-- Include folders --> <!-- Include folders -->
<string name="include_folders">Включени папки</string> <string name="include_folders">Включени папки</string>
@ -70,19 +70,19 @@
<string name="height">Височина</string> <string name="height">Височина</string>
<string name="keep_aspect_ratio">Запазете съотношението на страните</string> <string name="keep_aspect_ratio">Запазете съотношението на страните</string>
<string name="invalid_values">Моля въведете валидна резолюция</string> <string name="invalid_values">Моля въведете валидна резолюция</string>
<string name="resize_multiple_images">Resize multiple images</string> <string name="resize_multiple_images">Преоразмеряване на няколко изображения</string>
<string name="resize_factor">Resize factor</string> <string name="resize_factor">Коефициент на преоразмеряване</string>
<string name="resize_factor_info">Resize images to the given percentage, value must be within 10 and 90.</string> <string name="resize_factor_info">Преоразмерете изображенията до дадения процент, стойността трябва да е в рамките на 10 и 90.</string>
<string name="resize_factor_error">Enter a number between 10 and 90</string> <string name="resize_factor_error">Въведете число между 10 и 90</string>
<plurals name="failed_to_resize_images"> <plurals name="failed_to_resize_images">
<item quantity="one">Failed to resize %d image</item> <item quantity="one">Преоразмеряването неуспешно за %d изображение</item>
<item quantity="other">Failed to resize %d images</item> <item quantity="other">Преоразмеряването неуспешно за %d изображения</item>
</plurals> </plurals>
<string name="images_resized_successfully">Images resized successfully</string> <string name="images_resized_successfully">Изображенията са преоразмерени успешно</string>
<!-- Editor --> <!-- Editor -->
<string name="editor">Редактор</string> <string name="editor">Редактор</string>
<string name="basic_editor">Basic Editor</string> <string name="basic_editor">Базов редактор</string>
<string name="advanced_editor">Advanced Editor</string> <string name="advanced_editor">Разширен редактор</string>
<string name="rotate">Завъртане</string> <string name="rotate">Завъртане</string>
<string name="invalid_image_path">Неправилен път до изображението</string> <string name="invalid_image_path">Неправилен път до изображението</string>
<string name="invalid_video_path">Неправилен път до видеото</string> <string name="invalid_video_path">Неправилен път до видеото</string>
@ -102,9 +102,9 @@
<string name="rotate_left">Завъртане наляво</string> <string name="rotate_left">Завъртане наляво</string>
<string name="rotate_right">Завъртане надясно</string> <string name="rotate_right">Завъртане надясно</string>
<string name="rotate_one_eighty">Завъртане на 180º</string> <string name="rotate_one_eighty">Завъртане на 180º</string>
<string name="transform">Transform</string> <string name="transform">Трансформирай</string>
<string name="crop">Crop</string> <string name="crop">Изрежи</string>
<string name="draw">Draw</string> <string name="draw">Рисувай</string>
<string name="flip">Oбръщане</string> <string name="flip">Oбръщане</string>
<string name="flip_horizontally">Хоризонтално обръщане</string> <string name="flip_horizontally">Хоризонтално обръщане</string>
<string name="flip_vertically">Вертикално обръщане</string> <string name="flip_vertically">Вертикално обръщане</string>
@ -210,19 +210,19 @@
<string name="limit_folder_title">Ограничаване на заглавията на папките до един ред</string> <string name="limit_folder_title">Ограничаване на заглавията на папките до един ред</string>
<string name="square">Квадрат</string> <string name="square">Квадрат</string>
<string name="rounded_corners">Заоблени ъгли</string> <string name="rounded_corners">Заоблени ъгли</string>
<string name="export_favorite_paths">Експортиране на пътищата на любимите файлове</string> <string name="export_favorite_paths">Експортиране на любимите</string>
<string name="import_favorite_paths">Import favorites</string> <string name="import_favorite_paths">Импортиране на любими</string>
<string name="paths_imported_successfully">Paths imported successfully</string> <string name="paths_imported_successfully">Пътищата са импортирани успешно</string>
<string name="media_management_prompt">За да работят надеждно всички операции, моля задайте това приложение да управлява медията в настройките на вашето устройство.</string> <string name="media_management_prompt">За да работят надеждно всички операции, моля задайте това приложение да управлява медията в настройките на вашето устройство.</string>
<string name="password_protect_excluded">Защита на изключена папка с парола</string> <string name="password_protect_excluded">Защита на изключена папка с парола</string>
<string name="media_management_manual">Нещо се обърка, моля, влезте в Настройки на вашето устройство - Приложения - Достъп до специални приложения - Приложения за управление на медии и разрешете на това приложение да управлява медиите.</string> <string name="media_management_manual">Нещо се обърка, моля, влезте в Настройки на вашето устройство - Приложения - Достъп до специални приложения - Приложения за управление на медии и разрешете на това приложение да управлява медиите.</string>
<string name="media_management_note">Ако пренасочването не работи, моля, влезте в Настройки на вашето устройство - Приложения - Достъп до специални приложения - Приложения за управление на медии и разрешете на това приложение да управлява медиите.</string> <string name="media_management_note">Ако пренасочването не работи, моля, влезте в Настройки на вашето устройство - Приложения - Достъп до специални приложения - Приложения за управление на медии и разрешете на това приложение да управлява медиите.</string>
<string name="media_management_alternative">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.</string> <string name="media_management_alternative">Ако не искате да го направите, можете също да отидете в Настройки на вашето устройство - Приложения - Специален достъп до приложения - Приложения за управление на медии и да разрешите на това приложение да управлява медии.</string>
<string name="alternative_media_access">Alternatively, you can allow accessing media files only. In that case you will not be able to work with hidden files though.</string> <string name="alternative_media_access">Като алтернатива можете да разрешите достъп само до медийни файлове. В този случай обаче няма да можете да работите със скрити файлове.</string>
<string name="media_only">Media only</string> <string name="media_only">Само медия</string>
<string name="all_files">All files</string> <string name="all_files">Всички файлове</string>
<string name="search_all_files">Search all files instead of folders on the main screen</string> <string name="search_all_files">Търсете всички файлове вместо папки на главния екран</string>
<string name="show_all_folders">Show a menu button for toggling Show All Folders Content quickly</string> <string name="show_all_folders">Показване на бутон на менюто за бързо превключване на Показване на съдържанието на всички папки</string>
<!-- Setting sections --> <!-- Setting sections -->
<string name="thumbnails">Миниатюри</string> <string name="thumbnails">Миниатюри</string>
<string name="fullscreen_media">Медия на цял екран</string> <string name="fullscreen_media">Медия на цял екран</string>
@ -375,7 +375,7 @@
<string name="faq_15_text">Кешът на приложението може да отнеме до 250 MB, което гарантира по-бързо зареждане на изображението. Ако приложението заема още повече място, най-вероятно това е причинено от това, че имате елементи в кошчето. Тези файлове се броят към размера на приложението. Можете да изчистите кошчето, като го отворите и изтриете всички файлове или от настройките на приложението. Всеки файл в кошчето се изтрива автоматично след 30 дни.</string> <string name="faq_15_text">Кешът на приложението може да отнеме до 250 MB, което гарантира по-бързо зареждане на изображението. Ако приложението заема още повече място, най-вероятно това е причинено от това, че имате елементи в кошчето. Тези файлове се броят към размера на приложението. Можете да изчистите кошчето, като го отворите и изтриете всички файлове или от настройките на приложението. Всеки файл в кошчето се изтрива автоматично след 30 дни.</string>
<string name="faq_16_title">Какво се случи със скриването на файлове и папки и защо вече не мога да виждам скрити елементи\?</string> <string name="faq_16_title">Какво се случи със скриването на файлове и папки и защо вече не мога да виждам скрити елементи\?</string>
<string name="faq_16_text">Започвайки с Android 11, вече не можете да скривате или показвате файлове или папки, не можете да виждате скритите в приложения за галерия поради системни ограничения. За това ще трябва да използвате някакъв файлов мениджър.</string> <string name="faq_16_text">Започвайки с Android 11, вече не можете да скривате или показвате файлове или папки, не можете да виждате скритите в приложения за галерия поради системни ограничения. За това ще трябва да използвате някакъв файлов мениджър.</string>
<string name="faq_16_text_extra">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.</string> <string name="faq_16_text_extra">Или можете също да предоставите на тази галерия достъп до всички файлове през настройките на вашето устройство, което ще ни позволи да показваме скрити елементи и ще направи файловите операции по-надеждни като цяло.</string>
<string name="faq_17_title">Защо вече не мога да добавя липсващи папки\?</string> <string name="faq_17_title">Защо вече не мога да добавя липсващи папки\?</string>
<string name="faq_17_text">Това спря да работи поради системните промени, които дойдоха и с Android 11, приложението вече не може да преглежда истински папки, разчита на така наречения MediaStore при извличане на данни.</string> <string name="faq_17_text">Това спря да работи поради системните промени, които дойдоха и с Android 11, приложението вече не може да преглежда истински папки, разчита на така наречения MediaStore при извличане на данни.</string>
<string name="faq_18_title">Защо виждам реклами по време на възпроизвеждане на видео\?</string> <string name="faq_18_title">Защо виждам реклами по време на възпроизвеждане на видео\?</string>

View file

@ -75,8 +75,8 @@
<string name="resize_factor_info">Αλλάξτε το μέγεθος των εικόνων στο δεδομένο ποσοστό. Η τιμή πρέπει να είναι μεταξύ 10 και 90.</string> <string name="resize_factor_info">Αλλάξτε το μέγεθος των εικόνων στο δεδομένο ποσοστό. Η τιμή πρέπει να είναι μεταξύ 10 και 90.</string>
<string name="resize_factor_error">Εισάγετε έναν αριθμό μεταξύ 10 και 90</string> <string name="resize_factor_error">Εισάγετε έναν αριθμό μεταξύ 10 και 90</string>
<plurals name="failed_to_resize_images"> <plurals name="failed_to_resize_images">
<item quantity="one">Αποτυχία αλλαγής μεγέθους εικόνας %d</item> <item quantity="one">Αποτυχία αλλαγής μεγέθους %d εικόνας</item>
<item quantity="other">Αποτυχία αλλαγής μεγέθους εικόνων %d</item> <item quantity="other">Αποτυχία αλλαγής μεγέθους %d εικόνων</item>
</plurals> </plurals>
<string name="images_resized_successfully">Το μέγεθος των εικόνων άλλαξε με επιτυχία</string> <string name="images_resized_successfully">Το μέγεθος των εικόνων άλλαξε με επιτυχία</string>
<!-- Editor --> <!-- Editor -->

View file

@ -214,7 +214,7 @@
<string name="import_favorite_paths">Import favorites</string> <string name="import_favorite_paths">Import favorites</string>
<string name="paths_imported_successfully">Paths imported successfully</string> <string name="paths_imported_successfully">Paths imported successfully</string>
<string name="media_management_prompt">To make sure that all file operations work reliably, please make this app a Media management app in your device settings.</string> <string name="media_management_prompt">To make sure that all file operations work reliably, please make this app a Media management app in your device settings.</string>
<string name="password_protect_excluded">Password protect excluded folder visibility</string> <string name="password_protect_excluded">設定密碼保護,隱藏不顯示的資料夾</string>
<string name="media_management_manual">出錯了,請至裝置的設定 - 應用程式(和通知) - 特殊應用程式存取權 - 媒體管理應用程式,允許本 app 管理媒體。</string> <string name="media_management_manual">出錯了,請至裝置的設定 - 應用程式(和通知) - 特殊應用程式存取權 - 媒體管理應用程式,允許本 app 管理媒體。</string>
<string name="media_management_note">若重新導向未順利運作,請至裝置的設定 - 應用程式(和通知) - 特殊應用程式存取權 - 媒體管理應用程式,允許本 app 管理媒體。</string> <string name="media_management_note">若重新導向未順利運作,請至裝置的設定 - 應用程式(和通知) - 特殊應用程式存取權 - 媒體管理應用程式,允許本 app 管理媒體。</string>
<string name="media_management_alternative">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.</string> <string name="media_management_alternative">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.</string>