Merge pull request #38 from SimpleMobileTools/master

upd
This commit is contained in:
solokot 2018-10-23 13:00:31 +03:00 committed by GitHub
commit 15a65a474c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
80 changed files with 1815 additions and 809 deletions

1
.gitignore vendored
View file

@ -1,7 +1,6 @@
*.iml
.gradle
/local.properties
/gradle.properties
/.idea/
.DS_Store
/build

View file

@ -1,6 +1,37 @@
Changelog
==========
Version 5.1.0 *(2018-10-23)*
----------------------------
* Added support for panorama videos
* Added an extra check to avoid trying deleting files without write permission
* Added an initial implementation of renaming multiple items at once
* Added some performance improvements at item de/selection
* Allow enabling hidden item visibility at the copy/move destination picker
* Allow closing fullscreen view with swipe down gestures (can be disabled in settings)
* Fixed a glitch with Favorite items getting unselected every day
* Fixed exposure time displayed at long exposure photos
* Fixed fullscreen images being sometimes totally zoomed in after device rotation
* Fixed slideshow direction
* Made loading initial fullscreen view quicker and fullscreen toggling more reliable
* Not sure what else, nobody reads this anyway
Version 5.0.1 *(2018-10-17)*
----------------------------
* Adding some crashfixes
Version 5.0.0 *(2018-10-17)*
----------------------------
* Increased the minimal required Android OS version to 5 (Lollipop)
* Rewrote file selection for more robustness
* Added a new option for showing the Recycle Bin as the last folder
* Added Search for searching folders by names
* Replaced the G+ button with Reddit
* Couple smaller glitch fixes and improvements
Version 4.6.5 *(2018-10-02)*
----------------------------

View file

@ -9,10 +9,10 @@ android {
defaultConfig {
applicationId "com.simplemobiletools.gallery"
minSdkVersion 16
minSdkVersion 21
targetSdkVersion 28
versionCode 201
versionName "4.6.5"
versionCode 204
versionName "5.1.0"
multiDexEnabled true
setProperty("archivesBaseName", "gallery")
}
@ -40,17 +40,23 @@ android {
checkReleaseBuilds false
abortOnError false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'com.simplemobiletools:commons:4.9.1'
implementation 'com.simplemobiletools:commons:5.2.0'
implementation 'com.theartofdev.edmodo:android-image-cropper:2.7.0'
implementation 'androidx.multidex:multidex:2.0.0'
implementation 'it.sephiroth.android.exif:library:1.0.1'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.15'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2'
implementation 'com.google.android.exoplayer:exoplayer-core:2.8.4'
implementation 'com.google.android.exoplayer:exoplayer-core:2.9.0'
implementation 'com.google.vr:sdk-panowidget:1.170.0'
implementation 'com.google.vr:sdk-videowidget:1.170.0'
implementation 'org.apache.sanselan:sanselan:0.97-incubator'
implementation 'info.androidhive:imagefilters:1.0.7'
implementation 'com.squareup.picasso:picasso:2.71828'
@ -65,7 +71,7 @@ dependencies {
implementation 'com.github.tibbi:subsampling-scale-image-view:v3.10.1-fork'
// implementation 'com.github.chrisbanes:PhotoView:2.1.4'
implementation 'com.github.tibbi:PhotoView:2.1.4-fork'
implementation 'com.github.tibbi:PhotoView:2.2.1-fork'
}
Properties props = new Properties()

View file

@ -32,6 +32,14 @@
android:name=".activities.MainActivity"
android:resizeableActivity="true">
<meta-data
android:name="android.app.default_searchable"
android:resource="@xml/searchable"/>
<intent-filter>
<action android:name="android.intent.action.SEARCH"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PICK"/>
<category android:name="android.intent.category.DEFAULT"/>
@ -115,7 +123,12 @@
android:configChanges="orientation|keyboardHidden|screenSize"/>
<activity
android:name=".activities.PanoramaActivity"
android:name=".activities.PanoramaPhotoActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/FullScreenTheme"/>
<activity
android:name=".activities.PanoramaVideoActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/FullScreenTheme"/>

View file

@ -20,7 +20,7 @@ class ExcludedFoldersActivity : SimpleActivity(), RefreshRecyclerViewListener {
private fun updateFolders() {
val folders = ArrayList<String>()
config.excludedFolders.mapTo(folders, { it })
config.excludedFolders.mapTo(folders) { it }
manage_folders_placeholder.apply {
text = getString(R.string.excluded_activity_placeholder)
beVisibleIf(folders.isEmpty())
@ -49,7 +49,7 @@ class ExcludedFoldersActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
private fun addFolder() {
FilePickerDialog(this, config.lastFilepickerPath, false, config.shouldShowHidden) {
FilePickerDialog(this, config.lastFilepickerPath, false, config.shouldShowHidden, false, true) {
config.lastFilepickerPath = it
config.addExcludedFolder(it)
updateFolders()

View file

@ -53,7 +53,7 @@ class HiddenFoldersActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
private fun addFolder() {
FilePickerDialog(this, config.lastFilepickerPath, false, config.shouldShowHidden) {
FilePickerDialog(this, config.lastFilepickerPath, false, config.shouldShowHidden, false, true) {
config.lastFilepickerPath = it
Thread {
addNoMedia(it) {

View file

@ -21,7 +21,7 @@ class IncludedFoldersActivity : SimpleActivity(), RefreshRecyclerViewListener {
private fun updateFolders() {
val folders = ArrayList<String>()
config.includedFolders.mapTo(folders, { it })
config.includedFolders.mapTo(folders) { it }
manage_folders_placeholder.apply {
text = getString(R.string.included_activity_placeholder)
beVisibleIf(folders.isEmpty())
@ -50,7 +50,7 @@ class IncludedFoldersActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
private fun addFolder() {
FilePickerDialog(this, config.lastFilepickerPath, false, config.shouldShowHidden) {
FilePickerDialog(this, config.lastFilepickerPath, false, config.shouldShowHidden, false, true) {
config.lastFilepickerPath = it
config.addIncludedFolder(it)
updateFolders()

View file

@ -1,7 +1,9 @@
package com.simplemobiletools.gallery.activities
import android.app.Activity
import android.app.SearchManager
import android.content.ClipData
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
@ -12,7 +14,8 @@ import android.view.MenuItem
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.Toast
import androidx.recyclerview.widget.GridLayoutManager
import androidx.appcompat.widget.SearchView
import androidx.core.view.MenuItemCompat
import androidx.recyclerview.widget.RecyclerView
import com.simplemobiletools.commons.dialogs.CreateNewFolderDialog
import com.simplemobiletools.commons.dialogs.FilePickerDialog
@ -61,11 +64,14 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
private var mIsPasswordProtectionPending = false
private var mWasProtectionHandled = false
private var mShouldStopFetching = false
private var mIsSearchOpen = false
private var mLatestMediaId = 0L
private var mLatestMediaDateId = 0L
private var mLastMediaHandler = Handler()
private var mTempShowHiddenHandler = Handler()
private var mZoomListener: MyRecyclerView.MyZoomListener? = null
private var mSearchMenuItem: MenuItem? = null
private var mDirs = ArrayList<Directory>()
private var mStoredAnimateGifs = true
private var mStoredCropThumbnails = true
@ -214,6 +220,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
override fun onStop() {
super.onStop()
mSearchMenuItem?.collapseActionView()
if (config.temporarilyShowHidden || config.tempSkipDeleteConfirmation) {
mTempShowHiddenHandler.postDelayed({
config.temporarilyShowHidden = false
@ -243,10 +251,13 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
menu.apply {
findItem(R.id.increase_column_count).isVisible = config.viewTypeFolders == VIEW_TYPE_GRID && config.dirColumnCnt < MAX_COLUMN_COUNT
findItem(R.id.reduce_column_count).isVisible = config.viewTypeFolders == VIEW_TYPE_GRID && config.dirColumnCnt > 1
setupSearch(this)
}
}
menu.findItem(R.id.temporarily_show_hidden).isVisible = !config.shouldShowHidden
menu.findItem(R.id.stop_showing_hidden).isVisible = config.temporarilyShowHidden
return true
}
@ -293,6 +304,55 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
}
}
private fun setupSearch(menu: Menu) {
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
mSearchMenuItem = menu.findItem(R.id.search)
(mSearchMenuItem?.actionView as? SearchView)?.apply {
setSearchableInfo(searchManager.getSearchableInfo(componentName))
isSubmitButtonEnabled = false
setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String) = false
override fun onQueryTextChange(newText: String): Boolean {
if (mIsSearchOpen) {
searchQueryChanged(newText)
}
return true
}
})
}
MenuItemCompat.setOnActionExpandListener(mSearchMenuItem, object : MenuItemCompat.OnActionExpandListener {
override fun onMenuItemActionExpand(item: MenuItem?): Boolean {
mIsSearchOpen = true
directories_refresh_layout.isEnabled = false
return true
}
// this triggers on device rotation too, avoid doing anything
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
if (mIsSearchOpen) {
mIsSearchOpen = false
directories_refresh_layout.isEnabled = config.enablePullToRefresh
searchQueryChanged("")
}
return true
}
})
}
private fun searchQueryChanged(text: String) {
Thread {
val filtered = getUniqueSortedDirs(mDirs).filter { it.name.contains(text, true) } as ArrayList
filtered.sortBy { !it.name.startsWith(text, true) }
runOnUiThread {
getRecyclerAdapter()?.updateDirs(filtered)
measureRecyclerViewContent(filtered)
}
}.start()
}
private fun removeTempFolder() {
if (config.tempFolderPath.isNotEmpty()) {
val newFolder = File(config.tempFolderPath)
@ -544,7 +604,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
}
private fun createNewFolder() {
FilePickerDialog(this, internalStoragePath, false, config.shouldShowHidden) {
FilePickerDialog(this, internalStoragePath, false, config.shouldShowHidden, false, true) {
CreateNewFolderDialog(this, it) {
config.tempFolderPath = it
Thread {
@ -688,6 +748,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
// if hidden item showing is disabled but all Favorite items are hidden, hide the Favorites folder
mIsGettingDirs = false
mShouldStopFetching = false
if (!config.shouldShowHidden) {
val favoritesFolder = newDirs.firstOrNull { it.areFavorites() }
if (favoritesFolder != null && favoritesFolder.tmb.getFilenameFromPath().startsWith('.')) {
@ -714,9 +775,11 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
val hiddenString = getString(R.string.hidden)
val albumCovers = config.parseAlbumCovers()
val includedFolders = config.includedFolders
val tempFolderPath = config.tempFolderPath
val isSortingAscending = config.directorySorting and SORT_DESCENDING == 0
val getProperDateTaken = config.directorySorting and SORT_BY_DATE_TAKEN != 0
val favoritePaths = getFavoritePaths()
val dirPathsToRemove = ArrayList<String>()
try {
for (directory in dirs) {
@ -726,6 +789,9 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
val curMedia = mediaFetcher.getFilesFrom(directory.path, getImagesOnly, getVideosOnly, getProperDateTaken, favoritePaths)
val newDir = if (curMedia.isEmpty()) {
if (directory.path != tempFolderPath) {
dirPathsToRemove.add(directory.path)
}
directory
} else {
createDirectoryFromMedia(directory.path, curMedia, albumCovers, hiddenString, includedFolders, isSortingAscending)
@ -767,9 +833,18 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} catch (ignored: Exception) {
}
if (dirPathsToRemove.isNotEmpty()) {
val dirsToRemove = dirs.filter { dirPathsToRemove.contains(it.path) }
dirsToRemove.forEach {
mDirectoryDao.deleteDirPath(it.path)
}
dirs.removeAll(dirsToRemove)
showSortedDirs(dirs)
}
val foldersToScan = mediaFetcher.getFoldersToScan()
foldersToScan.add(FAVORITES)
if (config.showRecycleBinAtFolders) {
if (config.useRecycleBin && config.showRecycleBinAtFolders) {
foldersToScan.add(RECYCLE_BIN)
} else {
foldersToScan.remove(RECYCLE_BIN)
@ -825,6 +900,11 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} catch (e: Exception) {
config.everShownFolders = HashSet()
}
mDirs = dirs.clone() as ArrayList<Directory>
if (config.appRunCount < 5 && mDirs.size > 100) {
excludeSpamFolders()
}
}
private fun checkPlaceholderVisibility(dirs: ArrayList<Directory>) {
@ -834,14 +914,17 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
}
private fun showSortedDirs(dirs: ArrayList<Directory>) {
var sortedDirs = getSortedDirectories(dirs)
sortedDirs = sortedDirs.distinctBy { it.path.getDistinctPath() } as ArrayList<Directory>
val updatedDirs = getUniqueSortedDirs(dirs)
runOnUiThread {
(directories_grid.adapter as? DirectoryAdapter)?.updateDirs(sortedDirs)
(directories_grid.adapter as? DirectoryAdapter)?.updateDirs(updatedDirs)
}
}
private fun getUniqueSortedDirs(dirs: ArrayList<Directory>): ArrayList<Directory> {
val sortedDirs = dirs.distinctBy { it.path.getDistinctPath() } as ArrayList<Directory>
return getSortedDirectories(sortedDirs)
}
private fun createDirectoryFromMedia(path: String, curMedia: ArrayList<Medium>, albumCovers: ArrayList<AlbumCover>, hiddenString: String,
includedFolders: MutableSet<String>, isSortingAscending: Boolean): Directory {
var thumbnail = curMedia.firstOrNull { getDoesFilePathExist(it.path) }?.path ?: ""
@ -885,7 +968,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
directories_grid.adapter = this
}
} else {
(currAdapter as DirectoryAdapter).updateDirs(dirs)
showSortedDirs(dirs)
}
getRecyclerAdapter()?.dirs?.apply {
@ -966,7 +1049,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
}
private fun checkLastMediaChanged() {
if (isActivityDestroyed()) {
if (isDestroyed) {
return
}
@ -993,12 +1076,88 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
config.lastBinCheck = System.currentTimeMillis()
Handler().postDelayed({
Thread {
try {
mMediumDao.deleteOldRecycleBinItems(System.currentTimeMillis() - MONTH_MILLISECONDS)
} catch (e: Exception) {
}
}.start()
}, 3000L)
}
}
// exclude probably unwanted folders, for example facebook stickers are split between hundreds of separate folders like
// /storage/emulated/0/Android/data/com.facebook.orca/files/stickers/175139712676531/209575122566323
// /storage/emulated/0/Android/data/com.facebook.orca/files/stickers/497837993632037/499671223448714
private fun excludeSpamFolders() {
Thread {
try {
val internalPath = config.internalStoragePath
val sdPath = config.sdCardPath
val pathParts = ArrayList<ArrayList<String>>()
mDirs.asSequence().map { it.path.removePrefix(internalPath).removePrefix(sdPath) }.sorted().toList().forEach {
val parts = it.split("/").asSequence().filter { it.isNotEmpty() }.toMutableList() as ArrayList<String>
if (parts.size > 3) {
pathParts.add(parts)
}
}
val keys = getLongestCommonStrings(pathParts)
pathParts.clear()
keys.forEach { it ->
val parts = it.split("/").asSequence().filter { it.isNotEmpty() }.toMutableList() as ArrayList<String>
pathParts.add(parts)
}
getLongestCommonStrings(pathParts).forEach {
var file = File("$internalPath/$it")
if (file.exists()) {
config.addExcludedFolder(file.absolutePath)
} else {
file = File("$sdPath/$it")
if (file.exists()) {
config.addExcludedFolder(file.absolutePath)
}
}
}
} catch (e: Exception) {
}
}.start()
}
private fun getLongestCommonStrings(pathParts: ArrayList<ArrayList<String>>): ArrayList<String> {
val commonStrings = ArrayList<String>()
return try {
val cnt = pathParts.size
for (i in 0..cnt) {
var longestCommonString = ""
for (j in i..cnt) {
var currentCommonString = ""
if (i != j) {
val originalParts = pathParts.getOrNull(i)
val otherParts = pathParts.getOrNull(j)
if (originalParts != null && otherParts != null) {
originalParts.forEachIndexed { index, string ->
if (string == otherParts.getOrNull(index)) {
currentCommonString += "$string/"
if (currentCommonString.length > longestCommonString.length) {
longestCommonString = currentCommonString.trimEnd('/')
}
}
}
}
}
}
if (longestCommonString.isNotEmpty()) {
commonStrings.add(longestCommonString)
}
}
commonStrings.groupingBy { it }.eachCount().filter { it.value > 5 && it.key.length > 10 }.map { it.key }.toMutableList() as ArrayList<String>
} catch (e: Exception) {
ArrayList()
}
}
override fun refreshItems() {
getDirectories()
}
@ -1068,6 +1227,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
add(Release(182, R.string.release_182))
add(Release(184, R.string.release_184))
add(Release(201, R.string.release_201))
add(Release(202, R.string.release_202))
checkWhatsNew(this, BuildConfig.VERSION_CODE)
}
}

View file

@ -398,7 +398,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
}
private fun checkLastMediaChanged() {
if (isActivityDestroyed()) {
if (isDestroyed) {
return
}

View file

@ -1,11 +1,9 @@
package com.simplemobiletools.gallery.activities
import android.annotation.TargetApi
import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.Window
@ -14,20 +12,20 @@ import android.widget.RelativeLayout
import com.google.vr.sdk.widgets.pano.VrPanoramaEventListener
import com.google.vr.sdk.widgets.pano.VrPanoramaView
import com.simplemobiletools.commons.extensions.beVisible
import com.simplemobiletools.commons.extensions.onGlobalLayout
import com.simplemobiletools.commons.extensions.showErrorToast
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE
import com.simplemobiletools.commons.helpers.isLollipopPlus
import com.simplemobiletools.commons.helpers.isPiePlus
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.extensions.*
import com.simplemobiletools.gallery.helpers.PATH
import kotlinx.android.synthetic.main.activity_panorama.*
import kotlinx.android.synthetic.main.activity_panorama_photo.*
open class PanoramaActivity : SimpleActivity() {
open class PanoramaPhotoActivity : SimpleActivity() {
private val CARDBOARD_DISPLAY_MODE = 3
private var isFullScreen = false
private var isFullscreen = false
private var isExploreEnabled = true
private var isRendering = false
@ -35,7 +33,7 @@ open class PanoramaActivity : SimpleActivity() {
useDynamicTheme = false
requestWindowFeature(Window.FEATURE_NO_TITLE)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_panorama)
setContentView(R.layout.activity_panorama_photo)
supportActionBar?.hide()
if (isPiePlus()) {
@ -65,7 +63,6 @@ open class PanoramaActivity : SimpleActivity() {
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
override fun onResume() {
super.onResume()
panorama_view.resumeRendering()
@ -74,10 +71,8 @@ open class PanoramaActivity : SimpleActivity() {
updateStatusbarColor(Color.BLACK)
}
if (isLollipopPlus()) {
window.statusBarColor = resources.getColor(R.color.circle_black_background)
}
}
override fun onPause() {
super.onPause()
@ -113,11 +108,6 @@ open class PanoramaActivity : SimpleActivity() {
loadImageFromBitmap(bitmap, options)
setFlingingEnabled(true)
setPureTouchTracking(true)
setEventListener(object : VrPanoramaEventListener() {
override fun onClick() {
handleClick()
}
})
// add custom buttons so we can position them and toggle visibility as desired
setFullscreenButtonEnabled(false)
@ -128,6 +118,12 @@ open class PanoramaActivity : SimpleActivity() {
setOnClickListener {
handleClick()
}
setEventListener(object : VrPanoramaEventListener() {
override fun onClick() {
handleClick()
}
})
}
}
}.start()
@ -136,7 +132,7 @@ open class PanoramaActivity : SimpleActivity() {
}
window.decorView.setOnSystemUiVisibilityChangeListener { visibility ->
isFullScreen = visibility and View.SYSTEM_UI_FLAG_FULLSCREEN != 0
isFullscreen = visibility and View.SYSTEM_UI_FLAG_FULLSCREEN != 0
toggleButtonVisibility()
}
}
@ -164,26 +160,30 @@ open class PanoramaActivity : SimpleActivity() {
}
private fun setupButtonMargins() {
val navBarHeight = navigationBarHeight
(cardboard.layoutParams as RelativeLayout.LayoutParams).apply {
bottomMargin = navigationBarHeight
bottomMargin = navBarHeight
rightMargin = navigationBarWidth
}
(explore.layoutParams as RelativeLayout.LayoutParams).bottomMargin = navigationBarHeight
cardboard.onGlobalLayout {
panorama_gradient_background.layoutParams.height = navBarHeight + cardboard.height
}
}
private fun toggleButtonVisibility() {
cardboard.animate().alpha(if (isFullScreen) 0f else 1f)
cardboard.isClickable = !isFullScreen
explore.animate().alpha(if (isFullScreen) 0f else 1f)
explore.isClickable = !isFullScreen
arrayOf(cardboard, explore, panorama_gradient_background).forEach {
it.animate().alpha(if (isFullscreen) 0f else 1f)
it.isClickable = !isFullscreen
}
}
private fun handleClick() {
isFullScreen = !isFullScreen
isFullscreen = !isFullscreen
toggleButtonVisibility()
if (isFullScreen) {
if (isFullscreen) {
hideSystemUI(false)
} else {
showSystemUI(false)

View file

@ -0,0 +1,343 @@
package com.simplemobiletools.gallery.activities
import android.content.res.Configuration
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.view.View
import android.view.Window
import android.view.WindowManager
import android.view.animation.AnimationUtils
import android.widget.RelativeLayout
import android.widget.SeekBar
import com.google.vr.sdk.widgets.video.VrVideoEventListener
import com.google.vr.sdk.widgets.video.VrVideoView
import com.simplemobiletools.commons.extensions.getFormattedDuration
import com.simplemobiletools.commons.extensions.onGlobalLayout
import com.simplemobiletools.commons.extensions.showErrorToast
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE
import com.simplemobiletools.commons.helpers.isPiePlus
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.extensions.*
import com.simplemobiletools.gallery.helpers.HIDE_PLAY_PAUSE_DELAY
import com.simplemobiletools.gallery.helpers.MIN_SKIP_LENGTH
import com.simplemobiletools.gallery.helpers.PATH
import com.simplemobiletools.gallery.helpers.PLAY_PAUSE_VISIBLE_ALPHA
import kotlinx.android.synthetic.main.activity_panorama_video.*
import kotlinx.android.synthetic.main.bottom_video_time_holder.*
import java.io.File
open class PanoramaVideoActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListener {
private val CARDBOARD_DISPLAY_MODE = 3
private var mIsFullscreen = false
private var mIsExploreEnabled = true
private var mIsRendering = false
private var mIsPlaying = false
private var mIsDragged = false
private var mPlayOnReady = false
private var mDuration = 0
private var mCurrTime = 0
private var mHidePlayPauseHandler = Handler()
private var mTimerHandler = Handler()
public override fun onCreate(savedInstanceState: Bundle?) {
useDynamicTheme = false
requestWindowFeature(Window.FEATURE_NO_TITLE)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_panorama_video)
supportActionBar?.hide()
if (isPiePlus()) {
window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
}
setupButtons()
cardboard.setOnClickListener {
vr_video_view.displayMode = CARDBOARD_DISPLAY_MODE
}
explore.setOnClickListener {
mIsExploreEnabled = !mIsExploreEnabled
vr_video_view.setPureTouchTracking(mIsExploreEnabled)
explore.setImageResource(if (mIsExploreEnabled) R.drawable.ic_explore else R.drawable.ic_explore_off)
}
handlePermission(PERMISSION_WRITE_STORAGE) {
if (it) {
checkIntent()
} else {
toast(R.string.no_storage_permissions)
finish()
}
}
}
override fun onResume() {
super.onResume()
vr_video_view.resumeRendering()
mIsRendering = true
if (config.blackBackground) {
updateStatusbarColor(Color.BLACK)
}
window.statusBarColor = resources.getColor(R.color.circle_black_background)
}
override fun onPause() {
super.onPause()
vr_video_view.pauseRendering()
mIsRendering = false
}
override fun onDestroy() {
super.onDestroy()
if (mIsRendering) {
vr_video_view.shutdown()
}
if (!isChangingConfigurations) {
mHidePlayPauseHandler.removeCallbacksAndMessages(null)
mTimerHandler.removeCallbacksAndMessages(null)
}
}
private fun checkIntent() {
val path = intent.getStringExtra(PATH)
if (path == null) {
toast(R.string.invalid_image_path)
finish()
return
}
intent.removeExtra(PATH)
video_curr_time.setOnClickListener { skip(false) }
video_duration.setOnClickListener { skip(true) }
try {
val options = VrVideoView.Options()
options.inputType = VrVideoView.Options.TYPE_MONO
vr_video_view.apply {
loadVideo(Uri.fromFile(File(path)), options)
pauseVideo()
setFlingingEnabled(true)
setPureTouchTracking(true)
// add custom buttons so we can position them and toggle visibility as desired
setFullscreenButtonEnabled(false)
setInfoButtonEnabled(false)
setTransitionViewEnabled(false)
setStereoModeButtonEnabled(false)
setOnClickListener {
handleClick()
}
setEventListener(object : VrVideoEventListener() {
override fun onClick() {
handleClick()
}
override fun onLoadSuccess() {
if (mDuration == 0) {
setupDuration(duration)
setupTimer()
}
if (mPlayOnReady) {
mPlayOnReady = false
playVideo()
}
}
override fun onCompletion() {
videoCompleted()
}
})
}
video_play_outline.setOnClickListener {
togglePlayPause()
}
} catch (e: Exception) {
showErrorToast(e)
}
window.decorView.setOnSystemUiVisibilityChangeListener { visibility ->
mIsFullscreen = visibility and View.SYSTEM_UI_FLAG_FULLSCREEN != 0
toggleButtonVisibility()
}
}
override fun onConfigurationChanged(newConfig: Configuration?) {
super.onConfigurationChanged(newConfig)
setupButtons()
}
private fun setupDuration(duration: Long) {
mDuration = (duration / 1000).toInt()
video_seekbar.max = mDuration
video_duration.text = mDuration.getFormattedDuration()
setVideoProgress(0)
}
private fun setupTimer() {
runOnUiThread(object : Runnable {
override fun run() {
if (mIsPlaying && !mIsDragged) {
mCurrTime = (vr_video_view!!.currentPosition / 1000).toInt()
video_seekbar.progress = mCurrTime
video_curr_time.text = mCurrTime.getFormattedDuration()
}
mTimerHandler.postDelayed(this, 1000)
}
})
}
private fun togglePlayPause() {
mIsPlaying = !mIsPlaying
video_play_outline.alpha = PLAY_PAUSE_VISIBLE_ALPHA
mHidePlayPauseHandler.removeCallbacksAndMessages(null)
if (mIsPlaying) {
playVideo()
} else {
pauseVideo()
}
schedulePlayPauseFadeOut()
}
private fun playVideo() {
video_play_outline.setImageResource(R.drawable.ic_pause)
if (mCurrTime == mDuration) {
setVideoProgress(0)
mPlayOnReady = true
return
}
vr_video_view.playVideo()
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
private fun pauseVideo() {
vr_video_view.pauseVideo()
video_play_outline.setImageResource(R.drawable.ic_play)
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
private fun setVideoProgress(seconds: Int) {
vr_video_view.seekTo(seconds * 1000L)
video_seekbar.progress = seconds
mCurrTime = seconds
video_curr_time.text = seconds.getFormattedDuration()
}
private fun videoCompleted() {
mIsPlaying = false
mCurrTime = (vr_video_view.duration / 1000).toInt()
video_seekbar.progress = video_seekbar.max
video_curr_time.text = mDuration.getFormattedDuration()
pauseVideo()
video_play_outline.alpha = PLAY_PAUSE_VISIBLE_ALPHA
}
private fun schedulePlayPauseFadeOut() {
mHidePlayPauseHandler.removeCallbacksAndMessages(null)
mHidePlayPauseHandler.postDelayed({
video_play_outline.animate().alpha(0f).start()
}, HIDE_PLAY_PAUSE_DELAY)
}
private fun setupButtons() {
val navBarHeight = navigationBarHeight
video_time_holder.apply {
(layoutParams as RelativeLayout.LayoutParams).bottomMargin = navBarHeight
setPadding(paddingLeft, paddingTop, navigationBarWidth, paddingBottom)
}
video_time_holder.onGlobalLayout {
(explore.layoutParams as RelativeLayout.LayoutParams).bottomMargin = navBarHeight + video_time_holder.height
(cardboard.layoutParams as RelativeLayout.LayoutParams).apply {
bottomMargin = navBarHeight + video_time_holder.height
rightMargin = navigationBarWidth
}
vr_view_gradient_background.layoutParams.height = navBarHeight + video_time_holder.height + explore.height
explore.requestLayout()
}
}
private fun toggleButtonVisibility() {
val newAlpha = if (mIsFullscreen) 0f else 1f
arrayOf(cardboard, explore, vr_view_gradient_background).forEach {
it.animate().alpha(newAlpha)
it.isClickable = !mIsFullscreen
}
var anim = android.R.anim.fade_in
if (mIsFullscreen) {
anim = android.R.anim.fade_out
video_seekbar.setOnSeekBarChangeListener(null)
} else {
video_seekbar.setOnSeekBarChangeListener(this)
}
AnimationUtils.loadAnimation(this, anim).apply {
duration = 150
fillAfter = true
video_time_holder.startAnimation(this)
}
}
private fun handleClick() {
mIsFullscreen = !mIsFullscreen
toggleButtonVisibility()
if (mIsFullscreen) {
hideSystemUI(false)
} else {
showSystemUI(false)
}
}
private fun skip(forward: Boolean) {
if (forward && mCurrTime == mDuration) {
return
}
val curr = vr_video_view.currentPosition
val twoPercents = Math.max((vr_video_view.duration / 50).toInt(), MIN_SKIP_LENGTH)
val newProgress = if (forward) curr + twoPercents else curr - twoPercents
val roundProgress = Math.round(newProgress / 1000f)
val limitedProgress = Math.max(Math.min(vr_video_view.duration.toInt(), roundProgress), 0)
setVideoProgress(limitedProgress)
if (!mIsPlaying) {
togglePlayPause()
}
}
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (fromUser) {
setVideoProgress(progress)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
vr_video_view.pauseVideo()
mIsDragged = true
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
mIsPlaying = true
playVideo()
mIsDragged = false
schedulePlayPauseFadeOut()
}
}

View file

@ -10,7 +10,6 @@ import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.isActivityDestroyed
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.helpers.isNougatPlus
import com.simplemobiletools.commons.models.RadioItem
@ -113,7 +112,7 @@ class SetWallpaperActivity : SimpleActivity(), CropImageView.OnCropImageComplete
@SuppressLint("NewApi")
override fun onCropImageComplete(view: CropImageView?, result: CropImageView.CropResult) {
if (isActivityDestroyed())
if (isDestroyed)
return
if (result.error == null) {

View file

@ -18,10 +18,7 @@ import com.simplemobiletools.gallery.extensions.config
import com.simplemobiletools.gallery.extensions.emptyTheRecycleBin
import com.simplemobiletools.gallery.extensions.galleryDB
import com.simplemobiletools.gallery.extensions.showRecycleBinEmptyingDialog
import com.simplemobiletools.gallery.helpers.DEFAULT_BOTTOM_ACTIONS
import com.simplemobiletools.gallery.helpers.ROTATE_BY_ASPECT_RATIO
import com.simplemobiletools.gallery.helpers.ROTATE_BY_DEVICE_ROTATION
import com.simplemobiletools.gallery.helpers.ROTATE_BY_SYSTEM_SETTING
import com.simplemobiletools.gallery.helpers.*
import kotlinx.android.synthetic.main.activity_settings.*
import java.util.*
@ -61,6 +58,7 @@ class SettingsActivity : SimpleActivity() {
setupDeleteEmptyFolders()
setupAllowPhotoGestures()
setupAllowVideoGestures()
setupAllowDownGesture()
setupBottomActions()
setupShowMediaCount()
setupKeepLastModified()
@ -77,6 +75,7 @@ class SettingsActivity : SimpleActivity() {
setupManageBottomActions()
setupUseRecycleBin()
setupShowRecycleBin()
setupShowRecycleBinLast()
setupEmptyRecycleBin()
updateTextColors(settings_holder)
setupSectionColors()
@ -304,6 +303,14 @@ class SettingsActivity : SimpleActivity() {
}
}
private fun setupAllowDownGesture() {
settings_allow_down_gesture.isChecked = config.allowDownGesture
settings_allow_down_gesture_holder.setOnClickListener {
settings_allow_down_gesture.toggle()
config.allowDownGesture = settings_allow_down_gesture.isChecked
}
}
private fun setupShowMediaCount() {
settings_show_media_count.isChecked = config.showMediaCount
settings_show_media_count_holder.setOnClickListener {
@ -459,11 +466,14 @@ class SettingsActivity : SimpleActivity() {
private fun setupUseRecycleBin() {
settings_empty_recycle_bin_holder.beVisibleIf(config.useRecycleBin)
settings_show_recycle_bin_holder.beVisibleIf(config.useRecycleBin)
settings_show_recycle_bin_last_holder.beVisibleIf(config.useRecycleBin && config.showRecycleBinAtFolders)
settings_use_recycle_bin.isChecked = config.useRecycleBin
settings_use_recycle_bin_holder.setOnClickListener {
settings_use_recycle_bin.toggle()
config.useRecycleBin = settings_use_recycle_bin.isChecked
settings_empty_recycle_bin_holder.beVisibleIf(config.useRecycleBin)
settings_show_recycle_bin_holder.beVisibleIf(config.useRecycleBin)
settings_show_recycle_bin_last_holder.beVisibleIf(config.useRecycleBin && config.showRecycleBinAtFolders)
}
}
@ -472,6 +482,18 @@ class SettingsActivity : SimpleActivity() {
settings_show_recycle_bin_holder.setOnClickListener {
settings_show_recycle_bin.toggle()
config.showRecycleBinAtFolders = settings_show_recycle_bin.isChecked
settings_show_recycle_bin_last_holder.beVisibleIf(config.useRecycleBin && config.showRecycleBinAtFolders)
}
}
private fun setupShowRecycleBinLast() {
settings_show_recycle_bin_last.isChecked = config.showRecycleBinLast
settings_show_recycle_bin_last_holder.setOnClickListener {
settings_show_recycle_bin_last.toggle()
config.showRecycleBinLast = settings_show_recycle_bin_last.isChecked
if (config.showRecycleBinLast) {
config.removePinnedFolders(setOf(RECYCLE_BIN))
}
}
}

View file

@ -2,7 +2,6 @@ package com.simplemobiletools.gallery.activities
import android.animation.Animator
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.Activity
import android.content.Intent
@ -20,13 +19,13 @@ import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.provider.MediaStore
import androidx.viewpager.widget.ViewPager
import android.util.DisplayMetrics
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.WindowManager
import android.view.animation.DecelerateInterpolator
import androidx.viewpager.widget.ViewPager
import com.bumptech.glide.Glide
import com.simplemobiletools.commons.dialogs.PropertiesDialog
import com.simplemobiletools.commons.dialogs.RenameItemDialog
@ -103,7 +102,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
initFavorites()
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
override fun onResume() {
super.onResume()
if (!hasPermission(PERMISSION_WRITE_STORAGE)) {
@ -112,9 +110,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
}
if (config.bottomActions) {
if (isLollipopPlus()) {
window.navigationBarColor = Color.TRANSPARENT
}
} else {
setTranslucentNavigation()
}
@ -135,10 +131,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
}
supportActionBar?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
if (isLollipopPlus()) {
window.statusBarColor = Color.TRANSPARENT
}
}
override fun onPause() {
super.onPause()
@ -225,7 +219,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
supportActionBar?.title = mPath.getFilenameFromPath()
view_pager.onGlobalLayout {
if (!isActivityDestroyed()) {
if (!isDestroyed) {
if (mMediaFiles.isNotEmpty()) {
gotMedia(mMediaFiles as ArrayList<ThumbnailItem>)
}
@ -365,7 +359,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
private fun updatePagerItems(media: MutableList<Medium>) {
val pagerAdapter = MyPagerAdapter(this, supportFragmentManager, media)
if (!isActivityDestroyed()) {
if (!isDestroyed) {
view_pager.apply {
adapter = pagerAdapter
currentItem = mPos
@ -384,7 +378,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
private fun startSlideshow() {
if (getMediaForSlideshow()) {
view_pager.onGlobalLayout {
if (!isActivityDestroyed()) {
if (!isDestroyed) {
hideSystemUI(true)
mSlideshowInterval = config.slideshowInterval
mSlideshowMoveBackwards = config.slideshowMoveBackwards
@ -434,7 +428,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
val dragOffset = dragPosition - oldDragPosition
oldDragPosition = dragPosition
try {
view_pager.fakeDragBy(dragOffset * (if (forward) 1f else -1f))
view_pager.fakeDragBy(dragOffset * (if (forward) -1f else 1f))
} catch (e: Exception) {
stopSlideshow()
}
@ -450,9 +444,9 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
private fun slideshowEnded(forward: Boolean) {
if (config.loopSlideshow) {
if (forward) {
view_pager.setCurrentItem(0, false)
} else {
view_pager.setCurrentItem(view_pager.adapter!!.count - 1, false)
} else {
view_pager.setCurrentItem(0, false)
}
} else {
stopSlideshow()
@ -474,7 +468,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
if (mIsSlideshowActive) {
if (getCurrentMedium()!!.isImage() || getCurrentMedium()!!.isGIF()) {
mSlideshowHandler.postDelayed({
if (mIsSlideshowActive && !isActivityDestroyed()) {
if (mIsSlideshowActive && !isDestroyed) {
swipeToNextMedium()
}
}, mSlideshowInterval * 1000L)
@ -980,18 +974,11 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
initBottomActionsLayout()
}
@SuppressLint("NewApi")
private fun measureScreen() {
val metrics = DisplayMetrics()
if (isJellyBean1Plus()) {
windowManager.defaultDisplay.getRealMetrics(metrics)
screenWidth = metrics.widthPixels
screenHeight = metrics.heightPixels
} else {
windowManager.defaultDisplay.getMetrics(metrics)
screenWidth = metrics.widthPixels
screenHeight = metrics.heightPixels
}
}
private fun refreshViewPager() {

View file

@ -1,6 +1,5 @@
package com.simplemobiletools.gallery.adapters
import android.util.SparseArray
import android.view.Menu
import android.view.View
import android.view.ViewGroup
@ -11,6 +10,7 @@ import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.dialogs.PropertiesDialog
import com.simplemobiletools.commons.dialogs.RenameItemDialog
import com.simplemobiletools.commons.dialogs.RenameItemsDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.OTG_PATH
import com.simplemobiletools.commons.models.FileDirItem
@ -26,8 +26,6 @@ import com.simplemobiletools.gallery.models.AlbumCover
import com.simplemobiletools.gallery.models.Directory
import kotlinx.android.synthetic.main.directory_item_list.view.*
import java.io.File
import java.util.*
import kotlin.collections.ArrayList
class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directory>, val listener: DirectoryOperationsListener?, recyclerView: MyRecyclerView,
val isPickIntent: Boolean, fastScroller: FastScroller? = null, itemClick: (Any) -> Unit) :
@ -48,14 +46,6 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
override fun getActionMenuId() = R.menu.cab_directories
override fun prepareItemSelection(viewHolder: ViewHolder) {
viewHolder.itemView.dir_check?.background?.applyColorFilter(primaryColor)
}
override fun markViewHolderSelection(select: Boolean, viewHolder: ViewHolder?) {
viewHolder?.itemView?.dir_check?.beVisibleIf(select)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutType = if (isListViewType) R.layout.directory_item_list else R.layout.directory_item_grid
return createViewHolder(layoutType, parent)
@ -63,34 +53,35 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) {
val dir = dirs.getOrNull(position) ?: return
val view = holder.bindView(dir, true, !isPickIntent) { itemView, adapterPosition ->
holder.bindView(dir, true, !isPickIntent) { itemView, adapterPosition ->
setupView(itemView, dir)
}
bindViewHolder(holder, position, view)
bindViewHolder(holder)
}
override fun getItemCount() = dirs.size
override fun prepareActionMode(menu: Menu) {
if (getSelectedPaths().isEmpty()) {
val selectedPaths = getSelectedPaths()
if (selectedPaths.isEmpty()) {
return
}
val selectedPaths = getSelectedPaths()
val isOneItemSelected = isOneItemSelected()
menu.apply {
findItem(R.id.cab_rename).isVisible = isOneItemSelected() && !selectedPaths.contains(FAVORITES) && !selectedPaths.contains(RECYCLE_BIN)
findItem(R.id.cab_change_cover_image).isVisible = isOneItemSelected()
findItem(R.id.cab_rename).isVisible = !selectedPaths.contains(FAVORITES) && !selectedPaths.contains(RECYCLE_BIN)
findItem(R.id.cab_change_cover_image).isVisible = isOneItemSelected
findItem(R.id.cab_empty_recycle_bin).isVisible = isOneItemSelected() && selectedPaths.first() == RECYCLE_BIN
findItem(R.id.cab_empty_disable_recycle_bin).isVisible = isOneItemSelected() && selectedPaths.first() == RECYCLE_BIN
findItem(R.id.cab_empty_recycle_bin).isVisible = isOneItemSelected && selectedPaths.first() == RECYCLE_BIN
findItem(R.id.cab_empty_disable_recycle_bin).isVisible = isOneItemSelected && selectedPaths.first() == RECYCLE_BIN
checkHideBtnVisibility(this)
checkPinBtnVisibility(this)
checkHideBtnVisibility(this, selectedPaths)
checkPinBtnVisibility(this, selectedPaths)
}
}
override fun actionItemPressed(id: Int) {
if (selectedPositions.isEmpty()) {
if (selectedKeys.isEmpty()) {
return
}
@ -117,49 +108,33 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
override fun getIsItemSelectable(position: Int) = true
override fun getItemSelectionKey(position: Int) = dirs.getOrNull(position)?.path?.hashCode()
override fun getItemKeyPosition(key: Int) = dirs.indexOfFirst { it.path.hashCode() == key }
override fun onViewRecycled(holder: ViewHolder) {
super.onViewRecycled(holder)
if (!activity.isActivityDestroyed()) {
Glide.with(activity).clear(holder.itemView?.dir_thumbnail!!)
if (!activity.isDestroyed) {
Glide.with(activity).clear(holder.itemView.dir_thumbnail!!)
}
}
private fun checkHideBtnVisibility(menu: Menu) {
var hiddenCnt = 0
var unhiddenCnt = 0
selectedPositions.mapNotNull { dirs.getOrNull(it)?.path }.forEach {
if (File(it).doesThisOrParentHaveNoMedia()) {
hiddenCnt++
} else {
unhiddenCnt++
}
private fun checkHideBtnVisibility(menu: Menu, selectedPaths: ArrayList<String>) {
menu.findItem(R.id.cab_hide).isVisible = selectedPaths.any { !File(it).doesThisOrParentHaveNoMedia() }
menu.findItem(R.id.cab_unhide).isVisible = selectedPaths.any { File(it).doesThisOrParentHaveNoMedia() }
}
menu.findItem(R.id.cab_hide).isVisible = unhiddenCnt > 0
menu.findItem(R.id.cab_unhide).isVisible = hiddenCnt > 0
}
private fun checkPinBtnVisibility(menu: Menu) {
private fun checkPinBtnVisibility(menu: Menu, selectedPaths: ArrayList<String>) {
val pinnedFolders = config.pinnedFolders
var pinnedCnt = 0
var unpinnedCnt = 0
selectedPositions.mapNotNull { dirs.getOrNull(it)?.path }.forEach {
if (pinnedFolders.contains(it)) {
pinnedCnt++
} else {
unpinnedCnt++
}
}
menu.findItem(R.id.cab_pin).isVisible = unpinnedCnt > 0
menu.findItem(R.id.cab_unpin).isVisible = pinnedCnt > 0
menu.findItem(R.id.cab_pin).isVisible = selectedPaths.any { !pinnedFolders.contains(it) }
menu.findItem(R.id.cab_unpin).isVisible = selectedPaths.any { pinnedFolders.contains(it) }
}
private fun showProperties() {
if (selectedPositions.size <= 1) {
val path = dirs[selectedPositions.first()].path
if (selectedKeys.size <= 1) {
val path = getFirstSelectedItemPath() ?: return
if (path != FAVORITES && path != RECYCLE_BIN) {
PropertiesDialog(activity, dirs[selectedPositions.first()].path, config.shouldShowHidden)
PropertiesDialog(activity, path, config.shouldShowHidden)
}
} else {
PropertiesDialog(activity, getSelectedPaths().filter { it != FAVORITES && it != RECYCLE_BIN }.toMutableList(), config.shouldShowHidden)
@ -167,7 +142,8 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
}
private fun renameDir() {
val firstDir = dirs[selectedPositions.first()]
if (selectedKeys.size == 1) {
val firstDir = getFirstSelectedItem() ?: return
val sourcePath = firstDir.path
val dir = File(sourcePath)
if (activity.isAStorageRootFolder(dir.absolutePath)) {
@ -189,6 +165,12 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
}.start()
}
}
} else {
val paths = getSelectedPaths().filter { !activity.isAStorageRootFolder(it) } as ArrayList<String>
RenameItemsDialog(activity, paths) {
listener?.refreshItems()
}
}
}
private fun toggleFoldersVisibility(hide: Boolean) {
@ -283,18 +265,6 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
notifyItemRemoved(it)
}
val newViewHolders = SparseArray<ViewHolder>()
val cnt = viewHolders.size()
for (i in 0..cnt) {
if (affectedPositions.contains(i)) {
continue
}
val view = viewHolders.get(i, null)
val newIndex = i - selectedPositions.count { it <= i }
newViewHolders.put(newIndex, view)
}
viewHolders = newViewHolders
currentDirectoriesHash = newDirs.hashCode()
dirs = newDirs
@ -330,26 +300,24 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
private fun pinFolders(pin: Boolean) {
if (pin) {
config.addPinnedFolders(getSelectedPaths())
config.addPinnedFolders(getSelectedPaths().toHashSet())
} else {
config.removePinnedFolders(getSelectedPaths())
config.removePinnedFolders(getSelectedPaths().toHashSet())
}
currentDirectoriesHash = 0
pinnedFolders = config.pinnedFolders
listener?.recheckPinnedFolders()
notifyDataSetChanged()
finishActMode()
}
private fun copyMoveTo(isCopyOperation: Boolean) {
val paths = ArrayList<String>()
val showHidden = activity.config.shouldShowHidden
selectedPositions.forEach {
val path = dirs[it].path
if (path.startsWith(OTG_PATH)) {
paths.addAll(getOTGFilePaths(path, showHidden))
} else if (path != FAVORITES) {
File(path).listFiles()?.filter {
getSelectedPaths().forEach {
if (it.startsWith(OTG_PATH)) {
paths.addAll(getOTGFilePaths(it, showHidden))
} else if (it != FAVORITES) {
File(it).listFiles()?.filter {
!activity.getIsPathDirectory(it.absolutePath) && it.isMediaFile() && (showHidden || !it.name.startsWith('.'))
}?.mapTo(paths) { it.absolutePath }
}
@ -378,9 +346,9 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
if (config.skipDeleteConfirmation) {
deleteFolders()
} else {
val itemsCnt = selectedPositions.size
val itemsCnt = selectedKeys.size
val items = resources.getQuantityString(R.plurals.delete_items, itemsCnt, itemsCnt)
val fileDirItem = dirs.getOrNull(selectedPositions.first()) ?: return
val fileDirItem = getFirstSelectedItem() ?: return
val baseString = if (!config.useRecycleBin || (isOneItemSelected() && fileDirItem.isRecycleBin()) || (isOneItemSelected() && fileDirItem.areFavorites())) {
R.string.deletion_confirmation
} else {
@ -397,29 +365,24 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
}
private fun deleteFolders() {
if (selectedPositions.isEmpty()) {
if (selectedKeys.isEmpty()) {
return
}
val folders = ArrayList<File>(selectedPositions.size)
val removeFolders = ArrayList<Directory>(selectedPositions.size)
var SAFPath = ""
selectedPositions.forEach {
if (dirs.size > it) {
val path = dirs[it].path
val selectedDirs = getSelectedItems()
selectedDirs.forEach {
val path = it.path
if (activity.needsStupidWritePermissions(path) && config.treeUri.isEmpty()) {
SAFPath = path
}
}
}
activity.handleSAFDialog(SAFPath) {
selectedPositions.sortedDescending().forEach {
val directory = dirs.getOrNull(it)
if (directory != null) {
if (directory.areFavorites() || directory.isRecycleBin()) {
if (directory.isRecycleBin()) {
val foldersToDelete = ArrayList<File>(selectedKeys.size)
selectedDirs.forEach {
if (it.areFavorites() || it.isRecycleBin()) {
if (it.isRecycleBin()) {
tryEmptyRecycleBin(false)
} else {
Thread {
@ -428,28 +391,23 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
}.start()
}
if (selectedPositions.size == 1) {
if (selectedKeys.size == 1) {
finishActMode()
} else {
selectedPositions.remove(it)
toggleItemSelection(false, it)
}
} else {
folders.add(File(directory.path))
removeFolders.add(directory)
}
foldersToDelete.add(File(it.path))
}
}
listener?.deleteFolders(folders)
listener?.deleteFolders(foldersToDelete)
}
}
private fun changeAlbumCover(useDefault: Boolean) {
if (selectedPositions.size != 1)
if (selectedKeys.size != 1)
return
val path = dirs[selectedPositions.first()].path
val path = getFirstSelectedItemPath() ?: return
if (useDefault) {
val albumCovers = getAlbumCoversWithout(path)
@ -480,15 +438,15 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
listener?.refreshItems()
}
private fun getSelectedPaths(): HashSet<String> {
val paths = HashSet<String>(selectedPositions.size)
selectedPositions.forEach {
(dirs.getOrNull(it))?.apply {
paths.add(path)
}
}
return paths
}
private fun getSelectedItems() = dirs.filter { selectedKeys.contains(it.path.hashCode()) } as ArrayList<Directory>
private fun getSelectedPaths() = getSelectedItems().map { it.path } as ArrayList<String>
private fun getFirstSelectedItem() = getItemWithKey(selectedKeys.first())
private fun getFirstSelectedItemPath() = getFirstSelectedItem()?.path
private fun getItemWithKey(key: Int): Directory? = dirs.firstOrNull { it.path.hashCode() == key }
fun updateDirs(newDirs: ArrayList<Directory>) {
val directories = newDirs.clone() as ArrayList<Directory>
@ -516,6 +474,7 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
}
private fun setupView(view: View, directory: Directory) {
val isSelected = selectedKeys.contains(directory.path.hashCode())
view.apply {
dir_name.text = directory.name
dir_path?.text = "${directory.path.substringBeforeLast("/")}/"
@ -528,6 +487,11 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
else -> TYPE_IMAGES
}
dir_check?.beVisibleIf(isSelected)
if (isSelected) {
dir_check.background?.applyColorFilter(primaryColor)
}
activity.loadImage(thumbnailType, directory.tmb, dir_thumbnail, scrollHorizontally, animateGifs, cropThumbnails)
dir_pin.beVisibleIf(pinnedFolders.contains(directory.path))
dir_location.beVisibleIf(directory.location != LOCAITON_INTERNAL)

View file

@ -1,37 +1,34 @@
package com.simplemobiletools.gallery.adapters
import android.content.Context
import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.interfaces.FilterAdapterListener
import com.simplemobiletools.gallery.models.FilterItem
import kotlinx.android.synthetic.main.editor_filter_item.view.*
import java.util.*
class FiltersAdapter(val context: Context, val filterItems: ArrayList<FilterItem>, val itemClick: (Int) -> Unit) : RecyclerView.Adapter<FiltersAdapter.ViewHolder>(),
FilterAdapterListener {
class FiltersAdapter(val context: Context, val filterItems: ArrayList<FilterItem>, val itemClick: (Int) -> Unit) : RecyclerView.Adapter<FiltersAdapter.ViewHolder>() {
private var currentSelection = filterItems.first()
private var strokeBackground = context.resources.getDrawable(R.drawable.stroke_background)
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindView(filterItems[position], strokeBackground)
holder.bindView(filterItems[position])
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.editor_filter_item, parent, false)
return ViewHolder(view, this)
return ViewHolder(view)
}
override fun getItemCount() = filterItems.size
override fun getCurrentFilter() = currentSelection
fun getCurrentFilter() = currentSelection
override fun setCurrentFilter(position: Int) {
private fun setCurrentFilter(position: Int) {
val filterItem = filterItems.getOrNull(position) ?: return
if (currentSelection != filterItem) {
currentSelection = filterItem
@ -40,19 +37,19 @@ class FiltersAdapter(val context: Context, val filterItems: ArrayList<FilterItem
}
}
class ViewHolder(view: View, val filterAdapterListener: FilterAdapterListener) : RecyclerView.ViewHolder(view) {
fun bindView(filterItem: FilterItem, strokeBackground: Drawable): View {
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindView(filterItem: FilterItem): View {
itemView.apply {
editor_filter_item_label.text = filterItem.filter.name
editor_filter_item_thumbnail.setImageBitmap(filterItem.bitmap)
editor_filter_item_thumbnail.background = if (filterAdapterListener.getCurrentFilter() == filterItem) {
editor_filter_item_thumbnail.background = if (getCurrentFilter() == filterItem) {
strokeBackground
} else {
null
}
setOnClickListener {
filterAdapterListener.setCurrentFilter(adapterPosition)
setCurrentFilter(adapterPosition)
}
}
return itemView

View file

@ -25,12 +25,6 @@ class ManageFoldersAdapter(activity: BaseSimpleActivity, var folders: ArrayList<
override fun prepareActionMode(menu: Menu) {}
override fun prepareItemSelection(viewHolder: ViewHolder) {}
override fun markViewHolderSelection(select: Boolean, viewHolder: ViewHolder?) {
viewHolder?.itemView?.manage_folder_holder?.isSelected = select
}
override fun actionItemPressed(id: Int) {
when (id) {
R.id.cab_remove -> removeSelection()
@ -41,20 +35,27 @@ class ManageFoldersAdapter(activity: BaseSimpleActivity, var folders: ArrayList<
override fun getIsItemSelectable(position: Int) = true
override fun getItemSelectionKey(position: Int) = folders.getOrNull(position)?.hashCode()
override fun getItemKeyPosition(key: Int) = folders.indexOfFirst { it.hashCode() == key }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_manage_folder, parent)
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val folder = folders[position]
val view = holder.bindView(folder, true, true) { itemView, adapterPosition ->
holder.bindView(folder, true, true) { itemView, adapterPosition ->
setupView(itemView, folder)
}
bindViewHolder(holder, position, view)
bindViewHolder(holder)
}
override fun getItemCount() = folders.size
private fun getSelectedItems() = folders.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<String>
private fun setupView(view: View, folder: String) {
view.apply {
manage_folder_holder?.isSelected = selectedKeys.contains(folder.hashCode())
manage_folder_title.apply {
text = folder
setTextColor(config.textColor)
@ -63,20 +64,20 @@ class ManageFoldersAdapter(activity: BaseSimpleActivity, var folders: ArrayList<
}
private fun removeSelection() {
val removeFolders = ArrayList<String>(selectedPositions.size)
val removeFolders = ArrayList<String>(selectedKeys.size)
val positions = getSelectedItemPositions()
selectedPositions.sortedDescending().forEach {
val folder = folders[it]
removeFolders.add(folder)
getSelectedItems().forEach {
removeFolders.add(it)
if (isShowingExcludedFolders) {
config.removeExcludedFolder(folder)
config.removeExcludedFolder(it)
} else {
config.removeIncludedFolder(folder)
config.removeIncludedFolder(it)
}
}
folders.removeAll(removeFolders)
removeSelectedItems()
removeSelectedItems(positions)
if (folders.isEmpty()) {
listener?.refreshItems()
}

View file

@ -27,12 +27,6 @@ class ManageHiddenFoldersAdapter(activity: BaseSimpleActivity, var folders: Arra
override fun prepareActionMode(menu: Menu) {}
override fun prepareItemSelection(viewHolder: ViewHolder) {}
override fun markViewHolderSelection(select: Boolean, viewHolder: ViewHolder?) {
viewHolder?.itemView?.manage_folder_holder?.isSelected = select
}
override fun actionItemPressed(id: Int) {
when (id) {
R.id.cab_unhide -> tryUnhideFolders()
@ -43,20 +37,27 @@ class ManageHiddenFoldersAdapter(activity: BaseSimpleActivity, var folders: Arra
override fun getIsItemSelectable(position: Int) = true
override fun getItemSelectionKey(position: Int) = folders.getOrNull(position)?.hashCode()
override fun getItemKeyPosition(key: Int) = folders.indexOfFirst { it.hashCode() == key }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_manage_folder, parent)
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val folder = folders[position]
val view = holder.bindView(folder, true, true) { itemView, adapterPosition ->
holder.bindView(folder, true, true) { itemView, adapterPosition ->
setupView(itemView, folder)
}
bindViewHolder(holder, position, view)
bindViewHolder(holder)
}
override fun getItemCount() = folders.size
private fun getSelectedItems() = folders.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<String>
private fun setupView(view: View, folder: String) {
view.apply {
manage_folder_holder?.isSelected = selectedKeys.contains(folder.hashCode())
manage_folder_title.apply {
text = folder
setTextColor(config.textColor)
@ -65,12 +66,12 @@ class ManageHiddenFoldersAdapter(activity: BaseSimpleActivity, var folders: Arra
}
private fun tryUnhideFolders() {
val removeFolders = ArrayList<String>(selectedPositions.size)
val removeFolders = ArrayList<String>(selectedKeys.size)
val sdCardPaths = ArrayList<String>()
selectedPositions.forEach {
if (activity.isPathOnSD(folders[it])) {
sdCardPaths.add(folders[it])
getSelectedItems().forEach {
if (activity.isPathOnSD(it)) {
sdCardPaths.add(it)
}
}
@ -84,14 +85,14 @@ class ManageHiddenFoldersAdapter(activity: BaseSimpleActivity, var folders: Arra
}
private fun unhideFolders(removeFolders: ArrayList<String>) {
selectedPositions.sortedDescending().forEach {
val folder = folders[it]
removeFolders.add(folder)
activity.removeNoMedia(folder)
val position = getSelectedItemPositions()
getSelectedItems().forEach {
removeFolders.add(it)
activity.removeNoMedia(it)
}
folders.removeAll(removeFolders)
removeSelectedItems()
removeSelectedItems(position)
if (folders.isEmpty()) {
listener?.refreshItems()
}

View file

@ -13,6 +13,7 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.dialogs.PropertiesDialog
import com.simplemobiletools.commons.dialogs.RenameItemDialog
import com.simplemobiletools.commons.dialogs.RenameItemsDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.OTG_PATH
import com.simplemobiletools.commons.models.FileDirItem
@ -61,14 +62,6 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
override fun getActionMenuId() = R.menu.cab_media
override fun prepareItemSelection(viewHolder: ViewHolder) {
viewHolder.itemView?.medium_check?.background?.applyColorFilter(primaryColor)
}
override fun markViewHolderSelection(select: Boolean, viewHolder: ViewHolder?) {
viewHolder?.itemView?.medium_check?.beVisibleIf(select)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutType = if (viewType == ITEM_SECTION) {
R.layout.thumbnail_section
@ -89,14 +82,14 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
}
val allowLongPress = !allowMultiplePicks && tmbItem is Medium
val view = holder.bindView(tmbItem, tmbItem is Medium, allowLongPress) { itemView, adapterPosition ->
holder.bindView(tmbItem, tmbItem is Medium, allowLongPress) { itemView, adapterPosition ->
if (tmbItem is Medium) {
setupThumbnail(itemView, tmbItem)
} else {
setupSection(itemView, tmbItem as ThumbnailSection)
}
}
bindViewHolder(holder, position, view)
bindViewHolder(holder)
}
override fun getItemCount() = media.size
@ -111,19 +104,26 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
}
override fun prepareActionMode(menu: Menu) {
menu.apply {
findItem(R.id.cab_rename).isVisible = isOneItemSelected() && getSelectedMedia().firstOrNull()?.getIsInRecycleBin() == false
findItem(R.id.cab_open_with).isVisible = isOneItemSelected()
findItem(R.id.cab_confirm_selection).isVisible = isAGetIntent && allowMultiplePicks && selectedPositions.size > 0
findItem(R.id.cab_restore_recycle_bin_files).isVisible = getSelectedPaths().all { it.startsWith(activity.filesDir.absolutePath) }
val selectedItems = getSelectedItems()
if (selectedItems.isEmpty()) {
return
}
checkHideBtnVisibility(this)
checkFavoriteBtnVisibility(this)
val isOneItemSelected = isOneItemSelected()
val selectedPaths = selectedItems.map { it.path } as ArrayList<String>
menu.apply {
findItem(R.id.cab_rename).isVisible = selectedItems.firstOrNull()?.getIsInRecycleBin() == false
findItem(R.id.cab_open_with).isVisible = isOneItemSelected
findItem(R.id.cab_confirm_selection).isVisible = isAGetIntent && allowMultiplePicks && selectedKeys.isNotEmpty()
findItem(R.id.cab_restore_recycle_bin_files).isVisible = selectedPaths.all { it.startsWith(activity.filesDir.absolutePath) }
checkHideBtnVisibility(this, selectedItems)
checkFavoriteBtnVisibility(this, selectedItems)
}
}
override fun actionItemPressed(id: Int) {
if (selectedPositions.isEmpty()) {
if (selectedKeys.isEmpty()) {
return
}
@ -141,9 +141,9 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
R.id.cab_copy_to -> copyMoveTo(true)
R.id.cab_move_to -> copyMoveTo(false)
R.id.cab_select_all -> selectAll()
R.id.cab_open_with -> activity.openPath(getCurrentPath(), true)
R.id.cab_open_with -> openPath()
R.id.cab_fix_date_taken -> fixDateTaken()
R.id.cab_set_as -> activity.setAs(getCurrentPath())
R.id.cab_set_as -> setAs()
R.id.cab_delete -> checkDeleteConfirmation()
}
}
@ -152,12 +152,16 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
override fun getIsItemSelectable(position: Int) = !isASectionTitle(position)
override fun getItemSelectionKey(position: Int) = (media.getOrNull(position) as? Medium)?.path?.hashCode()
override fun getItemKeyPosition(key: Int) = media.indexOfFirst { (it as? Medium)?.path?.hashCode() == key }
override fun onViewRecycled(holder: ViewHolder) {
super.onViewRecycled(holder)
if (!activity.isActivityDestroyed()) {
if (!activity.isDestroyed) {
val itemView = holder.itemView
visibleItemPaths.remove(itemView?.photo_name?.tag)
val tmb = itemView?.medium_thumbnail
visibleItemPaths.remove(itemView.photo_name?.tag)
val tmb = itemView.medium_thumbnail
if (tmb != null) {
Glide.with(activity).clear(tmb)
}
@ -166,35 +170,15 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
fun isASectionTitle(position: Int) = media.getOrNull(position) is ThumbnailSection
private fun checkHideBtnVisibility(menu: Menu) {
var hiddenCnt = 0
var unhiddenCnt = 0
getSelectedMedia().forEach {
if (it.isHidden()) {
hiddenCnt++
} else {
unhiddenCnt++
}
private fun checkHideBtnVisibility(menu: Menu, selectedItems: ArrayList<Medium>) {
val isInRecycleBin = selectedItems.firstOrNull()?.getIsInRecycleBin() == true
menu.findItem(R.id.cab_hide).isVisible = !isInRecycleBin && selectedItems.any { !it.isHidden() }
menu.findItem(R.id.cab_unhide).isVisible = !isInRecycleBin && selectedItems.any { it.isHidden() }
}
val isInRecycleBin = getSelectedMedia().firstOrNull()?.getIsInRecycleBin() == true
menu.findItem(R.id.cab_hide).isVisible = unhiddenCnt > 0 && !isInRecycleBin
menu.findItem(R.id.cab_unhide).isVisible = hiddenCnt > 0 && !isInRecycleBin
}
private fun checkFavoriteBtnVisibility(menu: Menu) {
var favoriteCnt = 0
var nonFavoriteCnt = 0
getSelectedMedia().forEach {
if (it.isFavorite) {
favoriteCnt++
} else {
nonFavoriteCnt++
}
}
menu.findItem(R.id.cab_add_to_favorites).isVisible = nonFavoriteCnt > 0
menu.findItem(R.id.cab_remove_from_favorites).isVisible = favoriteCnt > 0
private fun checkFavoriteBtnVisibility(menu: Menu, selectedItems: ArrayList<Medium>) {
menu.findItem(R.id.cab_add_to_favorites).isVisible = selectedItems.any { !it.isFavorite }
menu.findItem(R.id.cab_remove_from_favorites).isVisible = selectedItems.any { it.isFavorite }
}
private fun confirmSelection() {
@ -202,8 +186,9 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
}
private fun showProperties() {
if (selectedPositions.size <= 1) {
PropertiesDialog(activity, (media[selectedPositions.first()] as Medium).path, config.shouldShowHidden)
if (selectedKeys.size <= 1) {
val path = getFirstSelectedItemPath() ?: return
PropertiesDialog(activity, path, config.shouldShowHidden)
} else {
val paths = getSelectedPaths()
PropertiesDialog(activity, paths, config.shouldShowHidden)
@ -211,7 +196,8 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
}
private fun renameFile() {
val oldPath = getCurrentPath()
if (selectedKeys.size == 1) {
val oldPath = getFirstSelectedItemPath() ?: return
RenameItemDialog(activity, oldPath) {
Thread {
activity.updateDBMediaPath(oldPath, it)
@ -223,15 +209,33 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
}
}.start()
}
} else {
RenameItemsDialog(activity, getSelectedPaths()) {
enableInstantLoad()
listener?.refreshItems()
finishActMode()
}
}
}
private fun editFile() {
activity.openEditor(getCurrentPath())
val path = getFirstSelectedItemPath() ?: return
activity.openEditor(path)
}
private fun openPath() {
val path = getFirstSelectedItemPath() ?: return
activity.openPath(path, true)
}
private fun setAs() {
val path = getFirstSelectedItemPath() ?: return
activity.setAs(path)
}
private fun toggleFileVisibility(hide: Boolean) {
Thread {
getSelectedMedia().forEach {
getSelectedItems().forEach {
activity.toggleFileVisibility(it.path, hide)
}
activity.runOnUiThread {
@ -244,7 +248,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
private fun toggleFavorites(add: Boolean) {
Thread {
val mediumDao = activity.galleryDB.MediumDao()
getSelectedMedia().forEach {
getSelectedItems().forEach {
it.isFavorite = add
mediumDao.updateFavorite(it.path, add)
}
@ -263,9 +267,9 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
}
private fun shareMedia() {
if (selectedPositions.size == 1 && selectedPositions.first() != -1) {
activity.shareMediumPath(getSelectedMedia().first().path)
} else if (selectedPositions.size > 1) {
if (selectedKeys.size == 1 && selectedKeys.first() != -1) {
activity.shareMediumPath(getSelectedItems().first().path)
} else if (selectedKeys.size > 1) {
activity.shareMediaPaths(getSelectedPaths())
}
}
@ -345,7 +349,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
}
private fun askConfirmDelete() {
val items = resources.getQuantityString(R.plurals.delete_items, selectedPositions.size, selectedPositions.size)
val items = resources.getQuantityString(R.plurals.delete_items, selectedKeys.size, selectedKeys.size)
val isRecycleBin = getSelectedPaths().first().startsWith(activity.filesDir.absolutePath)
val baseString = if (config.useRecycleBin && !isRecycleBin) R.string.move_to_recycle_bin_confirmation else R.string.deletion_confirmation
val question = String.format(resources.getString(baseString), items)
@ -355,48 +359,35 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
}
}
private fun getCurrentPath() = (media[selectedPositions.first()] as Medium).path
private fun deleteFiles() {
if (selectedPositions.isEmpty()) {
if (selectedKeys.isEmpty()) {
return
}
val fileDirItems = ArrayList<FileDirItem>(selectedPositions.size)
val removeMedia = ArrayList<Medium>(selectedPositions.size)
if (media.size <= selectedPositions.first()) {
finishActMode()
return
}
val SAFPath = (media[selectedPositions.first()] as Medium).path
val SAFPath = getSelectedPaths().firstOrNull { activity.isPathOnSD(it) } ?: getFirstSelectedItemPath() ?: return
activity.handleSAFDialog(SAFPath) {
selectedPositions.sortedDescending().forEach {
val thumbnailItem = media.getOrNull(it)
if (thumbnailItem is Medium) {
fileDirItems.add(FileDirItem(thumbnailItem.path, thumbnailItem.name))
removeMedia.add(thumbnailItem)
}
val fileDirItems = ArrayList<FileDirItem>(selectedKeys.size)
val removeMedia = ArrayList<Medium>(selectedKeys.size)
val position = getSelectedItemPositions()
getSelectedItems().forEach {
fileDirItems.add(FileDirItem(it.path, it.name))
removeMedia.add(it)
}
media.removeAll(removeMedia)
listener?.tryDeleteFiles(fileDirItems)
removeSelectedItems()
removeSelectedItems(position)
}
}
private fun getSelectedMedia(): List<Medium> {
val selectedMedia = ArrayList<Medium>(selectedPositions.size)
selectedPositions.forEach {
(media.getOrNull(it) as? Medium)?.apply {
selectedMedia.add(this)
}
}
return selectedMedia
}
private fun getSelectedItems() = media.filter { selectedKeys.contains((it as? Medium)?.path?.hashCode()) } as ArrayList<Medium>
private fun getSelectedPaths() = getSelectedMedia().map { it.path } as ArrayList<String>
private fun getSelectedPaths() = getSelectedItems().map { it.path } as ArrayList<String>
private fun getFirstSelectedItemPath() = getItemWithKey(selectedKeys.first())?.path
private fun getItemWithKey(key: Int): Medium? = media.firstOrNull { (it as? Medium)?.path?.hashCode() == key } as? Medium
fun updateMedia(newMedia: ArrayList<ThumbnailItem>) {
val thumbnailItems = newMedia.clone() as ArrayList<ThumbnailItem>
@ -437,12 +428,18 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
fun getItemBubbleText(position: Int, sorting: Int) = (media[position] as? Medium)?.getBubbleText(sorting)
private fun setupThumbnail(view: View, medium: Medium) {
val isSelected = selectedKeys.contains(medium.path.hashCode())
view.apply {
play_outline.beVisibleIf(medium.isVideo())
photo_name.beVisibleIf(displayFilenames || isListViewType)
photo_name.text = medium.name
photo_name.tag = medium.path
medium_check?.beVisibleIf(isSelected)
if (isSelected) {
medium_check?.background?.applyColorFilter(primaryColor)
}
var path = medium.path
if (hasOTGConnected && path.startsWith(OTG_PATH)) {
path = path.getOTGPublicPath(context)

View file

@ -2,11 +2,11 @@ package com.simplemobiletools.gallery.adapters
import android.os.Bundle
import android.os.Parcelable
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.viewpager.widget.PagerAdapter
import android.view.ViewGroup
import com.simplemobiletools.gallery.activities.ViewPagerActivity
import com.simplemobiletools.gallery.fragments.PhotoFragment
import com.simplemobiletools.gallery.fragments.VideoFragment

View file

@ -4,10 +4,7 @@ import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.RecyclerView
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.dialogs.FilePickerDialog
import com.simplemobiletools.commons.extensions.beGoneIf
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.views.MyGridLayoutManager
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.adapters.DirectoryAdapter
@ -24,6 +21,7 @@ class PickDirectoryDialog(val activity: BaseSimpleActivity, val sourcePath: Stri
var shownDirectories = ArrayList<Directory>()
var view = activity.layoutInflater.inflate(R.layout.dialog_directory_picker, null)
var isGridViewType = activity.config.viewTypeFolders == VIEW_TYPE_GRID
var showHidden = activity.config.shouldShowHidden
init {
(view.directories_grid.layoutManager as MyGridLayoutManager).apply {
@ -36,10 +34,23 @@ class PickDirectoryDialog(val activity: BaseSimpleActivity, val sourcePath: Stri
.setNegativeButton(R.string.cancel, null)
.setNeutralButton(R.string.other_folder) { dialogInterface, i -> showOtherFolder() }
.create().apply {
activity.setupDialogStuff(view, this, R.string.select_destination)
activity.setupDialogStuff(view, this, R.string.select_destination) {
view.directories_show_hidden.beVisibleIf(!context.config.shouldShowHidden)
view.directories_show_hidden.setOnClickListener {
activity.handleHiddenFolderPasswordProtection {
view.directories_show_hidden.beGone()
showHidden = true
fetchDirectories(true)
}
}
}
}
activity.getCachedDirectories {
fetchDirectories(false)
}
private fun fetchDirectories(forceShowHidden: Boolean) {
activity.getCachedDirectories(forceShowHidden = forceShowHidden) {
if (it.isNotEmpty()) {
activity.runOnUiThread {
gotDirectories(activity.addTempFolderIfNeeded(it))
@ -49,8 +60,7 @@ class PickDirectoryDialog(val activity: BaseSimpleActivity, val sourcePath: Stri
}
private fun showOtherFolder() {
val showHidden = activity.config.shouldShowHidden
FilePickerDialog(activity, sourcePath, false, showHidden, true) {
FilePickerDialog(activity, sourcePath, false, showHidden, true, true) {
callback(it)
}
}

View file

@ -32,7 +32,7 @@ class SaveAsDialog(val activity: BaseSimpleActivity, val path: String, val appen
save_as_name.setText(name)
save_as_path.setOnClickListener {
FilePickerDialog(activity, realPath, false, false, true) {
FilePickerDialog(activity, realPath, false, false, true, true) {
save_as_path.text = activity.humanizePath(it)
realPath = it
}

View file

@ -3,8 +3,8 @@ package com.simplemobiletools.gallery.extensions
import android.app.Activity
import android.content.Intent
import android.provider.MediaStore
import androidx.appcompat.app.AppCompatActivity
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.extensions.*
@ -60,8 +60,8 @@ fun Activity.launchCamera() {
}
fun SimpleActivity.launchAbout() {
val licenses = LICENSE_GLIDE or LICENSE_CROPPER or LICENSE_MULTISELECT or LICENSE_RTL or LICENSE_SUBSAMPLING or LICENSE_PATTERN or
LICENSE_REPRINT or LICENSE_GIF_DRAWABLE or LICENSE_PHOTOVIEW or LICENSE_PICASSO or LICENSE_EXOPLAYER or LICENSE_PANORAMA_VIEW or LICENSE_SANSELAN or LICENSE_FILTERS
val licenses = LICENSE_GLIDE or LICENSE_CROPPER or LICENSE_RTL or LICENSE_SUBSAMPLING or LICENSE_PATTERN or LICENSE_REPRINT or LICENSE_GIF_DRAWABLE or
LICENSE_PHOTOVIEW or LICENSE_PICASSO or LICENSE_EXOPLAYER or LICENSE_PANORAMA_VIEW or LICENSE_SANSELAN or LICENSE_FILTERS
val faqItems = arrayListOf(
FAQItem(R.string.faq_5_title_commons, R.string.faq_5_text_commons),

View file

@ -8,7 +8,6 @@ import android.database.sqlite.SQLiteException
import android.graphics.Point
import android.graphics.drawable.PictureDrawable
import android.media.AudioManager
import android.os.Build
import android.provider.MediaStore
import android.view.WindowManager
import android.widget.ImageView
@ -88,7 +87,6 @@ val Context.usableScreenSize: Point
val Context.realScreenSize: Point
get() {
val size = Point()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
windowManager.defaultDisplay.getRealSize(size)
return size
}
@ -125,6 +123,14 @@ fun Context.movePinnedDirectoriesToFront(dirs: ArrayList<Directory>): ArrayList<
dirs.add(0, newFolder)
}
}
if (config.useRecycleBin && config.showRecycleBinAtFolders && config.showRecycleBinLast) {
val binIndex = dirs.indexOfFirst { it.isRecycleBin() }
if (binIndex != -1) {
val bin = dirs.removeAt(binIndex)
dirs.add(bin)
}
}
return dirs
}
@ -328,7 +334,7 @@ fun Context.loadSVG(path: String, target: MySquareImageView, cropThumbnails: Boo
.into(target)
}
fun Context.getCachedDirectories(getVideosOnly: Boolean = false, getImagesOnly: Boolean = false, directoryDao: DirectoryDao = galleryDB.DirectoryDao(), callback: (ArrayList<Directory>) -> Unit) {
fun Context.getCachedDirectories(getVideosOnly: Boolean = false, getImagesOnly: Boolean = false, directoryDao: DirectoryDao = galleryDB.DirectoryDao(), forceShowHidden: Boolean = false, callback: (ArrayList<Directory>) -> Unit) {
Thread {
val directories = try {
directoryDao.getAll() as ArrayList<Directory>
@ -336,11 +342,11 @@ fun Context.getCachedDirectories(getVideosOnly: Boolean = false, getImagesOnly:
ArrayList<Directory>()
}
if (!config.showRecycleBinAtFolders) {
if (!config.showRecycleBinAtFolders || !config.useRecycleBin) {
directories.removeAll { it.isRecycleBin() }
}
val shouldShowHidden = config.shouldShowHidden
val shouldShowHidden = config.shouldShowHidden || forceShowHidden
val excludedPaths = config.excludedFolders
val includedPaths = config.includedFolders
var filteredDirectories = directories.filter { it.path.shouldFolderBeVisible(excludedPaths, includedPaths, shouldShowHidden) } as ArrayList<Directory>

View file

@ -1,6 +1,5 @@
package com.simplemobiletools.gallery.fragments
import android.annotation.SuppressLint
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Bitmap
@ -29,14 +28,15 @@ import com.davemorrissey.labs.subscaleview.ImageSource
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.OTG_PATH
import com.simplemobiletools.commons.helpers.isJellyBean1Plus
import com.simplemobiletools.commons.helpers.isLollipopPlus
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.PanoramaActivity
import com.simplemobiletools.gallery.activities.PanoramaPhotoActivity
import com.simplemobiletools.gallery.activities.PhotoActivity
import com.simplemobiletools.gallery.activities.ViewPagerActivity
import com.simplemobiletools.gallery.extensions.*
import com.simplemobiletools.gallery.helpers.*
import com.simplemobiletools.gallery.helpers.MEDIUM
import com.simplemobiletools.gallery.helpers.PATH
import com.simplemobiletools.gallery.helpers.PicassoDecoder
import com.simplemobiletools.gallery.helpers.PicassoRegionDecoder
import com.simplemobiletools.gallery.models.Medium
import com.simplemobiletools.gallery.svg.SvgSoftwareLayerSetter
import com.squareup.picasso.Callback
@ -73,6 +73,7 @@ class PhotoFragment : ViewPagerFragment() {
private var storedAllowDeepZoomableImages = false
private var storedShowHighestQuality = false
private var storedAllowOneFingerZoom = false
private var mOriginalSubsamplingScale = 0f
private var storedExtendedDetails = 0
lateinit var view: ViewGroup
@ -99,6 +100,20 @@ class PhotoFragment : ViewPagerFragment() {
}
}
}
if (context.config.allowDownGesture) {
gif_view.setOnTouchListener { v, event ->
handleEvent(event)
false
}
subsampling_view.setOnTouchListener { v, event ->
if (view.subsampling_view.scale == mOriginalSubsamplingScale) {
handleEvent(event)
}
false
}
}
}
if (ViewPagerActivity.screenWidth == 0 || ViewPagerActivity.screenHeight == 0) {
@ -208,28 +223,18 @@ class PhotoFragment : ViewPagerFragment() {
}
}
@SuppressLint("NewApi")
private fun measureScreen() {
val metrics = DisplayMetrics()
if (isJellyBean1Plus()) {
activity!!.windowManager.defaultDisplay.getRealMetrics(metrics)
ViewPagerActivity.screenWidth = metrics.widthPixels
ViewPagerActivity.screenHeight = metrics.heightPixels
} else {
activity!!.windowManager.defaultDisplay.getMetrics(metrics)
ViewPagerActivity.screenWidth = metrics.widthPixels
ViewPagerActivity.screenHeight = metrics.heightPixels
}
}
private fun photoFragmentVisibilityChanged(isVisible: Boolean) {
if (isVisible) {
scheduleZoomableView()
} else {
isSubsamplingVisible = false
view.subsampling_view.recycle()
view.subsampling_view.beGone()
loadZoomableViewHandler.removeCallbacksAndMessages(null)
hideZoomableView()
}
}
@ -280,7 +285,7 @@ class PhotoFragment : ViewPagerFragment() {
}
private fun loadSVG() {
Glide.with(this)
Glide.with(context!!)
.`as`(PictureDrawable::class.java)
.listener(SvgSoftwareLayerSetter())
.load(medium.path)
@ -351,7 +356,7 @@ class PhotoFragment : ViewPagerFragment() {
}
private fun openPanorama() {
Intent(context, PanoramaActivity::class.java).apply {
Intent(context, PanoramaPhotoActivity::class.java).apply {
putExtra(PATH, medium.path)
startActivity(this)
}
@ -380,7 +385,7 @@ class PhotoFragment : ViewPagerFragment() {
maxScale = 10f
beVisible()
isQuickScaleEnabled = context.config.oneFingerZoom
setResetScaleOnSizeChange(context.config.screenRotation != ROTATE_BY_ASPECT_RATIO)
setResetScaleOnSizeChange(false)
setImage(ImageSource.uri(path))
orientation = rotation
setEagerLoadingEnabled(false)
@ -393,6 +398,7 @@ class PhotoFragment : ViewPagerFragment() {
val useWidth = if (imageOrientation == ORIENTATION_ROTATE_90 || imageOrientation == ORIENTATION_ROTATE_270) sHeight else sWidth
val useHeight = if (imageOrientation == ORIENTATION_ROTATE_90 || imageOrientation == ORIENTATION_ROTATE_270) sWidth else sHeight
setDoubleTapZoomScale(getDoubleTapZoomScale(useWidth, useHeight))
mOriginalSubsamplingScale = scale
}
override fun onTileLoadError(e: Exception?) {
@ -440,7 +446,7 @@ class PhotoFragment : ViewPagerFragment() {
false
}
view.panorama_outline.beVisibleIf(isPanorama && isLollipopPlus())
view.panorama_outline.beVisibleIf(isPanorama)
}
private fun getImageOrientation(): Int {
@ -514,7 +520,7 @@ class PhotoFragment : ViewPagerFragment() {
override fun onDestroyView() {
super.onDestroyView()
if (activity?.isActivityDestroyed() == false) {
if (activity?.isDestroyed == false) {
view.subsampling_view.recycle()
}
loadZoomableViewHandler.removeCallbacksAndMessages(null)
@ -531,12 +537,22 @@ class PhotoFragment : ViewPagerFragment() {
}, 50)
}
} else {
hideZoomableView()
loadImage()
}
initExtendedDetails()
}
private fun hideZoomableView() {
if (context?.config?.allowZoomingImages == true) {
isSubsamplingVisible = false
view.subsampling_view.recycle()
view.subsampling_view.beGone()
loadZoomableViewHandler.removeCallbacksAndMessages(null)
}
}
private fun photoClicked() {
listener?.fragmentClicked()
}

View file

@ -1,13 +1,11 @@
package com.simplemobiletools.gallery.fragments
import android.annotation.TargetApi
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Point
import android.graphics.SurfaceTexture
import android.media.AudioManager
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.util.DisplayMetrics
@ -28,31 +26,28 @@ import com.google.android.exoplayer2.upstream.DataSpec
import com.google.android.exoplayer2.upstream.FileDataSource
import com.google.android.exoplayer2.video.VideoListener
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.isJellyBean1Plus
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.PanoramaVideoActivity
import com.simplemobiletools.gallery.activities.VideoActivity
import com.simplemobiletools.gallery.extensions.*
import com.simplemobiletools.gallery.helpers.MEDIUM
import com.simplemobiletools.gallery.helpers.MediaSideScroll
import com.simplemobiletools.gallery.helpers.*
import com.simplemobiletools.gallery.models.Medium
import com.simplemobiletools.gallery.views.MediaSideScroll
import kotlinx.android.synthetic.main.bottom_video_time_holder.view.*
import kotlinx.android.synthetic.main.pager_video_item.view.*
import java.io.File
class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, SeekBar.OnSeekBarChangeListener {
private val PROGRESS = "progress"
private val MIN_SKIP_LENGTH = 2000
private val HIDE_PAUSE_DELAY = 2000L
private val PLAY_PAUSE_VISIBLE_ALPHA = 0.8f
private var mTextureView: TextureView? = null
private var mCurrTimeView: TextView? = null
private var mSeekBar: SeekBar? = null
private var mTimeHolder: View? = null
private var mView: View? = null
private var mExoPlayer: SimpleExoPlayer? = null
private var mVideoSize = Point(0, 0)
private var mTimerHandler = Handler()
private var mHidePauseHandler = Handler()
private var mHidePlayPauseHandler = Handler()
private var mIsPlaying = false
private var mIsDragged = false
@ -60,6 +55,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
private var mIsFragmentVisible = false
private var mWasFragmentInit = false
private var mIsExoPlayerInitialized = false
private var mIsPanorama = false
private var mCurrTime = 0
private var mDuration = 0
@ -68,8 +64,9 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
private var mStoredBottomActions = true
private var mStoredExtendedDetails = 0
private lateinit var brightnessSideScroll: MediaSideScroll
private lateinit var volumeSideScroll: MediaSideScroll
private lateinit var mTimeHolder: View
private lateinit var mBrightnessSideScroll: MediaSideScroll
private lateinit var mVolumeSideScroll: MediaSideScroll
lateinit var medium: Medium
@ -77,11 +74,36 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
mView = inflater.inflate(R.layout.pager_video_item, container, false).apply {
instant_prev_item.setOnClickListener { listener?.goToPrevItem() }
instant_next_item.setOnClickListener { listener?.goToNextItem() }
video_curr_time.setOnClickListener { skip(false) }
video_duration.setOnClickListener { skip(true) }
video_holder.setOnClickListener { toggleFullscreen() }
video_preview.setOnClickListener { toggleFullscreen() }
panorama_outline.setOnClickListener { openPanorama() }
// adding an empty click listener just to avoid ripple animation at toggling fullscreen
video_seekbar.setOnClickListener { }
mTimeHolder = video_time_holder
mBrightnessSideScroll = video_brightness_controller
mVolumeSideScroll = video_volume_controller
mCurrTimeView = video_curr_time
if (context.config.allowDownGesture) {
video_preview.setOnTouchListener { v, event ->
handleEvent(event)
false
}
video_surface.setOnTouchListener { v, event ->
handleEvent(event)
false
}
}
}
storeStateVariables()
medium = arguments!!.getSerializable(MEDIUM) as Medium
Glide.with(context!!).load(medium.path).into(mView!!.video_preview)
// setMenuVisibility is not called at VideoActivity (third party intent)
if (!mIsFragmentVisible && activity is VideoActivity) {
@ -89,7 +111,23 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
}
mIsFullscreen = activity!!.window.decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_FULLSCREEN == View.SYSTEM_UI_FLAG_FULLSCREEN
initTimeHolder()
medium.path.getVideoResolution()?.apply {
mVideoSize.x = x
mVideoSize.y = y
mIsPanorama = x == y * 2
if (mIsPanorama) {
mView!!.apply {
panorama_outline.beVisible()
video_play_outline.beGone()
mVolumeSideScroll.beGone()
mBrightnessSideScroll.beGone()
Glide.with(context!!).load(medium.path).into(video_preview)
}
}
}
if (!mIsPanorama) {
setupPlayer()
if (savedInstanceState != null) {
mCurrTime = savedInstanceState.getInt(PROGRESS)
@ -98,39 +136,32 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
checkFullscreen()
mWasFragmentInit = true
mView!!.apply {
brightnessSideScroll = video_brightness_controller
brightnessSideScroll.initialize(activity!!, slide_info, true, container) { x, y ->
video_holder.performClick()
}
volumeSideScroll = video_volume_controller
volumeSideScroll.initialize(activity!!, slide_info, false, container) { x, y ->
video_holder.performClick()
}
video_curr_time.setOnClickListener { skip(false) }
video_duration.setOnClickListener { skip(true) }
Glide.with(context!!).load(medium.path).into(video_preview)
}
mExoPlayer = ExoPlayerFactory.newSimpleInstance(context, DefaultTrackSelector())
mExoPlayer!!.setSeekParameters(SeekParameters.CLOSEST_SYNC)
mExoPlayer!!.seekParameters = SeekParameters.CLOSEST_SYNC
initExoPlayerListeners()
medium.path.getVideoResolution()?.apply {
mVideoSize.x = x
mVideoSize.y = y
if (mVideoSize.x != 0 && mVideoSize.y != 0) {
setVideoSize()
}
setupVideoDuration()
mView!!.apply {
mBrightnessSideScroll.initialize(activity!!, slide_info, true, container) { x, y ->
video_holder.performClick()
}
mView!!.video_surface.onGlobalLayout {
mVolumeSideScroll.initialize(activity!!, slide_info, false, container) { x, y ->
video_holder.performClick()
}
video_surface.onGlobalLayout {
if (mIsFragmentVisible && context?.config?.autoplayVideos == true) {
playVideo()
}
}
}
}
setupVideoDuration()
return mView
}
@ -142,8 +173,8 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
val allowVideoGestures = config.allowVideoGestures
val allowInstantChange = config.allowInstantChange
mView!!.apply {
video_volume_controller.beVisibleIf(allowVideoGestures)
video_brightness_controller.beVisibleIf(allowVideoGestures)
video_volume_controller.beVisibleIf(allowVideoGestures && !mIsPanorama)
video_brightness_controller.beVisibleIf(allowVideoGestures && !mIsPanorama)
instant_prev_item.beVisibleIf(allowInstantChange)
instant_next_item.beVisibleIf(allowInstantChange)
@ -157,7 +188,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
initTimeHolder()
}
mView!!.video_time_holder.setBackgroundResource(if (config.bottomActions) 0 else R.drawable.gradient_background)
mTimeHolder.setBackgroundResource(if (config.bottomActions) 0 else R.drawable.gradient_background)
storeStateVariables()
}
@ -211,9 +242,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
mTextureView = mView!!.video_surface
mTextureView!!.setOnClickListener { toggleFullscreen() }
mTextureView!!.surfaceTextureListener = this
mView!!.video_holder.setOnClickListener { toggleFullscreen() }
initTimeHolder()
checkExtendedDetails()
}
@ -230,7 +259,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
val factory = DataSource.Factory { fileDataSource }
val audioSource = ExtractorMediaSource(fileDataSource.uri, factory, DefaultExtractorsFactory(), null, null)
mExoPlayer!!.audioStreamType = AudioManager.STREAM_MUSIC
mExoPlayer!!.audioStreamType = C.STREAM_TYPE_MUSIC
mExoPlayer!!.prepare(audioSource)
}
@ -300,19 +329,14 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
bottom += resources.getDimension(R.dimen.bottom_actions_height).toInt()
}
mTimeHolder!!.setPadding(left, top, right, bottom)
mTimeHolder.setPadding(left, top, right, bottom)
mCurrTimeView = mView!!.video_curr_time
mSeekBar = mView!!.video_seekbar
mSeekBar!!.setOnSeekBarChangeListener(this)
if (mIsFullscreen) {
mTimeHolder!!.beInvisible()
}
mTimeHolder.beInvisibleIf(mIsFullscreen)
}
private fun hasNavBar(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
val display = context!!.windowManager.defaultDisplay
val realDisplayMetrics = DisplayMetrics()
@ -327,12 +351,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
val displayHeight = displayMetrics.heightPixels
val displayWidth = displayMetrics.widthPixels
realWidth - displayWidth > 0 || realHeight - displayHeight > 0
} else {
val hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey()
val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK)
!hasMenuKey && !hasBackKey
}
return realWidth - displayWidth > 0 || realHeight - displayHeight > 0
}
private fun setupTimeHolder() {
@ -376,7 +395,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
AnimationUtils.loadAnimation(activity, anim).apply {
duration = 150
fillAfter = true
mTimeHolder?.startAnimation(this)
mTimeHolder.startAnimation(this)
}
}
@ -385,7 +404,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
return
mIsPlaying = !mIsPlaying
mHidePauseHandler.removeCallbacksAndMessages(null)
mHidePlayPauseHandler.removeCallbacksAndMessages(null)
if (mIsPlaying) {
playVideo()
} else {
@ -410,6 +429,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
mIsPlaying = true
mExoPlayer?.playWhenReady = true
mView!!.video_play_outline.setImageResource(R.drawable.ic_pause)
mView!!.video_play_outline.alpha = PLAY_PAUSE_VISIBLE_ALPHA
activity!!.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
schedulePlayPauseFadeOut()
}
@ -431,16 +451,16 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
}
private fun schedulePlayPauseFadeOut() {
mHidePauseHandler.removeCallbacksAndMessages(null)
mHidePauseHandler.postDelayed({
mHidePlayPauseHandler.removeCallbacksAndMessages(null)
mHidePlayPauseHandler.postDelayed({
mView!!.video_play_outline.animate().alpha(0f).start()
}, HIDE_PAUSE_DELAY)
}, HIDE_PLAY_PAUSE_DELAY)
}
private fun videoEnded() = mExoPlayer?.currentPosition ?: 0 >= mExoPlayer?.duration ?: 0
private fun setProgress(seconds: Int) {
mExoPlayer!!.seekTo(seconds * 1000L)
mExoPlayer?.seekTo(seconds * 1000L)
mSeekBar!!.progress = seconds
mCurrTimeView!!.text = seconds.getFormattedDuration()
}
@ -490,7 +510,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
releaseExoPlayer()
mSeekBar?.progress = 0
mTimerHandler.removeCallbacksAndMessages(null)
mHidePauseHandler.removeCallbacksAndMessages(null)
mHidePlayPauseHandler.removeCallbacksAndMessages(null)
mTextureView = null
}
@ -514,7 +534,6 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
}.start()
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private fun setVideoSize() {
if (activity == null || mTextureView == null)
return
@ -524,15 +543,10 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
val screenWidth: Int
val screenHeight: Int
if (isJellyBean1Plus()) {
val realMetrics = DisplayMetrics()
display.getRealMetrics(realMetrics)
screenWidth = realMetrics.widthPixels
screenHeight = realMetrics.heightPixels
} else {
screenWidth = display.width
screenHeight = display.height
}
val screenProportion = screenWidth.toFloat() / screenHeight.toFloat()
@ -570,7 +584,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
}
private fun skip(forward: Boolean) {
if (mExoPlayer == null) {
if (mExoPlayer == null || mIsPanorama) {
return
}
@ -603,15 +617,22 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
if (mExoPlayer == null)
return
if (!mIsPlaying) {
togglePlayPause()
} else {
if (mIsPlaying) {
mExoPlayer!!.playWhenReady = true
} else {
togglePlayPause()
}
mIsDragged = false
}
private fun openPanorama() {
Intent(context, PanoramaVideoActivity::class.java).apply {
putExtra(PATH, medium.path)
startActivity(this)
}
}
override fun fullscreenToggled(isFullscreen: Boolean) {
mIsFullscreen = isFullscreen
checkFullscreen()
@ -628,7 +649,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
private fun getExtendedDetailsY(height: Int): Float {
val smallMargin = resources.getDimension(R.dimen.small_margin)
val fullscreenOffset = smallMargin + if (mIsFullscreen) 0 else mTimeHolder!!.height
val fullscreenOffset = smallMargin + if (mIsFullscreen) 0 else mTimeHolder.height
return context!!.realScreenSize.y.toFloat() - height - fullscreenOffset
}
}

View file

@ -1,5 +1,6 @@
package com.simplemobiletools.gallery.fragments
import android.view.MotionEvent
import androidx.fragment.app.Fragment
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.OTG_PATH
@ -11,6 +12,11 @@ import java.io.File
abstract class ViewPagerFragment : Fragment() {
var listener: FragmentListener? = null
protected var mTouchDownX = 0f
protected var mTouchDownY = 0f
protected var mCloseDownThreshold = 100f
protected var mIgnoreCloseDown = false
abstract fun fullscreenToggled(isFullscreen: Boolean)
interface FragmentListener {
@ -68,4 +74,23 @@ abstract class ViewPagerFragment : Fragment() {
}
fun getPathToLoad(medium: Medium) = if (medium.path.startsWith(OTG_PATH)) medium.path.getOTGPublicPath(context!!) else medium.path
protected fun handleEvent(event: MotionEvent) {
when (event.actionMasked) {
MotionEvent.ACTION_DOWN -> {
mTouchDownX = event.x
mTouchDownY = event.y
}
MotionEvent.ACTION_POINTER_DOWN -> mIgnoreCloseDown = true
MotionEvent.ACTION_UP -> {
val diffX = mTouchDownX - event.x
val diffY = mTouchDownY - event.y
if (!mIgnoreCloseDown && Math.abs(diffY) > Math.abs(diffX) && diffY < -mCloseDownThreshold) {
activity?.supportFinishAfterTransition()
}
mIgnoreCloseDown = false
}
}
}
}

View file

@ -89,6 +89,9 @@ class Config(context: Context) : BaseConfig(context) {
val currPinnedFolders = HashSet<String>(pinnedFolders)
currPinnedFolders.addAll(paths)
pinnedFolders = currPinnedFolders
if (paths.contains(RECYCLE_BIN)) {
showRecycleBinLast = false
}
}
fun removePinnedFolders(paths: Set<String>) {
@ -392,4 +395,12 @@ class Config(context: Context) : BaseConfig(context) {
var showHighestQuality: Boolean
get() = prefs.getBoolean(SHOW_HIGHEST_QUALITY, false)
set(showHighestQuality) = prefs.edit().putBoolean(SHOW_HIGHEST_QUALITY, showHighestQuality).apply()
var showRecycleBinLast: Boolean
get() = prefs.getBoolean(SHOW_RECYCLE_BIN_LAST, false)
set(showRecycleBinLast) = prefs.edit().putBoolean(SHOW_RECYCLE_BIN_LAST, showRecycleBinLast).apply()
var allowDownGesture: Boolean
get() = prefs.getBoolean(ALLOW_DOWN_GESTURE, true)
set(allowDownGesture) = prefs.edit().putBoolean(ALLOW_DOWN_GESTURE, allowDownGesture).apply()
}

View file

@ -58,10 +58,12 @@ const val USE_RECYCLE_BIN = "use_recycle_bin"
const val GROUP_BY = "group_by"
const val EVER_SHOWN_FOLDERS = "ever_shown_folders"
const val SHOW_RECYCLE_BIN_AT_FOLDERS = "show_recycle_bin_at_folders"
const val SHOW_RECYCLE_BIN_LAST = "show_recycle_bin_last"
const val ALLOW_ZOOMING_IMAGES = "allow_zooming_images"
const val WAS_SVG_SHOWING_HANDLED = "was_svg_showing_handled"
const val LAST_BIN_CHECK = "last_bin_check"
const val SHOW_HIGHEST_QUALITY = "show_highest_quality"
const val ALLOW_DOWN_GESTURE = "allow_down_gesture"
// slideshow
const val SLIDESHOW_INTERVAL = "slideshow_interval"
@ -85,6 +87,9 @@ const val SHOW_TEMP_HIDDEN_DURATION = 300000L
const val CLICK_MAX_DURATION = 150
const val DRAG_THRESHOLD = 8
const val MONTH_MILLISECONDS = MONTH_SECONDS * 1000L
const val HIDE_PLAY_PAUSE_DELAY = 500L
const val PLAY_PAUSE_VISIBLE_ALPHA = 0.8f
const val MIN_SKIP_LENGTH = 2000
const val DIRECTORY = "directory"
const val MEDIUM = "medium"

View file

@ -1,9 +0,0 @@
package com.simplemobiletools.gallery.interfaces
import com.simplemobiletools.gallery.models.FilterItem
interface FilterAdapterListener {
fun getCurrentFilter(): FilterItem
fun setCurrentFilter(position: Int)
}

View file

@ -33,7 +33,7 @@ interface MediumDao {
@Query("DELETE FROM media WHERE full_path = :path COLLATE NOCASE")
fun deleteMediumPath(path: String)
@Query("DELETE FROM media WHERE deleted_ts < :timestmap")
@Query("DELETE FROM media WHERE deleted_ts < :timestmap AND deleted_ts != 0")
fun deleteOldRecycleBinItems(timestmap: Long)
@Query("UPDATE OR REPLACE media SET filename = :newFilename, full_path = :newFullPath, parent_path = :newParentPath WHERE full_path = :oldPath COLLATE NOCASE")

View file

@ -1,4 +1,4 @@
package com.simplemobiletools.gallery.helpers
package com.simplemobiletools.gallery.views
import android.app.Activity
import android.content.Context
@ -13,6 +13,8 @@ import android.widget.TextView
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.ViewPagerActivity
import com.simplemobiletools.gallery.extensions.audioManager
import com.simplemobiletools.gallery.helpers.CLICK_MAX_DURATION
import com.simplemobiletools.gallery.helpers.DRAG_THRESHOLD
// allow horizontal swipes through the layout, else it can cause glitches at zoomed in images
class MediaSideScroll(context: Context, attrs: AttributeSet) : RelativeLayout(context, attrs) {
@ -30,8 +32,8 @@ class MediaSideScroll(context: Context, attrs: AttributeSet) : RelativeLayout(co
private var mSlideInfoText = ""
private var mSlideInfoFadeHandler = Handler()
private var mParentView: ViewGroup? = null
private var activity: Activity? = null
private lateinit var activity: Activity
private lateinit var slideInfoView: TextView
private lateinit var callback: (Float, Float) -> Unit
@ -55,7 +57,7 @@ class MediaSideScroll(context: Context, attrs: AttributeSet) : RelativeLayout(co
}
override fun onTouchEvent(event: MotionEvent): Boolean {
if (mPassTouches) {
if (mPassTouches && activity == null) {
return false
}
@ -112,11 +114,11 @@ class MediaSideScroll(context: Context, attrs: AttributeSet) : RelativeLayout(co
return true
}
private fun getCurrentVolume() = activity.audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
private fun getCurrentVolume() = activity!!.audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
private fun getCurrentBrightness(): Int {
return try {
Settings.System.getInt(activity.contentResolver, Settings.System.SCREEN_BRIGHTNESS)
Settings.System.getInt(activity!!.contentResolver, Settings.System.SCREEN_BRIGHTNESS)
} catch (e: Settings.SettingNotFoundException) {
70
}
@ -132,11 +134,11 @@ class MediaSideScroll(context: Context, attrs: AttributeSet) : RelativeLayout(co
private fun volumePercentChanged(percent: Int) {
val stream = AudioManager.STREAM_MUSIC
val maxVolume = activity.audioManager.getStreamMaxVolume(stream)
val maxVolume = activity!!.audioManager.getStreamMaxVolume(stream)
val percentPerPoint = 100 / maxVolume
val addPoints = percent / percentPerPoint
val newVolume = Math.min(maxVolume, Math.max(0, mTouchDownValue + addPoints))
activity.audioManager.setStreamVolume(stream, newVolume, 0)
activity!!.audioManager.setStreamVolume(stream, newVolume, 0)
val absolutePercent = ((newVolume / maxVolume.toFloat()) * 100).toInt()
showValue(absolutePercent)
@ -156,9 +158,9 @@ class MediaSideScroll(context: Context, attrs: AttributeSet) : RelativeLayout(co
val absolutePercent = ((newBrightness / maxBrightness) * 100).toInt()
showValue(absolutePercent)
val attributes = activity.window.attributes
val attributes = activity!!.window.attributes
attributes.screenBrightness = absolutePercent / 100f
activity.window.attributes = attributes
activity!!.window.attributes = attributes
mSlideInfoFadeHandler.removeCallbacksAndMessages(null)
mSlideInfoFadeHandler.postDelayed({

View file

@ -12,12 +12,19 @@
android:layout_height="match_parent"
android:visibility="gone"/>
<ImageView
android:id="@+id/panorama_gradient_background"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@drawable/gradient_background"/>
<ImageView
android:id="@+id/cardboard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:padding="@dimen/activity_margin"
android:src="@drawable/ic_cardboard"/>
@ -25,8 +32,8 @@
android:id="@+id/explore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:padding="@dimen/activity_margin"
android:src="@drawable/ic_explore"/>

View file

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/vr_video_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF000000">
<com.google.vr.sdk.widgets.video.VrVideoView
android:id="@+id/vr_video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ImageView
android:id="@+id/vr_view_gradient_background"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@drawable/gradient_background"/>
<ImageView
android:id="@+id/explore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:padding="@dimen/activity_margin"
android:src="@drawable/ic_explore"/>
<ImageView
android:id="@+id/cardboard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:padding="@dimen/activity_margin"
android:src="@drawable/ic_cardboard"/>
<ImageView
android:id="@+id/video_play_outline"
android:layout_width="@dimen/play_outline_size_big"
android:layout_height="@dimen/play_outline_size_big"
android:layout_centerInParent="true"
android:background="@drawable/circle_black_background_with_inset"
android:padding="26dp"
android:src="@drawable/ic_play"/>
<include layout="@layout/bottom_video_time_holder"/>
</RelativeLayout>

View file

@ -644,6 +644,30 @@
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_allow_down_gesture_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/medium_margin"
android:background="?attr/selectableItemBackground"
android:paddingLeft="@dimen/normal_margin"
android:paddingTop="@dimen/activity_margin"
android:paddingRight="@dimen/normal_margin"
android:paddingBottom="@dimen/activity_margin">
<com.simplemobiletools.commons.views.MySwitchCompat
android:id="@+id/settings_allow_down_gesture"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:clickable="false"
android:paddingStart="@dimen/medium_margin"
android:paddingLeft="@dimen/medium_margin"
android:text="@string/allow_down_gesture"
app:switchPadding="@dimen/medium_margin"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_screen_rotation_holder"
android:layout_width="match_parent"
@ -1141,6 +1165,30 @@
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_show_recycle_bin_last_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/medium_margin"
android:background="?attr/selectableItemBackground"
android:paddingLeft="@dimen/normal_margin"
android:paddingTop="@dimen/activity_margin"
android:paddingRight="@dimen/normal_margin"
android:paddingBottom="@dimen/activity_margin">
<com.simplemobiletools.commons.views.MySwitchCompat
android:id="@+id/settings_show_recycle_bin_last"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:clickable="false"
android:paddingStart="@dimen/medium_margin"
android:paddingLeft="@dimen/medium_margin"
android:text="@string/show_recycle_bin_last"
app:switchPadding="@dimen/medium_margin"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_empty_recycle_bin_holder"
android:layout_width="match_parent"

View file

@ -11,9 +11,9 @@
<ImageView
android:id="@+id/bottom_favorite"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_star_off"
app:layout_constraintEnd_toStartOf="@+id/bottom_edit"
@ -22,9 +22,9 @@
<ImageView
android:id="@+id/bottom_edit"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_edit"
app:layout_constraintEnd_toStartOf="@+id/bottom_share"
@ -33,9 +33,9 @@
<ImageView
android:id="@+id/bottom_share"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_share"
app:layout_constraintEnd_toStartOf="@+id/bottom_delete"
@ -44,9 +44,9 @@
<ImageView
android:id="@+id/bottom_delete"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_delete"
app:layout_constraintEnd_toStartOf="@+id/bottom_rotate"
@ -55,9 +55,9 @@
<ImageView
android:id="@+id/bottom_rotate"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_rotate_right"
app:layout_constraintEnd_toStartOf="@+id/bottom_properties"
@ -66,9 +66,9 @@
<ImageView
android:id="@+id/bottom_properties"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_properties"
app:layout_constraintEnd_toStartOf="@+id/bottom_change_orientation"
@ -77,9 +77,9 @@
<ImageView
android:id="@+id/bottom_change_orientation"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_orientation_auto"
app:layout_constraintEnd_toStartOf="@+id/bottom_slideshow"
@ -88,9 +88,9 @@
<ImageView
android:id="@+id/bottom_slideshow"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_slideshow"
app:layout_constraintEnd_toStartOf="@+id/bottom_show_on_map"
@ -99,9 +99,9 @@
<ImageView
android:id="@+id/bottom_show_on_map"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_place"
app:layout_constraintEnd_toStartOf="@+id/bottom_toggle_file_visibility"
@ -110,9 +110,9 @@
<ImageView
android:id="@+id/bottom_toggle_file_visibility"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_hide"
app:layout_constraintEnd_toStartOf="@+id/bottom_rename"
@ -121,9 +121,9 @@
<ImageView
android:id="@+id/bottom_rename"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_rename_new"
app:layout_constraintEnd_toEndOf="@+id/bottom_set_as"
@ -132,9 +132,9 @@
<ImageView
android:id="@+id/bottom_set_as"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_set_as"
app:layout_constraintEnd_toEndOf="parent"

View file

@ -9,9 +9,9 @@
<TextView
android:id="@+id/bottom_aspect_ratio_free"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/activity_margin"
android:text="@string/free_aspect_ratio"
android:textAllCaps="true"
@ -23,9 +23,9 @@
<TextView
android:id="@+id/bottom_aspect_ratio_one_one"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/activity_margin"
android:text="1:1"
android:textColor="@android:color/white"
@ -36,9 +36,9 @@
<TextView
android:id="@+id/bottom_aspect_ratio_four_three"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/activity_margin"
android:text="4:3"
android:textColor="@android:color/white"
@ -49,9 +49,9 @@
<TextView
android:id="@+id/bottom_aspect_ratio_sixteen_nine"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/activity_margin"
android:text="16:9"
android:textColor="@android:color/white"

View file

@ -9,9 +9,9 @@
<ImageView
android:id="@+id/bottom_rotate"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/normal_margin"
android:src="@drawable/ic_rotate_right"
app:layout_constraintBottom_toBottomOf="parent"
@ -22,9 +22,9 @@
<ImageView
android:id="@+id/bottom_resize"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/normal_margin"
android:src="@drawable/ic_minimize"
app:layout_constraintBottom_toBottomOf="parent"
@ -35,9 +35,9 @@
<ImageView
android:id="@+id/bottom_aspect_ratio"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/normal_margin"
android:src="@drawable/ic_aspect_ratio"
app:layout_constraintBottom_toBottomOf="parent"
@ -48,9 +48,9 @@
<ImageView
android:id="@+id/bottom_flip_horizontally"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/normal_margin"
android:src="@drawable/ic_flip_horizontally"
app:layout_constraintBottom_toBottomOf="parent"
@ -61,9 +61,9 @@
<ImageView
android:id="@+id/bottom_flip_vertically"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/normal_margin"
android:src="@drawable/ic_flip_vertically"
app:layout_constraintBottom_toBottomOf="parent"

View file

@ -9,9 +9,9 @@
<ImageView
android:id="@+id/bottom_primary_filter"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/normal_margin"
android:src="@drawable/ic_photo_filter"
app:layout_constraintBottom_toBottomOf="parent"
@ -22,9 +22,9 @@
<ImageView
android:id="@+id/bottom_primary_crop_rotate"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/normal_margin"
android:src="@drawable/ic_crop_rotate"
app:layout_constraintBottom_toBottomOf="parent"

View file

@ -10,9 +10,9 @@
<ImageView
android:id="@+id/bottom_set_wallpaper_aspect_ratio"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/normal_margin"
android:src="@drawable/ic_minimize"
app:layout_constraintBottom_toBottomOf="parent"
@ -23,9 +23,9 @@
<ImageView
android:id="@+id/bottom_set_wallpaper_rotate"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/normal_margin"
android:src="@drawable/ic_rotate_right"
app:layout_constraintBottom_toBottomOf="parent"

View file

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/video_time_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<TextView
android:id="@+id/video_curr_time"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignTop="@+id/video_seekbar"
android:layout_alignBottom="@+id/video_seekbar"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center_vertical"
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
android:textColor="@android:color/white"
tools:text="00:00"/>
<com.simplemobiletools.commons.views.MySeekBar
android:id="@+id/video_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toStartOf="@+id/video_duration"
android:layout_toLeftOf="@+id/video_duration"
android:layout_toEndOf="@+id/video_curr_time"
android:layout_toRightOf="@+id/video_curr_time"
android:paddingTop="@dimen/activity_margin"
android:paddingBottom="@dimen/activity_margin"/>
<TextView
android:id="@+id/video_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/video_seekbar"
android:layout_alignBottom="@+id/video_seekbar"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center_vertical"
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
android:textColor="@android:color/white"
tools:text="00:00"/>
</RelativeLayout>

View file

@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/directories_holder"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
@ -21,8 +28,8 @@
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:paddingLeft="@dimen/normal_margin"
android:paddingStart="@dimen/normal_margin">
android:paddingStart="@dimen/normal_margin"
android:paddingLeft="@dimen/normal_margin">
<include layout="@layout/fastscroller_handle_vertical"/>
@ -32,12 +39,23 @@
android:id="@+id/directories_horizontal_fastscroller"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:paddingTop="@dimen/normal_margin">
<include layout="@layout/fastscroller_handle_horizontal"/>
</com.simplemobiletools.commons.views.FastScroller>
</RelativeLayout>
<com.simplemobiletools.commons.views.MyFloatingActionButton
android:id="@+id/directories_show_hidden"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/activity_margin"
android:src="@drawable/ic_unhide"
android:visibility="gone"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -47,7 +47,7 @@
android:visibility="gone"
tools:text="My image\nAnother line"/>
<com.simplemobiletools.gallery.helpers.MediaSideScroll
<com.simplemobiletools.gallery.views.MediaSideScroll
android:id="@+id/photo_brightness_controller"
android:layout_width="@dimen/media_side_slider_width"
android:layout_height="match_parent"

View file

@ -17,14 +17,14 @@
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
<com.simplemobiletools.gallery.helpers.MediaSideScroll
<com.simplemobiletools.gallery.views.MediaSideScroll
android:id="@+id/video_volume_controller"
android:layout_width="@dimen/media_side_slider_width"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"/>
<com.simplemobiletools.gallery.helpers.MediaSideScroll
<com.simplemobiletools.gallery.views.MediaSideScroll
android:id="@+id/video_brightness_controller"
android:layout_width="@dimen/media_side_slider_width"
android:layout_height="match_parent"/>
@ -60,13 +60,23 @@
android:alpha="0"
android:background="@drawable/black_rounded_background"
android:gravity="center"
android:paddingBottom="@dimen/medium_margin"
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
android:paddingTop="@dimen/medium_margin"
android:paddingRight="@dimen/activity_margin"
android:paddingBottom="@dimen/medium_margin"
android:textColor="@android:color/white"
android:textSize="@dimen/extra_big_text_size"/>
<ImageView
android:id="@+id/panorama_outline"
android:layout_width="@dimen/play_outline_size_big"
android:layout_height="@dimen/play_outline_size_big"
android:layout_centerInParent="true"
android:background="@drawable/circle_black_background_with_inset"
android:padding="28dp"
android:src="@drawable/ic_panorama"
android:visibility="gone"/>
<TextView
android:id="@+id/video_details"
android:layout_width="wrap_content"
@ -81,52 +91,5 @@
android:visibility="gone"
tools:text="My video\nAnother line"/>
<RelativeLayout
android:id="@+id/video_time_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<TextView
android:id="@+id/video_curr_time"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignBottom="@+id/video_seekbar"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignTop="@+id/video_seekbar"
android:gravity="center_vertical"
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
android:textColor="@android:color/white"
tools:text="00:00"/>
<com.simplemobiletools.commons.views.MySeekBar
android:id="@+id/video_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@+id/video_curr_time"
android:layout_toLeftOf="@+id/video_duration"
android:layout_toRightOf="@+id/video_curr_time"
android:layout_toStartOf="@+id/video_duration"
android:paddingBottom="@dimen/activity_margin"
android:paddingTop="@dimen/activity_margin"/>
<TextView
android:id="@+id/video_duration"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/video_seekbar"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/video_seekbar"
android:gravity="center_vertical"
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
android:textColor="@android:color/white"
tools:text="00:00"/>
</RelativeLayout>
<include layout="@layout/bottom_video_time_holder"/>
</RelativeLayout>

View file

@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/search"
android:icon="@drawable/ic_search"
android:title="@string/search"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="collapseActionView|ifRoom"/>
<item
android:id="@+id/sort"
android:icon="@drawable/ic_sort"

View file

@ -166,6 +166,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">المصغرات</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Thumbnails</string>

View file

@ -159,9 +159,10 @@
<string name="do_extra_check">Fer una verificació addicional per evitar que es mostrin fitxers no vàlids</string>
<string name="show_at_bottom">Mostra alguns botons d\'acció a la part inferior de la pantalla</string>
<string name="show_recycle_bin">Mostra la paperera de reciclatge a la pantalla de carpetes</string>
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="deep_zoomable_images">Imatges ampliades a mida</string>
<string name="show_highest_quality">Mostra imatges amb la màxima qualitat possible</string>
<string name="show_recycle_bin_last">Mostra la paperera de reciclatge com a últim element a la pantalla principal</string>
<string name="allow_down_gesture">Permet tancar la vista de pantalla completa amb un gest avall</string>
<!-- Setting sections -->
<string name="thumbnails">Miniatures</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Thumbnails</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Thumbnails</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Stark vergrösserbare Bilder</string>
<string name="show_highest_quality">Zeige Bilder in der höchstmöglichen Qualität</string>
<string name="show_recycle_bin_last">Zeige den Papierkorb als letztes Element auf dem Hauptbildschirm</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Thumbnails</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Βαθιά μεγέθυνση εικόνων</string>
<string name="show_highest_quality">Εμφάνιση εικόνων με την υψηλότερη δυνατή ποιότητα</string>
<string name="show_recycle_bin_last">Εμφάνιση του Κάδου ως τελευταίο στοιχείο στην κύρια οθόνη</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Εικονίδια</string>

View file

@ -159,9 +159,10 @@
<string name="do_extra_check">Hacer una comprobación adicional para evitar mostrar archivos inválidos</string>
<string name="show_at_bottom">Mostrar algunos botones de acción en la parte inferior de la pantalla</string>
<string name="show_recycle_bin">Mostrar la papelera de reciclaje en la pantalla de carpetas</string>
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="deep_zoomable_images">Imágenes ampliables con zoom</string>
<string name="show_highest_quality">Muestra imágenes con la mayor calidad posible</string>
<string name="show_recycle_bin_last">Mostrar la Papelera de reciclaje como el último elemento en la pantalla principal</string>
<string name="allow_down_gesture">Permite cerrar la vista de pantalla completa con un gesto hacia abajo.</string>
<!-- Setting sections -->
<string name="thumbnails">Miniaturas</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Esikatselukuvat</string>

View file

@ -1,22 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Simple Galerie</string>
<string name="app_name">Simple Gallery</string>
<string name="app_launcher_name">Galerie</string>
<string name="edit">Édition</string>
<string name="open_camera">Ouvrir appareil photo</string>
<string name="hidden">(caché)</string>
<string name="open_camera">Démarrer l\'appareil photo</string>
<string name="hidden">(masqué)</string>
<string name="excluded">(exclu)</string>
<string name="pin_folder">Épingler le dossier</string>
<string name="unpin_folder">Désépingler le dossier</string>
<string name="pin_to_the_top">Épingler en haut</string>
<string name="show_all">Afficher le contenu de tous les dossiers</string>
<string name="all_folders">Tous les dossiers</string>
<string name="folder_view">Permuter vers la vue du dossier</string>
<string name="folder_view">Affichage en vue \"Dossier\"</string>
<string name="other_folder">Autre dossier</string>
<string name="show_on_map">Afficher sur la carte</string>
<string name="unknown_location">Position inconnue</string>
<string name="increase_column_count">Augmenter le nombre de colonnes</string>
<string name="reduce_column_count">Réduire le nombre de colonnes</string>
<string name="increase_column_count">Ajouter une colonne</string>
<string name="reduce_column_count">Supprimer une colonne</string>
<string name="change_cover_image">Changer l\'image de couverture</string>
<string name="select_photo">Sélectionner une photo</string>
<string name="use_default">Utiliser par défaut</string>
@ -24,197 +24,200 @@
<string name="brightness">Luminosité</string>
<string name="lock_orientation">Verrouiller la rotation</string>
<string name="unlock_orientation">Déverrouiller la rotation</string>
<string name="change_orientation">Change orientation</string>
<string name="force_portrait">Force portrait</string>
<string name="force_landscape">Paysage de force</string>
<string name="change_orientation">Orientation</string>
<string name="force_portrait">Forcer la vue portrait</string>
<string name="force_landscape">Forcer la vue paysage</string>
<string name="use_default_orientation">Utiliser l\'orientation par défaut</string>
<string name="fix_date_taken">Fixe Date Valeur prise</string>
<string name="fixing">Fixation....</string>
<string name="dates_fixed_successfully">Dates fixées avec succès</string>
<string name="fix_date_taken">Corriger la valeur des dates de prise des photos</string>
<string name="fixing">Correction en cours....</string>
<string name="dates_fixed_successfully">Dates corrigées</string>
<!-- Filter -->
<string name="filter_media">Filtrer les médias</string>
<string name="images">Images</string>
<string name="videos">Vidéos</string>
<string name="gifs">GIF</string>
<string name="raw_images">RAW images</string>
<string name="gifs">GIFs</string>
<string name="raw_images">Images RAW</string>
<string name="svgs">SVGs</string>
<string name="no_media_with_filters">Aucun fichier média trouvé avec les filtres sélectionnés.</string>
<string name="change_filters_underlined"><u >Changer les filtres</u></string>
<string name="no_media_with_filters">Aucun fichier média trouvé avec les filtres sélectionnés</string>
<string name="change_filters_underlined"><u>Modifier les filtres</u></string>
<!-- Hide / Exclude -->
<string name="hide_folder_description">Cette option masque le dossier en ajoutant un fichier \'.nomedia\' à l\'intérieur, cela masquera aussi tous les sous-dossiers. Vous pouvez les voir en modifiant l\'option \'Afficher les dossiers cachés\' dans les paramètres. Continuer ?</string>
<string name="hide_folder_description">Cette option masque le dossier en ajoutant un fichier \".nomedia\" à l\'intérieur, cela masquera aussi tous les sous-dossiers. Vous pouvez les voir en appuyant sur le symbole \"Œil\" (permettant l\'affichage) depuis les paramètres. Continuer ?</string>
<string name="exclude">Exclure</string>
<string name="excluded_folders">Dossiers exclus</string>
<string name="manage_excluded_folders">Gérer les dossiers exclus</string>
<string name="exclude_folder_description">Cela va exclure la sélection ainsi que ses sous-dossiers depuis Simple Galerie uniquement. Vous pouvez gérer les dossiers exclus depuis les paramètres.</string>
<string name="exclude_folder_description">Cela va exclure la sélection ainsi que ses sous-dossiers depuis Simple Gallery uniquement. Vous pouvez gérer les dossiers exclus depuis les paramètres.</string>
<string name="exclude_folder_parent">Exclure un dossier parent ?</string>
<string name="excluded_activity_placeholder">Exclure des dossiers les masquera ainsi que leurs sous-dossiers uniquement dans Simple Galerie, ils seront toujours visibles depuis d\'autres applications.\\Si vous voulez aussi les masquer ailleurs, utilisez la fonction Masquer.</string>
<string name="excluded_activity_placeholder">Exclure des dossiers les masquera ainsi que leurs sous-dossiers uniquement dans Simple Gallery, ils seront toujours visibles depuis d\'autres applications.\n\nSi vous voulez aussi les masquer ailleurs, utilisez la fonction \"Masquer\".</string>
<string name="remove_all">Tout supprimer</string>
<string name="remove_all_description">Supprimer tous les dossiers de la liste des exclusions ? Ceci n\'effacera pas les dossiers.</string>
<string name="remove_all_description">Supprimer tous les dossiers de la liste des exclusions ? Cela n\'effacera pas les dossiers.</string>
<string name="hidden_folders">Dossiers masqués</string>
<string name="manage_hidden_folders">Gérer les dossiers masqués</string>
<string name="hidden_folders_placeholder">Il semblerait que vous n\'ayez pas de dossier cachés avec un fichier \".nomedia\".</string>
<string name="hidden_folders_placeholder">Il semblerait que vous n\'ayez pas de dossier masqués avec un fichier \".nomedia\".</string>
<!-- Include folders -->
<string name="include_folders">Dossiers inclus</string>
<string name="manage_included_folders">Gérer les dossiers inclus</string>
<string name="include_folders">Dossiers ajoutés</string>
<string name="manage_included_folders">Gérer les dossiers ajoutés</string>
<string name="add_folder">Ajouter un dossier</string>
<string name="included_activity_placeholder">Si vous avez des dossiers contenant des médias et qu\'ils ne sont pas reconnus par l\'application, vous pouvez les ajouter manuellement ici.</string>
<string name="included_activity_placeholder">Si vous avez des dossiers contenant des médias qui ne sont pas affichés dans l\'application, vous pouvez les ajouter manuellement ici.\n\nCet ajout n\'exclura aucun autre dossier.</string>
<!-- Resizing -->
<string name="resize">Redimensionner</string>
<string name="resize_and_save">Redimensionner la sélection et enregistrer</string>
<string name="width">Largeur</string>
<string name="height">Hauteur</string>
<string name="keep_aspect_ratio">Garder le ratio</string>
<string name="keep_aspect_ratio">Conserver le rapport d\'affichage</string>
<string name="invalid_values">Veuillez entrer une résolution valide</string>
<!-- Editor -->
<string name="editor">Éditeur</string>
<string name="save">Sauvegarder</string>
<string name="rotate">Tourner</string>
<string name="rotate">Pivoter</string>
<string name="path">Chemin</string>
<string name="invalid_image_path">Chemin invalide</string>
<string name="image_editing_failed">Échec de l\'édition de l\'image</string>
<string name="edit_image_with">Éditer l\'image avec :</string>
<string name="edit_image_with">Modifier l\'image avec :</string>
<string name="no_editor_found">Aucun éditeur d\'image trouvé</string>
<string name="unknown_file_location">Emplacement du fichier inconnu.</string>
<string name="error_saving_file">Ne parvient pas à réécrire par dessus le fichier source</string>
<string name="unknown_file_location">Emplacement du fichier inconnu</string>
<string name="error_saving_file">Impossible de remplacer le fichier source</string>
<string name="rotate_left">Pivoter à gauche</string>
<string name="rotate_right">Pivoter à droite</string>
<string name="rotate_one_eighty">Pivoter à 180º</string>
<string name="flip">Retourner</string>
<string name="flip_horizontally">Retourner horizontalement</string>
<string name="flip_vertically">Retourner verticalement</string>
<string name="edit_with">Éditer avec</string>
<string name="free_aspect_ratio">Gratuit</string> <!-- available as an option: 1:1, 4:3, 16:9, free -->
<string name="edit_with">Modifier avec</string>
<string name="free_aspect_ratio">Libre</string> <!-- available as an option: 1:1, 4:3, 16:9, free -->
<!-- Set wallpaper -->
<string name="simple_wallpaper">Simple fond d\'écran</string>
<string name="simple_wallpaper">Fond d\'écran simple</string>
<string name="set_as_wallpaper">Définir comme fond d\'écran</string>
<string name="set_as_wallpaper_failed">Échec de la définition en tant que fond d\'écran.</string>
<string name="set_as_wallpaper_failed">Échec de la définition en tant que fond d\'écran</string>
<string name="set_as_wallpaper_with">Définir comme fond d\'écran avec :</string>
<string name="setting_wallpaper">Paramètres de fond d\'écran</string>
<string name="wallpaper_set_successfully">Fond d\'écran défini avec succès</string>
<string name="portrait_aspect_ratio">Ratio d\'aspect portrait</string>
<string name="landscape_aspect_ratio">Ratio d\'aspect paysage</string>
<string name="home_screen">Page d\'accueil</string>
<string name="lock_screen">Écran de verrouillage</string>
<string name="home_and_lock_screen">Page d\'accueil et écran de verrouillage</string>
<string name="setting_wallpaper">Définition du fond d\'écran en cours</string>
<string name="wallpaper_set_successfully">Fond d\'écran défini</string>
<string name="portrait_aspect_ratio">Rapport d\'affichage portrait</string>
<string name="landscape_aspect_ratio">Rapport d\'affichage paysage</string>
<string name="home_screen">Écran d\'accueil</string>
<string name="lock_screen">Écran de verrouillage</string>
<string name="home_and_lock_screen">Écran d\'accueil et écran de déverrouillage</string>
<!-- Slideshow -->
<string name="slideshow">Diaporama</string>
<string name="interval">Intervalle (secondes) :</string>
<string name="include_photos">Inclure photos</string>
<string name="include_videos">Inclure vidéos</string>
<string name="include_gifs">Inclure GIF</string>
<string name="include_gifs">Inclure GIFs</string>
<string name="random_order">Ordre aléatoire</string>
<string name="use_fade">Utiliser un fondu</string>
<string name="move_backwards">Revenir en arrière</string>
<string name="move_backwards">Défilement inverse</string>
<string name="loop_slideshow">Diaporama en boucle</string>
<string name="slideshow_ended">Diaporama terminé</string>
<string name="no_media_for_slideshow">Aucun média trouvé pour le diaporama</string>
<!-- View types -->
<string name="change_view_type">Changer le type de vue</string>
<string name="change_view_type">Changer de mode d\'affichage</string>
<string name="grid">Grille</string>
<string name="list">Liste</string>
<string name="group_direct_subfolders">Sous-dossiers de groupe direct</string>
<!-- Grouping at media thumbnails -->
<string name="group_by">Grouper par</string>
<string name="do_not_group_files">Ne pas regrouper les fichiers</string>
<string name="do_not_group_files">Ne pas grouper les fichiers</string>
<string name="by_folder">Dossier</string>
<string name="by_last_modified">Dernière modification</string>
<string name="by_date_taken">Date de prise</string>
<string name="by_last_modified">Date de modification</string>
<string name="by_date_taken">Date de prise de vue</string>
<string name="by_file_type">Type de fichier</string>
<string name="by_extension">Extension</string>
<string name="use_for_this_folder">Définir pour ce dossier uniquement</string>
<!-- Settings -->
<string name="autoplay_videos">Lecture automatique des vidéos</string>
<string name="toggle_filename">Permuter la visibilité des noms de fichier</string>
<string name="loop_videos">Lire en boucle les vidéos</string>
<string name="animate_gifs">GIF animés sur les miniatures</string>
<string name="max_brightness">Luminosité maximale lors de l\'affichage de media</string>
<string name="crop_thumbnails">Rogner les miniatures en carrés</string>
<string name="screen_rotation_by">Pivoter les medias plein écran selon</string>
<string name="loop_videos">Lecture en boucle des vidéos</string>
<string name="animate_gifs">GIFs animés sur les miniatures</string>
<string name="max_brightness">Luminosité maximale</string>
<string name="crop_thumbnails">Recadrer les miniatures en carrés</string>
<string name="screen_rotation_by">Pivoter l\'affichage selon</string>
<string name="screen_rotation_system_setting">Paramètres système</string>
<string name="screen_rotation_device_rotation">Rotation de l\'appareil</string>
<string name="screen_rotation_aspect_ratio">Ratio d\'aspect</string>
<string name="black_background_at_fullscreen">Fond et barre de statut noir en plein écran</string>
<string name="screen_rotation_aspect_ratio">Rapport d\'affichage</string>
<string name="black_background_at_fullscreen">Arrière-plan et barre d\'état noirs</string>
<string name="scroll_thumbnails_horizontally">Défilement des miniatures horizontalement</string>
<string name="hide_system_ui_at_fullscreen">Masquer automatiquement l\'interface utilisateur si média en plein écran</string>
<string name="hide_system_ui_at_fullscreen">Masquer automatiquement l\'interface utilisateur</string>
<string name="delete_empty_folders">Supprimer les dossiers vides après avoir supprimé leur contenu</string>
<string name="allow_photo_gestures">Permettre le contrôle de la luminosité de la photo avec des gestes verticaux.</string>
<string name="allow_video_gestures">Permettre le contrôle du volume vidéo et de la luminosité avec des gestes verticaux</string>
<string name="show_media_count">Afficher le nombre de fichiers dans les dossiers sur l\'écran principal</string>
<string name="replace_share_with_rotate">Remplacer Partager par Pivoter si menu en plein écran</string>
<string name="show_extended_details">Afficher les détails supplémentaires par dessus le média en plein écran</string>
<string name="manage_extended_details">Gérer les détails supplémentaires</string>
<string name="one_finger_zoom">Autoriser le zoom avec un doigt sur un média en plein écran</string>
<string name="allow_instant_change">Autoriser le changement instantané de média en cliquant sur les côtés de l\'écran</string>
<string name="allow_deep_zooming_images">Permet de zoomer en profondeur</string>
<string name="hide_extended_details">Masquer les détails supplémentaires lorsque la barre d\'état est masquée</string>
<string name="do_extra_check">Faire une vérification supplémentaire pour éviter de montrer des fichiers invalides</string>
<string name="show_at_bottom">Afficher quelques boutons d\'action en bas de l\'écran</string>
<string name="show_recycle_bin">Afficher la corbeille à l\'écran Dossiers</string>
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_photo_gestures">Contrôler la luminosité de la photo avec des gestes verticaux</string>
<string name="allow_video_gestures">Contrôler le volume et la luminosité de la vidéo avec des gestes verticaux</string>
<string name="show_media_count">Afficher le nombre de fichiers dans les dossiers</string>
<string name="replace_share_with_rotate">Remplacer \"Partager\" par \"Pivoter\" en plein écran</string>
<string name="show_extended_details">Afficher en surimpression les informations supplémentaires du média en plein écran</string>
<string name="manage_extended_details">Gérer les informations supplémentaires</string>
<string name="one_finger_zoom">Effectuer le zoom avec un doigt sur une image en plein écran</string>
<string name="allow_instant_change">Changement instantané de média en appuyant sur les côtés de l\'écran</string>
<string name="allow_deep_zooming_images">Utiliser le zoom maximal des images</string>
<string name="hide_extended_details">Ne pas afficher les informations supplémentaires si la barre d\'état est masquée</string>
<string name="do_extra_check">Éviter l\'affichage de fichiers non conformes</string>
<string name="show_hidden_items">Afficher les éléments masqués</string>
<string name="show_at_bottom">Afficher les boutons d\'action</string>
<string name="show_recycle_bin">Afficher la corbeille en vue \"Dossier\"</string>
<string name="deep_zoomable_images">Niveau de zoom maximal des images</string>
<string name="show_highest_quality">Afficher les images avec la meilleur qualité possible</string>
<string name="show_recycle_bin_last">Afficher la corbeille en dernière place sur l\'écran principal</string>
<string name="allow_down_gesture">Fermeture de la vue plein écran par un geste vers le bas</string>
<!-- Setting sections -->
<string name="thumbnails">Vignettes</string>
<string name="fullscreen_media">Média plein écran</string>
<string name="thumbnails">Miniatures</string>
<string name="fullscreen_media">Affichage en plein écran</string>
<string name="extended_details">Détails supplémentaires</string>
<string name="bottom_actions">Actions en bas</string>
<string name="bottom_actions">Menu d\'actions sur la bas de l\'écran</string>
<!-- Bottom actions -->
<string name="manage_bottom_actions">Gérer les actions visible du bas</string>
<string name="toggle_favorite">Basculer favori</string>
<string name="manage_bottom_actions">Gérer le menu d\'actions</string>
<string name="toggle_favorite">Ajouter aux favoris</string>
<string name="toggle_file_visibility">Changer la visibilité des fichiers</string>
<!-- FAQ -->
<string name="faq_1_title">Comment faire de Simple Galerie ma galerie par défaut ?</string>
<string name="faq_1_text">Il faut dans un premier temps trouver la galerie par défaut dans la section « Applications » des paramètres du téléphone, puis toucher « Ouvrir par défaut » et enfin selectionner « Réinitialiser les paramètres par défaut ». La prochaine fois que vous ouvrirez une image ou une vidéo, il vous sera proposé de choisir une application, choisissez Simple Gallery puis « Toujours ».</string>
<string name="faq_2_title">J\'ai verrouillé l\'appli avec un mot de passe et je ne m\'en rappelle plus. Que faire ?</string>
<string name="faq_2_text">Il y a deux façons de procéder. Soit vous reinstallez l\'appli, soit retrouver l\'appli dans les paramètres du téléphone et toucher « Effacer les données ». Cela va seulement remettre à zéro les paramètres de l\'appli et ne supprimera pas vos fichiers.</string>
<string name="faq_3_title">Comment faire pour qu\'un album soit toujours tout en haut ?</string>
<string name="faq_3_text">Vous avez juste à faire un appui long sur l\'album en question et choisir l\'icône « Epingler » dans le menu d\'actions. Vous pouvez en épingler plusieurs, les éléments épinglés seront alors triés dans l\'ordre par défaut.</string>
<string name="faq_1_title">Comment faire de Simple Gallery ma galerie par défaut ?</string>
<string name="faq_1_text">Il faut dans un premier temps, trouver l\'application \"galerie\" par défaut dans la section \"Applications\" des paramètres de l\'appareil, puis appuyer sur \"Ouvrir par défaut\", et enfin sélectionner \"Réinitialiser les paramètres par défaut\". La prochaine fois que vous ouvrirez une image ou une vidéo, il vous sera proposé de choisir une application, choisissez \"Simple Gallery\" puis \"Toujours\".</string>
<string name="faq_2_title">J\'ai verrouillé l\'application avec un mot de passe et je ne m\'en rappelle plus. Que faire ?</string>
<string name="faq_2_text">Il y a deux façons de procéder. Soit vous réinstallez l\'application, soit vous recherchez l\'application dans les paramètres de l\'appareil et appuyez sur \"Effacer les données\". Cela va seulement réinitialiser les paramètres de l\'application et ne supprimera pas vos fichiers.</string>
<string name="faq_3_title">Comment faire pour qu\'un album soit toujours affiché tout en haut ?</string>
<string name="faq_3_text">Vous devez simplement à effectuer un appui prolongé sur l\'album en question et choisir l\'icône \"Épingler\" dans le menu d\'actions. Vous pouvez en épingler plusieurs. Les éléments épinglés seront alors triés selon l\'ordre par défaut.</string>
<string name="faq_4_title">Comment avancer rapidement dans les vidéos ?</string>
<string name="faq_4_text">Vous pouvez appuyer sur le temps actuel ou la durée totale de la vidéo sur la barre de progression, la vidéo reculera ou avancera selon votre choix.</string>
<string name="faq_5_title">Quelle est la différence entre cacher et exclure un répertoire ?</string>
<string name="faq_5_text">Exclure n\'affiche pas le dossier dans Simple Galerie uniquement, alors que Cacher le cache pour l\'intégralité du système, y compris les autres galeries. Dans le dernier cas, un fichier \".nomedia\" est créé dans le répertoire caché, et peut s\'enlever avec n\'importe quel explorateur de fichiers.</string>
<string name="faq_6_title">Pourquoi des répertoires avec des pochettes d\'albums musicaux ou des miniatures d\'images sont affichés ?</string>
<string name="faq_6_text">Cela peut arriver de voir des albums qui ne devraient pas être affichés. Vous pouvez les exclure facilement en faisaint un appui long sur eux puis en sélectionnant « Exclure », après quoi vous pouvez aussi sélectionner le répertoire parent, ce qui devrait éviter l\'apparition d\'albums similaires.</string>
<string name="faq_4_text">Vous pouvez appuyer sur la durée actuelle ou totale de la vidéo sur la barre de progression, la vidéo reculera ou avancera selon votre choix.</string>
<string name="faq_5_title">Quelle est la différence entre masquer et exclure un dossier ?</string>
<string name="faq_5_text">\"Exclure un dossier\" permet de ne pas l\'afficher uniquement dans Simple Gallery, alors que \"Masquer un dossier\" rend le dossier invisible sur l\'ensemble de l\'appareil, y compris les autres applications de galerie. Dans le dernier cas, un fichier \".nomedia\" est créé dans le dossier masqué, et peut être supprimé avec n\'importe quel explorateur de fichiers.</string>
<string name="faq_6_title">Pourquoi des dossiers avec des pochettes d\'albums musicaux ou des miniatures d\'images sont affichés ?</string>
<string name="faq_6_text">Il est possible que des albums qui ne devraient pas être affichés le soient. Vous pouvez les exclure facilement en les sélectionnant par un appui prolongé, puis en choisissant l\'option \"Exclure\", après quoi vous pouvez aussi sélectionner le dossier parent, ce qui devrait éviter l\'apparition d\'albums similaires.</string>
<string name="faq_7_title">Un dossier avec des images n\'apparaît pas. Que faire ?</string>
<string name="faq_7_text">Cela peut arriver pour de multiples raisons, mais c\'est facile à résoudre. Allez dans « Paramètres » puis « Gérer les dossiers inclus », sélectionnez le plus et sélectionnez le dossier voulu.</string>
<string name="faq_7_text">Cela peut arriver pour de multiples raisons, mais c\'est facile à résoudre. Allez dans \"Paramètres\", puis \"Gérer les dossiers inclus\", appuyez sur \"+\" et sélectionnez le dossier voulu.</string>
<string name="faq_8_title">Comment faire apparaître uniquement certains dossiers ?</string>
<string name="faq_8_text">Ajouter un répértoire dans les dossiers inclus n\'exclut rien automatiquement. Pour ce faire, il faut aller dans « Paramètres » puis « Gérer les dossiers exclus », exclure le répertoire racine \"/\", puis ajouter les répertoires souhaités dans « Paramètres » puis « Gérer les répertoires inclus ». Seuls les répertoires selectionnés seront visibles, du fait que les exclusions et inclusions sont récursives, et si un répertoire est à la fois exclus et inclus, il sera affiché.</string>
<string name="faq_9_title">Les images en plein écran contiennent des artéfacts, est-ce possible d\'améliorer la qualité ?</string>
<string name="faq_9_text">Oui, il existe dans « Paramètres » une option « Remplacer les images zoomables profondes par des images de meilleure qualité », mais les images seront alors floues si vous zoomez trop.</string>
<string name="faq_8_text">Ajouter un dossier dans les \"Dossiers inclus\" rend visible l\'ensemble du contenu du dossier. Pour exclure certains dossiers, il faut aller dans \"Paramètres\", puis \"Gérer les dossiers exclus\", exclure le dossier racine \"/\", puis ajouter les dossiers souhaités dans \"Paramètres\", puis \"Gérer les dossiers inclus\". Seuls les dossiers sélectionnés seront visibles, du fait que les exclusions et inclusions sont récursives, et si un dossier est à la fois exclus et inclus, il sera affiché.</string>
<string name="faq_9_title">Les images en plein écran contiennent des artefacts, est-ce possible d\'améliorer la qualité ?</string>
<string name="faq_9_text">Oui, il existe dans \"Paramètres\" une option \"Afficher les images avec la plus haute qualité possible\", mais les images seront alors floues si vous zoomez trop.</string>
<string name="faq_10_title">Puis-je recadrer des images avec cette application ?</string>
<string name="faq_10_text">Oui, vous pouvez recadrer les images dans l\'éditeur en faisant glisser les coins de l\'image. Vous pouvez accéder à l\'éditeur en appuyant longuement sur une vignette d\'image et en sélectionnant Modifier, ou en sélectionnant Modifier en mode plein écran.</string>
<string name="faq_11_title">Puis-je en quelque sorte regrouper les vignettes des fichiers multimédias ?</string>
<string name="faq_11_text">Bien sûr, il vous suffit d\'utiliser l\'option de menu \"Grouper par\" lorsque vous êtes dans l\'affichage des vignettes. Vous pouvez regrouper les fichiers selon plusieurs critères, y compris la date de prise de vue. Si vous utilisez la fonction \"Afficher le contenu de tous les dossiers\", vous pouvez également les regrouper par dossiers.</string>
<string name="faq_12_title">Le tri par date prise ne semble pas fonctionner correctement, comment puis-je le corriger ?</string>
<string name="faq_12_text">Il est très probablement causé par les fichiers copiés quelque part. Vous pouvez le corriger en sélectionnant les vignettes du fichier et en sélectionnant \"Fix Date Taken value\".</string>
<string name="faq_13_title">I see some color banding on the images. How can I improve the quality?</string>
<string name="faq_13_text">The current solution for displaying images works fine in the vast majority of cases, but if you want even better image quality, you can enable the \"Show images in the highest possible quality\" at the app settings, in the \"Deep zoomable images\" section.</string>
<string name="faq_14_title">I have hidden a file/folder. How can I unhide it?</string>
<string name="faq_14_text">You can either press the \"Temporarily show hidden items\" menu item at the main screen, or toggle \"Show hidden items\" in the app settings to see the hidden item. If you want to unhide it, just long press it and select \"Unhide\". Folders are hidden by adding a hidden \".nomedia\" file into them, you can delete the file with any file manager too.</string>
<string name="faq_10_text">Oui, vous pouvez recadrer les images dans l\'éditeur en faisant glisser les coins de l\'image. Vous pouvez accéder à l\'éditeur en appuyant longuement sur une vignette d\'image et en sélectionnant \"Modifier\", ou en sélectionnant \"Modifier\" en mode plein écran.</string>
<string name="faq_11_title">Puis-je regrouper les miniatures des fichiers multimédias ?</string>
<string name="faq_11_text">Bien sûr, il vous suffit d\'utiliser l\'option de menu \"Grouper par\" lorsque vous êtes dans l\'affichage des miniatures. Vous pouvez regrouper les fichiers selon plusieurs critères, y compris la date de prise de vue. Si vous utilisez la fonction \"Afficher le contenu de tous les dossiers\", vous pouvez également les regrouper par dossier.</string>
<string name="faq_12_title">Le tri par date de prise de vue ne semble pas fonctionner correctement, comment puis-je le corriger ?</string>
<string name="faq_12_text">Il est très probablement causé par les fichiers copiés quelque part. Vous pouvez le corriger en sélectionnant les miniatures du fichier et en sélectionnant \"Corriger la valeur des dates de prise des photos\".</string>
<string name="faq_13_title">Je vois des bandes de couleurs sur les images. Comment puis-je améliorer la qualité ?</string>
<string name="faq_13_text">La solution actuelle d\'affichage des images fonctionne bien dans la grande majorité des cas, mais si vous voulez une qualité d\'image encore meilleure, vous pouvez activer l\'option \"Afficher les images avec la plus haute qualité possible\" dans la section \"Niveau de zoom maximal des images\" des paramètres de l\'application.</string>
<string name="faq_14_title">J\'ai masqué un fichier ou un dossier. Comment puis-je en rétablir l\'affichage ?</string>
<string name="faq_14_text">Vous pouvez soit appuyer sur l\'option \"Afficher les fichiers masqués\" du menu de l\'écran principal, ou appuyer sur le bouton \"Afficher les éléments masqués\" dans les paramètres de l\'application. Si vous voulez rétablir leur affichage, effectuez un appui prolongé dessus et appuyez sur le symbole \"Œil\" permettant l\'affichage. Les dossiers sont masqués en ajoutant un fichier \".nomedia\" à leur racine, vous pouvez également supprimer ce fichier avec n\importe quel explorateur de fichiers.</string>
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
<!-- Short description has to have less than 80 chars -->
<string name="app_short_description">Un album pour visionner photos et vidéos sans publicité.</string>
<string name="app_short_description">Une galerie pour visionner photos et vidéos sans publicité.</string>
<string name="app_long_description">
Un simple outil pour visionner les photos et les vidéos. Elles peuvent être triées par dates, tailles, noms dans les deux sens (alphabétique comme désalphabétique), il est possible de zoomer sur les photos. Les fichiers sont affichés sur de multiples colonnes en fonction de la taille de l\'écran, vous pouvez changer le nombre de colonnes par pincement. Elles peuvent être renommées, partagées, supprimées, copiées et déplacées. Les images peuvent en plus être tournées, rognées ou être définies comme fond d\'écran directement depuis l\'application.
Un outil simple pour visionner les photos et les vidéos. Elles peuvent être triées par dates, dimensions, noms dans les deux ordres (alphabétique ou alphabétique inversé), il est possible de zoomer sur les photos. Les fichiers sont affichés sur de multiples colonnes en fonction de la dimension de l\'écran, vous pouvez changer le nombre de colonnes par pincement. Elles peuvent être renommées, partagées, supprimées, copiées et déplacées. Les images peuvent en plus être pivotées, rognées ou être définies comme fond d\'écran directement depuis l\'application.
La galerie est également proposée pour une utilisation comme tierce partie pour la prévisualisation des images/vidéos, ajouter des pièces jointes aux clients email, etc… C\'est parfait pour un usage au quotidien.
La galerie est également proposée pour une utilisation comme tierce partie pour la prévisualisation des images/vidéos, ajouter des pièces jointes aux clients de courriel, etc… C\'est parfait pour un usage au quotidien.
L\'autorisation d\'empreinte digitale est nécessaire pour verrouiller les dossiers cachés et/ou l\'application.
L\'autorisation d\'empreinte digitale est nécessaire pour verrouiller les dossiers masqués et/ou l\'application.
L\'application ne contient ni publicité ni autorisation inutile. Elle est totalement opensource et est également fournie avec des couleurs personnalisables.
L\'application ne contient ni publicité, ni autorisation inutile. Elle est totalement opensource et est également fournie avec des couleurs personnalisables.
Cette application fait partie d\'une plus grande suite. Vous pouvez trouver les autres applications sur https://www.simplemobiletools.com
</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Iconas</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Sličice</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Thumbnails</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Immagini ingrandibili a fondo</string>
<string name="show_highest_quality">Mostra le immagini alla massima qualità possibile</string>
<string name="show_recycle_bin_last">Mostra il cestino come ultimo elemento nella schermata principale</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Miniature</string>

View file

@ -132,36 +132,37 @@
<string name="by_extension">拡張子</string>
<!-- Settings -->
<string name="autoplay_videos">ビデオを自動再生する</string>
<string name="autoplay_videos">ビデオを自動再生</string>
<string name="toggle_filename">ファイル名の表示を切り替え</string>
<string name="loop_videos">ビデオを繰り返し再生する</string>
<string name="animate_gifs">アニメーションGIFのサムネイルを動かす</string>
<string name="max_brightness">メディア再生時に明るさを最大にする</string>
<string name="loop_videos">ビデオを繰り返し再生</string>
<string name="animate_gifs">アニメーションGIFを動かす</string>
<string name="max_brightness">再生時に明るさを最大にする</string>
<string name="crop_thumbnails">サムネイルを正方形に切り取る</string>
<string name="screen_rotation_by">メディア再生時のフルスクリーン表示切り替え</string>
<string name="screen_rotation_by">フルスクリーン再生の表示切り替え</string>
<string name="screen_rotation_system_setting">システム設定に従う</string>
<string name="screen_rotation_device_rotation">端末の向きに従う</string>
<string name="screen_rotation_aspect_ratio">メディアの縦横比に従う</string>
<string name="black_background_at_fullscreen">表示の背景色とステータスバーの背景色を黒にする</string>
<string name="black_background_at_fullscreen">メディア表示の背景色を黒にする</string>
<string name="scroll_thumbnails_horizontally">サムネイル画面を横方向にスクロール</string>
<string name="hide_system_ui_at_fullscreen">フルスクリーン時にシステムUIを非表示にする</string>
<string name="delete_empty_folders">フォルダが空になったらフォルダも削除する</string>
<string name="allow_photo_gestures">垂直のジェスチャーで写真の明るさを制御する</string>
<string name="allow_video_gestures">音量と明るさを縦のジェスチャーで変更する</string>
<string name="show_media_count">フォルダ内のメディア数を表示する</string>
<string name="hide_system_ui_at_fullscreen">全画面ではシステムUIを非表示</string>
<string name="delete_empty_folders">空になったフォルダは削除する</string>
<string name="allow_photo_gestures">垂直の動作で写真の明るさを制御</string>
<string name="allow_video_gestures">音量と明るさを縦の動作で変更</string>
<string name="show_media_count">フォルダ内のメディア数を表示する</string>
<string name="replace_share_with_rotate">フルスクリーン時の「共有」を「回転」に置き換える</string>
<string name="show_extended_details">フルスクリーンに詳細を重ねて表示する</string>
<string name="manage_extended_details">詳細表示を管理する</string>
<string name="one_finger_zoom">メディアを指ひとつでズーム可能にする</string>
<string name="allow_instant_change">画面の端を押してメディアをスライドする</string>
<string name="allow_deep_zooming_images">Allow deep zooming images</string>
<string name="one_finger_zoom">メディアを指だけでズームする</string>
<string name="allow_instant_change">端を押してメディアをスライド</string>
<string name="allow_deep_zooming_images">深いズームを許可</string>
<string name="hide_extended_details">ステータスバーが非表示の時は詳細を隠す</string>
<string name="do_extra_check">無効なファイルを見せない調整を行う</string>
<string name="show_at_bottom">画面下部にアクションボタンを表示する</string>
<string name="show_recycle_bin">フォルダ画面にごみ箱を表示する</string>
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="do_extra_check">無効なファイルは見せない</string>
<string name="show_at_bottom">画面の下にはアクションを表示</string>
<string name="show_recycle_bin">フォルダ画面にごみ箱を表示</string>
<string name="deep_zoomable_images">画像のズームを深くする</string>
<string name="show_highest_quality">可能な限り高品質で画像を表示</string>
<string name="show_recycle_bin_last">ごみ箱をメイン画面の最後に表示</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">サムネイル設定</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">섬네일</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Miniatiūros</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Minibilder</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Afbeeldingen ver inzoomen</string>
<string name="show_highest_quality">Afbeeldingen in de hoogst mogelijke kwaliteit weergeven</string>
<string name="show_recycle_bin_last">Prullenbak als laatste item tonen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Miniatuurvoorbeelden</string>

View file

@ -38,7 +38,7 @@
<string name="videos">Filmy</string>
<string name="gifs">GIFy</string>
<string name="raw_images">Obrazy RAW</string>
<string name="svgs">SVGs</string>
<string name="svgs">Obrazy SVG</string>
<string name="no_media_with_filters">Nie znalazłem multimediów z wybranymi filtrami.</string>
<string name="change_filters_underlined"><u>Zmień filtry</u></string>
@ -159,9 +159,10 @@
   <string name="do_extra_check">Dodatkowe sprawdzenie w celu uniknięcia pokazywania niewłaściwych plików</string>
<string name="show_at_bottom">Pokazuj niektóre przyciski akcji na dole ekranu</string>
<string name="show_recycle_bin">Pokazuj kosz w widoku folderów</string>
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="deep_zoomable_images">Duże powiększanie obrazów</string>
<string name="show_highest_quality">Pokazuj obrazy w najwyższej możliwej rozdzielczości</string>
<string name="show_recycle_bin_last">Pokazuj kosz jako ostatni element na głównym ekranie</string>
<string name="allow_down_gesture">Zezwalaj na zamykanie pełnoekranowego widoku gestem pociągnięcia w dół</string>
<!-- Setting sections -->
   <string name="thumbnails">Miniatury</string>
@ -199,10 +200,10 @@
<string name="faq_11_text">Tak. Użyj opcji \'Grupuj według\', gdy jesteś w widoku miniatur. Grupować je możesz według wielu kryteriów, włącznie z datą ich utworzenia. Ponadto, jeśli użyjesz opcji \'Pokazuj całą zawartość folderów\', możesz je także grupować według folderów.</string>
<string name="faq_12_title">Sortowanie według daty utworzenia nie działa poprawnie. Dlaczego tak się dzieje i jak mogę to naprawić?</string>
<string name="faq_12_text">Dzieje się tak, gdyż prawdopodobnie pliki zostały skądś do urządzenia skopiowane. Naprawić to można wybierając miniatury plików, a następnie opcję \'Napraw datę utworzenia\'.</string>
<string name="faq_13_title">I see some color banding on the images. How can I improve the quality?</string>
<string name="faq_13_text">The current solution for displaying images works fine in the vast majority of cases, but if you want even better image quality, you can enable the \"Show images in the highest possible quality\" at the app settings, in the \"Deep zoomable images\" section.</string>
<string name="faq_14_title">I have hidden a file/folder. How can I unhide it?</string>
<string name="faq_14_text">You can either press the \"Temporarily show hidden items\" menu item at the main screen, or toggle \"Show hidden items\" in the app settings to see the hidden item. If you want to unhide it, just long press it and select \"Unhide\". Folders are hidden by adding a hidden \".nomedia\" file into them, you can delete the file with any file manager too.</string>
<string name="faq_13_title">Na obrazach widzę wyraźne zmiany w kolorach. Jak mogę to naprawić?</string>
<string name="faq_13_text">Obecne rozwiązanie służące wyświetlaniu obrazów działa jak powinno w większości w przypadków. Jeśli jednak tak nie jest, pomocna może okazać się opcja \"Pokazuj obrazy w najwyższej możliwej jakości\" w sekcji \"Duże powiększanie obrazów\".</string>
<string name="faq_14_title">Mam ukryte pliki i / lub foldery. Jak mogę zobaczyć?</string>
<string name="faq_14_text">Możesz to zrobić albo wybierając opcję \"Tymczasowo pokaż ukryte multimedia\" w menu na ekranie głównym, lub \"Pokazuj ukryte elementy\" w ustawieniach. Foldery są ukrywane poprzez dodanie do nich pustego, ukrytego pliku \".nomedia\", usunąć go możesz dowolnym menedżerem plików.</string>
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
<!-- Short description has to have less than 80 chars -->

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Miniaturas</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Mostrar fotos com a melhor qualidade possível</string>
<string name="show_recycle_bin_last">Mostrar a reciclagem como o último item do ecrã principal</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Miniaturas</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Масштабируемые изображения</string>
<string name="show_highest_quality">Показывать изображения с максимально высоким качеством</string>
<string name="show_recycle_bin_last">Показывать корзину как последний элемент на главном экране</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Миниатюры</string>

View file

@ -146,7 +146,7 @@
<string name="scroll_thumbnails_horizontally">Prehliadať miniatúry vodorovne</string>
<string name="hide_system_ui_at_fullscreen">Automaticky skrývať systémové lišty pri celoobrazovkových médiách</string>
<string name="delete_empty_folders">Odstrániť prázdne priečinky po vymazaní ich obsahu</string>
<string name="allow_photo_gestures">Allow controlling photo brightness with vertical gestures</string>
<string name="allow_photo_gestures">Povoliť ovládanie jasu vertikálnymi ťahmi</string>
<string name="allow_video_gestures">Povoliť ovládanie hlasitosti a jasu videí vertikálnymi ťahmi</string>
<string name="show_media_count">Zobraziť počet médií v priečinku na hlavnej obrazovke</string>
<string name="replace_share_with_rotate">Nahradiť Zdieľanie s Otočením v celoobrazovkovom menu</string>
@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Hlboko priblížiteľné obrázky</string>
<string name="show_highest_quality">Zobrazovať obrázky v najlepšej možnej kvalite</string>
<string name="show_recycle_bin_last">Zobraziť odpadkový kôš ako poslednú položku na hlavnej obrazovke</string>
<string name="allow_down_gesture">Povoliť zatváranie celoobrazovkového režimu potiahnutím prsta dole</string>
<!-- Setting sections -->
<string name="thumbnails">Náhľady</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Miniatyrer</string>

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Thumbnails</string>

View file

@ -0,0 +1,229 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Simple Gallery</string>
<string name="app_launcher_name">Галерея</string>
<string name="edit">Редагувати</string>
<string name="open_camera">Запустити камеру</string>
<string name="hidden">(приховане)</string>
<string name="excluded">(виключене)</string>
<string name="pin_folder">Закріпити теку</string>
<string name="unpin_folder">Відкріпити теку</string>
<string name="pin_to_the_top">Закріпити зверху</string>
<string name="show_all">Показати вміст усіх тек</string>
<string name="all_folders">Усі теки</string>
<string name="folder_view">Перемкнути у перегляд за теками</string>
<string name="other_folder">Інша тека</string>
<string name="show_on_map">Показати на мапі</string>
<string name="unknown_location">Невідоме місцерозташування</string>
<string name="increase_column_count">Збільшити кількість колонок</string>
<string name="reduce_column_count">Зменшити кількість колонок</string>
<string name="change_cover_image">Змінити обкладинку</string>
<string name="select_photo">Вибрати фото</string>
<string name="use_default">Використовувати за-замовчуванням</string>
<string name="volume">Об\'єм</string>
<string name="brightness">Яскравість</string>
<string name="lock_orientation">Закріпити орієнтацію</string>
<string name="unlock_orientation">Відкріпити орієнтацію</string>
<string name="change_orientation">Змінити орієнтацію</string>
<string name="force_portrait">Примусова портретна орієнтація</string>
<string name="force_landscape">Примусова ландшафтна орієнтація</string>
<string name="use_default_orientation">Орієнтація за-замовчуванням</string>
<string name="fix_date_taken">Виправити дату зйомки</string>
<string name="fixing">Виправлення…</string>
<string name="dates_fixed_successfully">Дати успішно виправлені</string>
<!-- Filter -->
<string name="filter_media">Фільтр мультимедійних файлів</string>
<string name="images">Зображення</string>
<string name="videos">Відео</string>
<string name="gifs">GIF-зображення</string>
<string name="raw_images">RAW-зображення</string>
<string name="svgs">SVG-зображення</string>
<string name="no_media_with_filters">З вибраними фільтрами мультимедійні файли не знайдено.</string>
<string name="change_filters_underlined"><u>Змінити фільтри</u></string>
<!-- Hide / Exclude -->
<string name="hide_folder_description">Ця функція приховує теку шляхом додавання в неї файлу \".nomedia\"; це також приховає і підтеки. Ви можете побачити приховані теки, обравши опцію \'Показати приховані елементи\' в \"Налаштуваннях\". Продовжити?</string>
<string name="exclude">Виключити</string>
<string name="excluded_folders">Виключені теки</string>
<string name="manage_excluded_folders">Керування виключеними теками</string>
<string name="exclude_folder_description">Ця дія виключить обрані теки з їх підтеками тільки з Simple Gallery. Керувати виключеними теками можна у \"Налаштуваннях\".</string>
<string name="exclude_folder_parent">Виключити батьківську теку натомість?</string>
<string name="excluded_activity_placeholder">Виключення тек приховає їх разом з їх підтеками тільки у Simple Gallery, але вони все ще будуть видимі у інших додатках.\n\nЯкщо ви хочете приховати їх і від інших додатків, використовуйте функцію \"Приховати\".</string>
<string name="remove_all">Видалити все</string>
<string name="remove_all_description">Видалити всі теки зі списку виключених? Це не видалить теки з пристрою.</string>
<string name="hidden_folders">Приховані теки</string>
<string name="manage_hidden_folders">Керування прихованими теками</string>
<string name="hidden_folders_placeholder">Схоже, у вас немає тек, прихованих за допомогою файлу \".nomedia\".</string>
<!-- Include folders -->
<string name="include_folders">Включені теки</string>
<string name="manage_included_folders">Керування включеними теками</string>
<string name="add_folder">Додати теку</string>
<string name="included_activity_placeholder">Якщо у вас є теки з медіафайлами, але вони не були розпізнані додатком, ви можете додати їх тут вручну.\n\nДодавання елементів сюди не виключить будь-яку іншу теку.</string>
<!-- Resizing -->
<string name="resize">Змінити розмір</string>
<string name="resize_and_save">Змінити розмір вибраного і зберегти</string>
<string name="width">Ширина</string>
<string name="height">Висота</string>
<string name="keep_aspect_ratio">Зберігати співвідношення сторін</string>
<string name="invalid_values">Введіть допустиму роздільну здатність</string>
<!-- Editor -->
<string name="editor">Редактор</string>
<string name="save">Зберегти</string>
<string name="rotate">Обернути</string>
<string name="path">Шлях</string>
<string name="invalid_image_path">Неприпустимий шлях до зображення</string>
<string name="image_editing_failed">Не вдалося редагувати зображення</string>
<string name="edit_image_with">Редагувати зображення за допомогою:</string>
<string name="no_editor_found">Не знайдено редакторів зображень</string>
<string name="unknown_file_location">Невідоме розташування файлу</string>
<string name="error_saving_file">Не вдалося перезаписати вихідний файл</string>
<string name="rotate_left">Обернути ліворуч</string>
<string name="rotate_right">Обернути праворуч</string>
<string name="rotate_one_eighty">Обернути на 180º</string>
<string name="flip">Віддзеркалити</string>
<string name="flip_horizontally">Віддзеркалити горизонтально</string>
<string name="flip_vertically">Віддзеркалити вертикально</string>
<string name="edit_with">Редагувати за допомогою</string>
<string name="free_aspect_ratio">Вільне співвідношення сторін</string> <!-- available as an option: 1:1, 4:3, 16:9, free -->
<!-- Set wallpaper -->
<string name="simple_wallpaper">Simple Wallpaper</string>
<string name="set_as_wallpaper">Встановити як шпалери</string>
<string name="set_as_wallpaper_failed">Не вдалося встановити шпалери</string>
<string name="set_as_wallpaper_with">Встановити шпалери за допомогою:</string>
<string name="setting_wallpaper">Встановлення шпалер…</string>
<string name="wallpaper_set_successfully">Шпалери успішно встановлено</string>
<string name="portrait_aspect_ratio">Співвідношення сторін в портретній орієнтації</string>
<string name="landscape_aspect_ratio">Співвідношення сторін в ландшафтній орієнтації</string>
<string name="home_screen">Домашній екран</string>
<string name="lock_screen">Екран блокування</string>
<string name="home_and_lock_screen">Домашній екран і екран блокування</string>
<!-- Slideshow -->
<string name="slideshow">Слайдшоу</string>
<string name="interval">Інтервал (секунди):</string>
<string name="include_photos">Включити фото</string>
<string name="include_videos">Включити відео</string>
<string name="include_gifs">Включити GIF-зображення</string>
<string name="random_order">Випадковий порядок</string>
<string name="use_fade">Використовувати анімацію затухання</string>
<string name="move_backwards">Рухатися назад</string>
<string name="loop_slideshow">Зациклити показ слайдів</string>
<string name="slideshow_ended">Слайдшоу закінчено</string>
<string name="no_media_for_slideshow">Не знайдено медіафайлів для показу у слайдшоу</string>
<!-- View types -->
<string name="change_view_type">Змінити тип перегляду</string>
<string name="grid">Сітка</string>
<string name="list">Список</string>
<string name="group_direct_subfolders">Групувати безпосередні підтеки</string>
<!-- Grouping at media thumbnails -->
<string name="group_by">Групувати за…</string>
<string name="do_not_group_files">Не групувати файли</string>
<string name="by_folder">текою</string>
<string name="by_last_modified">останньою зміною</string>
<string name="by_date_taken">датою зйомки</string>
<string name="by_file_type">типом файлу</string>
<string name="by_extension">розширенням</string>
<!-- Settings -->
<string name="autoplay_videos">Відтворювати відео автоматично</string>
<string name="toggle_filename">Перемкнути відображення імені файлу</string>
<string name="loop_videos">Зациклити відео</string>
<string name="animate_gifs">Анімувати ескізи GIF-файлів</string>
<string name="max_brightness">Максимальна яскравість екрану при повноекранному перегляді медіафайлу</string>
<string name="crop_thumbnails">Обрізати ескізи у квадрат</string>
<string name="screen_rotation_by">При повноекранному перегляді обертати за…</string>
<string name="screen_rotation_system_setting">системними налаштуваннями</string>
<string name="screen_rotation_device_rotation">поворотом пристрою</string>
<string name="screen_rotation_aspect_ratio">співвідношенням сторін</string>
<string name="black_background_at_fullscreen">Чорне тло і рядок стану при повноекранному перегляді</string>
<string name="scroll_thumbnails_horizontally">Гортати ескізи горизонтально</string>
<string name="hide_system_ui_at_fullscreen">Автоматично приховувати системний інтерфейс при повноекранному перегляді</string>
<string name="delete_empty_folders">Видаляти порожні теки після видалення їх вмісту</string>
<string name="allow_photo_gestures">Дозволити керування яскравістю фотографій вертикальними жестами</string>
<string name="allow_video_gestures">Дозволити керування яскравістю та гучністю відео вертикальними жестами</string>
<string name="show_media_count">Показувати кількість файлів у теці на головному екрані</string>
<string name="replace_share_with_rotate">Замінити \"Поділитися\" на \"Обернути\" в повноекранному меню</string>
<string name="show_extended_details">Показувати розширені подробиці при повноекранному перегляді</string>
<string name="manage_extended_details">Керування розширеними подробицями</string>
<string name="one_finger_zoom">Дозволити масштабування одним пальцем при повноекранному перегляді</string>
<string name="allow_instant_change">Дозволити миттєво змінювати медіафайл натисканням на сторони екрану</string>
<string name="allow_deep_zooming_images">Дозволити глибоке масштабування зображень</string>
<string name="hide_extended_details">Приховати розширені подробиці, коли рядок стану прихований</string>
<string name="do_extra_check">Робити додаткову перевірку для запобігання відображенню недійсних файлів</string>
<string name="show_at_bottom">Показати деякі кнопки дій внизу екрану</string>
<string name="show_recycle_bin">Показувати \"Кошик\" на головному екрані</string>
<string name="deep_zoomable_images">Глибокомасштабовані зображення</string>
<string name="show_highest_quality">Показувати зображення в найвищій можливій якості</string>
<string name="show_recycle_bin_last">Показувати \"Кошик\" останнім елементом на головному екрані</string>
<string name="allow_down_gesture">Дозволити закриття повноекранного перегляду свайпом згори вниз</string>
<!-- Setting sections -->
<string name="thumbnails">Ескізи</string>
<string name="fullscreen_media">Повноекранний перегляд</string>
<string name="extended_details">Розширені подробиці</string>
<string name="bottom_actions">Кнопки дій внизу екрану</string>
<!-- Bottom actions -->
<string name="manage_bottom_actions">Керування видимими кнопками дій внизу екрану</string>
<string name="toggle_favorite">Перемкнути улюблене</string>
<string name="toggle_file_visibility">Перемкнути видимість файлу</string>
<!-- FAQ -->
<string name="faq_1_title">Як зробити Simple Gallery галереєю за-замовчуванням?</string>
<string name="faq_1_text">Спочатку необхідно знайти поточну галерею за-замовчуванням в розділі \"Додатки\" налаштувань вашого пристрою. Знайдіть і натисніть на кнопку \"Використовувати за-замовчуванням\" абощо, потім оберіть \"Очистити замовчування\".
Наступного разу коли ви намагатиметеся відкрити зображення або відео, ви побачите вікно з вибором додатків для цього. Оберіть Simple Gallery та зробіть його додатком за-замовчуванням.</string>
<string name="faq_2_title">Я заблокував додаток за допомогою паролю і забув його. Що я можу зробити?</string>
<string name="faq_2_text">Ви можете вирішити цю проблему двома способами: перевстановити додаток або знайти його в розділі \"Додатки\" налаштувань вашого пристрою та обрати \"Очистити дані\". Це скине усі ваші налаштування додатка, але не видалить жодного медіафайлу.</string>
<string name="faq_3_title">Як зробити альбом завжди доступним у верхній частині?</string>
<string name="faq_3_text">Ви можете виконати довге натискання на бажаному альбомі і вибрати піктограму \"Закріпити\" у меню дій, що закріпить його вгорі. Ви також можете закріпити декілька тек; закріплені елементи будуть відсортовані за методом сортування за-замовчуванням.</string>
<string name="faq_4_title">Як я можу швидко прокручувати відео?</string>
<string name="faq_4_text">Ви можете натиснути на текст поточного таймінгу або на текст загальної тривалості відео на прогрес-барі, що перемістить відео або назад, або вперед.</string>
<string name="faq_5_title">В чому полягає різниця між приховуванням та виключенням теки?</string>
<string name="faq_5_text">\"Виключити\" запобігає відображенню теки тільки в додатку Simple Gallery, в той час як \"Приховати\" працює на системному рівні і приховує теку і в інших галереях також. Це здійснюється шляхом створення порожнього файлу \".nomedia\" в заданій теці, який може бути видалений пізніше будь-яким файловим менеджером.</string>
<string name="faq_6_title">Чому відображаються теки з музичними обкладинками або стікерами?</string>
<string name="faq_6_text">Може так трапитися, що з\'являться деякі незвичні альбоми. Їх можна легко виключити довгим натисканням і вибором \"Виключити\". В наступному діалозі у вас буде можливість обрати бітьківську теку. Швидше за все, це дозволить також запобігти появі інших пов\'язаних альбомів.</string>
<string name="faq_7_title">Тека з зображеннями не відображається, що мені робити?</string>
<string name="faq_7_text">У цього може бути кілька причин, проте вирішення доволі просте. Перейдіть в \"Налаштування\" -> \"Керування виключеними теками\", оберіть \"Плюс\" та перейдіть до потрібної теки.</string>
<string name="faq_8_title">Що робити, якщо я хочу, щоб лише кілька окремих тек були видимими?</string>
<string name="faq_8_text">Додавання теки до \"Включених тек\" автоматично не виключає нічого. Що ви можете зробити, то це перейти в \"Налаштування\" -> \"Керування виключеними теками\", виключити кореневу теку \"/\", потім додати бажані теки через \"Налаштування\" -> \"Керування включеними теками\".
Це зробить видимими лише обрані теки. Якщо тека є одночасно і виключеною, і включеною, вона відобразиться, оскільки і виключення, і включення є рекурсивним.</string>
<string name="faq_9_title">Повноекранні зображення мають дивні артефакти. Чи можна якось покращити якість?</string>
<string name="faq_9_text">Так, у \"Налаштуваннях\" є перемикач з текстом \"Замінити глибокомасштабовані зображення іншими кращої якості\", скористайтеся ним. Він покращить якість зображень, але вони будуть розмиватися, якщо ви занадто їх збільшуватимете.</string>
<string name="faq_10_title">Чи можу я обрізати зображення у цьому додатку?</string>
<string name="faq_10_text">Так, обрізати зображення можна у редакторі шляхом перетягування кутів зображення. Відкрити редактор можна або довгим натисканням на ескіз зображення і наступним вибором \"Редагувати\", або вибором \"Редагувати\" при повноекранному перегляді.</string>
<string name="faq_11_title">Чи можу я якимось чином згрупувати ескізи медіафайлів?</string>
<string name="faq_11_text">Звісно, просто скористайтеся пунктом меню \"Групувати за…\", знаходячись на екрані ескізів. Групувати файли можна за кількома критеріями, включаючи дату зйомки. Якщо ви використовуєте функцію \"Показати вміст усіх тек\", ви також можете групувати їх за теками.</string>
<string name="faq_12_title">Сортування за датою зйомки, здається, працює некоректно. Як я можу це виправити?</string>
<string name="faq_12_text">Найбільш вірогідна причина цього - копіювання фалів з іншого місця. Це можна виправити, обравши ескізи файлів і потім - \"Виправити дату зйомки\".</string>
<string name="faq_13_title">Я бачу деякі кольорові нашарування на зображенні. Як я можу покращити якість?</string>
<string name="faq_13_text">Поточне рішення для показу зображень відмінно працює в переважній більшості випадків, але якщо вам потрібна ще краща якість зображень, ви можете увімкнути опцію \"Показувати зображення в найвищій можливій якості\" в розділі \"Глибокомасштабовані зображення\" налаштувань додатку.</string>
<string name="faq_14_title">Я приховав файл / теку. Як я можу відмінити цю дію?</string>
<string name="faq_14_text">Щоб побачити приховані елементи, ви можете або натиснути пункт меню \"Тимчасово показати приховані елементи\" на головному екрані, або перемкнути опцію \"Показати приховані елементи\" в налаштуваннях додатку. Якщо ви більше не хочете приховувати елемент, довго натисніть на нього і оберіть \"Не приховувати\". Теки приховуються шляхом створення прихованого файлу \".nomedia\" в них, тож ви також можете видалити цей файл будь-яким файловим менеджером.</string>
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
<!-- Short description has to have less than 80 chars -->
<string name="app_short_description">Галерея для перегляду фото та відео без реклами.</string>
<string name="app_long_description">
Простий інструмент для перегляду фотографій і відео. Елементи можна сортувати за датою, розміром, ім\'ям як за зростанням, так і за спаданням, фотографії можна масштабувати. Медіафайли показуються у кілька колонок залежно від розміру екрану, їх кількість може бути змінена жестом \"щипок екрану\". Медіафайли можна перейменовувати, копіювати, переміщувати, видаляти або ділитися ними. Зображення також можна обрізати, обертати, віддзеркалювати або встановлювати як шпалери безпосередньо з додатку.
Галерея також пропонується для використання третіми сторонами для перегляду зображень / відео, додавання долучень до клієнтів електронної пошти тощо. Вона ідеально підходить для щоденного використання.
Дозвіл на доступ до відбитків пальців потрібен для блокування відображення прихованих елементів або для блокування всього застосунку.
Не містить реклами або непотрібних дозволів. Додаток повністю OpenSource, забезпечує налаштування кольорів.
Цей додаток є частиною великої серії схожих додатків. Ви можете знайти решту з них на https://www.simplemobiletools.com
</string>
<!--
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>

View file

@ -1,7 +0,0 @@
<resources>
<style name="FullScreenTheme" parent="AppTheme.Base">
<item name="android:windowTranslucentNavigation">true</item>
</style>
</resources>

View file

@ -24,13 +24,13 @@
<string name="brightness">亮度</string>
<string name="lock_orientation">锁定方向</string>
<string name="unlock_orientation">解锁方向</string>
<string name="change_orientation">Change orientation</string>
<string name="force_portrait">Force portrait</string>
<string name="force_landscape">Force landscape</string>
<string name="use_default_orientation">Use default orientation</string>
<string name="fix_date_taken">Fix Date Taken value</string>
<string name="fixing">Fixing</string>
<string name="dates_fixed_successfully">Dates fixed successfully</string>
<string name="change_orientation">改变方向</string>
<string name="force_portrait">强制竖屏</string>
<string name="force_landscape">强制横屏</string>
<string name="use_default_orientation">默认</string>
<string name="fix_date_taken">修复拍摄日期</string>
<string name="fixing">正在修复</string>
<string name="dates_fixed_successfully">日期修复成功</string>
<!-- Filter -->
<string name="filter_media">要显示的媒体文件</string>
@ -88,7 +88,7 @@
<string name="flip_horizontally">水平翻转</string>
<string name="flip_vertically">垂直翻转</string>
<string name="edit_with">编辑方式</string>
<string name="free_aspect_ratio">Free</string> <!-- available as an option: 1:1, 4:3, 16:9, free -->
<string name="free_aspect_ratio">自由</string> <!-- available as an option: 1:1, 4:3, 16:9, free -->
<!-- Set wallpaper -->
<string name="simple_wallpaper">简约壁纸</string>
@ -154,25 +154,26 @@
<string name="manage_extended_details">要显示的详细信息项目</string>
<string name="one_finger_zoom">单指缩放</string>
<string name="allow_instant_change">通过单击屏幕边缘来切换媒体</string>
<string name="allow_deep_zooming_images">Allow deep zooming images</string>
<string name="allow_deep_zooming_images">允许深度放大图像</string>
<string name="hide_extended_details">当状态栏隐藏时隐藏扩展详情</string>
<string name="do_extra_check">额外检查以避免显示无效的文件</string>
<string name="show_at_bottom">在屏幕底部显示一些操作按钮</string>
<string name="show_recycle_bin">Show the Recycle Bin at the folders screen</string>
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="show_at_bottom">显示底栏</string>
<string name="show_recycle_bin">在文件夹界面显示回收站</string>
<string name="deep_zoomable_images">深度放大图像</string>
<string name="show_highest_quality">以最高质量显示图像</string>
<string name="show_recycle_bin_last">在主屏幕界面的最后一项显示回收站</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">缩略图</string>
<string name="fullscreen_media">全屏显示媒体</string>
<string name="extended_details">扩展详情</string>
<string name="bottom_actions">Bottom actions</string>
<string name="bottom_actions">底栏选项</string>
<!-- Bottom actions -->
<string name="manage_bottom_actions">Manage visible bottom actions</string>
<string name="toggle_favorite">Toggle favorite</string>
<string name="toggle_file_visibility">Toggle file visibility</string>
<string name="manage_bottom_actions">管理底栏选项</string>
<string name="toggle_favorite">收藏</string>
<string name="toggle_file_visibility">隐藏文件</string>
<!-- FAQ -->
<string name="faq_1_title">如何把简约图库设置为设备的默认图库?</string>
@ -197,12 +198,12 @@
<string name="faq_10_text">当然,通过长按图片缩略图并选择编辑,或在全屏视图中选择编辑来打开编辑器。你可以通过拖动图片边角来剪裁图像。</string>
<string name="faq_11_title">我能将媒体文件缩略图分组吗?</string>
<string name="faq_11_text">当然,只需在缩略图视图中使用\"分组依据\"菜单项即可。您可以依据多个条件对文件进行分组,包括拍摄日期。如果您使用了\"显示所有文件夹内容\"功能,则可以按文件夹对它们进行分组。</string>
<string name="faq_12_title">Sorting by Date Taken doesn\'t seem to work properly, how can I fix it?</string>
<string name="faq_12_text">It is most likely caused by the files being copied from somewhere. You can fix it by selecting the file thumbnails and selecting \"Fix Date Taken value\".</string>
<string name="faq_13_title">I see some color banding on the images. How can I improve the quality?</string>
<string name="faq_13_text">The current solution for displaying images works fine in the vast majority of cases, but if you want even better image quality, you can enable the \"Show images in the highest possible quality\" at the app settings, in the \"Deep zoomable images\" section.</string>
<string name="faq_14_title">I have hidden a file/folder. How can I unhide it?</string>
<string name="faq_14_text">You can either press the \"Temporarily show hidden items\" menu item at the main screen, or toggle \"Show hidden items\" in the app settings to see the hidden item. If you want to unhide it, just long press it and select \"Unhide\". Folders are hidden by adding a hidden \".nomedia\" file into them, you can delete the file with any file manager too.</string>
<string name="faq_12_title">按拍摄日期排序似乎有异常,我该如何解决?</string>
<string name="faq_12_text">很可能是因为图片是从某处复制过来的。您可以长按文件缩略图并选择\"修复拍摄日期\"来修复它。</string>
<string name="faq_13_title">我看到图像上有一些色带。如何提高提高质量?</string>
<string name="faq_13_text">目前显示图像的方案在绝大多数情况下都能正常工作,如果您想要更好的图像质量,您可以在设置中启用\"以最高质量显示图像\"。</string>
<string name="faq_14_title">我隐藏了某个文件/文件夹。如何取消隐藏?</string>
<string name="faq_14_text">您可以点击主界面上的\"暂时显示隐藏的项目\"选项,或在设置中开启\"显示隐藏的项目\"。 如果你想取消隐藏它,长按它并选择\"取消隐藏\"即可。 我们是通过向文件夹中添加\".nomedia\"文件来隐藏文件夹的,使用文件管理器删除该文件也可以取消隐藏。</string>
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
<!-- Short description has to have less than 80 chars -->

View file

@ -162,6 +162,7 @@
<string name="deep_zoomable_images">可深度縮放的圖片</string>
<string name="show_highest_quality">以最高品質顯示圖片</string>
<string name="show_recycle_bin_last">回收桶顯示在主畫面最後一項</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">縮圖</string>

View file

@ -2,6 +2,7 @@
<resources>
<!-- Release notes -->
<string name="release_202">Added a new option for showing the Recycle Bin as the last folder</string>
<string name="release_201">
Added a new settings toggle \"Show images in the highest possible quality\"\n
Allow faster video seeking by dragging a finger at the bottom seekbar

View file

@ -162,7 +162,7 @@
<string name="deep_zoomable_images">Deep zoomable images</string>
<string name="show_highest_quality">Show images in the highest possible quality</string>
<string name="show_recycle_bin_last">Show the Recycle Bin as the last item on the main screen</string>
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<!-- Setting sections -->
<string name="thumbnails">Thumbnails</string>

View file

@ -4,6 +4,7 @@
<style name="FullScreenTheme.Base" parent="AppTheme">
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
<style name="FullScreenTheme" parent="FullScreenTheme.Base"/>

View file

@ -9,7 +9,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0'
classpath 'com.android.tools.build:gradle:3.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong

2
gradle.properties Normal file
View file

@ -0,0 +1,2 @@
android.enableJetifier=true
android.useAndroidX=true