31
CHANGELOG.md
|
@ -1,6 +1,37 @@
|
|||
Changelog
|
||||
==========
|
||||
|
||||
Version 4.3.2 *(2018-07-04)*
|
||||
----------------------------
|
||||
|
||||
* Added Panorama photo support
|
||||
* Allow customizing visible fullscreen bottom actions
|
||||
* Allow forcing portrait/landscape modes at fullscreen view
|
||||
* Use Exoplayer for playing videos
|
||||
* Many smaller UX and stability improvements
|
||||
|
||||
Version 4.3.1 *(2018-06-28)*
|
||||
----------------------------
|
||||
|
||||
* Adding some crashfixes
|
||||
|
||||
Version 4.3.0 *(2018-06-28)*
|
||||
----------------------------
|
||||
|
||||
* Added a Recycle Bin
|
||||
* Allow grouping media thumbnails by different criteria
|
||||
* Fixed some calculation glitches around fastscroller
|
||||
* Change the fullscreen Edit icon to a pencil
|
||||
* Allow sorting "Show All" separately
|
||||
* Many smaller stability and UX improvements
|
||||
|
||||
Version 4.2.1 *(2018-06-20)*
|
||||
----------------------------
|
||||
|
||||
* Allow selecting Favorite items for easy access
|
||||
* Fix sorting by Date Taken after files have been copied
|
||||
* Couple other stability and UX improvements
|
||||
|
||||
Version 4.2.0 *(2018-06-18)*
|
||||
----------------------------
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ android {
|
|||
applicationId "com.simplemobiletools.gallery"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 27
|
||||
versionCode 180
|
||||
versionName "4.2.0"
|
||||
versionCode 184
|
||||
versionName "4.3.2"
|
||||
multiDexEnabled true
|
||||
setProperty("archivesBaseName", "gallery")
|
||||
}
|
||||
|
@ -47,17 +47,20 @@ ext {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.simplemobiletools:commons:4.2.8'
|
||||
implementation 'com.simplemobiletools:commons:4.3.27'
|
||||
implementation 'com.theartofdev.edmodo:android-image-cropper:2.7.0'
|
||||
implementation 'com.android.support:multidex:1.0.3'
|
||||
implementation 'it.sephiroth.android.exif:library:1.0.1'
|
||||
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.12'
|
||||
implementation 'com.github.chrisbanes:PhotoView:2.1.3'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
||||
implementation 'com.google.android.exoplayer:exoplayer-core:2.8.2'
|
||||
implementation 'com.google.vr:sdk-panowidget:1.150.0'
|
||||
implementation 'org.apache.sanselan:sanselan:0.97-incubator'
|
||||
|
||||
kapt "android.arch.persistence.room:compiler:1.1.0"
|
||||
implementation "android.arch.persistence.room:runtime:1.1.0"
|
||||
annotationProcessor "android.arch.persistence.room:compiler:1.1.0"
|
||||
kapt "android.arch.persistence.room:compiler:1.1.1"
|
||||
implementation "android.arch.persistence.room:runtime:1.1.1"
|
||||
annotationProcessor "android.arch.persistence.room:compiler:1.1.1"
|
||||
|
||||
//implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.9.0'
|
||||
implementation 'com.github.tibbi:subsampling-scale-image-view:v3.10.0-fork'
|
||||
|
|
1
app/proguard-rules.pro
vendored
|
@ -1,2 +1,3 @@
|
|||
-keep class com.simplemobiletools.** { *; }
|
||||
-dontwarn com.simplemobiletools.**
|
||||
-dontwarn org.apache.**
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.simplemobiletools.gallery"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.SET_WALLPAPER"/>
|
||||
|
||||
<uses-sdk
|
||||
tools:overrideLibrary="com.google.vr.widgets.common, com.google.vr.sdk.widgets.pano"/>
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
android:allowBackup="true"
|
||||
|
@ -112,6 +116,11 @@
|
|||
android:name=".activities.PhotoVideoActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"/>
|
||||
|
||||
<activity
|
||||
android:name=".activities.PanoramaActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:theme="@style/FullScreenTheme"/>
|
||||
|
||||
<activity
|
||||
android:name=".activities.IncludedFoldersActivity"
|
||||
android:label="@string/include_folders"
|
||||
|
|
|
@ -32,6 +32,7 @@ import com.simplemobiletools.gallery.dialogs.FilterMediaDialog
|
|||
import com.simplemobiletools.gallery.extensions.*
|
||||
import com.simplemobiletools.gallery.helpers.*
|
||||
import com.simplemobiletools.gallery.interfaces.DirectoryDao
|
||||
import com.simplemobiletools.gallery.interfaces.DirectoryOperationsListener
|
||||
import com.simplemobiletools.gallery.models.AlbumCover
|
||||
import com.simplemobiletools.gallery.models.Directory
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
|
@ -39,7 +40,7 @@ import kotlinx.android.synthetic.main.activity_main.*
|
|||
import java.io.*
|
||||
import java.util.*
|
||||
|
||||
class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
||||
class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||
private val PICK_MEDIA = 2
|
||||
private val PICK_WALLPAPER = 3
|
||||
private val LAST_MEDIA_CHECK_PERIOD = 3000L
|
||||
|
@ -109,6 +110,19 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
if (!config.wasOTGHandled && hasPermission(PERMISSION_WRITE_STORAGE)) {
|
||||
checkOTGInclusion()
|
||||
}
|
||||
|
||||
if (!config.wereFavoritesPinned) {
|
||||
config.addPinnedFolders(hashSetOf(FAVORITES))
|
||||
config.wereFavoritesPinned = true
|
||||
}
|
||||
|
||||
if (!config.wasRecycleBinPinned) {
|
||||
config.addPinnedFolders(hashSetOf(RECYCLE_BIN))
|
||||
config.wasRecycleBinPinned = true
|
||||
config.saveFolderGrouping(SHOW_ALL, GROUP_BY_DATE_TAKEN or GROUP_DESCENDING)
|
||||
}
|
||||
|
||||
checkRecycleBinItems()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
|
@ -133,8 +147,9 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
}
|
||||
|
||||
if (mStoredScrollHorizontally != config.scrollHorizontally) {
|
||||
getRecyclerAdapter()?.updateScrollHorizontally(config.viewTypeFolders != VIEW_TYPE_LIST && config.scrollHorizontally)
|
||||
setupScrollDirection()
|
||||
mLoadedInitialPhotos = false
|
||||
directories_grid.adapter = null
|
||||
getDirectories()
|
||||
}
|
||||
|
||||
if (mStoredTextColor != config.textColor) {
|
||||
|
@ -207,8 +222,10 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
menuInflater.inflate(R.menu.menu_main_intent, menu)
|
||||
} else {
|
||||
menuInflater.inflate(R.menu.menu_main, menu)
|
||||
menu.findItem(R.id.increase_column_count).isVisible = config.viewTypeFolders == VIEW_TYPE_GRID && config.dirColumnCnt < MAX_COLUMN_COUNT
|
||||
menu.findItem(R.id.reduce_column_count).isVisible = config.viewTypeFolders == VIEW_TYPE_GRID && config.dirColumnCnt > 1
|
||||
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
|
||||
}
|
||||
}
|
||||
menu.findItem(R.id.temporarily_show_hidden).isVisible = !config.shouldShowHidden
|
||||
menu.findItem(R.id.stop_showing_hidden).isVisible = config.temporarilyShowHidden
|
||||
|
@ -264,7 +281,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
if (newFolder.exists() && newFolder.isDirectory) {
|
||||
if (newFolder.list()?.isEmpty() == true) {
|
||||
toast(String.format(getString(R.string.deleting_folder), config.tempFolderPath), Toast.LENGTH_LONG)
|
||||
tryDeleteFileDirItem(newFolder.toFileDirItem(applicationContext), true)
|
||||
tryDeleteFileDirItem(newFolder.toFileDirItem(applicationContext), true, true)
|
||||
}
|
||||
}
|
||||
config.tempFolderPath = ""
|
||||
|
@ -317,10 +334,13 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
|
||||
private fun showSortingDialog() {
|
||||
ChangeSortingDialog(this, true, false) {
|
||||
directories_grid.adapter = null
|
||||
if (config.directorySorting and SORT_BY_DATE_MODIFIED > 0 || config.directorySorting and SORT_BY_DATE_TAKEN > 0) {
|
||||
getDirectories()
|
||||
} else {
|
||||
Thread {
|
||||
gotDirectories(getCurrentlyDisplayedDirs())
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -329,6 +349,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
FilterMediaDialog(this) {
|
||||
mLoadedInitialPhotos = false
|
||||
directories_refresh_layout.isRefreshing = true
|
||||
directories_grid.adapter = null
|
||||
getDirectories()
|
||||
}
|
||||
}
|
||||
|
@ -336,7 +357,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
private fun showAllMedia() {
|
||||
config.showAll = true
|
||||
Intent(this, MediaActivity::class.java).apply {
|
||||
putExtra(DIRECTORY, "/")
|
||||
putExtra(DIRECTORY, "")
|
||||
|
||||
if (mIsThirdPartyIntent) {
|
||||
handleMediaIntent(this)
|
||||
|
@ -375,12 +396,37 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
private fun toggleTemporarilyShowHidden(show: Boolean) {
|
||||
mLoadedInitialPhotos = false
|
||||
config.temporarilyShowHidden = show
|
||||
directories_grid.adapter = null
|
||||
getDirectories()
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
override fun deleteFolders(folders: ArrayList<File>) {
|
||||
val fileDirItems = folders.map { FileDirItem(it.absolutePath, it.name, true) } as ArrayList<FileDirItem>
|
||||
fileDirItems.forEach {
|
||||
toast(String.format(getString(R.string.deleting_folder), it.name), Toast.LENGTH_LONG)
|
||||
}
|
||||
|
||||
if (config.useRecycleBin) {
|
||||
val pathsToDelete = ArrayList<String>()
|
||||
fileDirItems.filter { it.isDirectory }.forEach {
|
||||
val files = File(it.path).listFiles()
|
||||
files?.filter { it.absolutePath.isImageVideoGif() }?.mapTo(pathsToDelete) { it.absolutePath }
|
||||
}
|
||||
|
||||
movePathsInRecycleBin(pathsToDelete) {
|
||||
if (it) {
|
||||
deleteFilteredFolders(fileDirItems, folders)
|
||||
} else {
|
||||
toast(R.string.unknown_error_occurred)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
deleteFilteredFolders(fileDirItems, folders)
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteFilteredFolders(fileDirItems: ArrayList<FileDirItem>, folders: ArrayList<File>) {
|
||||
deleteFolders(fileDirItems) {
|
||||
runOnUiThread {
|
||||
refreshItems()
|
||||
|
@ -416,6 +462,32 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
layoutManager.spanCount = config.dirColumnCnt
|
||||
}
|
||||
|
||||
private fun measureRecyclerViewContent(directories: ArrayList<Directory>) {
|
||||
directories_grid.onGlobalLayout {
|
||||
if (config.scrollHorizontally) {
|
||||
calculateContentWidth(directories)
|
||||
} else {
|
||||
calculateContentHeight(directories)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateContentWidth(directories: ArrayList<Directory>) {
|
||||
val layoutManager = directories_grid.layoutManager as MyGridLayoutManager
|
||||
val thumbnailWidth = layoutManager.getChildAt(0)?.width ?: 0
|
||||
val fullWidth = ((directories.size - 1) / layoutManager.spanCount + 1) * thumbnailWidth
|
||||
directories_horizontal_fastscroller.setContentWidth(fullWidth)
|
||||
directories_horizontal_fastscroller.setScrollToX(directories_grid.computeHorizontalScrollOffset())
|
||||
}
|
||||
|
||||
private fun calculateContentHeight(directories: ArrayList<Directory>) {
|
||||
val layoutManager = directories_grid.layoutManager as MyGridLayoutManager
|
||||
val thumbnailHeight = layoutManager.getChildAt(0)?.height ?: 0
|
||||
val fullHeight = ((directories.size - 1) / layoutManager.spanCount + 1) * thumbnailHeight
|
||||
directories_vertical_fastscroller.setContentHeight(fullHeight)
|
||||
directories_vertical_fastscroller.setScrollToY(directories_grid.computeVerticalScrollOffset())
|
||||
}
|
||||
|
||||
private fun initZoomListener() {
|
||||
if (config.viewTypeFolders == VIEW_TYPE_GRID) {
|
||||
val layoutManager = directories_grid.layoutManager as MyGridLayoutManager
|
||||
|
@ -451,25 +523,29 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
FilePickerDialog(this, internalStoragePath, false, config.shouldShowHidden) {
|
||||
CreateNewFolderDialog(this, it) {
|
||||
config.tempFolderPath = it
|
||||
Thread {
|
||||
gotDirectories(addTempFolderIfNeeded(getCurrentlyDisplayedDirs()))
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun increaseColumnCount() {
|
||||
directories_vertical_fastscroller.measureRecyclerViewOnRedraw()
|
||||
directories_horizontal_fastscroller.measureRecyclerViewOnRedraw()
|
||||
config.dirColumnCnt = ++(directories_grid.layoutManager as MyGridLayoutManager).spanCount
|
||||
invalidateOptionsMenu()
|
||||
directories_grid.adapter?.notifyDataSetChanged()
|
||||
columnCountChanged()
|
||||
}
|
||||
|
||||
private fun reduceColumnCount() {
|
||||
directories_vertical_fastscroller.measureRecyclerViewOnRedraw()
|
||||
directories_horizontal_fastscroller.measureRecyclerViewOnRedraw()
|
||||
config.dirColumnCnt = --(directories_grid.layoutManager as MyGridLayoutManager).spanCount
|
||||
columnCountChanged()
|
||||
}
|
||||
|
||||
private fun columnCountChanged() {
|
||||
invalidateOptionsMenu()
|
||||
directories_grid.adapter?.notifyDataSetChanged()
|
||||
getRecyclerAdapter()?.dirs?.apply {
|
||||
measureRecyclerViewContent(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isPickImageIntent(intent: Intent) = isPickIntent(intent) && (hasImageContentData(intent) || isImageType(intent))
|
||||
|
@ -585,6 +661,14 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
}
|
||||
|
||||
private fun gotDirectories(newDirs: ArrayList<Directory>) {
|
||||
// if hidden item showing is disabled but all Favorite items are hidden, hide the Favorites folder
|
||||
if (!config.shouldShowHidden) {
|
||||
val favoritesFolder = newDirs.firstOrNull { it.areFavorites() }
|
||||
if (favoritesFolder != null && favoritesFolder.tmb.getFilenameFromPath().startsWith('.')) {
|
||||
newDirs.remove(favoritesFolder)
|
||||
}
|
||||
}
|
||||
|
||||
val dirs = getSortedDirectories(newDirs)
|
||||
var isPlaceholderVisible = dirs.isEmpty()
|
||||
|
||||
|
@ -598,7 +682,6 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
}
|
||||
|
||||
// cached folders have been loaded, recheck folders one by one starting with the first displayed
|
||||
Thread {
|
||||
val mediaFetcher = MediaFetcher(applicationContext)
|
||||
val getImagesOnly = mIsPickImageIntent || mIsGetImageContentIntent
|
||||
val getVideosOnly = mIsPickVideoIntent || mIsGetVideoContentIntent
|
||||
|
@ -639,19 +722,26 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
|
||||
// update directories and media files in the local db, delete invalid items
|
||||
updateDBDirectory(directory)
|
||||
if (!directory.isRecycleBin()) {
|
||||
mediumDao.insertAll(curMedia)
|
||||
}
|
||||
getCachedMedia(directory.path, getVideosOnly, getImagesOnly) {
|
||||
it.forEach {
|
||||
if (!curMedia.contains(it)) {
|
||||
mediumDao.deleteMediumPath(it.path)
|
||||
val path = (it as? Medium)?.path
|
||||
if (path != null) {
|
||||
mediumDao.deleteMediumPath(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ignored: ConcurrentModificationException) {
|
||||
}
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
|
||||
val foldersToScan = mediaFetcher.getFoldersToScan()
|
||||
foldersToScan.add(FAVORITES)
|
||||
foldersToScan.add(RECYCLE_BIN)
|
||||
dirs.forEach {
|
||||
foldersToScan.remove(it.path)
|
||||
}
|
||||
|
@ -676,8 +766,10 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
dirs.add(newDir)
|
||||
showSortedDirs(dirs)
|
||||
directoryDao.insert(newDir)
|
||||
if (folder != RECYCLE_BIN) {
|
||||
mediumDao.insertAll(newMedia)
|
||||
}
|
||||
}
|
||||
|
||||
mIsGettingDirs = false
|
||||
mLoadedInitialPhotos = true
|
||||
|
@ -685,11 +777,18 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
|
||||
runOnUiThread {
|
||||
directories_refresh_layout.isRefreshing = false
|
||||
directories_vertical_fastscroller.measureRecyclerView()
|
||||
checkPlaceholderVisibility(dirs)
|
||||
}
|
||||
checkInvalidDirectories(dirs, directoryDao)
|
||||
}.start()
|
||||
|
||||
val everShownFolders = config.everShownFolders as HashSet
|
||||
dirs.mapTo(everShownFolders) { it.path }
|
||||
|
||||
try {
|
||||
config.everShownFolders = everShownFolders
|
||||
} catch (e: Exception) {
|
||||
config.everShownFolders = HashSet()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPlaceholderVisibility(dirs: ArrayList<Directory>) {
|
||||
|
@ -703,7 +802,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
sortedDirs = sortedDirs.distinctBy { it.path.getDistinctPath() } as ArrayList<Directory>
|
||||
|
||||
runOnUiThread {
|
||||
(directories_grid.adapter as DirectoryAdapter).updateDirs(sortedDirs)
|
||||
(directories_grid.adapter as? DirectoryAdapter)?.updateDirs(sortedDirs)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -721,7 +820,11 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
}
|
||||
|
||||
val mediaTypes = curMedia.getDirMediaTypes()
|
||||
val dirName = checkAppendingHidden(path, hiddenString, includedFolders)
|
||||
val dirName = when (path) {
|
||||
FAVORITES -> getString(R.string.favorites)
|
||||
RECYCLE_BIN -> getString(R.string.recycle_bin)
|
||||
else -> checkAppendingHidden(path, hiddenString, includedFolders)
|
||||
}
|
||||
|
||||
val firstItem = curMedia.first()
|
||||
val lastItem = curMedia.last()
|
||||
|
@ -733,10 +836,11 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
|
||||
private fun setupAdapter(dirs: ArrayList<Directory>) {
|
||||
val currAdapter = directories_grid.adapter
|
||||
val directories = dirs.clone() as ArrayList<Directory>
|
||||
if (currAdapter == null) {
|
||||
initZoomListener()
|
||||
val fastscroller = if (config.scrollHorizontally) directories_horizontal_fastscroller else directories_vertical_fastscroller
|
||||
DirectoryAdapter(this, dirs, this, directories_grid, isPickIntent(intent) || isGetAnyContentIntent(intent), fastscroller) {
|
||||
DirectoryAdapter(this, directories, this, directories_grid, isPickIntent(intent) || isGetAnyContentIntent(intent), fastscroller) {
|
||||
val path = (it as Directory).path
|
||||
if (path != config.tempFolderPath) {
|
||||
itemClicked(path)
|
||||
|
@ -746,15 +850,17 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
directories_grid.adapter = this
|
||||
}
|
||||
} else {
|
||||
(currAdapter as DirectoryAdapter).updateDirs(dirs)
|
||||
(currAdapter as DirectoryAdapter).updateDirs(directories)
|
||||
}
|
||||
|
||||
getRecyclerAdapter()?.dirs?.apply {
|
||||
measureRecyclerViewContent(this)
|
||||
}
|
||||
setupScrollDirection()
|
||||
}
|
||||
|
||||
private fun setupScrollDirection() {
|
||||
val allowHorizontalScroll = config.scrollHorizontally && config.viewTypeFolders == VIEW_TYPE_GRID
|
||||
|
||||
directories_vertical_fastscroller.isHorizontal = false
|
||||
directories_vertical_fastscroller.beGoneIf(allowHorizontalScroll)
|
||||
|
||||
|
@ -776,7 +882,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
|
||||
private fun checkInvalidDirectories(dirs: ArrayList<Directory>, directoryDao: DirectoryDao) {
|
||||
val invalidDirs = ArrayList<Directory>()
|
||||
dirs.forEach {
|
||||
dirs.filter { !it.areFavorites() && !it.isRecycleBin() }.forEach {
|
||||
if (!getDoesFilePathExist(it.path)) {
|
||||
invalidDirs.add(it)
|
||||
} else if (it.path != config.tempFolderPath) {
|
||||
|
@ -788,6 +894,20 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
}
|
||||
}
|
||||
|
||||
if (getFavoritePaths().isEmpty()) {
|
||||
val favoritesFolder = dirs.firstOrNull { it.areFavorites() }
|
||||
if (favoritesFolder != null) {
|
||||
invalidDirs.add(favoritesFolder)
|
||||
}
|
||||
}
|
||||
|
||||
if (config.useRecycleBin) {
|
||||
val binFolder = dirs.firstOrNull { it.path == RECYCLE_BIN }
|
||||
if (binFolder != null && galleryDB.MediumDao().getDeletedMedia().isEmpty()) {
|
||||
invalidDirs.add(binFolder)
|
||||
}
|
||||
}
|
||||
|
||||
if (invalidDirs.isNotEmpty()) {
|
||||
dirs.removeAll(invalidDirs)
|
||||
showSortedDirs(dirs)
|
||||
|
@ -833,12 +953,28 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
}, LAST_MEDIA_CHECK_PERIOD)
|
||||
}
|
||||
|
||||
private fun checkRecycleBinItems() {
|
||||
if (config.useRecycleBin) {
|
||||
Thread {
|
||||
val mediumDao = galleryDB.MediumDao()
|
||||
val deletedMedia = mediumDao.getDeletedMedia()
|
||||
deletedMedia.forEach {
|
||||
if (System.currentTimeMillis() > it.deletedTS + MONTH_MILLISECONDS) {
|
||||
mediumDao.deleteMediumPath(it.path)
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
override fun refreshItems() {
|
||||
getDirectories()
|
||||
}
|
||||
|
||||
override fun recheckPinnedFolders() {
|
||||
Thread {
|
||||
gotDirectories(movePinnedDirectoriesToFront(getCurrentlyDisplayedDirs()))
|
||||
}.start()
|
||||
}
|
||||
|
||||
override fun updateDirectories(directories: ArrayList<Directory>) {
|
||||
|
@ -896,6 +1032,9 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
add(Release(177, R.string.release_177))
|
||||
add(Release(178, R.string.release_178))
|
||||
add(Release(180, R.string.release_180))
|
||||
add(Release(181, R.string.release_181))
|
||||
add(Release(182, R.string.release_182))
|
||||
add(Release(184, R.string.release_184))
|
||||
checkWhatsNew(this, BuildConfig.VERSION_CODE)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,18 +33,22 @@ import com.simplemobiletools.commons.views.MyRecyclerView
|
|||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.adapters.MediaAdapter
|
||||
import com.simplemobiletools.gallery.asynctasks.GetMediaAsynctask
|
||||
import com.simplemobiletools.gallery.dialogs.ChangeGroupingDialog
|
||||
import com.simplemobiletools.gallery.dialogs.ChangeSortingDialog
|
||||
import com.simplemobiletools.gallery.dialogs.ExcludeFolderDialog
|
||||
import com.simplemobiletools.gallery.dialogs.FilterMediaDialog
|
||||
import com.simplemobiletools.gallery.extensions.*
|
||||
import com.simplemobiletools.gallery.helpers.*
|
||||
import com.simplemobiletools.gallery.interfaces.MediaOperationsListener
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import com.simplemobiletools.gallery.models.ThumbnailItem
|
||||
import com.simplemobiletools.gallery.models.ThumbnailSection
|
||||
import kotlinx.android.synthetic.main.activity_media.*
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
||||
class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
||||
private val LAST_MEDIA_CHECK_PERIOD = 3000L
|
||||
|
||||
private var mPath = ""
|
||||
|
@ -72,7 +76,7 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
private var mStoredPrimaryColor = 0
|
||||
|
||||
companion object {
|
||||
var mMedia = ArrayList<Medium>()
|
||||
var mMedia = ArrayList<ThumbnailItem>()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -121,8 +125,9 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
}
|
||||
|
||||
if (mStoredScrollHorizontally != config.scrollHorizontally) {
|
||||
getMediaAdapter()?.updateScrollHorizontally(config.viewTypeFiles != VIEW_TYPE_LIST || !config.scrollHorizontally)
|
||||
setupScrollDirection()
|
||||
mLoadedInitialPhotos = false
|
||||
media_grid.adapter = null
|
||||
getMedia()
|
||||
}
|
||||
|
||||
if (mStoredTextColor != config.textColor) {
|
||||
|
@ -188,9 +193,15 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
|
||||
val isFolderHidden = File(mPath).containsNoMedia()
|
||||
menu.apply {
|
||||
findItem(R.id.hide_folder).isVisible = !isFolderHidden && !mShowAll
|
||||
findItem(R.id.unhide_folder).isVisible = isFolderHidden && !mShowAll
|
||||
findItem(R.id.exclude_folder).isVisible = !mShowAll
|
||||
findItem(R.id.group).isVisible = !config.scrollHorizontally
|
||||
|
||||
findItem(R.id.hide_folder).isVisible = !isFolderHidden && !mShowAll && mPath != FAVORITES && mPath != RECYCLE_BIN
|
||||
findItem(R.id.unhide_folder).isVisible = isFolderHidden && !mShowAll && mPath != FAVORITES && mPath != RECYCLE_BIN
|
||||
findItem(R.id.exclude_folder).isVisible = !mShowAll && mPath != FAVORITES && mPath != RECYCLE_BIN
|
||||
|
||||
findItem(R.id.empty_recycle_bin).isVisible = mPath == RECYCLE_BIN
|
||||
findItem(R.id.empty_disable_recycle_bin).isVisible = mPath == RECYCLE_BIN
|
||||
findItem(R.id.restore_all_files).isVisible = mPath == RECYCLE_BIN
|
||||
|
||||
findItem(R.id.folder_view).isVisible = mShowAll
|
||||
findItem(R.id.open_camera).isVisible = mShowAll
|
||||
|
@ -213,10 +224,14 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
when (item.itemId) {
|
||||
R.id.sort -> showSortingDialog()
|
||||
R.id.filter -> showFilterMediaDialog()
|
||||
R.id.empty_recycle_bin -> emptyRecycleBin()
|
||||
R.id.empty_disable_recycle_bin -> emptyAndDisableRecycleBin()
|
||||
R.id.restore_all_files -> restoreAllFiles()
|
||||
R.id.toggle_filename -> toggleFilenameVisibility()
|
||||
R.id.open_camera -> launchCamera()
|
||||
R.id.folder_view -> switchToFolderView()
|
||||
R.id.change_view_type -> changeViewType()
|
||||
R.id.group -> showGroupByDialog()
|
||||
R.id.hide_folder -> tryHideFolder()
|
||||
R.id.unhide_folder -> unhideFolder()
|
||||
R.id.exclude_folder -> tryExcludeFolder()
|
||||
|
@ -268,9 +283,13 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
return true
|
||||
}
|
||||
|
||||
// this triggers on device rotation too, avoid doing anything
|
||||
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
|
||||
if (mIsSearchOpen) {
|
||||
mIsSearchOpen = false
|
||||
media_refresh_layout.isEnabled = config.enablePullToRefresh
|
||||
searchQueryChanged("")
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
@ -278,10 +297,12 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
|
||||
private fun searchQueryChanged(text: String) {
|
||||
Thread {
|
||||
val filtered = mMedia.filter { it.name.contains(text, true) } as ArrayList
|
||||
filtered.sortBy { !it.name.startsWith(text, true) }
|
||||
val filtered = mMedia.filter { it is Medium && it.name.contains(text, true) } as ArrayList
|
||||
filtered.sortBy { it is Medium && !it.name.startsWith(text, true) }
|
||||
val grouped = MediaFetcher(applicationContext).groupMedia(filtered as ArrayList<Medium>, mPath)
|
||||
runOnUiThread {
|
||||
getMediaAdapter()?.updateMedia(filtered)
|
||||
getMediaAdapter()?.updateMedia(grouped)
|
||||
measureRecyclerViewContent(grouped)
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
@ -290,6 +311,8 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
handlePermission(PERMISSION_WRITE_STORAGE) {
|
||||
if (it) {
|
||||
val dirName = when {
|
||||
mPath == FAVORITES -> getString(R.string.favorites)
|
||||
mPath == RECYCLE_BIN -> getString(R.string.recycle_bin)
|
||||
mPath == OTG_PATH -> getString(R.string.otg)
|
||||
mPath.startsWith(OTG_PATH) -> mPath.trimEnd('/').substringAfterLast('/')
|
||||
else -> getHumanizedFilename(mPath)
|
||||
|
@ -316,14 +339,19 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
initZoomListener()
|
||||
val fastscroller = if (config.scrollHorizontally) media_horizontal_fastscroller else media_vertical_fastscroller
|
||||
MediaAdapter(this, mMedia, this, mIsGetImageIntent || mIsGetVideoIntent || mIsGetAnyIntent, mAllowPickingMultiple, media_grid, fastscroller) {
|
||||
itemClicked((it as Medium).path)
|
||||
if (it is Medium) {
|
||||
itemClicked(it.path)
|
||||
}
|
||||
}.apply {
|
||||
setupZoomListener(mZoomListener)
|
||||
media_grid.adapter = this
|
||||
}
|
||||
setupLayoutManager()
|
||||
} else {
|
||||
(currAdapter as MediaAdapter).updateMedia(mMedia)
|
||||
}
|
||||
|
||||
measureRecyclerViewContent(mMedia)
|
||||
setupScrollDirection()
|
||||
}
|
||||
|
||||
|
@ -335,8 +363,7 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
media_horizontal_fastscroller.isHorizontal = true
|
||||
media_horizontal_fastscroller.beVisibleIf(allowHorizontalScroll)
|
||||
|
||||
val sorting = config.getFileSorting(mPath)
|
||||
|
||||
val sorting = config.getFileSorting(if (mShowAll) SHOW_ALL else mPath)
|
||||
if (allowHorizontalScroll) {
|
||||
media_horizontal_fastscroller.allowBubbleDisplay = config.showInfoBubble
|
||||
media_horizontal_fastscroller.setViews(media_grid, media_refresh_layout) {
|
||||
|
@ -350,11 +377,19 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
}
|
||||
}
|
||||
|
||||
private fun getBubbleTextItem(index: Int, sorting: Int) = getMediaAdapter()?.media?.getOrNull(index)?.getBubbleText(sorting) ?: ""
|
||||
private fun getBubbleTextItem(index: Int, sorting: Int): String {
|
||||
var realIndex = index
|
||||
val mediaAdapter = getMediaAdapter()
|
||||
if (mediaAdapter?.isASectionTitle(index) == true) {
|
||||
realIndex++
|
||||
}
|
||||
return mediaAdapter?.getItemBubbleText(realIndex, sorting) ?: ""
|
||||
}
|
||||
|
||||
private fun checkLastMediaChanged() {
|
||||
if (isActivityDestroyed())
|
||||
if (isActivityDestroyed()) {
|
||||
return
|
||||
}
|
||||
|
||||
mLastMediaHandler.removeCallbacksAndMessages(null)
|
||||
mLastMediaHandler.postDelayed({
|
||||
|
@ -375,8 +410,9 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
}
|
||||
|
||||
private fun showSortingDialog() {
|
||||
ChangeSortingDialog(this, false, !config.showAll, mPath) {
|
||||
ChangeSortingDialog(this, false, true, mPath) {
|
||||
mLoadedInitialPhotos = false
|
||||
media_grid.adapter = null
|
||||
getMedia()
|
||||
}
|
||||
}
|
||||
|
@ -385,10 +421,37 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
FilterMediaDialog(this) {
|
||||
mLoadedInitialPhotos = false
|
||||
media_refresh_layout.isRefreshing = true
|
||||
media_grid.adapter = null
|
||||
getMedia()
|
||||
}
|
||||
}
|
||||
|
||||
private fun emptyRecycleBin() {
|
||||
showRecycleBinEmptyingDialog {
|
||||
emptyTheRecycleBin {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun emptyAndDisableRecycleBin() {
|
||||
showRecycleBinEmptyingDialog {
|
||||
emptyAndDisableTheRecycleBin {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun restoreAllFiles() {
|
||||
val paths = mMedia.filter { it is Medium }.map { (it as Medium).path } as ArrayList<String>
|
||||
restoreRecycleBinPaths(paths) {
|
||||
Thread {
|
||||
galleryDB.DirectoryDao().deleteDirPath(RECYCLE_BIN)
|
||||
}.start()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleFilenameVisibility() {
|
||||
config.displayFileNames = !config.displayFileNames
|
||||
getMediaAdapter()?.updateDisplayFilenames(config.displayFileNames)
|
||||
|
@ -414,6 +477,14 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
}
|
||||
}
|
||||
|
||||
private fun showGroupByDialog() {
|
||||
ChangeGroupingDialog(this, mPath) {
|
||||
mLoadedInitialPhotos = false
|
||||
media_grid.adapter = null
|
||||
getMedia()
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryHideFolder() {
|
||||
if (config.wasHideFolderTooltipShown) {
|
||||
hideFolder()
|
||||
|
@ -454,7 +525,7 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
private fun deleteDirectoryIfEmpty() {
|
||||
val fileDirItem = FileDirItem(mPath, mPath.getFilenameFromPath())
|
||||
if (config.deleteEmptyFolders && !fileDirItem.isDownloadsFolder() && fileDirItem.isDirectory && fileDirItem.getProperFileCount(applicationContext, true) == 0) {
|
||||
tryDeleteFileDirItem(fileDirItem, true)
|
||||
tryDeleteFileDirItem(fileDirItem, true, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -473,15 +544,22 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
} else {
|
||||
gotMedia(it, true)
|
||||
}
|
||||
startAsyncTask()
|
||||
}
|
||||
} else {
|
||||
media_refresh_layout.isRefreshing = true
|
||||
startAsyncTask()
|
||||
}
|
||||
|
||||
mLoadedInitialPhotos = true
|
||||
}
|
||||
|
||||
private fun startAsyncTask() {
|
||||
mCurrAsyncTask?.stopFetching()
|
||||
mCurrAsyncTask = GetMediaAsynctask(applicationContext, mPath, mIsGetImageIntent, mIsGetVideoIntent, mShowAll) {
|
||||
Thread {
|
||||
gotMedia(it)
|
||||
}.start()
|
||||
}
|
||||
|
||||
mCurrAsyncTask!!.execute()
|
||||
|
@ -489,8 +567,10 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
|
||||
private fun isDirEmpty(): Boolean {
|
||||
return if (mMedia.size <= 0 && config.filterMedia > 0) {
|
||||
if (mPath != FAVORITES && mPath != RECYCLE_BIN) {
|
||||
deleteDirectoryIfEmpty()
|
||||
deleteDBDirectory()
|
||||
}
|
||||
finish()
|
||||
true
|
||||
} else {
|
||||
|
@ -540,6 +620,62 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
}
|
||||
|
||||
layoutManager.spanCount = config.mediaColumnCnt
|
||||
val adapter = getMediaAdapter()
|
||||
layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return if (adapter?.isASectionTitle(position) == true) {
|
||||
layoutManager.spanCount
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun measureRecyclerViewContent(media: ArrayList<ThumbnailItem>) {
|
||||
media_grid.onGlobalLayout {
|
||||
if (config.scrollHorizontally) {
|
||||
calculateContentWidth(media)
|
||||
} else {
|
||||
calculateContentHeight(media)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateContentWidth(media: ArrayList<ThumbnailItem>) {
|
||||
val layoutManager = media_grid.layoutManager as MyGridLayoutManager
|
||||
val thumbnailWidth = layoutManager.getChildAt(0)?.width ?: 0
|
||||
val fullWidth = ((media.size - 1) / layoutManager.spanCount + 1) * thumbnailWidth
|
||||
media_horizontal_fastscroller.setContentWidth(fullWidth)
|
||||
media_horizontal_fastscroller.setScrollToX(media_grid.computeHorizontalScrollOffset())
|
||||
}
|
||||
|
||||
private fun calculateContentHeight(media: ArrayList<ThumbnailItem>) {
|
||||
val layoutManager = media_grid.layoutManager as MyGridLayoutManager
|
||||
val pathToCheck = if (mPath.isEmpty()) SHOW_ALL else mPath
|
||||
val hasSections = config.getFolderGrouping(pathToCheck) and GROUP_BY_NONE == 0 && !config.scrollHorizontally
|
||||
val sectionTitleHeight = if (hasSections) layoutManager.getChildAt(0)?.height ?: 0 else 0
|
||||
val thumbnailHeight = if (hasSections) layoutManager.getChildAt(1)?.height ?: 0 else layoutManager.getChildAt(0)?.height
|
||||
?: 0
|
||||
|
||||
var fullHeight = 0
|
||||
var curSectionItems = 0
|
||||
media.forEach {
|
||||
if (it is ThumbnailSection) {
|
||||
fullHeight += sectionTitleHeight
|
||||
if (curSectionItems != 0) {
|
||||
val rows = ((curSectionItems - 1) / layoutManager.spanCount + 1)
|
||||
fullHeight += rows * thumbnailHeight
|
||||
}
|
||||
curSectionItems = 0
|
||||
} else {
|
||||
curSectionItems++
|
||||
}
|
||||
}
|
||||
|
||||
fullHeight += ((curSectionItems - 1) / layoutManager.spanCount + 1) * thumbnailHeight
|
||||
media_vertical_fastscroller.setContentHeight(fullHeight)
|
||||
media_vertical_fastscroller.setScrollToY(media_grid.computeVerticalScrollOffset())
|
||||
}
|
||||
|
||||
private fun initZoomListener() {
|
||||
|
@ -574,19 +710,19 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
}
|
||||
|
||||
private fun increaseColumnCount() {
|
||||
media_vertical_fastscroller.measureRecyclerViewOnRedraw()
|
||||
media_horizontal_fastscroller.measureRecyclerViewOnRedraw()
|
||||
config.mediaColumnCnt = ++(media_grid.layoutManager as MyGridLayoutManager).spanCount
|
||||
invalidateOptionsMenu()
|
||||
media_grid.adapter?.notifyDataSetChanged()
|
||||
columnCountChanged()
|
||||
}
|
||||
|
||||
private fun reduceColumnCount() {
|
||||
media_vertical_fastscroller.measureRecyclerViewOnRedraw()
|
||||
media_horizontal_fastscroller.measureRecyclerViewOnRedraw()
|
||||
config.mediaColumnCnt = --(media_grid.layoutManager as MyGridLayoutManager).spanCount
|
||||
columnCountChanged()
|
||||
}
|
||||
|
||||
private fun columnCountChanged() {
|
||||
invalidateOptionsMenu()
|
||||
media_grid.adapter?.notifyDataSetChanged()
|
||||
measureRecyclerViewContent(mMedia)
|
||||
}
|
||||
|
||||
private fun isSetWallpaperIntent() = intent.getBooleanExtra(SET_WALLPAPER_INTENT, false)
|
||||
|
@ -642,22 +778,15 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
Intent(this, ViewPagerActivity::class.java).apply {
|
||||
putExtra(PATH, path)
|
||||
putExtra(SHOW_ALL, mShowAll)
|
||||
putExtra(SHOW_FAVORITES, mPath == FAVORITES)
|
||||
putExtra(SHOW_RECYCLE_BIN, mPath == RECYCLE_BIN)
|
||||
startActivity(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun gotMedia(media: ArrayList<Medium>, isFromCache: Boolean = false) {
|
||||
val mediaToInsert = media.clone() as ArrayList<Medium>
|
||||
Thread {
|
||||
mLatestMediaId = getLatestMediaId()
|
||||
mLatestMediaDateId = getLatestMediaByDateId()
|
||||
if (!isFromCache) {
|
||||
galleryDB.MediumDao().insertAll(mediaToInsert)
|
||||
}
|
||||
}.start()
|
||||
|
||||
private fun gotMedia(media: ArrayList<ThumbnailItem>, isFromCache: Boolean = false) {
|
||||
mIsGettingMedia = false
|
||||
checkLastMediaChanged()
|
||||
mMedia = media
|
||||
|
@ -671,26 +800,52 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
val allowHorizontalScroll = config.scrollHorizontally && config.viewTypeFiles == VIEW_TYPE_GRID
|
||||
media_vertical_fastscroller.beVisibleIf(media_grid.isVisible() && !allowHorizontalScroll)
|
||||
media_horizontal_fastscroller.beVisibleIf(media_grid.isVisible() && allowHorizontalScroll)
|
||||
|
||||
setupAdapter()
|
||||
}
|
||||
|
||||
mLatestMediaId = getLatestMediaId()
|
||||
mLatestMediaDateId = getLatestMediaByDateId()
|
||||
if (!isFromCache) {
|
||||
val mediaToInsert = (mMedia.clone() as ArrayList<ThumbnailItem>).filter { it is Medium && it.deletedTS == 0L }.map { it as Medium }
|
||||
galleryDB.MediumDao().insertAll(mediaToInsert)
|
||||
}
|
||||
}
|
||||
|
||||
override fun tryDeleteFiles(fileDirItems: ArrayList<FileDirItem>) {
|
||||
val filtered = fileDirItems.filter { it.path.isImageVideoGif() } as ArrayList
|
||||
val deletingItems = resources.getQuantityString(R.plurals.deleting_items, filtered.size, filtered.size)
|
||||
toast(deletingItems)
|
||||
|
||||
if (config.useRecycleBin && !filtered.first().path.startsWith(filesDir.toString())) {
|
||||
movePathsInRecycleBin(filtered.map { it.path } as ArrayList<String>) {
|
||||
if (it) {
|
||||
deleteFilteredFiles(filtered)
|
||||
} else {
|
||||
toast(R.string.unknown_error_occurred)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
deleteFilteredFiles(filtered)
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteFilteredFiles(filtered: ArrayList<FileDirItem>) {
|
||||
deleteFiles(filtered) {
|
||||
if (!it) {
|
||||
toast(R.string.unknown_error_occurred)
|
||||
return@deleteFiles
|
||||
}
|
||||
|
||||
mMedia.removeAll { filtered.map { it.path }.contains(it.path) }
|
||||
mMedia.removeAll { filtered.map { it.path }.contains((it as? Medium)?.path) }
|
||||
|
||||
Thread {
|
||||
val mediumDao = galleryDB.MediumDao()
|
||||
val useRecycleBin = config.useRecycleBin
|
||||
filtered.forEach {
|
||||
if (!useRecycleBin) {
|
||||
mediumDao.deleteMediumPath(it.path)
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
|
||||
if (mMedia.isEmpty()) {
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
package com.simplemobiletools.gallery.activities
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
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.showErrorToast
|
||||
import com.simplemobiletools.commons.extensions.toast
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.extensions.*
|
||||
import com.simplemobiletools.gallery.helpers.PATH
|
||||
import kotlinx.android.synthetic.main.activity_panorama.*
|
||||
|
||||
open class PanoramaActivity : SimpleActivity() {
|
||||
private val CARDBOARD_DISPLAY_MODE = 3
|
||||
|
||||
private var isFullScreen = false
|
||||
private var isExploreEnabled = true
|
||||
private var isRendering = false
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
useDynamicTheme = false
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_panorama)
|
||||
supportActionBar?.hide()
|
||||
setupButtonMargins()
|
||||
|
||||
cardboard.setOnClickListener {
|
||||
panorama_view.displayMode = CARDBOARD_DISPLAY_MODE
|
||||
}
|
||||
|
||||
explore.setOnClickListener {
|
||||
isExploreEnabled = !isExploreEnabled
|
||||
panorama_view.setPureTouchTracking(isExploreEnabled)
|
||||
explore.setImageResource(if (isExploreEnabled) 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()
|
||||
panorama_view.resumeRendering()
|
||||
isRendering = true
|
||||
if (config.blackBackground) {
|
||||
updateStatusbarColor(Color.BLACK)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
panorama_view.pauseRendering()
|
||||
isRendering = false
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
if (isRendering) {
|
||||
panorama_view.shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkIntent() {
|
||||
val path = intent.getStringExtra(PATH)
|
||||
if (path == null) {
|
||||
toast(R.string.invalid_image_path)
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
intent.removeExtra(PATH)
|
||||
|
||||
try {
|
||||
val options = VrPanoramaView.Options()
|
||||
options.inputType = VrPanoramaView.Options.TYPE_MONO
|
||||
Thread {
|
||||
val bitmap = getBitmapToLoad(path)
|
||||
runOnUiThread {
|
||||
panorama_view.apply {
|
||||
beVisible()
|
||||
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)
|
||||
setInfoButtonEnabled(false)
|
||||
setTransitionViewEnabled(false)
|
||||
setStereoModeButtonEnabled(false)
|
||||
|
||||
setOnClickListener {
|
||||
handleClick()
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
}
|
||||
|
||||
window.decorView.setOnSystemUiVisibilityChangeListener { visibility ->
|
||||
isFullScreen = visibility and View.SYSTEM_UI_FLAG_FULLSCREEN != 0
|
||||
toggleButtonVisibility()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration?) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
setupButtonMargins()
|
||||
}
|
||||
|
||||
private fun getBitmapToLoad(path: String): Bitmap? {
|
||||
val options = BitmapFactory.Options()
|
||||
options.inSampleSize = 1
|
||||
var bitmap: Bitmap? = null
|
||||
|
||||
for (i in 0..10) {
|
||||
try {
|
||||
bitmap = BitmapFactory.decodeFile(path, options)
|
||||
break
|
||||
} catch (e: OutOfMemoryError) {
|
||||
options.inSampleSize *= 2
|
||||
}
|
||||
}
|
||||
|
||||
return bitmap
|
||||
}
|
||||
|
||||
private fun setupButtonMargins() {
|
||||
(cardboard.layoutParams as RelativeLayout.LayoutParams).apply {
|
||||
bottomMargin = navigationBarHeight
|
||||
rightMargin = navigationBarWidth
|
||||
}
|
||||
|
||||
(explore.layoutParams as RelativeLayout.LayoutParams).bottomMargin = navigationBarHeight
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
private fun handleClick() {
|
||||
isFullScreen = !isFullScreen
|
||||
toggleButtonVisibility()
|
||||
if (isFullScreen) {
|
||||
hideSystemUI(false)
|
||||
} else {
|
||||
showSystemUI(false)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -85,7 +85,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
|||
}
|
||||
}
|
||||
|
||||
showSystemUI()
|
||||
showSystemUI(true)
|
||||
val bundle = Bundle()
|
||||
val file = File(mUri.toString())
|
||||
val type = when {
|
||||
|
@ -95,7 +95,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
|||
else -> TYPE_RAWS
|
||||
}
|
||||
|
||||
mMedium = Medium(null, getFilenameFromUri(mUri!!), mUri.toString(), mUri!!.path.getParentPath(), 0, 0, file.length(), type, false)
|
||||
mMedium = Medium(null, getFilenameFromUri(mUri!!), mUri.toString(), mUri!!.path.getParentPath(), 0, 0, file.length(), type, false, 0L)
|
||||
supportActionBar?.title = mMedium!!.name
|
||||
bundle.putSerializable(MEDIUM, mMedium)
|
||||
|
||||
|
@ -178,24 +178,32 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
|||
}
|
||||
|
||||
private fun initBottomActionButtons() {
|
||||
bottom_favorite.beGone()
|
||||
bottom_delete.beGone()
|
||||
|
||||
bottom_edit.setOnClickListener {
|
||||
openEditor(mUri!!.toString())
|
||||
arrayListOf(bottom_favorite, bottom_delete, bottom_rotate, bottom_properties, bottom_change_orientation, bottom_slideshow, bottom_show_on_map, bottom_toggle_file_visibility).forEach {
|
||||
it.beGone()
|
||||
}
|
||||
|
||||
val visibleBottomActions = if (config.bottomActions) config.visibleBottomActions else 0
|
||||
bottom_edit.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_EDIT != 0)
|
||||
bottom_edit.setOnClickListener {
|
||||
if (mUri != null && bottom_actions.alpha == 1f) {
|
||||
openEditor(mUri!!.toString())
|
||||
}
|
||||
}
|
||||
|
||||
bottom_share.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_SHARE != 0)
|
||||
bottom_share.setOnClickListener {
|
||||
if (mUri != null && bottom_actions.alpha == 1f) {
|
||||
sharePath(mUri!!.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun fragmentClicked() {
|
||||
mIsFullScreen = !mIsFullScreen
|
||||
if (mIsFullScreen) {
|
||||
hideSystemUI()
|
||||
hideSystemUI(true)
|
||||
} else {
|
||||
showSystemUI()
|
||||
showSystemUI(true)
|
||||
}
|
||||
|
||||
if (!bottom_actions.isGone()) {
|
||||
|
|
|
@ -6,16 +6,19 @@ import android.os.Bundle
|
|||
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.dialogs.SecurityDialog
|
||||
import com.simplemobiletools.commons.extensions.beVisibleIf
|
||||
import com.simplemobiletools.commons.extensions.getAdjustedPrimaryColor
|
||||
import com.simplemobiletools.commons.extensions.handleHiddenFolderPasswordProtection
|
||||
import com.simplemobiletools.commons.extensions.updateTextColors
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.PROTECTION_FINGERPRINT
|
||||
import com.simplemobiletools.commons.helpers.SHOW_ALL_TABS
|
||||
import com.simplemobiletools.commons.helpers.sumByLong
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.dialogs.ManageBottomActionsDialog
|
||||
import com.simplemobiletools.gallery.dialogs.ManageExtendedDetailsDialog
|
||||
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
|
||||
|
@ -24,6 +27,7 @@ import java.util.*
|
|||
|
||||
class SettingsActivity : SimpleActivity() {
|
||||
lateinit var res: Resources
|
||||
private var mRecycleBinContentSize = 0L
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -68,6 +72,9 @@ class SettingsActivity : SimpleActivity() {
|
|||
setupHideExtendedDetails()
|
||||
setupManageExtendedDetails()
|
||||
setupSkipDeleteConfirmation()
|
||||
setupManageBottomActions()
|
||||
setupUseRecycleBin()
|
||||
setupEmptyRecycleBin()
|
||||
updateTextColors(settings_holder)
|
||||
setupSectionColors()
|
||||
}
|
||||
|
@ -75,7 +82,7 @@ class SettingsActivity : SimpleActivity() {
|
|||
private fun setupSectionColors() {
|
||||
val adjustedPrimaryColor = getAdjustedPrimaryColor()
|
||||
arrayListOf(visibility_label, videos_label, thumbnails_label, scrolling_label, fullscreen_media_label, security_label,
|
||||
file_operations_label, extended_details_label).forEach {
|
||||
file_operations_label, extended_details_label, bottom_actions_label, recycle_bin_label).forEach {
|
||||
it.setTextColor(adjustedPrimaryColor)
|
||||
}
|
||||
}
|
||||
|
@ -287,14 +294,6 @@ class SettingsActivity : SimpleActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun setupBottomActions() {
|
||||
settings_bottom_actions.isChecked = config.bottomActions
|
||||
settings_bottom_actions_holder.setOnClickListener {
|
||||
settings_bottom_actions.toggle()
|
||||
config.bottomActions = settings_bottom_actions.isChecked
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupShowMediaCount() {
|
||||
settings_show_media_count.isChecked = config.showMediaCount
|
||||
settings_show_media_count_holder.setOnClickListener {
|
||||
|
@ -409,4 +408,57 @@ class SettingsActivity : SimpleActivity() {
|
|||
ROTATE_BY_DEVICE_ROTATION -> R.string.screen_rotation_device_rotation
|
||||
else -> R.string.screen_rotation_aspect_ratio
|
||||
})
|
||||
|
||||
private fun setupBottomActions() {
|
||||
settings_bottom_actions.isChecked = config.bottomActions
|
||||
settings_bottom_actions_holder.setOnClickListener {
|
||||
settings_bottom_actions.toggle()
|
||||
config.bottomActions = settings_bottom_actions.isChecked
|
||||
settings_manage_bottom_actions_holder.beVisibleIf(config.bottomActions)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupManageBottomActions() {
|
||||
settings_manage_bottom_actions_holder.beVisibleIf(config.bottomActions)
|
||||
settings_manage_bottom_actions_holder.setOnClickListener {
|
||||
ManageBottomActionsDialog(this) {
|
||||
if (config.visibleBottomActions == 0) {
|
||||
settings_bottom_actions_holder.callOnClick()
|
||||
config.bottomActions = false
|
||||
config.visibleBottomActions = DEFAULT_BOTTOM_ACTIONS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupUseRecycleBin() {
|
||||
settings_empty_recycle_bin_holder.beVisibleIf(config.useRecycleBin)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupEmptyRecycleBin() {
|
||||
Thread {
|
||||
mRecycleBinContentSize = galleryDB.MediumDao().getDeletedMedia().sumByLong { it.size }
|
||||
runOnUiThread {
|
||||
settings_empty_recycle_bin_size.text = mRecycleBinContentSize.formatSize()
|
||||
}
|
||||
}.start()
|
||||
|
||||
settings_empty_recycle_bin_holder.setOnClickListener {
|
||||
if (mRecycleBinContentSize == 0L) {
|
||||
toast(R.string.recycle_bin_empty)
|
||||
} else {
|
||||
showRecycleBinEmptyingDialog {
|
||||
emptyTheRecycleBin()
|
||||
mRecycleBinContentSize = 0L
|
||||
settings_empty_recycle_bin_size.text = 0L.formatSize()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import com.simplemobiletools.gallery.fragments.VideoFragment
|
|||
import com.simplemobiletools.gallery.fragments.ViewPagerFragment
|
||||
import com.simplemobiletools.gallery.helpers.*
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import com.simplemobiletools.gallery.models.ThumbnailItem
|
||||
import kotlinx.android.synthetic.main.activity_medium.*
|
||||
import kotlinx.android.synthetic.main.bottom_actions.*
|
||||
import java.io.File
|
||||
|
@ -70,7 +71,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
private var mIsOrientationLocked = false
|
||||
|
||||
private var mStoredReplaceZoomableImages = false
|
||||
private var mStoredBottomActions = true
|
||||
private var mMediaFiles = ArrayList<Medium>()
|
||||
private var mFavoritePaths = ArrayList<String>()
|
||||
|
||||
|
@ -83,7 +83,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_medium)
|
||||
mMediaFiles = MediaActivity.mMedia.clone() as ArrayList<Medium>
|
||||
(MediaActivity.mMedia.clone() as ArrayList<ThumbnailItem>).filter { it is Medium }.mapTo(mMediaFiles) { it as Medium }
|
||||
|
||||
handlePermission(PERMISSION_WRITE_STORAGE) {
|
||||
if (it) {
|
||||
|
@ -95,7 +95,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}
|
||||
|
||||
storeStateVariables()
|
||||
initBottomActions()
|
||||
initFavorites()
|
||||
}
|
||||
|
||||
|
@ -120,10 +119,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
refreshViewPager()
|
||||
}
|
||||
|
||||
if (mStoredBottomActions != config.bottomActions) {
|
||||
initBottomActions()
|
||||
}
|
||||
|
||||
supportActionBar?.setBackgroundDrawable(resources.getDrawable(R.drawable.actionbar_gradient_background))
|
||||
|
||||
if (config.maxBrightness) {
|
||||
|
@ -197,9 +193,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}
|
||||
|
||||
if (!getDoesFilePathExist(mPath)) {
|
||||
Thread {
|
||||
scanPathRecursively(mPath)
|
||||
}.start()
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
@ -214,9 +207,15 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
config.isThirdPartyIntent = true
|
||||
}
|
||||
|
||||
showSystemUI()
|
||||
showSystemUI(true)
|
||||
|
||||
mDirectory = mPath.getParentPath()
|
||||
val isShowingFavorites = intent.getBooleanExtra(SHOW_FAVORITES, false)
|
||||
val isShowingRecycleBin = intent.getBooleanExtra(SHOW_RECYCLE_BIN, false)
|
||||
mDirectory = when {
|
||||
isShowingFavorites -> FAVORITES
|
||||
isShowingRecycleBin -> RECYCLE_BIN
|
||||
else -> mPath.getParentPath()
|
||||
}
|
||||
if (mDirectory.startsWith(OTG_PATH.trimEnd('/'))) {
|
||||
mDirectory += "/"
|
||||
}
|
||||
|
@ -225,7 +224,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
view_pager.onGlobalLayout {
|
||||
if (!isActivityDestroyed()) {
|
||||
if (mMediaFiles.isNotEmpty()) {
|
||||
gotMedia(mMediaFiles)
|
||||
gotMedia(mMediaFiles as ArrayList<ThumbnailItem>)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -251,6 +250,10 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
checkSystemUI()
|
||||
if (!bottom_actions.isGone()) {
|
||||
bottom_actions.animate().alpha(if (mIsFullScreen) 0f else 1f).start()
|
||||
arrayOf(bottom_favorite, bottom_edit, bottom_share, bottom_delete, bottom_rotate, bottom_properties, bottom_change_orientation,
|
||||
bottom_slideshow, bottom_show_on_map, bottom_toggle_file_visibility, bottom_rename).forEach {
|
||||
it.isClickable = !mIsFullScreen
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -268,34 +271,38 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}
|
||||
|
||||
private fun setupRotation() {
|
||||
if (mIsOrientationLocked) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED
|
||||
}
|
||||
} else if (config.screenRotation == ROTATE_BY_DEVICE_ROTATION) {
|
||||
if (!mIsOrientationLocked) {
|
||||
if (config.screenRotation == ROTATE_BY_DEVICE_ROTATION) {
|
||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR
|
||||
} else if (config.screenRotation == ROTATE_BY_SYSTEM_SETTING) {
|
||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_viewpager, menu)
|
||||
val currentMedium = getCurrentMedium() ?: return true
|
||||
currentMedium.isFavorite = mFavoritePaths.contains(currentMedium.path)
|
||||
val visibleBottomActions = if (config.bottomActions) config.visibleBottomActions else 0
|
||||
|
||||
menu.apply {
|
||||
findItem(R.id.menu_delete).isVisible = !config.bottomActions
|
||||
findItem(R.id.menu_share).isVisible = !config.bottomActions
|
||||
findItem(R.id.menu_edit).isVisible = !config.bottomActions
|
||||
findItem(R.id.menu_rotate).isVisible = currentMedium.isImage()
|
||||
findItem(R.id.menu_show_on_map).isVisible = visibleBottomActions and BOTTOM_ACTION_SHOW_ON_MAP == 0
|
||||
findItem(R.id.menu_slideshow).isVisible = visibleBottomActions and BOTTOM_ACTION_SLIDESHOW == 0
|
||||
findItem(R.id.menu_properties).isVisible = visibleBottomActions and BOTTOM_ACTION_PROPERTIES == 0
|
||||
findItem(R.id.menu_delete).isVisible = visibleBottomActions and BOTTOM_ACTION_DELETE == 0
|
||||
findItem(R.id.menu_share).isVisible = visibleBottomActions and BOTTOM_ACTION_SHARE == 0
|
||||
findItem(R.id.menu_edit).isVisible = visibleBottomActions and BOTTOM_ACTION_EDIT == 0
|
||||
findItem(R.id.menu_rename).isVisible = visibleBottomActions and BOTTOM_ACTION_RENAME == 0
|
||||
findItem(R.id.menu_rotate).isVisible = currentMedium.isImage() && visibleBottomActions and BOTTOM_ACTION_ROTATE == 0
|
||||
findItem(R.id.menu_save_as).isVisible = mRotationDegrees != 0
|
||||
findItem(R.id.menu_hide).isVisible = !currentMedium.name.startsWith('.')
|
||||
findItem(R.id.menu_unhide).isVisible = currentMedium.name.startsWith('.')
|
||||
findItem(R.id.menu_add_to_favorites).isVisible = !currentMedium.isFavorite && !config.bottomActions
|
||||
findItem(R.id.menu_remove_from_favorites).isVisible = currentMedium.isFavorite && !config.bottomActions
|
||||
findItem(R.id.menu_lock_orientation).isVisible = mRotationDegrees == 0
|
||||
findItem(R.id.menu_lock_orientation).title = getString(if (mIsOrientationLocked) R.string.unlock_orientation else R.string.lock_orientation)
|
||||
findItem(R.id.menu_hide).isVisible = !currentMedium.isHidden() && visibleBottomActions and BOTTOM_ACTION_TOGGLE_VISIBILITY == 0
|
||||
findItem(R.id.menu_unhide).isVisible = currentMedium.isHidden() && visibleBottomActions and BOTTOM_ACTION_TOGGLE_VISIBILITY == 0
|
||||
findItem(R.id.menu_add_to_favorites).isVisible = !currentMedium.isFavorite && visibleBottomActions and BOTTOM_ACTION_TOGGLE_FAVORITE == 0
|
||||
findItem(R.id.menu_remove_from_favorites).isVisible = currentMedium.isFavorite && visibleBottomActions and BOTTOM_ACTION_TOGGLE_FAVORITE == 0
|
||||
findItem(R.id.menu_restore_file).isVisible = currentMedium.path.startsWith(filesDir.toString())
|
||||
findItem(R.id.menu_change_orientation).isVisible = mRotationDegrees == 0 && visibleBottomActions and BOTTOM_ACTION_CHANGE_ORIENTATION == 0
|
||||
findItem(R.id.menu_change_orientation).icon = resources.getDrawable(getChangeOrientationIcon())
|
||||
findItem(R.id.menu_rotate).setShowAsAction(
|
||||
if (mRotationDegrees != 0) {
|
||||
MenuItem.SHOW_AS_ACTION_ALWAYS
|
||||
|
@ -304,8 +311,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
})
|
||||
}
|
||||
|
||||
if (config.bottomActions) {
|
||||
updateFavoriteIcon(currentMedium)
|
||||
if (visibleBottomActions != 0) {
|
||||
updateBottomActionIcons(currentMedium)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -322,7 +329,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
R.id.menu_open_with -> openPath(getCurrentPath(), true)
|
||||
R.id.menu_hide -> toggleFileVisibility(true)
|
||||
R.id.menu_unhide -> toggleFileVisibility(false)
|
||||
R.id.menu_share -> shareMedium(getCurrentMedium()!!)
|
||||
R.id.menu_share -> shareMediumPath(getCurrentPath())
|
||||
R.id.menu_delete -> checkDeleteConfirmation()
|
||||
R.id.menu_rename -> renameFile()
|
||||
R.id.menu_edit -> openEditor(getCurrentPath())
|
||||
|
@ -330,10 +337,13 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
R.id.menu_show_on_map -> showOnMap()
|
||||
R.id.menu_rotate_right -> rotateImage(90)
|
||||
R.id.menu_rotate_left -> rotateImage(270)
|
||||
R.id.menu_rotate_one_eighty -> rotateImage(180)
|
||||
R.id.menu_add_to_favorites -> toggleFavorite()
|
||||
R.id.menu_remove_from_favorites -> toggleFavorite()
|
||||
R.id.menu_rotate_one_eighty -> rotateImage(180)
|
||||
R.id.menu_lock_orientation -> toggleLockOrientation()
|
||||
R.id.menu_restore_file -> restoreFile()
|
||||
R.id.menu_force_portrait -> toggleOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
|
||||
R.id.menu_force_landscape -> toggleOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
|
||||
R.id.menu_default_orientation -> toggleOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
|
||||
R.id.menu_save_as -> saveImageAs()
|
||||
R.id.menu_settings -> launchSettings()
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
|
@ -344,7 +354,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
private fun storeStateVariables() {
|
||||
config.apply {
|
||||
mStoredReplaceZoomableImages = replaceZoomableImages
|
||||
mStoredBottomActions = bottomActions
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,7 +379,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
if (getMediaForSlideshow()) {
|
||||
view_pager.onGlobalLayout {
|
||||
if (!isActivityDestroyed()) {
|
||||
hideSystemUI()
|
||||
hideSystemUI(true)
|
||||
mSlideshowInterval = config.slideshowInterval
|
||||
mSlideshowMoveBackwards = config.slideshowMoveBackwards
|
||||
mIsSlideshowActive = true
|
||||
|
@ -448,7 +457,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
private fun stopSlideshow() {
|
||||
if (mIsSlideshowActive) {
|
||||
mIsSlideshowActive = false
|
||||
showSystemUI()
|
||||
showSystemUI(true)
|
||||
mSlideshowHandler.removeCallbacksAndMessages(null)
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
}
|
||||
|
@ -516,7 +525,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}
|
||||
}
|
||||
|
||||
private fun toggleFileVisibility(hide: Boolean) {
|
||||
private fun toggleFileVisibility(hide: Boolean, callback: (() -> Unit)? = null) {
|
||||
toggleFileVisibility(getCurrentPath(), hide) {
|
||||
val newFileName = it.getFilenameFromPath()
|
||||
supportActionBar?.title = newFileName
|
||||
|
@ -527,6 +536,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
getCurrentMedia()[mPos] = this
|
||||
}
|
||||
invalidateOptionsMenu()
|
||||
callback?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -538,16 +548,22 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
supportInvalidateOptionsMenu()
|
||||
}
|
||||
|
||||
private fun toggleLockOrientation() {
|
||||
mIsOrientationLocked = !mIsOrientationLocked
|
||||
if (mIsOrientationLocked) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED
|
||||
private fun toggleOrientation(orientation: Int) {
|
||||
requestedOrientation = orientation
|
||||
mIsOrientationLocked = orientation != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
private fun getChangeOrientationIcon(): Int {
|
||||
return if (mIsOrientationLocked) {
|
||||
if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
|
||||
R.drawable.ic_orientation_portrait
|
||||
} else {
|
||||
R.drawable.ic_orientation_landscape
|
||||
}
|
||||
} else {
|
||||
setupRotation()
|
||||
R.drawable.ic_orientation_auto
|
||||
}
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
private fun saveImageAs() {
|
||||
|
@ -589,7 +605,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}
|
||||
|
||||
if (getDoesFilePathExist(newPath)) {
|
||||
tryDeleteFileDirItem(FileDirItem(newPath, newPath.getFilenameFromPath()))
|
||||
tryDeleteFileDirItem(FileDirItem(newPath, newPath.getFilenameFromPath()), false, true)
|
||||
}
|
||||
|
||||
copyFile(tmpPath, newPath)
|
||||
|
@ -618,7 +634,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
} finally {
|
||||
tryDeleteFileDirItem(tmpFileDirItem)
|
||||
tryDeleteFileDirItem(tmpFileDirItem, false, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -761,26 +777,85 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}
|
||||
|
||||
private fun initBottomActionButtons() {
|
||||
val visibleBottomActions = if (config.bottomActions) config.visibleBottomActions else 0
|
||||
bottom_favorite.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_TOGGLE_FAVORITE != 0)
|
||||
bottom_favorite.setOnClickListener {
|
||||
toggleFavorite()
|
||||
}
|
||||
|
||||
bottom_edit.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_EDIT != 0)
|
||||
bottom_edit.setOnClickListener {
|
||||
openEditor(getCurrentPath())
|
||||
}
|
||||
|
||||
bottom_share.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_SHARE != 0)
|
||||
bottom_share.setOnClickListener {
|
||||
shareMedium(getCurrentMedium()!!)
|
||||
shareMediumPath(getCurrentPath())
|
||||
}
|
||||
|
||||
bottom_delete.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_DELETE != 0)
|
||||
bottom_delete.setOnClickListener {
|
||||
checkDeleteConfirmation()
|
||||
}
|
||||
|
||||
bottom_rotate.setOnClickListener {
|
||||
rotateImage(90)
|
||||
}
|
||||
|
||||
private fun updateFavoriteIcon(medium: Medium) {
|
||||
val icon = if (medium.isFavorite) R.drawable.ic_star_on else R.drawable.ic_star_off
|
||||
bottom_favorite.setImageResource(icon)
|
||||
bottom_properties.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_PROPERTIES != 0)
|
||||
bottom_properties.setOnClickListener {
|
||||
showProperties()
|
||||
}
|
||||
|
||||
bottom_change_orientation.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_CHANGE_ORIENTATION != 0)
|
||||
bottom_change_orientation.setOnClickListener {
|
||||
requestedOrientation = when (requestedOrientation) {
|
||||
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE -> ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||
else -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||
}
|
||||
mIsOrientationLocked = requestedOrientation != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||
updateBottomActionIcons(getCurrentMedium())
|
||||
}
|
||||
|
||||
bottom_slideshow.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_SLIDESHOW != 0)
|
||||
bottom_slideshow.setOnClickListener {
|
||||
initSlideshow()
|
||||
}
|
||||
|
||||
bottom_show_on_map.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_SHOW_ON_MAP != 0)
|
||||
bottom_show_on_map.setOnClickListener {
|
||||
showOnMap()
|
||||
}
|
||||
|
||||
bottom_toggle_file_visibility.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_TOGGLE_VISIBILITY != 0)
|
||||
bottom_toggle_file_visibility.setOnClickListener {
|
||||
getCurrentMedium()?.apply {
|
||||
toggleFileVisibility(!isHidden()) {
|
||||
updateBottomActionIcons(getCurrentMedium())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bottom_rename.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_RENAME != 0)
|
||||
bottom_rename.setOnClickListener {
|
||||
renameFile()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateBottomActionIcons(medium: Medium?) {
|
||||
if (medium == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val favoriteIcon = if (medium.isFavorite) R.drawable.ic_star_on else R.drawable.ic_star_off
|
||||
bottom_favorite.setImageResource(favoriteIcon)
|
||||
|
||||
val hideIcon = if (medium.isHidden()) R.drawable.ic_unhide else R.drawable.ic_hide
|
||||
bottom_toggle_file_visibility.setImageResource(hideIcon)
|
||||
|
||||
bottom_rotate.beVisibleIf(config.visibleBottomActions and BOTTOM_ACTION_ROTATE != 0 && getCurrentMedium()?.isImage() == true)
|
||||
bottom_change_orientation.setImageResource(getChangeOrientationIcon())
|
||||
}
|
||||
|
||||
private fun toggleFavorite() {
|
||||
|
@ -797,6 +872,12 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}.start()
|
||||
}
|
||||
|
||||
private fun restoreFile() {
|
||||
restoreRecycleBinPath(getCurrentPath()) {
|
||||
refreshViewPager()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
||||
if (requestCode == REQUEST_EDIT_IMAGE) {
|
||||
if (resultCode == Activity.RESULT_OK && resultData != null) {
|
||||
|
@ -813,6 +894,10 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}
|
||||
|
||||
private fun checkDeleteConfirmation() {
|
||||
if (getCurrentMedium() == null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (config.tempSkipDeleteConfirmation || config.skipDeleteConfirmation) {
|
||||
deleteConfirmed()
|
||||
} else {
|
||||
|
@ -821,17 +906,35 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}
|
||||
|
||||
private fun askConfirmDelete() {
|
||||
DeleteWithRememberDialog(this, getString(R.string.proceed_with_deletion)) {
|
||||
val message = if (config.useRecycleBin && !getCurrentMedium()!!.getIsInRecycleBin()) R.string.are_you_sure_recycle_bin else R.string.are_you_sure_delete
|
||||
DeleteWithRememberDialog(this, getString(message)) {
|
||||
config.tempSkipDeleteConfirmation = it
|
||||
deleteConfirmed()
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteConfirmed() {
|
||||
val path = getCurrentMedia()[mPos].path
|
||||
tryDeleteFileDirItem(FileDirItem(path, path.getFilenameFromPath())) {
|
||||
val path = getCurrentMedia().getOrNull(mPos)?.path ?: return
|
||||
if (getIsPathDirectory(path)) {
|
||||
return
|
||||
}
|
||||
|
||||
val fileDirItem = FileDirItem(path, path.getFilenameFromPath())
|
||||
if (config.useRecycleBin && !getCurrentMedium()!!.getIsInRecycleBin()) {
|
||||
movePathsInRecycleBin(arrayListOf(path)) {
|
||||
if (it) {
|
||||
tryDeleteFileDirItem(fileDirItem, false, false) {
|
||||
refreshViewPager()
|
||||
}
|
||||
} else {
|
||||
toast(R.string.unknown_error_occurred)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tryDeleteFileDirItem(fileDirItem, false, true) {
|
||||
refreshViewPager()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isDirEmpty(media: ArrayList<Medium>): Boolean {
|
||||
|
@ -884,7 +987,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}.execute()
|
||||
}
|
||||
|
||||
private fun gotMedia(media: ArrayList<Medium>) {
|
||||
private fun gotMedia(thumbnailItems: ArrayList<ThumbnailItem>) {
|
||||
val media = thumbnailItems.filter { it is Medium }.map { it as Medium } as ArrayList<Medium>
|
||||
if (isDirEmpty(media) || media.hashCode() == mPrevHashcode) {
|
||||
return
|
||||
}
|
||||
|
@ -901,6 +1005,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
updatePagerItems(mMediaFiles.toMutableList())
|
||||
invalidateOptionsMenu()
|
||||
checkOrientation()
|
||||
initBottomActions()
|
||||
}
|
||||
|
||||
private fun getPositionInList(items: MutableList<Medium>): Int {
|
||||
|
@ -916,7 +1021,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
private fun deleteDirectoryIfEmpty() {
|
||||
val fileDirItem = FileDirItem(mDirectory, mDirectory.getFilenameFromPath(), getIsPathDirectory(mDirectory))
|
||||
if (config.deleteEmptyFolders && !fileDirItem.isDownloadsFolder() && fileDirItem.isDirectory && fileDirItem.getProperFileCount(applicationContext, true) == 0) {
|
||||
tryDeleteFileDirItem(fileDirItem, true)
|
||||
tryDeleteFileDirItem(fileDirItem, true, true)
|
||||
}
|
||||
|
||||
scanPathRecursively(mDirectory)
|
||||
|
@ -967,10 +1072,10 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
|
||||
private fun checkSystemUI() {
|
||||
if (mIsFullScreen) {
|
||||
hideSystemUI()
|
||||
hideSystemUI(true)
|
||||
} else {
|
||||
stopSlideshow()
|
||||
showSystemUI()
|
||||
showSystemUI(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.simplemobiletools.gallery.dialogs.ExcludeFolderDialog
|
|||
import com.simplemobiletools.gallery.dialogs.PickMediumDialog
|
||||
import com.simplemobiletools.gallery.extensions.*
|
||||
import com.simplemobiletools.gallery.helpers.*
|
||||
import com.simplemobiletools.gallery.interfaces.DirectoryOperationsListener
|
||||
import com.simplemobiletools.gallery.models.AlbumCover
|
||||
import com.simplemobiletools.gallery.models.Directory
|
||||
import kotlinx.android.synthetic.main.directory_item_list.view.*
|
||||
|
@ -28,7 +29,7 @@ import java.io.File
|
|||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directory>, val listener: DirOperationsListener?, recyclerView: MyRecyclerView,
|
||||
class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directory>, val listener: DirectoryOperationsListener?, recyclerView: MyRecyclerView,
|
||||
val isPickIntent: Boolean, fastScroller: FastScroller? = null, itemClick: (Any) -> Unit) :
|
||||
MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
|
||||
|
||||
|
@ -62,7 +63,7 @@ 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, !isPickIntent) { itemView, adapterPosition ->
|
||||
val view = holder.bindView(dir, true, !isPickIntent) { itemView, adapterPosition ->
|
||||
setupView(itemView, dir)
|
||||
}
|
||||
bindViewHolder(holder, position, view)
|
||||
|
@ -71,10 +72,14 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
override fun getItemCount() = dirs.size
|
||||
|
||||
override fun prepareActionMode(menu: Menu) {
|
||||
val selectedPaths = getSelectedPaths()
|
||||
menu.apply {
|
||||
findItem(R.id.cab_rename).isVisible = isOneItemSelected()
|
||||
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_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)
|
||||
}
|
||||
|
@ -91,6 +96,8 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
R.id.cab_pin -> pinFolders(true)
|
||||
R.id.cab_unpin -> pinFolders(false)
|
||||
R.id.cab_hide -> toggleFoldersVisibility(true)
|
||||
R.id.cab_empty_recycle_bin -> emptyRecycleBin()
|
||||
R.id.cab_empty_disable_recycle_bin -> emptyAndDisableRecycleBin()
|
||||
R.id.cab_unhide -> toggleFoldersVisibility(false)
|
||||
R.id.cab_exclude -> tryExcludeFolder()
|
||||
R.id.cab_copy_to -> copyMoveTo(true)
|
||||
|
@ -104,6 +111,8 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
|
||||
override fun getSelectableItemCount() = dirs.size
|
||||
|
||||
override fun getIsItemSelectable(position: Int) = true
|
||||
|
||||
override fun onViewRecycled(holder: ViewHolder) {
|
||||
super.onViewRecycled(holder)
|
||||
if (!activity.isActivityDestroyed()) {
|
||||
|
@ -144,11 +153,12 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
|
||||
private fun showProperties() {
|
||||
if (selectedPositions.size <= 1) {
|
||||
val path = dirs[selectedPositions.first()].path
|
||||
if (path != FAVORITES && path != RECYCLE_BIN) {
|
||||
PropertiesDialog(activity, dirs[selectedPositions.first()].path, config.shouldShowHidden)
|
||||
}
|
||||
} else {
|
||||
val paths = ArrayList<String>()
|
||||
selectedPositions.forEach { paths.add(dirs[it].path) }
|
||||
PropertiesDialog(activity, paths, config.shouldShowHidden)
|
||||
PropertiesDialog(activity, getSelectedPaths().filter { it != FAVORITES && it != RECYCLE_BIN }.toMutableList(), config.shouldShowHidden)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,7 +188,7 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
}
|
||||
|
||||
private fun toggleFoldersVisibility(hide: Boolean) {
|
||||
getSelectedPaths().forEach {
|
||||
getSelectedPaths().filter { it != FAVORITES && it != RECYCLE_BIN }.forEach {
|
||||
val path = it
|
||||
if (hide) {
|
||||
if (config.wasHideFolderTooltipShown) {
|
||||
|
@ -204,13 +214,29 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
}
|
||||
}
|
||||
|
||||
private fun emptyRecycleBin() {
|
||||
activity.showRecycleBinEmptyingDialog {
|
||||
activity.emptyTheRecycleBin {
|
||||
listener?.refreshItems()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun emptyAndDisableRecycleBin() {
|
||||
activity.showRecycleBinEmptyingDialog {
|
||||
activity.emptyAndDisableTheRecycleBin {
|
||||
listener?.refreshItems()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateFolderNames() {
|
||||
val includedFolders = activity.config.includedFolders
|
||||
val hidden = activity.getString(R.string.hidden)
|
||||
dirs.forEach {
|
||||
it.name = activity.checkAppendingHidden(it.path, hidden, includedFolders)
|
||||
}
|
||||
listener?.updateDirectories(dirs.toList() as ArrayList)
|
||||
listener?.updateDirectories(dirs.toMutableList() as ArrayList)
|
||||
activity.runOnUiThread {
|
||||
updateDirs(dirs)
|
||||
}
|
||||
|
@ -252,7 +278,6 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
dirs = newDirs
|
||||
|
||||
finishActMode()
|
||||
fastScroller?.measureRecyclerView()
|
||||
listener?.updateDirectories(newDirs)
|
||||
}
|
||||
}
|
||||
|
@ -260,13 +285,13 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
}
|
||||
|
||||
private fun tryExcludeFolder() {
|
||||
val paths = getSelectedPaths()
|
||||
val paths = getSelectedPaths().filter { it != PATH }.toSet()
|
||||
if (paths.size == 1) {
|
||||
ExcludeFolderDialog(activity, paths.toList()) {
|
||||
ExcludeFolderDialog(activity, paths.toMutableList()) {
|
||||
listener?.refreshItems()
|
||||
finishActMode()
|
||||
}
|
||||
} else {
|
||||
} else if (paths.size > 1) {
|
||||
activity.config.addExcludedFolders(paths)
|
||||
listener?.refreshItems()
|
||||
finishActMode()
|
||||
|
@ -293,7 +318,7 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
val path = dirs[it].path
|
||||
if (path.startsWith(OTG_PATH)) {
|
||||
paths.addAll(getOTGFilePaths(path, showHidden))
|
||||
} else {
|
||||
} else if (path != FAVORITES) {
|
||||
File(path).listFiles()?.filter {
|
||||
!activity.getIsPathDirectory(it.absolutePath) && it.isImageVideoGif() && (showHidden || !it.name.startsWith('.'))
|
||||
}?.mapTo(paths) { it.absolutePath }
|
||||
|
@ -325,7 +350,8 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
} else {
|
||||
val itemsCnt = selectedPositions.size
|
||||
val items = resources.getQuantityString(R.plurals.delete_items, itemsCnt, itemsCnt)
|
||||
var question = String.format(resources.getString(R.string.deletion_confirmation), items)
|
||||
val baseString = if (config.useRecycleBin) R.string.move_to_recycle_bin_confirmation else R.string.deletion_confirmation
|
||||
var question = String.format(resources.getString(baseString), items)
|
||||
val warning = resources.getQuantityString(R.plurals.delete_warning, itemsCnt, itemsCnt)
|
||||
question += "\n\n$warning"
|
||||
ConfirmationDialog(activity, question) {
|
||||
|
@ -355,13 +381,21 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
activity.handleSAFDialog(SAFPath) {
|
||||
selectedPositions.sortedDescending().forEach {
|
||||
val directory = dirs[it]
|
||||
if (directory.areFavorites() || directory.isRecycleBin()) {
|
||||
if (selectedPositions.size == 1) {
|
||||
finishActMode()
|
||||
} else {
|
||||
selectedPositions.remove(it)
|
||||
toggleItemSelection(false, it)
|
||||
}
|
||||
} else {
|
||||
folders.add(File(directory.path))
|
||||
removeFolders.add(directory)
|
||||
}
|
||||
}
|
||||
|
||||
dirs.removeAll(removeFolders)
|
||||
listener?.deleteFolders(folders)
|
||||
removeSelectedItems()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -409,10 +443,9 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
fun updateDirs(newDirs: ArrayList<Directory>) {
|
||||
if (newDirs.hashCode() != currentDirectoriesHash) {
|
||||
currentDirectoriesHash = newDirs.hashCode()
|
||||
dirs = newDirs.clone() as ArrayList<Directory>
|
||||
dirs = newDirs
|
||||
notifyDataSetChanged()
|
||||
finishActMode()
|
||||
fastScroller?.measureRecyclerView()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -431,11 +464,6 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun updateScrollHorizontally(scrollHorizontally: Boolean) {
|
||||
this.scrollHorizontally = scrollHorizontally
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private fun setupView(view: View, directory: Directory) {
|
||||
view.apply {
|
||||
dir_name.text = directory.name
|
||||
|
@ -466,14 +494,4 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface DirOperationsListener {
|
||||
fun refreshItems()
|
||||
|
||||
fun deleteFolders(folders: ArrayList<File>)
|
||||
|
||||
fun recheckPinnedFolders()
|
||||
|
||||
fun updateDirectories(directories: ArrayList<Directory>)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,11 +39,13 @@ class ManageFoldersAdapter(activity: BaseSimpleActivity, var folders: ArrayList<
|
|||
|
||||
override fun getSelectableItemCount() = folders.size
|
||||
|
||||
override fun getIsItemSelectable(position: Int) = true
|
||||
|
||||
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) { itemView, adapterPosition ->
|
||||
val view = holder.bindView(folder, true, true) { itemView, adapterPosition ->
|
||||
setupView(itemView, folder)
|
||||
}
|
||||
bindViewHolder(holder, position, view)
|
||||
|
|
|
@ -41,11 +41,13 @@ class ManageHiddenFoldersAdapter(activity: BaseSimpleActivity, var folders: Arra
|
|||
|
||||
override fun getSelectableItemCount() = folders.size
|
||||
|
||||
override fun getIsItemSelectable(position: Int) = true
|
||||
|
||||
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) { itemView, adapterPosition ->
|
||||
val view = holder.bindView(folder, true, true) { itemView, adapterPosition ->
|
||||
setupView(itemView, folder)
|
||||
}
|
||||
bindViewHolder(holder, position, view)
|
||||
|
|
|
@ -19,15 +19,21 @@ import com.simplemobiletools.gallery.R
|
|||
import com.simplemobiletools.gallery.dialogs.DeleteWithRememberDialog
|
||||
import com.simplemobiletools.gallery.extensions.*
|
||||
import com.simplemobiletools.gallery.helpers.VIEW_TYPE_LIST
|
||||
import com.simplemobiletools.gallery.interfaces.MediaOperationsListener
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import com.simplemobiletools.gallery.models.ThumbnailItem
|
||||
import com.simplemobiletools.gallery.models.ThumbnailSection
|
||||
import kotlinx.android.synthetic.main.photo_video_item_grid.view.*
|
||||
import kotlinx.android.synthetic.main.thumbnail_section.view.*
|
||||
|
||||
class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>, val listener: MediaOperationsListener?, val isAGetIntent: Boolean,
|
||||
val allowMultiplePicks: Boolean, recyclerView: MyRecyclerView, fastScroller: FastScroller? = null,
|
||||
itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
|
||||
class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<ThumbnailItem>, val listener: MediaOperationsListener?, val isAGetIntent: Boolean,
|
||||
val allowMultiplePicks: Boolean, recyclerView: MyRecyclerView, fastScroller: FastScroller? = null, itemClick: (Any) -> Unit) :
|
||||
MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
|
||||
|
||||
private val INSTANT_LOAD_DURATION = 2000L
|
||||
private val IMAGE_LOAD_DELAY = 100L
|
||||
private val ITEM_SECTION = 0
|
||||
private val ITEM_MEDIUM = 1
|
||||
|
||||
private val config = activity.config
|
||||
private val isListViewType = config.viewTypeFiles == VIEW_TYPE_LIST
|
||||
|
@ -58,28 +64,55 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val layoutType = if (isListViewType) R.layout.photo_video_item_list else R.layout.photo_video_item_grid
|
||||
val layoutType = if (viewType == ITEM_SECTION) {
|
||||
R.layout.thumbnail_section
|
||||
} else {
|
||||
if (isListViewType) {
|
||||
R.layout.photo_video_item_list
|
||||
} else {
|
||||
R.layout.photo_video_item_grid
|
||||
}
|
||||
}
|
||||
return createViewHolder(layoutType, parent)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) {
|
||||
val medium = media.getOrNull(position) ?: return
|
||||
visibleItemPaths.add(medium.path)
|
||||
val view = holder.bindView(medium, !allowMultiplePicks) { itemView, adapterPosition ->
|
||||
setupView(itemView, medium)
|
||||
val tmbItem = media.getOrNull(position) ?: return
|
||||
if (tmbItem is Medium) {
|
||||
visibleItemPaths.add(tmbItem.path)
|
||||
}
|
||||
|
||||
val allowLongPress = !allowMultiplePicks && tmbItem is Medium
|
||||
val view = 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)
|
||||
}
|
||||
|
||||
override fun getItemCount() = media.size
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val tmbItem = media[position]
|
||||
return if (tmbItem is ThumbnailSection) {
|
||||
ITEM_SECTION
|
||||
} else {
|
||||
ITEM_MEDIUM
|
||||
}
|
||||
}
|
||||
|
||||
override fun prepareActionMode(menu: Menu) {
|
||||
menu.apply {
|
||||
findItem(R.id.cab_rename).isVisible = isOneItemSelected()
|
||||
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.toString()) }
|
||||
|
||||
checkHideBtnVisibility(this)
|
||||
checkFavoriteBtnVisibility(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,6 +128,9 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
R.id.cab_edit -> editFile()
|
||||
R.id.cab_hide -> toggleFileVisibility(true)
|
||||
R.id.cab_unhide -> toggleFileVisibility(false)
|
||||
R.id.cab_add_to_favorites -> toggleFavorites(true)
|
||||
R.id.cab_remove_from_favorites -> toggleFavorites(false)
|
||||
R.id.cab_restore_recycle_bin_files -> restoreFiles()
|
||||
R.id.cab_share -> shareMedia()
|
||||
R.id.cab_copy_to -> copyMoveTo(true)
|
||||
R.id.cab_move_to -> copyMoveTo(false)
|
||||
|
@ -105,22 +141,29 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
}
|
||||
}
|
||||
|
||||
override fun getSelectableItemCount() = media.size
|
||||
override fun getSelectableItemCount() = media.filter { it is Medium }.size
|
||||
|
||||
override fun getIsItemSelectable(position: Int) = !isASectionTitle(position)
|
||||
|
||||
override fun onViewRecycled(holder: ViewHolder) {
|
||||
super.onViewRecycled(holder)
|
||||
if (!activity.isActivityDestroyed()) {
|
||||
val itemView = holder.itemView
|
||||
visibleItemPaths.remove(itemView?.photo_name?.tag)
|
||||
Glide.with(activity).clear(itemView?.medium_thumbnail!!)
|
||||
val tmb = itemView?.medium_thumbnail
|
||||
if (tmb != null) {
|
||||
Glide.with(activity).clear(tmb)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isASectionTitle(position: Int) = media.getOrNull(position) is ThumbnailSection
|
||||
|
||||
private fun checkHideBtnVisibility(menu: Menu) {
|
||||
var hiddenCnt = 0
|
||||
var unhiddenCnt = 0
|
||||
selectedPositions.mapNotNull { media.getOrNull(it) }.forEach {
|
||||
if (it.name.startsWith('.')) {
|
||||
getSelectedMedia().forEach {
|
||||
if (it.isHidden()) {
|
||||
hiddenCnt++
|
||||
} else {
|
||||
unhiddenCnt++
|
||||
|
@ -131,17 +174,30 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
menu.findItem(R.id.cab_unhide).isVisible = hiddenCnt > 0
|
||||
}
|
||||
|
||||
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 confirmSelection() {
|
||||
val paths = getSelectedMedia().map { it.path } as ArrayList<String>
|
||||
listener?.selectedPaths(paths)
|
||||
listener?.selectedPaths(getSelectedPaths())
|
||||
}
|
||||
|
||||
private fun showProperties() {
|
||||
if (selectedPositions.size <= 1) {
|
||||
PropertiesDialog(activity, media[selectedPositions.first()].path, config.shouldShowHidden)
|
||||
PropertiesDialog(activity, (media[selectedPositions.first()] as Medium).path, config.shouldShowHidden)
|
||||
} else {
|
||||
val paths = ArrayList<String>()
|
||||
selectedPositions.forEach { paths.add(media[it].path) }
|
||||
val paths = getSelectedPaths()
|
||||
PropertiesDialog(activity, paths, config.shouldShowHidden)
|
||||
}
|
||||
}
|
||||
|
@ -177,19 +233,42 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
}.start()
|
||||
}
|
||||
|
||||
private fun toggleFavorites(add: Boolean) {
|
||||
Thread {
|
||||
val mediumDao = activity.galleryDB.MediumDao()
|
||||
getSelectedMedia().forEach {
|
||||
it.isFavorite = add
|
||||
mediumDao.updateFavorite(it.path, add)
|
||||
}
|
||||
activity.runOnUiThread {
|
||||
listener?.refreshItems()
|
||||
finishActMode()
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun restoreFiles() {
|
||||
activity.restoreRecycleBinPaths(getSelectedPaths()) {
|
||||
listener?.refreshItems()
|
||||
finishActMode()
|
||||
}
|
||||
}
|
||||
|
||||
private fun shareMedia() {
|
||||
if (selectedPositions.size == 1 && selectedPositions.first() != -1) {
|
||||
activity.shareMedium(getSelectedMedia()[0])
|
||||
activity.shareMediumPath(getSelectedMedia().first().path)
|
||||
} else if (selectedPositions.size > 1) {
|
||||
activity.shareMedia(getSelectedMedia())
|
||||
activity.shareMediaPaths(getSelectedPaths())
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyMoveTo(isCopyOperation: Boolean) {
|
||||
val paths = ArrayList<String>()
|
||||
selectedPositions.forEach { paths.add(media[it].path) }
|
||||
val paths = getSelectedPaths()
|
||||
|
||||
val fileDirItems = paths.map {
|
||||
FileDirItem(it, it.getFilenameFromPath())
|
||||
} as ArrayList
|
||||
|
||||
val fileDirItems = paths.map { FileDirItem(it, it.getFilenameFromPath()) } as ArrayList
|
||||
activity.tryCopyMoveFilesTo(fileDirItems, isCopyOperation) {
|
||||
config.tempFolderPath = ""
|
||||
activity.applicationContext.rescanFolderMedia(it)
|
||||
|
@ -210,14 +289,16 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
|
||||
private fun askConfirmDelete() {
|
||||
val items = resources.getQuantityString(R.plurals.delete_items, selectedPositions.size, selectedPositions.size)
|
||||
val question = String.format(resources.getString(R.string.deletion_confirmation), items)
|
||||
val isRecycleBin = getSelectedPaths().first().startsWith(activity.filesDir.toString())
|
||||
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)
|
||||
DeleteWithRememberDialog(activity, question) {
|
||||
config.tempSkipDeleteConfirmation = it
|
||||
deleteFiles()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCurrentPath() = media[selectedPositions.first()].path
|
||||
private fun getCurrentPath() = (media[selectedPositions.first()] as Medium).path
|
||||
|
||||
private fun deleteFiles() {
|
||||
if (selectedPositions.isEmpty()) {
|
||||
|
@ -232,12 +313,14 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
return
|
||||
}
|
||||
|
||||
val SAFPath = media[selectedPositions.first()].path
|
||||
val SAFPath = (media[selectedPositions.first()] as Medium).path
|
||||
activity.handleSAFDialog(SAFPath) {
|
||||
selectedPositions.sortedDescending().forEach {
|
||||
val medium = media[it]
|
||||
fileDirItems.add(FileDirItem(medium.path, medium.name))
|
||||
removeMedia.add(medium)
|
||||
val thumbnailItem = media[it]
|
||||
if (thumbnailItem is Medium) {
|
||||
fileDirItems.add(FileDirItem(thumbnailItem.path, thumbnailItem.name))
|
||||
removeMedia.add(thumbnailItem)
|
||||
}
|
||||
}
|
||||
|
||||
media.removeAll(removeMedia)
|
||||
|
@ -248,19 +331,24 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
|
||||
private fun getSelectedMedia(): List<Medium> {
|
||||
val selectedMedia = ArrayList<Medium>(selectedPositions.size)
|
||||
selectedPositions.forEach { selectedMedia.add(media[it]) }
|
||||
selectedPositions.forEach {
|
||||
(media.getOrNull(it) as? Medium)?.apply {
|
||||
selectedMedia.add(this)
|
||||
}
|
||||
}
|
||||
return selectedMedia
|
||||
}
|
||||
|
||||
fun updateMedia(newMedia: ArrayList<Medium>) {
|
||||
private fun getSelectedPaths() = getSelectedMedia().map { it.path } as ArrayList<String>
|
||||
|
||||
fun updateMedia(newMedia: ArrayList<ThumbnailItem>) {
|
||||
if (newMedia.hashCode() != currentMediaHash) {
|
||||
currentMediaHash = newMedia.hashCode()
|
||||
Handler().postDelayed({
|
||||
media = newMedia.clone() as ArrayList<Medium>
|
||||
media = newMedia
|
||||
enableInstantLoad()
|
||||
notifyDataSetChanged()
|
||||
finishActMode()
|
||||
fastScroller?.measureRecyclerView()
|
||||
}, 100L)
|
||||
}
|
||||
}
|
||||
|
@ -281,11 +369,6 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun updateScrollHorizontally(scrollHorizontally: Boolean) {
|
||||
this.scrollHorizontally = scrollHorizontally
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private fun enableInstantLoad() {
|
||||
loadImageInstantly = true
|
||||
delayHandler.postDelayed({
|
||||
|
@ -293,27 +376,29 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
}, INSTANT_LOAD_DURATION)
|
||||
}
|
||||
|
||||
private fun setupView(view: View, medium: Medium) {
|
||||
fun getItemBubbleText(position: Int, sorting: Int) = (media[position] as? Medium)?.getBubbleText(sorting)
|
||||
|
||||
private fun setupThumbnail(view: View, medium: Medium) {
|
||||
view.apply {
|
||||
play_outline.beVisibleIf(medium.isVideo())
|
||||
photo_name.beVisibleIf(displayFilenames || isListViewType)
|
||||
photo_name.text = medium.name
|
||||
photo_name.tag = medium.path
|
||||
|
||||
var thumbnailPath = medium.path
|
||||
if (hasOTGConnected && thumbnailPath.startsWith(OTG_PATH)) {
|
||||
thumbnailPath = thumbnailPath.getOTGPublicPath(context)
|
||||
var path = medium.path
|
||||
if (hasOTGConnected && path.startsWith(OTG_PATH)) {
|
||||
path = path.getOTGPublicPath(context)
|
||||
}
|
||||
|
||||
if (loadImageInstantly) {
|
||||
activity.loadImage(medium.type, thumbnailPath, medium_thumbnail, scrollHorizontally, animateGifs, cropThumbnails)
|
||||
activity.loadImage(medium.type, path, medium_thumbnail, scrollHorizontally, animateGifs, cropThumbnails)
|
||||
} else {
|
||||
medium_thumbnail.setImageDrawable(null)
|
||||
medium_thumbnail.isHorizontalScrolling = scrollHorizontally
|
||||
delayHandler.postDelayed({
|
||||
val isVisible = visibleItemPaths.contains(medium.path)
|
||||
if (isVisible) {
|
||||
activity.loadImage(medium.type, thumbnailPath, medium_thumbnail, scrollHorizontally, animateGifs, cropThumbnails)
|
||||
activity.loadImage(medium.type, path, medium_thumbnail, scrollHorizontally, animateGifs, cropThumbnails)
|
||||
}
|
||||
}, IMAGE_LOAD_DELAY)
|
||||
}
|
||||
|
@ -325,11 +410,10 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
}
|
||||
}
|
||||
|
||||
interface MediaOperationsListener {
|
||||
fun refreshItems()
|
||||
|
||||
fun tryDeleteFiles(fileDirItems: ArrayList<FileDirItem>)
|
||||
|
||||
fun selectedPaths(paths: ArrayList<String>)
|
||||
private fun setupSection(view: View, section: ThumbnailSection) {
|
||||
view.apply {
|
||||
thumbnail_section.text = section.title
|
||||
thumbnail_section.setTextColor(textColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,18 +6,21 @@ import com.simplemobiletools.commons.helpers.SORT_BY_DATE_TAKEN
|
|||
import com.simplemobiletools.gallery.extensions.config
|
||||
import com.simplemobiletools.gallery.extensions.getFavoritePaths
|
||||
import com.simplemobiletools.gallery.helpers.MediaFetcher
|
||||
import com.simplemobiletools.gallery.helpers.SHOW_ALL
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import com.simplemobiletools.gallery.models.ThumbnailItem
|
||||
import java.util.*
|
||||
|
||||
class GetMediaAsynctask(val context: Context, val mPath: String, val isPickImage: Boolean = false, val isPickVideo: Boolean = false,
|
||||
val showAll: Boolean, val callback: (media: ArrayList<Medium>) -> Unit) :
|
||||
AsyncTask<Void, Void, ArrayList<Medium>>() {
|
||||
val showAll: Boolean, val callback: (media: ArrayList<ThumbnailItem>) -> Unit) :
|
||||
AsyncTask<Void, Void, ArrayList<ThumbnailItem>>() {
|
||||
private val mediaFetcher = MediaFetcher(context)
|
||||
|
||||
override fun doInBackground(vararg params: Void): ArrayList<Medium> {
|
||||
val getProperDateTaken = context.config.getFileSorting(mPath) and SORT_BY_DATE_TAKEN != 0
|
||||
override fun doInBackground(vararg params: Void): ArrayList<ThumbnailItem> {
|
||||
val pathToUse = if (showAll) SHOW_ALL else mPath
|
||||
val getProperDateTaken = context.config.getFileSorting(pathToUse) and SORT_BY_DATE_TAKEN != 0
|
||||
val favoritePaths = context.getFavoritePaths()
|
||||
return if (showAll) {
|
||||
val media = if (showAll) {
|
||||
val foldersToScan = mediaFetcher.getFoldersToScan()
|
||||
val media = ArrayList<Medium>()
|
||||
foldersToScan.forEach {
|
||||
|
@ -25,14 +28,15 @@ class GetMediaAsynctask(val context: Context, val mPath: String, val isPickImage
|
|||
media.addAll(newMedia)
|
||||
}
|
||||
|
||||
MediaFetcher(context).sortMedia(media, context.config.getFileSorting(""))
|
||||
mediaFetcher.sortMedia(media, context.config.getFileSorting(SHOW_ALL))
|
||||
media
|
||||
} else {
|
||||
mediaFetcher.getFilesFrom(mPath, isPickImage, isPickVideo, getProperDateTaken, favoritePaths)
|
||||
}
|
||||
return mediaFetcher.groupMedia(media, pathToUse)
|
||||
}
|
||||
|
||||
override fun onPostExecute(media: ArrayList<Medium>) {
|
||||
override fun onPostExecute(media: ArrayList<ThumbnailItem>) {
|
||||
super.onPostExecute(media)
|
||||
callback(media)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import com.simplemobiletools.gallery.interfaces.MediumDao
|
|||
import com.simplemobiletools.gallery.models.Directory
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
|
||||
@Database(entities = [(Directory::class), (Medium::class)], version = 3)
|
||||
@Database(entities = [(Directory::class), (Medium::class)], version = 4)
|
||||
abstract class GalleryDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun DirectoryDao(): DirectoryDao
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
package com.simplemobiletools.gallery.dialogs
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.View
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.beVisibleIf
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.extensions.config
|
||||
import com.simplemobiletools.gallery.helpers.*
|
||||
import kotlinx.android.synthetic.main.dialog_change_grouping.view.*
|
||||
|
||||
class ChangeGroupingDialog(val activity: BaseSimpleActivity, val path: String = "", val callback: () -> Unit) :
|
||||
DialogInterface.OnClickListener {
|
||||
private var currGrouping = 0
|
||||
private var config = activity.config
|
||||
private val pathToUse = if (path.isEmpty()) SHOW_ALL else path
|
||||
private var view: View
|
||||
|
||||
init {
|
||||
view = activity.layoutInflater.inflate(R.layout.dialog_change_grouping, null).apply {
|
||||
grouping_dialog_use_for_this_folder.isChecked = config.hasCustomGrouping(pathToUse)
|
||||
grouping_dialog_radio_folder.beVisibleIf(path.isEmpty())
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok, this)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this, R.string.group_by)
|
||||
}
|
||||
|
||||
currGrouping = config.getFolderGrouping(pathToUse)
|
||||
setupGroupRadio()
|
||||
setupOrderRadio()
|
||||
}
|
||||
|
||||
private fun setupGroupRadio() {
|
||||
val groupingRadio = view.grouping_dialog_radio_grouping
|
||||
|
||||
val groupBtn = when {
|
||||
currGrouping and GROUP_BY_NONE != 0 -> groupingRadio.grouping_dialog_radio_none
|
||||
currGrouping and GROUP_BY_LAST_MODIFIED != 0 -> groupingRadio.grouping_dialog_radio_last_modified
|
||||
currGrouping and GROUP_BY_DATE_TAKEN != 0 -> groupingRadio.grouping_dialog_radio_date_taken
|
||||
currGrouping and GROUP_BY_FILE_TYPE != 0 -> groupingRadio.grouping_dialog_radio_file_type
|
||||
currGrouping and GROUP_BY_EXTENSION != 0 -> groupingRadio.grouping_dialog_radio_extension
|
||||
else -> groupingRadio.grouping_dialog_radio_folder
|
||||
}
|
||||
groupBtn.isChecked = true
|
||||
}
|
||||
|
||||
private fun setupOrderRadio() {
|
||||
val orderRadio = view.grouping_dialog_radio_order
|
||||
var orderBtn = orderRadio.grouping_dialog_radio_ascending
|
||||
|
||||
if (currGrouping and GROUP_DESCENDING != 0) {
|
||||
orderBtn = orderRadio.grouping_dialog_radio_descending
|
||||
}
|
||||
orderBtn.isChecked = true
|
||||
}
|
||||
|
||||
override fun onClick(dialog: DialogInterface, which: Int) {
|
||||
val groupingRadio = view.grouping_dialog_radio_grouping
|
||||
var grouping = when (groupingRadio.checkedRadioButtonId) {
|
||||
R.id.grouping_dialog_radio_none -> GROUP_BY_NONE
|
||||
R.id.grouping_dialog_radio_last_modified -> GROUP_BY_LAST_MODIFIED
|
||||
R.id.grouping_dialog_radio_date_taken -> GROUP_BY_DATE_TAKEN
|
||||
R.id.grouping_dialog_radio_file_type -> GROUP_BY_FILE_TYPE
|
||||
R.id.grouping_dialog_radio_extension -> GROUP_BY_EXTENSION
|
||||
else -> GROUP_BY_FOLDER
|
||||
}
|
||||
|
||||
if (view.grouping_dialog_radio_order.checkedRadioButtonId == R.id.grouping_dialog_radio_descending) {
|
||||
grouping = grouping or GROUP_DESCENDING
|
||||
}
|
||||
|
||||
if (view.grouping_dialog_use_for_this_folder.isChecked) {
|
||||
config.saveFolderGrouping(pathToUse, grouping)
|
||||
} else {
|
||||
config.removeFolderGrouping(pathToUse)
|
||||
config.groupBy = grouping
|
||||
}
|
||||
callback()
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import com.simplemobiletools.commons.extensions.setupDialogStuff
|
|||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.extensions.config
|
||||
import com.simplemobiletools.gallery.helpers.SHOW_ALL
|
||||
import kotlinx.android.synthetic.main.dialog_change_sorting.view.*
|
||||
|
||||
class ChangeSortingDialog(val activity: BaseSimpleActivity, val isDirectorySorting: Boolean, showFolderCheckbox: Boolean,
|
||||
|
@ -16,13 +17,14 @@ class ChangeSortingDialog(val activity: BaseSimpleActivity, val isDirectorySorti
|
|||
DialogInterface.OnClickListener {
|
||||
private var currSorting = 0
|
||||
private var config = activity.config
|
||||
private var pathToUse = if (!isDirectorySorting && path.isEmpty()) SHOW_ALL else path
|
||||
private var view: View
|
||||
|
||||
init {
|
||||
view = activity.layoutInflater.inflate(R.layout.dialog_change_sorting, null).apply {
|
||||
use_for_this_folder_divider.beVisibleIf(showFolderCheckbox)
|
||||
sorting_dialog_use_for_this_folder.beVisibleIf(showFolderCheckbox)
|
||||
sorting_dialog_use_for_this_folder.isChecked = config.hasCustomSorting(path)
|
||||
sorting_dialog_use_for_this_folder.isChecked = config.hasCustomSorting(pathToUse)
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
|
@ -32,7 +34,7 @@ class ChangeSortingDialog(val activity: BaseSimpleActivity, val isDirectorySorti
|
|||
activity.setupDialogStuff(view, this, R.string.sort_by)
|
||||
}
|
||||
|
||||
currSorting = if (isDirectorySorting) config.directorySorting else config.getFileSorting(path)
|
||||
currSorting = if (isDirectorySorting) config.directorySorting else config.getFileSorting(pathToUse)
|
||||
setupSortRadio()
|
||||
setupOrderRadio()
|
||||
}
|
||||
|
@ -78,9 +80,9 @@ class ChangeSortingDialog(val activity: BaseSimpleActivity, val isDirectorySorti
|
|||
config.directorySorting = sorting
|
||||
} else {
|
||||
if (view.sorting_dialog_use_for_this_folder.isChecked) {
|
||||
config.saveFileSorting(path, sorting)
|
||||
config.saveFileSorting(pathToUse, sorting)
|
||||
} else {
|
||||
config.removeFileSorting(path)
|
||||
config.removeFileSorting(pathToUse)
|
||||
config.sorting = sorting
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ class DeleteWithRememberDialog(val activity: Activity, val message: String, val
|
|||
init {
|
||||
view.delete_remember_title.text = message
|
||||
val builder = AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.yes, { dialog, which -> dialogConfirmed() })
|
||||
.setPositiveButton(R.string.yes) { dialog, which -> dialogConfirmed() }
|
||||
.setNegativeButton(R.string.no, null)
|
||||
|
||||
dialog = builder.create().apply {
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package com.simplemobiletools.gallery.dialogs
|
||||
|
||||
import android.support.v7.app.AlertDialog
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.extensions.config
|
||||
import com.simplemobiletools.gallery.helpers.*
|
||||
import kotlinx.android.synthetic.main.dialog_manage_bottom_actions.view.*
|
||||
|
||||
class ManageBottomActionsDialog(val activity: BaseSimpleActivity, val callback: (result: Int) -> Unit) {
|
||||
private var view = activity.layoutInflater.inflate(R.layout.dialog_manage_bottom_actions, null)
|
||||
|
||||
init {
|
||||
val actions = activity.config.visibleBottomActions
|
||||
view.apply {
|
||||
manage_bottom_actions_toggle_favorite.isChecked = actions and BOTTOM_ACTION_TOGGLE_FAVORITE != 0
|
||||
manage_bottom_actions_edit.isChecked = actions and BOTTOM_ACTION_EDIT != 0
|
||||
manage_bottom_actions_share.isChecked = actions and BOTTOM_ACTION_SHARE != 0
|
||||
manage_bottom_actions_delete.isChecked = actions and BOTTOM_ACTION_DELETE != 0
|
||||
manage_bottom_actions_rotate.isChecked = actions and BOTTOM_ACTION_ROTATE != 0
|
||||
manage_bottom_actions_properties.isChecked = actions and BOTTOM_ACTION_PROPERTIES != 0
|
||||
manage_bottom_actions_change_orientation.isChecked = actions and BOTTOM_ACTION_CHANGE_ORIENTATION != 0
|
||||
manage_bottom_actions_slideshow.isChecked = actions and BOTTOM_ACTION_PROPERTIES != 0
|
||||
manage_bottom_actions_show_on_map.isChecked = actions and BOTTOM_ACTION_SHOW_ON_MAP != 0
|
||||
manage_bottom_actions_toggle_visibility.isChecked = actions and BOTTOM_ACTION_TOGGLE_VISIBILITY != 0
|
||||
manage_bottom_actions_rename.isChecked = actions and BOTTOM_ACTION_RENAME != 0
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() }
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun dialogConfirmed() {
|
||||
var result = 0
|
||||
view.apply {
|
||||
if (manage_bottom_actions_toggle_favorite.isChecked)
|
||||
result += BOTTOM_ACTION_TOGGLE_FAVORITE
|
||||
if (manage_bottom_actions_edit.isChecked)
|
||||
result += BOTTOM_ACTION_EDIT
|
||||
if (manage_bottom_actions_share.isChecked)
|
||||
result += BOTTOM_ACTION_SHARE
|
||||
if (manage_bottom_actions_delete.isChecked)
|
||||
result += BOTTOM_ACTION_DELETE
|
||||
if (manage_bottom_actions_rotate.isChecked)
|
||||
result += BOTTOM_ACTION_ROTATE
|
||||
if (manage_bottom_actions_properties.isChecked)
|
||||
result += BOTTOM_ACTION_PROPERTIES
|
||||
if (manage_bottom_actions_change_orientation.isChecked)
|
||||
result += BOTTOM_ACTION_CHANGE_ORIENTATION
|
||||
if (manage_bottom_actions_slideshow.isChecked)
|
||||
result += BOTTOM_ACTION_SLIDESHOW
|
||||
if (manage_bottom_actions_show_on_map.isChecked)
|
||||
result += BOTTOM_ACTION_SHOW_ON_MAP
|
||||
if (manage_bottom_actions_toggle_visibility.isChecked)
|
||||
result += BOTTOM_ACTION_TOGGLE_VISIBILITY
|
||||
if (manage_bottom_actions_rename.isChecked)
|
||||
result += BOTTOM_ACTION_RENAME
|
||||
}
|
||||
|
||||
activity.config.visibleBottomActions = result
|
||||
callback(result)
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ class ManageExtendedDetailsDialog(val activity: BaseSimpleActivity, val callback
|
|||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok, { dialog, which -> dialogConfirmed() })
|
||||
.setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() }
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this)
|
||||
|
|
|
@ -12,13 +12,15 @@ import com.simplemobiletools.gallery.adapters.MediaAdapter
|
|||
import com.simplemobiletools.gallery.asynctasks.GetMediaAsynctask
|
||||
import com.simplemobiletools.gallery.extensions.config
|
||||
import com.simplemobiletools.gallery.extensions.getCachedMedia
|
||||
import com.simplemobiletools.gallery.helpers.SHOW_ALL
|
||||
import com.simplemobiletools.gallery.helpers.VIEW_TYPE_GRID
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import com.simplemobiletools.gallery.models.ThumbnailItem
|
||||
import kotlinx.android.synthetic.main.dialog_medium_picker.view.*
|
||||
|
||||
class PickMediumDialog(val activity: BaseSimpleActivity, val path: String, val callback: (path: String) -> Unit) {
|
||||
var dialog: AlertDialog
|
||||
var shownMedia = ArrayList<Medium>()
|
||||
var shownMedia = ArrayList<ThumbnailItem>()
|
||||
val view = activity.layoutInflater.inflate(R.layout.dialog_medium_picker, null)
|
||||
var isGridViewType = activity.config.viewTypeFiles == VIEW_TYPE_GRID
|
||||
|
||||
|
@ -31,13 +33,13 @@ class PickMediumDialog(val activity: BaseSimpleActivity, val path: String, val c
|
|||
dialog = AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setNeutralButton(R.string.other_folder, { dialogInterface, i -> showOtherFolder() })
|
||||
.setNeutralButton(R.string.other_folder) { dialogInterface, i -> showOtherFolder() }
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this, R.string.select_photo)
|
||||
}
|
||||
|
||||
activity.getCachedMedia(path) {
|
||||
val media = it.filter { !it.isVideo() } as ArrayList
|
||||
val media = it.filter { it is Medium && !it.isVideo() } as ArrayList
|
||||
if (media.isNotEmpty()) {
|
||||
activity.runOnUiThread {
|
||||
gotMedia(media)
|
||||
|
@ -57,18 +59,20 @@ class PickMediumDialog(val activity: BaseSimpleActivity, val path: String, val c
|
|||
}
|
||||
}
|
||||
|
||||
private fun gotMedia(media: ArrayList<Medium>) {
|
||||
private fun gotMedia(media: ArrayList<ThumbnailItem>) {
|
||||
if (media.hashCode() == shownMedia.hashCode())
|
||||
return
|
||||
|
||||
shownMedia = media
|
||||
val adapter = MediaAdapter(activity, media, null, true, false, view.media_grid) {
|
||||
callback((it as Medium).path)
|
||||
val adapter = MediaAdapter(activity, shownMedia, null, true, false, view.media_grid, null) {
|
||||
if (it is Medium) {
|
||||
callback(it.path)
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
val scrollHorizontally = activity.config.scrollHorizontally && isGridViewType
|
||||
val sorting = activity.config.getFileSorting(path)
|
||||
val sorting = activity.config.getFileSorting(if (path.isEmpty()) SHOW_ALL else path)
|
||||
view.apply {
|
||||
media_grid.adapter = adapter
|
||||
|
||||
|
@ -81,12 +85,12 @@ class PickMediumDialog(val activity: BaseSimpleActivity, val path: String, val c
|
|||
if (scrollHorizontally) {
|
||||
media_horizontal_fastscroller.allowBubbleDisplay = activity.config.showInfoBubble
|
||||
media_horizontal_fastscroller.setViews(media_grid) {
|
||||
media_horizontal_fastscroller.updateBubbleText(media[it].getBubbleText(sorting))
|
||||
media_horizontal_fastscroller.updateBubbleText((media[it] as? Medium)?.getBubbleText(sorting) ?: "")
|
||||
}
|
||||
} else {
|
||||
media_vertical_fastscroller.allowBubbleDisplay = activity.config.showInfoBubble
|
||||
media_vertical_fastscroller.setViews(media_grid) {
|
||||
media_vertical_fastscroller.updateBubbleText(media[it].getBubbleText(sorting))
|
||||
media_vertical_fastscroller.updateBubbleText((media[it] as? Medium)?.getBubbleText(sorting) ?: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.provider.MediaStore
|
|||
import android.support.v7.app.AppCompatActivity
|
||||
import android.view.View
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.FAQItem
|
||||
|
@ -15,8 +16,9 @@ import com.simplemobiletools.gallery.R
|
|||
import com.simplemobiletools.gallery.activities.SimpleActivity
|
||||
import com.simplemobiletools.gallery.dialogs.PickDirectoryDialog
|
||||
import com.simplemobiletools.gallery.helpers.NOMEDIA
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.util.*
|
||||
|
||||
fun Activity.sharePath(path: String) {
|
||||
|
@ -27,12 +29,11 @@ fun Activity.sharePaths(paths: ArrayList<String>) {
|
|||
sharePathsIntent(paths, BuildConfig.APPLICATION_ID)
|
||||
}
|
||||
|
||||
fun Activity.shareMedium(medium: Medium) {
|
||||
sharePath(medium.path)
|
||||
fun Activity.shareMediumPath(path: String) {
|
||||
sharePath(path)
|
||||
}
|
||||
|
||||
fun Activity.shareMedia(media: List<Medium>) {
|
||||
val paths = media.map { it.path } as ArrayList
|
||||
fun Activity.shareMediaPaths(paths: ArrayList<String>) {
|
||||
sharePaths(paths)
|
||||
}
|
||||
|
||||
|
@ -59,7 +60,7 @@ fun Activity.launchCamera() {
|
|||
|
||||
fun SimpleActivity.launchAbout() {
|
||||
val faqItems = arrayListOf(
|
||||
FAQItem(R.string.faq_3_title_commons, R.string.faq_3_text_commons),
|
||||
FAQItem(R.string.faq_5_title_commons, R.string.faq_5_text_commons),
|
||||
FAQItem(R.string.faq_1_title, R.string.faq_1_text),
|
||||
FAQItem(R.string.faq_2_title, R.string.faq_2_text),
|
||||
FAQItem(R.string.faq_3_title, R.string.faq_3_text),
|
||||
|
@ -70,21 +71,29 @@ fun SimpleActivity.launchAbout() {
|
|||
FAQItem(R.string.faq_8_title, R.string.faq_8_text),
|
||||
FAQItem(R.string.faq_9_title, R.string.faq_9_text),
|
||||
FAQItem(R.string.faq_10_title, R.string.faq_10_text),
|
||||
FAQItem(R.string.faq_11_title, R.string.faq_11_text),
|
||||
FAQItem(R.string.faq_2_title_commons, R.string.faq_2_text_commons))
|
||||
|
||||
startAboutActivity(R.string.app_name, 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, BuildConfig.VERSION_NAME, faqItems)
|
||||
or LICENSE_SUBSAMPLING or LICENSE_PATTERN or LICENSE_REPRINT or LICENSE_GIF_DRAWABLE or LICENSE_PHOTOVIEW or LICENSE_EXOPLAYER or
|
||||
LICENSE_PANORAMA_VIEW or LICENSE_SANSELAN, BuildConfig.VERSION_NAME, faqItems)
|
||||
}
|
||||
|
||||
fun AppCompatActivity.showSystemUI() {
|
||||
fun AppCompatActivity.showSystemUI(toggleActionBarVisibility: Boolean) {
|
||||
if (toggleActionBarVisibility) {
|
||||
supportActionBar?.show()
|
||||
}
|
||||
|
||||
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
}
|
||||
|
||||
fun AppCompatActivity.hideSystemUI() {
|
||||
fun AppCompatActivity.hideSystemUI(toggleActionBarVisibility: Boolean) {
|
||||
if (toggleActionBarVisibility) {
|
||||
supportActionBar?.hide()
|
||||
}
|
||||
|
||||
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
|
||||
|
@ -134,7 +143,7 @@ fun BaseSimpleActivity.removeNoMedia(path: String, callback: (() -> Unit)? = nul
|
|||
return
|
||||
}
|
||||
|
||||
tryDeleteFileDirItem(file.toFileDirItem(applicationContext)) {
|
||||
tryDeleteFileDirItem(file.toFileDirItem(applicationContext), false, false) {
|
||||
callback?.invoke()
|
||||
}
|
||||
}
|
||||
|
@ -169,12 +178,92 @@ fun BaseSimpleActivity.tryCopyMoveFilesTo(fileDirItems: ArrayList<FileDirItem>,
|
|||
}
|
||||
}
|
||||
|
||||
fun BaseSimpleActivity.tryDeleteFileDirItem(fileDirItem: FileDirItem, allowDeleteFolder: Boolean = false, callback: ((wasSuccess: Boolean) -> Unit)? = null) {
|
||||
fun BaseSimpleActivity.tryDeleteFileDirItem(fileDirItem: FileDirItem, allowDeleteFolder: Boolean = false, deleteFromDatabase: Boolean,
|
||||
callback: ((wasSuccess: Boolean) -> Unit)? = null) {
|
||||
deleteFile(fileDirItem, allowDeleteFolder) {
|
||||
callback?.invoke(it)
|
||||
|
||||
if (deleteFromDatabase) {
|
||||
Thread {
|
||||
galleryDB.MediumDao().deleteMediumPath(fileDirItem.path)
|
||||
runOnUiThread {
|
||||
callback?.invoke(it)
|
||||
}
|
||||
}.start()
|
||||
} else {
|
||||
callback?.invoke(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun BaseSimpleActivity.movePathsInRecycleBin(paths: ArrayList<String>, callback: ((wasSuccess: Boolean) -> Unit)?) {
|
||||
Thread {
|
||||
var pathsCnt = paths.size
|
||||
paths.forEach {
|
||||
val file = File(it)
|
||||
val internalFile = File(filesDir, it)
|
||||
try {
|
||||
file.copyRecursively(internalFile, true)
|
||||
galleryDB.MediumDao().updateDeleted(it, System.currentTimeMillis())
|
||||
pathsCnt--
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
}
|
||||
callback?.invoke(pathsCnt == 0)
|
||||
}.start()
|
||||
}
|
||||
|
||||
fun BaseSimpleActivity.restoreRecycleBinPath(path: String, callback: () -> Unit) {
|
||||
restoreRecycleBinPaths(arrayListOf(path), callback)
|
||||
}
|
||||
|
||||
fun BaseSimpleActivity.restoreRecycleBinPaths(paths: ArrayList<String>, callback: () -> Unit) {
|
||||
Thread {
|
||||
val mediumDao = galleryDB.MediumDao()
|
||||
paths.forEach {
|
||||
val source = it
|
||||
val destination = it.removePrefix(filesDir.toString())
|
||||
|
||||
var inputStream: InputStream? = null
|
||||
var out: OutputStream? = null
|
||||
try {
|
||||
out = getFileOutputStreamSync(destination, source.getMimeType())
|
||||
inputStream = getFileInputStreamSync(source)!!
|
||||
inputStream.copyTo(out!!)
|
||||
mediumDao.updateDeleted(destination, 0)
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
} finally {
|
||||
inputStream?.close()
|
||||
out?.close()
|
||||
}
|
||||
}
|
||||
|
||||
runOnUiThread {
|
||||
callback()
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
fun BaseSimpleActivity.emptyTheRecycleBin(callback: (() -> Unit)? = null) {
|
||||
Thread {
|
||||
filesDir.deleteRecursively()
|
||||
galleryDB.MediumDao().clearRecycleBin()
|
||||
galleryDB.DirectoryDao().deleteRecycleBin()
|
||||
toast(R.string.recycle_bin_emptied)
|
||||
callback?.invoke()
|
||||
}.start()
|
||||
}
|
||||
|
||||
fun BaseSimpleActivity.emptyAndDisableTheRecycleBin(callback: () -> Unit) {
|
||||
Thread {
|
||||
emptyTheRecycleBin {
|
||||
config.useRecycleBin = false
|
||||
callback()
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
fun BaseSimpleActivity.showRecycleBinEmptyingDialog(callback: () -> Unit) {
|
||||
ConfirmationDialog(this, "", R.string.empty_recycle_bin_confirmation, R.string.yes, R.string.no) {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,8 +24,10 @@ import com.simplemobiletools.gallery.asynctasks.GetMediaAsynctask
|
|||
import com.simplemobiletools.gallery.databases.GalleryDatabase
|
||||
import com.simplemobiletools.gallery.helpers.*
|
||||
import com.simplemobiletools.gallery.interfaces.DirectoryDao
|
||||
import com.simplemobiletools.gallery.interfaces.MediumDao
|
||||
import com.simplemobiletools.gallery.models.Directory
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import com.simplemobiletools.gallery.models.ThumbnailItem
|
||||
import com.simplemobiletools.gallery.views.MySquareImageView
|
||||
import pl.droidsonroids.gif.GifDrawable
|
||||
import java.io.File
|
||||
|
@ -163,11 +165,15 @@ fun Context.rescanFolderMediaSync(path: String) {
|
|||
Thread {
|
||||
val newMedia = it
|
||||
val mediumDao = galleryDB.MediumDao()
|
||||
mediumDao.insertAll(newMedia)
|
||||
val media = newMedia.filter { it is Medium } as ArrayList<Medium>
|
||||
mediumDao.insertAll(media)
|
||||
|
||||
cached.forEach {
|
||||
if (!newMedia.contains(it)) {
|
||||
mediumDao.deleteMediumPath(it.path)
|
||||
val mediumPath = (it as? Medium)?.path
|
||||
if (mediumPath != null) {
|
||||
mediumDao.deleteMediumPath(mediumPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
|
@ -315,11 +321,20 @@ fun Context.getCachedDirectories(getVideosOnly: Boolean = false, getImagesOnly:
|
|||
}.start()
|
||||
}
|
||||
|
||||
fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImagesOnly: Boolean = false, callback: (ArrayList<Medium>) -> Unit) {
|
||||
fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImagesOnly: Boolean = false, callback: (ArrayList<ThumbnailItem>) -> Unit) {
|
||||
Thread {
|
||||
val mediaFetcher = MediaFetcher(this)
|
||||
val mediumDao = galleryDB.MediumDao()
|
||||
val foldersToScan = if (path == "/") MediaFetcher(this).getFoldersToScan() else arrayListOf(path)
|
||||
val foldersToScan = if (path.isEmpty()) mediaFetcher.getFoldersToScan() else arrayListOf(path)
|
||||
var media = ArrayList<Medium>()
|
||||
if (path == FAVORITES) {
|
||||
media.addAll(mediumDao.getFavorites())
|
||||
}
|
||||
|
||||
if (path == RECYCLE_BIN) {
|
||||
media.addAll(getUpdatedDeletedMedia(mediumDao))
|
||||
}
|
||||
|
||||
val shouldShowHidden = config.shouldShowHidden
|
||||
foldersToScan.forEach {
|
||||
try {
|
||||
|
@ -345,18 +360,25 @@ fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImag
|
|||
}
|
||||
}) as ArrayList<Medium>
|
||||
|
||||
MediaFetcher(this).sortMedia(media, config.getFileSorting(path))
|
||||
callback(media.clone() as ArrayList<Medium>)
|
||||
val pathToUse = if (path.isEmpty()) SHOW_ALL else path
|
||||
mediaFetcher.sortMedia(media, config.getFileSorting(pathToUse))
|
||||
val grouped = mediaFetcher.groupMedia(media, pathToUse)
|
||||
callback(grouped.clone() as ArrayList<ThumbnailItem>)
|
||||
|
||||
val recycleBinPath = filesDir.toString()
|
||||
media.filter { !getDoesFilePathExist(it.path) }.forEach {
|
||||
if (it.path.startsWith(recycleBinPath)) {
|
||||
mediumDao.deleteMediumPath(it.path.removePrefix(recycleBinPath))
|
||||
} else {
|
||||
mediumDao.deleteMediumPath(it.path)
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
fun Context.removeInvalidDBDirectories(dirs: ArrayList<Directory>? = null, directoryDao: DirectoryDao = galleryDB.DirectoryDao()) {
|
||||
val dirsToCheck = dirs ?: directoryDao.getAll()
|
||||
dirsToCheck.filter { !getDoesFilePathExist(it.path) && it.path != config.tempFolderPath }.forEach {
|
||||
dirsToCheck.filter { !it.areFavorites() && !it.isRecycleBin() && !getDoesFilePathExist(it.path) && it.path != config.tempFolderPath }.forEach {
|
||||
directoryDao.deleteDirPath(it.path)
|
||||
}
|
||||
}
|
||||
|
@ -373,6 +395,14 @@ fun Context.updateDBDirectory(directory: Directory) {
|
|||
|
||||
fun Context.getOTGFolderChildren(path: String) = getDocumentFile(path)?.listFiles()
|
||||
|
||||
fun Context.getOTGFolderChildrenNames(path: String) = getOTGFolderChildren(path)?.map { it.name }?.toList()
|
||||
fun Context.getOTGFolderChildrenNames(path: String) = getOTGFolderChildren(path)?.map { it.name }?.toMutableList()
|
||||
|
||||
fun Context.getFavoritePaths() = galleryDB.MediumDao().getFavoritePaths() as ArrayList<String>
|
||||
|
||||
fun Context.getUpdatedDeletedMedia(mediumDao: MediumDao): ArrayList<Medium> {
|
||||
val media = mediumDao.getDeletedMedia() as ArrayList<Medium>
|
||||
media.forEach {
|
||||
it.path = File(filesDir, it.path).toString()
|
||||
}
|
||||
return media
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.simplemobiletools.gallery.fragments
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
|
@ -26,16 +27,21 @@ 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.isLollipopPlus
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.activities.PanoramaActivity
|
||||
import com.simplemobiletools.gallery.activities.PhotoActivity
|
||||
import com.simplemobiletools.gallery.activities.ViewPagerActivity
|
||||
import com.simplemobiletools.gallery.extensions.*
|
||||
import com.simplemobiletools.gallery.helpers.GlideRotateTransformation
|
||||
import com.simplemobiletools.gallery.helpers.MEDIUM
|
||||
import com.simplemobiletools.gallery.helpers.PATH
|
||||
import com.simplemobiletools.gallery.helpers.ROTATE_BY_ASPECT_RATIO
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import it.sephiroth.android.library.exif2.ExifInterface
|
||||
import kotlinx.android.synthetic.main.pager_photo_item.view.*
|
||||
import org.apache.sanselan.common.byteSources.ByteSourceInputStream
|
||||
import org.apache.sanselan.formats.jpeg.JpegImageParser
|
||||
import pl.droidsonroids.gif.GifDrawable
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
|
@ -46,6 +52,7 @@ class PhotoFragment : ViewPagerFragment() {
|
|||
private var isFullscreen = false
|
||||
private var wasInit = false
|
||||
private var useHalfResolution = false
|
||||
private var isPanorama = false
|
||||
private var imageOrientation = -1
|
||||
private var gifDrawable: GifDrawable? = null
|
||||
|
||||
|
@ -62,6 +69,7 @@ class PhotoFragment : ViewPagerFragment() {
|
|||
photo_view.setOnClickListener { photoClicked() }
|
||||
instant_prev_item.setOnClickListener { listener?.goToPrevItem() }
|
||||
instant_next_item.setOnClickListener { listener?.goToNextItem() }
|
||||
panorama_outline.setOnClickListener { openPanorama() }
|
||||
|
||||
instant_prev_item.parentView = container
|
||||
instant_next_item.parentView = container
|
||||
|
@ -118,6 +126,7 @@ class PhotoFragment : ViewPagerFragment() {
|
|||
loadImage()
|
||||
initExtendedDetails()
|
||||
wasInit = true
|
||||
checkIfPanorama()
|
||||
|
||||
return view
|
||||
}
|
||||
|
@ -286,6 +295,13 @@ class PhotoFragment : ViewPagerFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun openPanorama() {
|
||||
Intent(context, PanoramaActivity::class.java).apply {
|
||||
putExtra(PATH, medium.path)
|
||||
startActivity(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addZoomableView() {
|
||||
if (!context!!.config.replaceZoomableImages && medium.isImage() && isFragmentVisible && view.subsampling_view.isGone()) {
|
||||
ViewPagerActivity.wasDecodedByGlide = false
|
||||
|
@ -329,6 +345,18 @@ class PhotoFragment : ViewPagerFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun checkIfPanorama() {
|
||||
isPanorama = try {
|
||||
val inputStream = if (medium.path.startsWith("content:/")) context!!.contentResolver.openInputStream(Uri.parse(medium.path)) else File(medium.path).inputStream()
|
||||
val imageParser = JpegImageParser().getXmpXml(ByteSourceInputStream(inputStream, medium.name), HashMap<String, Any>())
|
||||
imageParser.contains("GPano:UsePanoramaViewer=\"True\"", true)
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
|
||||
view.panorama_outline.beVisibleIf(isPanorama && isLollipopPlus())
|
||||
}
|
||||
|
||||
private fun getImageOrientation(): Int {
|
||||
val defaultOrientation = -1
|
||||
var orient = defaultOrientation
|
||||
|
|
|
@ -1,21 +1,32 @@
|
|||
package com.simplemobiletools.gallery.fragments
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Point
|
||||
import android.graphics.SurfaceTexture
|
||||
import android.media.AudioManager
|
||||
import android.media.MediaPlayer
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.support.annotation.RequiresApi
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.*
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import com.google.android.exoplayer2.*
|
||||
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory
|
||||
import com.google.android.exoplayer2.source.ExtractorMediaSource
|
||||
import com.google.android.exoplayer2.source.TrackGroupArray
|
||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray
|
||||
import com.google.android.exoplayer2.upstream.ContentDataSource
|
||||
import com.google.android.exoplayer2.upstream.DataSource
|
||||
import com.google.android.exoplayer2.upstream.DataSpec
|
||||
import com.google.android.exoplayer2.upstream.FileDataSource
|
||||
import com.google.android.exoplayer2.video.VideoListener
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.isJellyBean1Plus
|
||||
import com.simplemobiletools.gallery.BuildConfig
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.activities.VideoActivity
|
||||
import com.simplemobiletools.gallery.extensions.*
|
||||
|
@ -24,32 +35,30 @@ import com.simplemobiletools.gallery.helpers.MediaSideScroll
|
|||
import com.simplemobiletools.gallery.models.Medium
|
||||
import kotlinx.android.synthetic.main.pager_video_item.view.*
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSeekBarChangeListener {
|
||||
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 mMediaPlayer: MediaPlayer? = null
|
||||
private var mSurfaceView: SurfaceView? = null
|
||||
private var mSurfaceHolder: SurfaceHolder? = null
|
||||
private var mTextureView: TextureView? = null
|
||||
private var mCurrTimeView: TextView? = null
|
||||
private var mTimerHandler: Handler? = 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 mIsPlaying = false
|
||||
private var mIsDragged = false
|
||||
private var mIsFullscreen = false
|
||||
private var mIsFragmentVisible = false
|
||||
private var mPlayOnPrepare = false
|
||||
private var wasEncoded = false
|
||||
private var wasInit = false
|
||||
private var isPrepared = false
|
||||
private var mWasInit = false
|
||||
private var mCurrTime = 0
|
||||
private var mDuration = 0
|
||||
private var mEncodedPath = ""
|
||||
|
||||
private var mStoredShowExtendedDetails = false
|
||||
private var mStoredHideExtendedDetails = false
|
||||
|
@ -77,7 +86,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
|||
}
|
||||
|
||||
mIsFullscreen = activity!!.window.decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_FULLSCREEN == View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
mView!!.video_play_outline.alpha = if (mIsFullscreen) 0f else 1f
|
||||
mView!!.video_play_outline.alpha = if (mIsFullscreen) 0f else PLAY_PAUSE_VISIBLE_ALPHA
|
||||
|
||||
setupPlayer()
|
||||
if (savedInstanceState != null) {
|
||||
|
@ -85,7 +94,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
|||
}
|
||||
|
||||
checkFullscreen()
|
||||
wasInit = true
|
||||
mWasInit = true
|
||||
|
||||
mView!!.apply {
|
||||
brightnessSideScroll = video_brightness_controller
|
||||
|
@ -102,6 +111,66 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
|||
video_duration.setOnClickListener { skip(true) }
|
||||
}
|
||||
|
||||
mExoPlayer = ExoPlayerFactory.newSimpleInstance(context, DefaultTrackSelector())
|
||||
mExoPlayer!!.addListener(object : Player.EventListener {
|
||||
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) {}
|
||||
|
||||
override fun onSeekProcessed() {}
|
||||
|
||||
override fun onTracksChanged(trackGroups: TrackGroupArray?, trackSelections: TrackSelectionArray?) {}
|
||||
|
||||
override fun onPlayerError(error: ExoPlaybackException?) {
|
||||
activity?.showErrorToast(error.toString())
|
||||
}
|
||||
|
||||
override fun onLoadingChanged(isLoading: Boolean) {}
|
||||
|
||||
override fun onPositionDiscontinuity(reason: Int) {}
|
||||
|
||||
override fun onRepeatModeChanged(repeatMode: Int) {}
|
||||
|
||||
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {}
|
||||
|
||||
override fun onTimelineChanged(timeline: Timeline?, manifest: Any?, reason: Int) {}
|
||||
|
||||
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
|
||||
when (playbackState) {
|
||||
Player.STATE_READY -> videoPrepared()
|
||||
Player.STATE_ENDED -> videoCompleted()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
mExoPlayer!!.addVideoListener(object : VideoListener {
|
||||
override fun onVideoSizeChanged(width: Int, height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float) {
|
||||
mVideoSize.x = width
|
||||
mVideoSize.y = height
|
||||
setVideoSize()
|
||||
}
|
||||
|
||||
override fun onRenderedFirstFrame() {}
|
||||
})
|
||||
|
||||
val isContentUri = medium.path.startsWith("content://")
|
||||
val uri = if (isContentUri) Uri.parse(medium.path) else Uri.fromFile(File(medium.path))
|
||||
val dataSpec = DataSpec(uri)
|
||||
val fileDataSource = if (isContentUri) ContentDataSource(context) else FileDataSource()
|
||||
try {
|
||||
fileDataSource.open(dataSpec)
|
||||
} catch (e: Exception) {
|
||||
activity?.showErrorToast(e)
|
||||
}
|
||||
|
||||
val factory = DataSource.Factory { fileDataSource }
|
||||
val audioSource = ExtractorMediaSource(fileDataSource.uri, factory, DefaultExtractorsFactory(), null, null)
|
||||
mExoPlayer!!.audioStreamType = AudioManager.STREAM_MUSIC
|
||||
mExoPlayer!!.prepare(audioSource)
|
||||
medium.path.getVideoResolution()?.apply {
|
||||
mVideoSize.x = x
|
||||
mVideoSize.y = y
|
||||
setVideoSize()
|
||||
}
|
||||
|
||||
return mView
|
||||
}
|
||||
|
||||
|
@ -157,26 +226,23 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
|||
|
||||
mView!!.video_play_outline.setOnClickListener { togglePlayPause() }
|
||||
|
||||
mSurfaceView = mView!!.video_surface
|
||||
mSurfaceHolder = mSurfaceView!!.holder
|
||||
mSurfaceHolder!!.addCallback(this)
|
||||
mSurfaceView!!.setOnClickListener { toggleFullscreen() }
|
||||
mTextureView = mView!!.video_surface
|
||||
mTextureView!!.setOnClickListener { toggleFullscreen() }
|
||||
mTextureView!!.surfaceTextureListener = this
|
||||
mView!!.video_holder.setOnClickListener { toggleFullscreen() }
|
||||
|
||||
initTimeHolder()
|
||||
checkExtendedDetails()
|
||||
initMediaPlayer()
|
||||
}
|
||||
|
||||
override fun setMenuVisibility(menuVisible: Boolean) {
|
||||
super.setMenuVisibility(menuVisible)
|
||||
if (mIsFragmentVisible && !menuVisible) {
|
||||
pauseVideo()
|
||||
releaseMediaPlayer()
|
||||
}
|
||||
|
||||
mIsFragmentVisible = menuVisible
|
||||
if (menuVisible && wasInit) {
|
||||
initMediaPlayer()
|
||||
if (menuVisible && mWasInit) {
|
||||
if (context?.config?.autoplayVideos == true) {
|
||||
playVideo()
|
||||
}
|
||||
|
@ -252,20 +318,19 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
|||
private fun setupTimeHolder() {
|
||||
mSeekBar!!.max = mDuration
|
||||
mView!!.video_duration.text = mDuration.getFormattedDuration()
|
||||
mTimerHandler = Handler()
|
||||
setupTimer()
|
||||
}
|
||||
|
||||
private fun setupTimer() {
|
||||
activity!!.runOnUiThread(object : Runnable {
|
||||
override fun run() {
|
||||
if (mMediaPlayer != null && !mIsDragged && mIsPlaying) {
|
||||
mCurrTime = mMediaPlayer!!.currentPosition / 1000
|
||||
if (mExoPlayer != null && !mIsDragged && mIsPlaying) {
|
||||
mCurrTime = (mExoPlayer!!.currentPosition / 1000).toInt()
|
||||
mSeekBar!!.progress = mCurrTime
|
||||
mCurrTimeView!!.text = mCurrTime.getFormattedDuration()
|
||||
}
|
||||
|
||||
mTimerHandler!!.postDelayed(this, 1000)
|
||||
mTimerHandler.postDelayed(this, 1000)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -299,9 +364,8 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
|||
if (activity == null || !isAdded)
|
||||
return
|
||||
|
||||
initMediaPlayer()
|
||||
|
||||
mIsPlaying = !mIsPlaying
|
||||
mHidePauseHandler.removeCallbacksAndMessages(null)
|
||||
if (mIsPlaying) {
|
||||
playVideo()
|
||||
} else {
|
||||
|
@ -310,102 +374,65 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
|||
}
|
||||
|
||||
fun playVideo() {
|
||||
if (mMediaPlayer != null && isPrepared) {
|
||||
mIsPlaying = true
|
||||
mMediaPlayer?.start()
|
||||
} else {
|
||||
mPlayOnPrepare = true
|
||||
}
|
||||
|
||||
mView!!.video_play_outline.setImageDrawable(resources.getDrawable(R.drawable.img_pause_outline_big))
|
||||
activity!!.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
}
|
||||
|
||||
private fun pauseVideo() {
|
||||
mIsPlaying = false
|
||||
mMediaPlayer?.pause()
|
||||
mView?.video_play_outline?.setImageDrawable(resources.getDrawable(R.drawable.img_play_outline_big))
|
||||
activity!!.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
}
|
||||
|
||||
private fun initMediaPlayer() {
|
||||
if (mMediaPlayer != null || !mIsFragmentVisible) {
|
||||
if (mExoPlayer == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val mediumPath = if (wasEncoded) mEncodedPath else getPathToLoad(medium)
|
||||
if (videoEnded()) {
|
||||
setProgress(0)
|
||||
}
|
||||
|
||||
// this workaround is needed for example if the filename contains a colon
|
||||
val fileUri = if (mediumPath.startsWith("/")) context!!.getFilePublicUri(File(mediumPath), BuildConfig.APPLICATION_ID) else Uri.parse(mediumPath)
|
||||
try {
|
||||
mMediaPlayer = MediaPlayer().apply {
|
||||
setDataSource(context, fileUri)
|
||||
setDisplay(mSurfaceHolder)
|
||||
setOnCompletionListener { videoCompleted() }
|
||||
setOnVideoSizeChangedListener { mediaPlayer, width, height -> setVideoSize() }
|
||||
setOnPreparedListener { videoPrepared(it) }
|
||||
setAudioStreamType(AudioManager.STREAM_MUSIC)
|
||||
prepare()
|
||||
mIsPlaying = true
|
||||
mExoPlayer?.playWhenReady = true
|
||||
mView!!.video_play_outline.setImageDrawable(resources.getDrawable(R.drawable.img_pause_outline_big))
|
||||
activity!!.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
mHidePauseHandler.postDelayed({
|
||||
mView!!.video_play_outline.animate().alpha(0f).start()
|
||||
}, HIDE_PAUSE_DELAY)
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
mEncodedPath = Uri.encode(getPathToLoad(medium))
|
||||
if (wasEncoded) {
|
||||
releaseMediaPlayer()
|
||||
} else {
|
||||
wasEncoded = true
|
||||
mMediaPlayer = null
|
||||
initMediaPlayer()
|
||||
|
||||
private fun pauseVideo() {
|
||||
if (mExoPlayer == null) {
|
||||
return
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
releaseMediaPlayer()
|
||||
|
||||
mIsPlaying = false
|
||||
if (!videoEnded()) {
|
||||
mExoPlayer?.playWhenReady = false
|
||||
}
|
||||
|
||||
mView?.video_play_outline?.setImageDrawable(resources.getDrawable(R.drawable.img_play_outline_big))
|
||||
mView!!.video_play_outline.alpha = PLAY_PAUSE_VISIBLE_ALPHA
|
||||
activity!!.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
|
||||
}
|
||||
|
||||
private fun videoEnded() = mExoPlayer!!.currentPosition >= mExoPlayer!!.duration
|
||||
|
||||
private fun setProgress(seconds: Int) {
|
||||
mMediaPlayer!!.seekTo(seconds * 1000)
|
||||
mExoPlayer!!.seekTo(seconds * 1000L)
|
||||
mSeekBar!!.progress = seconds
|
||||
mCurrTimeView!!.text = seconds.getFormattedDuration()
|
||||
}
|
||||
|
||||
private fun addPreviewImage() {
|
||||
mMediaPlayer!!.start()
|
||||
mMediaPlayer!!.pause()
|
||||
}
|
||||
|
||||
private fun cleanup() {
|
||||
pauseVideo()
|
||||
mCurrTimeView?.text = 0.getFormattedDuration()
|
||||
releaseMediaPlayer()
|
||||
mSeekBar?.progress = 0
|
||||
mTimerHandler?.removeCallbacksAndMessages(null)
|
||||
mSurfaceView = null
|
||||
mSurfaceHolder?.removeCallback(this)
|
||||
mSurfaceHolder = null
|
||||
}
|
||||
|
||||
private fun releaseMediaPlayer() {
|
||||
mMediaPlayer?.setSurface(null)
|
||||
mMediaPlayer?.release()
|
||||
mMediaPlayer = null
|
||||
}
|
||||
|
||||
private fun videoPrepared(mediaPlayer: MediaPlayer) {
|
||||
isPrepared = true
|
||||
mDuration = mediaPlayer.duration / 1000
|
||||
addPreviewImage()
|
||||
private fun videoPrepared() {
|
||||
if (mDuration == 0) {
|
||||
mDuration = (mExoPlayer!!.duration / 1000).toInt()
|
||||
setupTimeHolder()
|
||||
setProgress(mCurrTime)
|
||||
|
||||
if (mIsFragmentVisible && (context!!.config.autoplayVideos || mPlayOnPrepare)) {
|
||||
if (mIsFragmentVisible && (context!!.config.autoplayVideos)) {
|
||||
playVideo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun videoCompleted() {
|
||||
if (!isAdded) {
|
||||
if (!isAdded || mExoPlayer == null) {
|
||||
return
|
||||
}
|
||||
|
||||
mCurrTime = (mExoPlayer!!.duration / 1000).toInt()
|
||||
if (listener?.videoEnded() == false && context!!.config.loopVideos) {
|
||||
playVideo()
|
||||
} else {
|
||||
|
@ -415,37 +442,43 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
|||
}
|
||||
}
|
||||
|
||||
override fun surfaceCreated(holder: SurfaceHolder) {
|
||||
mSurfaceHolder = holder
|
||||
if (mIsFragmentVisible) {
|
||||
initMediaPlayer()
|
||||
}
|
||||
private fun cleanup() {
|
||||
pauseVideo()
|
||||
mCurrTimeView?.text = 0.getFormattedDuration()
|
||||
releaseExoPlayer()
|
||||
mSeekBar?.progress = 0
|
||||
mTimerHandler.removeCallbacksAndMessages(null)
|
||||
mHidePauseHandler.removeCallbacksAndMessages(null)
|
||||
mTextureView = null
|
||||
}
|
||||
|
||||
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
|
||||
if (width != 0 && height != 0 && mSurfaceView != null) {
|
||||
setVideoSize()
|
||||
}
|
||||
private fun releaseExoPlayer() {
|
||||
mExoPlayer?.stop()
|
||||
mExoPlayer?.release()
|
||||
mExoPlayer = null
|
||||
}
|
||||
|
||||
override fun surfaceDestroyed(holder: SurfaceHolder) {
|
||||
releaseMediaPlayer()
|
||||
override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) {
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
override fun onSurfaceTextureUpdated(surface: SurfaceTexture?) {
|
||||
}
|
||||
|
||||
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture?): Boolean {
|
||||
releaseExoPlayer()
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onSurfaceTextureAvailable(surface: SurfaceTexture?, width: Int, height: Int) {
|
||||
mExoPlayer?.setVideoSurface(Surface(mTextureView!!.surfaceTexture))
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
private fun setVideoSize() {
|
||||
if (mSurfaceHolder == null)
|
||||
mSurfaceHolder = mSurfaceView!!.holder
|
||||
|
||||
if (activity == null || mSurfaceHolder == null || !mSurfaceHolder!!.surface.isValid)
|
||||
if (activity == null || mTextureView == null)
|
||||
return
|
||||
|
||||
initMediaPlayer()
|
||||
if (mMediaPlayer == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val videoProportion = mMediaPlayer!!.videoWidth.toFloat() / mMediaPlayer!!.videoHeight.toFloat()
|
||||
val videoProportion = mVideoSize.x.toFloat() / mVideoSize.y.toFloat()
|
||||
val display = activity!!.windowManager.defaultDisplay
|
||||
val screenWidth: Int
|
||||
val screenHeight: Int
|
||||
|
@ -462,7 +495,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
|||
|
||||
val screenProportion = screenWidth.toFloat() / screenHeight.toFloat()
|
||||
|
||||
mSurfaceView!!.layoutParams.apply {
|
||||
mTextureView!!.layoutParams.apply {
|
||||
if (videoProportion > screenProportion) {
|
||||
width = screenWidth
|
||||
height = (screenWidth.toFloat() / videoProportion).toInt()
|
||||
|
@ -470,7 +503,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
|||
width = (videoProportion * screenHeight.toFloat()).toInt()
|
||||
height = screenHeight
|
||||
}
|
||||
mSurfaceView!!.layoutParams = this
|
||||
mTextureView!!.layoutParams = this
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -496,15 +529,15 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
|||
}
|
||||
|
||||
private fun skip(forward: Boolean) {
|
||||
if (mMediaPlayer == null) {
|
||||
if (mExoPlayer == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val curr = mMediaPlayer!!.currentPosition
|
||||
val twoPercents = Math.max(mMediaPlayer!!.duration / 50, MIN_SKIP_LENGTH)
|
||||
val curr = mExoPlayer!!.currentPosition
|
||||
val twoPercents = Math.max((mExoPlayer!!.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(mMediaPlayer!!.duration / 1000, roundProgress), 0)
|
||||
val limitedProgress = Math.max(Math.min(mExoPlayer!!.duration.toInt(), roundProgress), 0)
|
||||
setProgress(limitedProgress)
|
||||
if (!mIsPlaying) {
|
||||
togglePlayPause()
|
||||
|
@ -512,17 +545,16 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
|||
}
|
||||
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (mMediaPlayer != null && fromUser) {
|
||||
if (mExoPlayer != null && fromUser) {
|
||||
setProgress(progress)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStartTrackingTouch(seekBar: SeekBar) {
|
||||
initMediaPlayer()
|
||||
if (mMediaPlayer == null)
|
||||
if (mExoPlayer == null)
|
||||
return
|
||||
|
||||
mMediaPlayer!!.pause()
|
||||
mExoPlayer!!.playWhenReady = false
|
||||
mIsDragged = true
|
||||
}
|
||||
|
||||
|
@ -530,7 +562,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
|||
if (!mIsPlaying) {
|
||||
togglePlayPause()
|
||||
} else {
|
||||
mMediaPlayer?.start()
|
||||
mExoPlayer!!.playWhenReady = true
|
||||
}
|
||||
|
||||
mIsDragged = false
|
||||
|
@ -549,7 +581,16 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
|||
}
|
||||
}
|
||||
|
||||
mView!!.video_play_outline.animate().alpha(if (isFullscreen) 0f else 1f).start()
|
||||
mView!!.video_play_outline.animate().alpha(if (isFullscreen && mIsPlaying) 0f else PLAY_PAUSE_VISIBLE_ALPHA).start()
|
||||
if (isFullscreen) {
|
||||
mHidePauseHandler.removeCallbacksAndMessages(null)
|
||||
} else {
|
||||
mHidePauseHandler.postDelayed({
|
||||
if (mExoPlayer?.currentPosition ?: 0 > 0) {
|
||||
mView!!.video_play_outline.animate().alpha(0f).start()
|
||||
}
|
||||
}, HIDE_PAUSE_DELAY)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getExtendedDetailsY(height: Int): Float {
|
||||
|
|
|
@ -36,6 +36,28 @@ class Config(context: Context) : BaseConfig(context) {
|
|||
|
||||
fun hasCustomSorting(path: String) = prefs.contains(SORT_FOLDER_PREFIX + path.toLowerCase())
|
||||
|
||||
fun saveFolderGrouping(path: String, value: Int) {
|
||||
if (path.isEmpty()) {
|
||||
groupBy = value
|
||||
} else {
|
||||
prefs.edit().putInt(GROUP_FOLDER_PREFIX + path.toLowerCase(), value).apply()
|
||||
}
|
||||
}
|
||||
|
||||
fun getFolderGrouping(path: String): Int {
|
||||
var groupBy = prefs.getInt(GROUP_FOLDER_PREFIX + path.toLowerCase(), groupBy)
|
||||
if (path != SHOW_ALL && groupBy and GROUP_BY_FOLDER != 0) {
|
||||
groupBy -= GROUP_BY_FOLDER + 1
|
||||
}
|
||||
return groupBy
|
||||
}
|
||||
|
||||
fun removeFolderGrouping(path: String) {
|
||||
prefs.edit().remove(GROUP_FOLDER_PREFIX + path.toLowerCase()).apply()
|
||||
}
|
||||
|
||||
fun hasCustomGrouping(path: String) = prefs.contains(GROUP_FOLDER_PREFIX + path.toLowerCase())
|
||||
|
||||
var wasHideFolderTooltipShown: Boolean
|
||||
get() = prefs.getBoolean(HIDE_FOLDER_TOOLTIP_SHOWN, false)
|
||||
set(wasShown) = prefs.edit().putBoolean(HIDE_FOLDER_TOOLTIP_SHOWN, wasShown).apply()
|
||||
|
@ -239,10 +261,6 @@ class Config(context: Context) : BaseConfig(context) {
|
|||
get() = prefs.getBoolean(ALLOW_VIDEO_GESTURES, true)
|
||||
set(allowVideoGestures) = prefs.edit().putBoolean(ALLOW_VIDEO_GESTURES, allowVideoGestures).apply()
|
||||
|
||||
var bottomActions: Boolean
|
||||
get() = prefs.getBoolean(BOTTOM_ACTIONS, true)
|
||||
set(bottomActions) = prefs.edit().putBoolean(BOTTOM_ACTIONS, bottomActions).apply()
|
||||
|
||||
var showMediaCount: Boolean
|
||||
get() = prefs.getBoolean(SHOW_MEDIA_COUNT, true)
|
||||
set(showMediaCount) = prefs.edit().putBoolean(SHOW_MEDIA_COUNT, showMediaCount).apply()
|
||||
|
@ -322,4 +340,33 @@ class Config(context: Context) : BaseConfig(context) {
|
|||
var tempSkipDeleteConfirmation: Boolean
|
||||
get() = prefs.getBoolean(TEMP_SKIP_DELETE_CONFIRMATION, false)
|
||||
set(tempSkipDeleteConfirmation) = prefs.edit().putBoolean(TEMP_SKIP_DELETE_CONFIRMATION, tempSkipDeleteConfirmation).apply()
|
||||
|
||||
var wereFavoritesPinned: Boolean
|
||||
get() = prefs.getBoolean(WERE_FAVORITES_PINNED, false)
|
||||
set(wereFavoritesPinned) = prefs.edit().putBoolean(WERE_FAVORITES_PINNED, wereFavoritesPinned).apply()
|
||||
|
||||
var wasRecycleBinPinned: Boolean
|
||||
get() = prefs.getBoolean(WAS_RECYCLE_BIN_PINNED, false)
|
||||
set(wasRecycleBinPinned) = prefs.edit().putBoolean(WAS_RECYCLE_BIN_PINNED, wasRecycleBinPinned).apply()
|
||||
|
||||
var groupBy: Int
|
||||
get() = prefs.getInt(GROUP_BY, GROUP_BY_NONE)
|
||||
set(groupBy) = prefs.edit().putInt(GROUP_BY, groupBy).apply()
|
||||
|
||||
var useRecycleBin: Boolean
|
||||
get() = prefs.getBoolean(USE_RECYCLE_BIN, true)
|
||||
set(useRecycleBin) = prefs.edit().putBoolean(USE_RECYCLE_BIN, useRecycleBin).apply()
|
||||
|
||||
var bottomActions: Boolean
|
||||
get() = prefs.getBoolean(BOTTOM_ACTIONS, true)
|
||||
set(bottomActions) = prefs.edit().putBoolean(BOTTOM_ACTIONS, bottomActions).apply()
|
||||
|
||||
var visibleBottomActions: Int
|
||||
get() = prefs.getInt(VISIBLE_BOTTOM_ACTIONS, DEFAULT_BOTTOM_ACTIONS)
|
||||
set(visibleBottomActions) = prefs.edit().putInt(VISIBLE_BOTTOM_ACTIONS, visibleBottomActions).apply()
|
||||
|
||||
// if a user hides a folder, then enables temporary hidden folder displaying, make sure we show it properly
|
||||
var everShownFolders: Set<String>
|
||||
get() = prefs.getStringSet(EVER_SHOWN_FOLDERS, HashSet<String>())
|
||||
set(everShownFolders) = prefs.edit().putStringSet(EVER_SHOWN_FOLDERS, everShownFolders).apply()
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package com.simplemobiletools.gallery.helpers
|
||||
|
||||
import com.simplemobiletools.commons.helpers.MONTH_SECONDS
|
||||
|
||||
// shared preferences
|
||||
const val DIRECTORY_SORT_ORDER = "directory_sort_order"
|
||||
const val SORT_FOLDER_PREFIX = "sort_folder_"
|
||||
const val GROUP_FOLDER_PREFIX = "group_folder_"
|
||||
const val SHOW_HIDDEN_MEDIA = "show_hidden_media"
|
||||
const val TEMPORARILY_SHOW_HIDDEN = "temporarily_show_hidden"
|
||||
const val IS_THIRD_PARTY_INTENT = "is_third_party_intent"
|
||||
|
@ -49,6 +52,12 @@ const val LAST_FILEPICKER_PATH = "last_filepicker_path"
|
|||
const val WAS_OTG_HANDLED = "was_otg_handled"
|
||||
const val TEMP_SKIP_DELETE_CONFIRMATION = "temp_skip_delete_confirmation"
|
||||
const val BOTTOM_ACTIONS = "bottom_actions"
|
||||
const val VISIBLE_BOTTOM_ACTIONS = "visible_bottom_actions"
|
||||
const val WERE_FAVORITES_PINNED = "were_favorites_pinned"
|
||||
const val WAS_RECYCLE_BIN_PINNED = "was_recycle_bin_pinned"
|
||||
const val USE_RECYCLE_BIN = "use_recycle_bin"
|
||||
const val GROUP_BY = "group_by"
|
||||
const val EVER_SHOWN_FOLDERS = "ever_shown_folders"
|
||||
|
||||
// slideshow
|
||||
const val SLIDESHOW_INTERVAL = "slideshow_interval"
|
||||
|
@ -64,10 +73,14 @@ const val SLIDESHOW_SCROLL_DURATION = 500L
|
|||
|
||||
const val NOMEDIA = ".nomedia"
|
||||
const val FAVORITES = "favorites"
|
||||
const val RECYCLE_BIN = "recycle_bin"
|
||||
const val SHOW_FAVORITES = "show_favorites"
|
||||
const val SHOW_RECYCLE_BIN = "show_recycle_bin"
|
||||
const val MAX_COLUMN_COUNT = 20
|
||||
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 DIRECTORY = "directory"
|
||||
const val MEDIUM = "medium"
|
||||
|
@ -110,3 +123,26 @@ const val TYPE_RAWS = 8
|
|||
const val LOCAITON_INTERNAL = 1
|
||||
const val LOCATION_SD = 2
|
||||
const val LOCATION_OTG = 3
|
||||
|
||||
const val GROUP_BY_NONE = 1
|
||||
const val GROUP_BY_LAST_MODIFIED = 2
|
||||
const val GROUP_BY_DATE_TAKEN = 4
|
||||
const val GROUP_BY_FILE_TYPE = 8
|
||||
const val GROUP_BY_EXTENSION = 16
|
||||
const val GROUP_BY_FOLDER = 32
|
||||
const val GROUP_DESCENDING = 1024
|
||||
|
||||
// bottom actions
|
||||
const val BOTTOM_ACTION_TOGGLE_FAVORITE = 1
|
||||
const val BOTTOM_ACTION_EDIT = 2
|
||||
const val BOTTOM_ACTION_SHARE = 4
|
||||
const val BOTTOM_ACTION_DELETE = 8
|
||||
const val BOTTOM_ACTION_ROTATE = 16
|
||||
const val BOTTOM_ACTION_PROPERTIES = 32
|
||||
const val BOTTOM_ACTION_CHANGE_ORIENTATION = 64
|
||||
const val BOTTOM_ACTION_SLIDESHOW = 128
|
||||
const val BOTTOM_ACTION_SHOW_ON_MAP = 256
|
||||
const val BOTTOM_ACTION_TOGGLE_VISIBILITY = 512
|
||||
const val BOTTOM_ACTION_RENAME = 1024
|
||||
|
||||
const val DEFAULT_BOTTOM_ACTIONS = BOTTOM_ACTION_TOGGLE_FAVORITE or BOTTOM_ACTION_EDIT or BOTTOM_ACTION_SHARE or BOTTOM_ACTION_DELETE
|
||||
|
|
|
@ -4,14 +4,16 @@ import android.content.Context
|
|||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.provider.MediaStore
|
||||
import android.text.format.DateFormat
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.gallery.extensions.config
|
||||
import com.simplemobiletools.gallery.extensions.getDistinctPath
|
||||
import com.simplemobiletools.gallery.extensions.getOTGFolderChildren
|
||||
import com.simplemobiletools.gallery.extensions.shouldFolderBeVisible
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.extensions.*
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import com.simplemobiletools.gallery.models.ThumbnailItem
|
||||
import com.simplemobiletools.gallery.models.ThumbnailSection
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class MediaFetcher(val context: Context) {
|
||||
var shouldStop = false
|
||||
|
@ -112,7 +114,7 @@ class MediaFetcher(val context: Context) {
|
|||
val foldersToIgnore = arrayListOf("/storage/emulated/legacy")
|
||||
val config = context.config
|
||||
val includedFolders = config.includedFolders
|
||||
var foldersToScan = ArrayList<String>()
|
||||
var foldersToScan = config.everShownFolders.toMutableList() as ArrayList
|
||||
|
||||
cursor.use {
|
||||
if (cursor.moveToFirst()) {
|
||||
|
@ -159,7 +161,19 @@ class MediaFetcher(val context: Context) {
|
|||
private fun getMediaInFolder(folder: String, isPickImage: Boolean, isPickVideo: Boolean, filterMedia: Int, getProperDateTaken: Boolean,
|
||||
favoritePaths: ArrayList<String>): ArrayList<Medium> {
|
||||
val media = ArrayList<Medium>()
|
||||
val files = File(folder).listFiles() ?: return media
|
||||
|
||||
val deletedMedia = if (folder == RECYCLE_BIN) {
|
||||
context.getUpdatedDeletedMedia(context.galleryDB.MediumDao())
|
||||
} else {
|
||||
ArrayList()
|
||||
}
|
||||
|
||||
val files = when (folder) {
|
||||
FAVORITES -> favoritePaths.map { File(it) }.toTypedArray()
|
||||
RECYCLE_BIN -> deletedMedia.map { File(it.path) }.toTypedArray()
|
||||
else -> File(folder).listFiles() ?: return media
|
||||
}
|
||||
|
||||
val doExtraCheck = context.config.doExtraCheck
|
||||
val showHidden = context.config.shouldShowHidden
|
||||
val dateTakens = if (getProperDateTaken) getFolderDateTakens(folder) else HashMap()
|
||||
|
@ -197,6 +211,12 @@ class MediaFetcher(val context: Context) {
|
|||
if (size <= 0L || (doExtraCheck && !file.exists()))
|
||||
continue
|
||||
|
||||
val path = file.absolutePath
|
||||
if (folder == RECYCLE_BIN) {
|
||||
deletedMedia.firstOrNull { it.path == path }?.apply {
|
||||
media.add(this)
|
||||
}
|
||||
} else {
|
||||
val lastModified = file.lastModified()
|
||||
var dateTaken = lastModified
|
||||
|
||||
|
@ -211,11 +231,11 @@ class MediaFetcher(val context: Context) {
|
|||
else -> TYPE_RAWS
|
||||
}
|
||||
|
||||
val path = file.absolutePath
|
||||
val isFavorite = favoritePaths.contains(path)
|
||||
val medium = Medium(null, filename, path, folder, lastModified, dateTaken, size, type, isFavorite)
|
||||
val medium = Medium(null, filename, path, file.parent, lastModified, dateTaken, size, type, isFavorite, 0L)
|
||||
media.add(medium)
|
||||
}
|
||||
}
|
||||
return media
|
||||
}
|
||||
|
||||
|
@ -270,7 +290,7 @@ class MediaFetcher(val context: Context) {
|
|||
|
||||
val path = Uri.decode(file.uri.toString().replaceFirst("${context.config.OTGTreeUri}/document/${context.config.OTGPartition}%3A", OTG_PATH))
|
||||
val isFavorite = favoritePaths.contains(path)
|
||||
val medium = Medium(null, filename, path, folder, dateModified, dateTaken, size, type, isFavorite)
|
||||
val medium = Medium(null, filename, path, folder, dateModified, dateTaken, size, type, isFavorite, 0L)
|
||||
media.add(medium)
|
||||
}
|
||||
|
||||
|
@ -323,4 +343,82 @@ class MediaFetcher(val context: Context) {
|
|||
result
|
||||
})
|
||||
}
|
||||
|
||||
fun groupMedia(media: ArrayList<Medium>, path: String): ArrayList<ThumbnailItem> {
|
||||
val mediumGroups = LinkedHashMap<String, ArrayList<Medium>>()
|
||||
val pathToCheck = if (path.isEmpty()) SHOW_ALL else path
|
||||
val currentGrouping = context.config.getFolderGrouping(pathToCheck)
|
||||
if (currentGrouping and GROUP_BY_NONE != 0) {
|
||||
return media as ArrayList<ThumbnailItem>
|
||||
}
|
||||
|
||||
val thumbnailItems = ArrayList<ThumbnailItem>()
|
||||
if (context.config.scrollHorizontally) {
|
||||
media.mapTo(thumbnailItems) { it }
|
||||
return thumbnailItems
|
||||
}
|
||||
|
||||
media.forEach {
|
||||
val key = it.getGroupingKey(currentGrouping)
|
||||
if (!mediumGroups.containsKey(key)) {
|
||||
mediumGroups[key] = ArrayList()
|
||||
}
|
||||
mediumGroups[key]!!.add(it)
|
||||
}
|
||||
|
||||
val sortDescending = currentGrouping and GROUP_DESCENDING != 0
|
||||
val sorted = mediumGroups.toSortedMap(if (sortDescending) compareByDescending { it } else compareBy { it })
|
||||
mediumGroups.clear()
|
||||
for ((key, value) in sorted) {
|
||||
mediumGroups[key] = value
|
||||
}
|
||||
|
||||
val today = formatDate(System.currentTimeMillis().toString())
|
||||
val yesterday = formatDate((System.currentTimeMillis() - DAY_SECONDS * 1000).toString())
|
||||
for ((key, value) in mediumGroups) {
|
||||
val sectionKey = getFormattedKey(key, currentGrouping, today, yesterday)
|
||||
thumbnailItems.add(ThumbnailSection(sectionKey))
|
||||
thumbnailItems.addAll(value)
|
||||
}
|
||||
|
||||
return thumbnailItems
|
||||
}
|
||||
|
||||
private fun getFormattedKey(key: String, grouping: Int, today: String, yesterday: String): String {
|
||||
return when {
|
||||
grouping and GROUP_BY_LAST_MODIFIED != 0 || grouping and GROUP_BY_DATE_TAKEN != 0 -> getFinalDate(formatDate(key), today, yesterday)
|
||||
grouping and GROUP_BY_FILE_TYPE != 0 -> getFileTypeString(key)
|
||||
grouping and GROUP_BY_EXTENSION != 0 -> key.toUpperCase()
|
||||
grouping and GROUP_BY_FOLDER != 0 -> context.humanizePath(key)
|
||||
else -> key
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFinalDate(date: String, today: String, yesterday: String): String {
|
||||
return when (date) {
|
||||
today -> context.getString(R.string.today)
|
||||
yesterday -> context.getString(R.string.yesterday)
|
||||
else -> date
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatDate(timestamp: String): String {
|
||||
return if (timestamp.areDigitsOnly()) {
|
||||
val cal = Calendar.getInstance(Locale.ENGLISH)
|
||||
cal.timeInMillis = timestamp.toLong()
|
||||
return DateFormat.format("dd MMM yyyy", cal).toString()
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFileTypeString(key: String): String {
|
||||
val stringId = when (key.toInt()) {
|
||||
TYPE_IMAGES -> R.string.images
|
||||
TYPE_VIDEOS -> R.string.videos
|
||||
TYPE_GIFS -> R.string.gifs
|
||||
else -> R.string.raw_images
|
||||
}
|
||||
return context.getString(stringId)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.arch.persistence.room.Dao
|
|||
import android.arch.persistence.room.Insert
|
||||
import android.arch.persistence.room.OnConflictStrategy.REPLACE
|
||||
import android.arch.persistence.room.Query
|
||||
import com.simplemobiletools.gallery.helpers.RECYCLE_BIN
|
||||
import com.simplemobiletools.gallery.models.Directory
|
||||
|
||||
@Dao
|
||||
|
@ -17,12 +18,15 @@ interface DirectoryDao {
|
|||
@Insert(onConflict = REPLACE)
|
||||
fun insertAll(directories: List<Directory>)
|
||||
|
||||
@Query("DELETE FROM directories WHERE path = :path")
|
||||
@Query("DELETE FROM directories WHERE path = :path COLLATE NOCASE")
|
||||
fun deleteDirPath(path: String)
|
||||
|
||||
@Query("UPDATE OR REPLACE directories SET thumbnail = :thumbnail, media_count = :mediaCnt, last_modified = :lastModified, date_taken = :dateTaken, size = :size, media_types = :mediaTypes WHERE path = :path")
|
||||
@Query("UPDATE OR REPLACE directories SET thumbnail = :thumbnail, media_count = :mediaCnt, last_modified = :lastModified, date_taken = :dateTaken, size = :size, media_types = :mediaTypes WHERE path = :path COLLATE NOCASE")
|
||||
fun updateDirectory(path: String, thumbnail: String, mediaCnt: Int, lastModified: Long, dateTaken: Long, size: Long, mediaTypes: Int)
|
||||
|
||||
@Query("UPDATE directories SET thumbnail = :thumbnail, filename = :name, path = :newPath WHERE path = :oldPath")
|
||||
@Query("UPDATE directories SET thumbnail = :thumbnail, filename = :name, path = :newPath WHERE path = :oldPath COLLATE NOCASE")
|
||||
fun updateDirectoryAfterRename(thumbnail: String, name: String, newPath: String, oldPath: String)
|
||||
|
||||
@Query("DELETE FROM directories WHERE path = \'$RECYCLE_BIN\' COLLATE NOCASE")
|
||||
fun deleteRecycleBin()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package com.simplemobiletools.gallery.interfaces
|
||||
|
||||
import com.simplemobiletools.gallery.models.Directory
|
||||
import java.io.File
|
||||
|
||||
interface DirectoryOperationsListener {
|
||||
fun refreshItems()
|
||||
|
||||
fun deleteFolders(folders: ArrayList<File>)
|
||||
|
||||
fun recheckPinnedFolders()
|
||||
|
||||
fun updateDirectories(directories: ArrayList<Directory>)
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.simplemobiletools.gallery.interfaces
|
||||
|
||||
import com.simplemobiletools.commons.models.FileDirItem
|
||||
|
||||
interface MediaOperationsListener {
|
||||
fun refreshItems()
|
||||
|
||||
fun tryDeleteFiles(fileDirItems: ArrayList<FileDirItem>)
|
||||
|
||||
fun selectedPaths(paths: ArrayList<String>)
|
||||
}
|
|
@ -8,24 +8,36 @@ import com.simplemobiletools.gallery.models.Medium
|
|||
|
||||
@Dao
|
||||
interface MediumDao {
|
||||
@Query("SELECT filename, full_path, parent_path, last_modified, date_taken, size, type, is_favorite FROM media WHERE parent_path = :path")
|
||||
@Query("SELECT filename, full_path, parent_path, last_modified, date_taken, size, type, is_favorite, deleted_ts FROM media WHERE deleted_ts = 0 AND parent_path = :path COLLATE NOCASE")
|
||||
fun getMediaFromPath(path: String): List<Medium>
|
||||
|
||||
@Query("SELECT full_path FROM media WHERE is_favorite = 1")
|
||||
@Query("SELECT filename, full_path, parent_path, last_modified, date_taken, size, type, is_favorite, deleted_ts FROM media WHERE deleted_ts = 0 AND is_favorite = 1")
|
||||
fun getFavorites(): List<Medium>
|
||||
|
||||
@Query("SELECT full_path FROM media WHERE deleted_ts = 0 AND is_favorite = 1")
|
||||
fun getFavoritePaths(): List<String>
|
||||
|
||||
@Query("SELECT filename, full_path, parent_path, last_modified, date_taken, size, type, is_favorite, deleted_ts FROM media WHERE deleted_ts != 0")
|
||||
fun getDeletedMedia(): List<Medium>
|
||||
|
||||
@Insert(onConflict = REPLACE)
|
||||
fun insert(medium: Medium)
|
||||
|
||||
@Insert(onConflict = REPLACE)
|
||||
fun insertAll(media: List<Medium>)
|
||||
|
||||
@Query("DELETE FROM media WHERE full_path = :path")
|
||||
@Query("DELETE FROM media WHERE full_path = :path COLLATE NOCASE")
|
||||
fun deleteMediumPath(path: String)
|
||||
|
||||
@Query("UPDATE OR REPLACE media SET filename = :newFilename, full_path = :newFullPath, parent_path = :newParentPath WHERE full_path = :oldPath")
|
||||
@Query("UPDATE OR REPLACE media SET filename = :newFilename, full_path = :newFullPath, parent_path = :newParentPath WHERE full_path = :oldPath COLLATE NOCASE")
|
||||
fun updateMedium(oldPath: String, newParentPath: String, newFilename: String, newFullPath: String)
|
||||
|
||||
@Query("UPDATE media SET is_favorite = :isFavorite WHERE full_path = :path")
|
||||
@Query("UPDATE media SET is_favorite = :isFavorite WHERE full_path = :path COLLATE NOCASE")
|
||||
fun updateFavorite(path: String, isFavorite: Boolean)
|
||||
|
||||
@Query("UPDATE media SET deleted_ts = :deletedTS WHERE full_path = :path COLLATE NOCASE")
|
||||
fun updateDeleted(path: String, deletedTS: Long)
|
||||
|
||||
@Query("DELETE FROM media WHERE deleted_ts != 0")
|
||||
fun clearRecycleBin()
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import com.simplemobiletools.commons.helpers.SORT_BY_DATE_MODIFIED
|
|||
import com.simplemobiletools.commons.helpers.SORT_BY_NAME
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_PATH
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_SIZE
|
||||
import com.simplemobiletools.gallery.helpers.FAVORITES
|
||||
import com.simplemobiletools.gallery.helpers.RECYCLE_BIN
|
||||
import java.io.Serializable
|
||||
|
||||
@Entity(tableName = "directories", indices = [Index(value = "path", unique = true)])
|
||||
|
@ -36,4 +38,8 @@ data class Directory(
|
|||
sorting and SORT_BY_DATE_MODIFIED != 0 -> modified.formatDate()
|
||||
else -> taken.formatDate()
|
||||
}
|
||||
|
||||
fun areFavorites() = path == FAVORITES
|
||||
|
||||
fun isRecycleBin() = path == RECYCLE_BIN
|
||||
}
|
||||
|
|
|
@ -6,15 +6,14 @@ import android.arch.persistence.room.Index
|
|||
import android.arch.persistence.room.PrimaryKey
|
||||
import com.simplemobiletools.commons.extensions.formatDate
|
||||
import com.simplemobiletools.commons.extensions.formatSize
|
||||
import com.simplemobiletools.commons.extensions.getFilenameExtension
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_DATE_MODIFIED
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_NAME
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_PATH
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_SIZE
|
||||
import com.simplemobiletools.gallery.helpers.TYPE_GIFS
|
||||
import com.simplemobiletools.gallery.helpers.TYPE_IMAGES
|
||||
import com.simplemobiletools.gallery.helpers.TYPE_RAWS
|
||||
import com.simplemobiletools.gallery.helpers.TYPE_VIDEOS
|
||||
import com.simplemobiletools.gallery.helpers.*
|
||||
import java.io.Serializable
|
||||
import java.util.*
|
||||
|
||||
@Entity(tableName = "media", indices = [(Index(value = "full_path", unique = true))])
|
||||
data class Medium(
|
||||
|
@ -26,10 +25,11 @@ data class Medium(
|
|||
@ColumnInfo(name = "date_taken") var taken: Long,
|
||||
@ColumnInfo(name = "size") val size: Long,
|
||||
@ColumnInfo(name = "type") val type: Int,
|
||||
@ColumnInfo(name = "is_favorite") var isFavorite: Boolean) : Serializable {
|
||||
@ColumnInfo(name = "is_favorite") var isFavorite: Boolean,
|
||||
@ColumnInfo(name = "deleted_ts") var deletedTS: Long) : Serializable, ThumbnailItem() {
|
||||
|
||||
companion object {
|
||||
private const val serialVersionUID = -6553149366975455L
|
||||
private const val serialVersionUID = -6553149366975655L
|
||||
}
|
||||
|
||||
fun isGif() = type == TYPE_GIFS
|
||||
|
@ -40,6 +40,8 @@ data class Medium(
|
|||
|
||||
fun isRaw() = type == TYPE_RAWS
|
||||
|
||||
fun isHidden() = name.startsWith('.')
|
||||
|
||||
fun getBubbleText(sorting: Int) = when {
|
||||
sorting and SORT_BY_NAME != 0 -> name
|
||||
sorting and SORT_BY_PATH != 0 -> path
|
||||
|
@ -47,4 +49,29 @@ data class Medium(
|
|||
sorting and SORT_BY_DATE_MODIFIED != 0 -> modified.formatDate()
|
||||
else -> taken.formatDate()
|
||||
}
|
||||
|
||||
fun getGroupingKey(groupBy: Int): String {
|
||||
return when {
|
||||
groupBy and GROUP_BY_LAST_MODIFIED != 0 -> getDayStartTS(modified)
|
||||
groupBy and GROUP_BY_DATE_TAKEN != 0 -> getDayStartTS(taken)
|
||||
groupBy and GROUP_BY_FILE_TYPE != 0 -> type.toString()
|
||||
groupBy and GROUP_BY_EXTENSION != 0 -> name.getFilenameExtension().toLowerCase()
|
||||
groupBy and GROUP_BY_FOLDER != 0 -> parentPath
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun getIsInRecycleBin() = deletedTS != 0L
|
||||
|
||||
private fun getDayStartTS(ts: Long): String {
|
||||
val calendar = Calendar.getInstance(Locale.ENGLISH).apply {
|
||||
timeInMillis = ts
|
||||
set(Calendar.HOUR_OF_DAY, 0)
|
||||
set(Calendar.MINUTE, 0)
|
||||
set(Calendar.SECOND, 0)
|
||||
set(Calendar.MILLISECOND, 0)
|
||||
}
|
||||
|
||||
return calendar.timeInMillis.toString()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
package com.simplemobiletools.gallery.models
|
||||
|
||||
open class ThumbnailItem
|
|
@ -0,0 +1,3 @@
|
|||
package com.simplemobiletools.gallery.models
|
||||
|
||||
data class ThumbnailSection(val title: String) : ThumbnailItem()
|
|
@ -19,7 +19,7 @@ class RefreshMediaReceiver : BroadcastReceiver() {
|
|||
|
||||
Thread {
|
||||
val medium = Medium(null, path.getFilenameFromPath(), path, path.getParentPath(), System.currentTimeMillis(), System.currentTimeMillis(),
|
||||
File(path).length(), getFileType(path), false)
|
||||
File(path).length(), getFileType(path), false, 0L)
|
||||
context.galleryDB.MediumDao().insert(medium)
|
||||
}.start()
|
||||
}
|
||||
|
|
BIN
app/src/main/res/drawable-hdpi/ic_cardboard.png
Normal file
After Width: | Height: | Size: 488 B |
Before Width: | Height: | Size: 680 B After Width: | Height: | Size: 680 B |
BIN
app/src/main/res/drawable-hdpi/ic_explore.png
Normal file
After Width: | Height: | Size: 450 B |
BIN
app/src/main/res/drawable-hdpi/ic_explore_off.png
Normal file
After Width: | Height: | Size: 531 B |
BIN
app/src/main/res/drawable-hdpi/ic_panorama.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
app/src/main/res/drawable-hdpi/ic_slideshow.png
Normal file
After Width: | Height: | Size: 221 B |
BIN
app/src/main/res/drawable-xhdpi/ic_cardboard.png
Normal file
After Width: | Height: | Size: 585 B |
Before Width: | Height: | Size: 812 B After Width: | Height: | Size: 812 B |
BIN
app/src/main/res/drawable-xhdpi/ic_explore.png
Normal file
After Width: | Height: | Size: 569 B |
BIN
app/src/main/res/drawable-xhdpi/ic_explore_off.png
Normal file
After Width: | Height: | Size: 670 B |
BIN
app/src/main/res/drawable-xhdpi/ic_panorama.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_slideshow.png
Normal file
After Width: | Height: | Size: 219 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_cardboard.png
Normal file
After Width: | Height: | Size: 996 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_explore.png
Normal file
After Width: | Height: | Size: 845 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_explore_off.png
Normal file
After Width: | Height: | Size: 979 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_panorama.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_slideshow.png
Normal file
After Width: | Height: | Size: 308 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_cardboard.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 994 B After Width: | Height: | Size: 994 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_explore.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_explore_off.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_panorama.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_slideshow.png
Normal file
After Width: | Height: | Size: 373 B |
33
app/src/main/res/layout/activity_panorama.xml
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/panorama_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#FF000000">
|
||||
|
||||
<com.google.vr.sdk.widgets.pano.VrPanoramaView
|
||||
android:id="@+id/panorama_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/cardboard"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:padding="@dimen/activity_margin"
|
||||
android:src="@drawable/ic_cardboard"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/explore"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:padding="@dimen/activity_margin"
|
||||
android:src="@drawable/ic_explore"/>
|
||||
|
||||
</RelativeLayout>
|
|
@ -649,29 +649,6 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_bottom_actions_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_bottom_actions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/show_at_bottom"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_screen_rotation_holder"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -941,5 +918,144 @@
|
|||
android:text="@string/skip_delete_confirmation"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/bottom_actions_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="@color/divider_grey"
|
||||
android:importantForAccessibility="no"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/bottom_actions_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/bigger_margin"
|
||||
android:layout_marginStart="@dimen/bigger_margin"
|
||||
android:layout_marginTop="@dimen/activity_margin"
|
||||
android:text="@string/bottom_actions"
|
||||
android:textAllCaps="true"
|
||||
android:textSize="@dimen/smaller_text_size"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_bottom_actions_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_bottom_actions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/show_at_bottom"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_manage_bottom_actions_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/settings_manage_bottom_actions"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/manage_bottom_actions"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/recycle_bin_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="@color/divider_grey"
|
||||
android:importantForAccessibility="no"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/recycle_bin_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/bigger_margin"
|
||||
android:layout_marginStart="@dimen/bigger_margin"
|
||||
android:layout_marginTop="@dimen/activity_margin"
|
||||
android:text="@string/recycle_bin"
|
||||
android:textAllCaps="true"
|
||||
android:textSize="@dimen/smaller_text_size"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_use_recycle_bin_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_use_recycle_bin"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/move_items_into_recycle_bin"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_empty_recycle_bin_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/bigger_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/bigger_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/settings_empty_recycle_bin_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toLeftOf="@+id/settings_empty_recycle_bin_size"
|
||||
android:layout_toStartOf="@+id/settings_empty_recycle_bin_size"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingRight="@dimen/medium_margin"
|
||||
android:text="@string/empty_recycle_bin"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/settings_empty_recycle_bin_size"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginEnd="@dimen/small_margin"
|
||||
android:layout_marginRight="@dimen/small_margin"
|
||||
android:background="@null"
|
||||
android:clickable="false"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/splash_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
|
@ -49,8 +49,85 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_delete"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_rotate"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_share"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_rotate"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_rotate_right"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_properties"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_delete"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_properties"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_properties"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_change_orientation"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_rotate"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_change_orientation"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_orientation_auto"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_slideshow"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_properties"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_slideshow"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_slideshow"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_show_on_map"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_change_orientation"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_show_on_map"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_place"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_toggle_file_visibility"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_slideshow"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_toggle_file_visibility"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_hide"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_rename"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_show_on_map"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_rename"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_rename_new"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_toggle_file_visibility"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
|
113
app/src/main/res/layout/dialog_change_grouping.xml
Normal file
|
@ -0,0 +1,113 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/grouping_dialog_scrollview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/grouping_dialog_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/grouping_dialog_radio_grouping"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/medium_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyCompatRadioButton
|
||||
android:id="@+id/grouping_dialog_radio_none"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/medium_margin"
|
||||
android:paddingTop="@dimen/medium_margin"
|
||||
android:text="@string/do_not_group_files"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyCompatRadioButton
|
||||
android:id="@+id/grouping_dialog_radio_last_modified"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/medium_margin"
|
||||
android:paddingTop="@dimen/medium_margin"
|
||||
android:text="@string/by_last_modified"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyCompatRadioButton
|
||||
android:id="@+id/grouping_dialog_radio_date_taken"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/medium_margin"
|
||||
android:paddingTop="@dimen/medium_margin"
|
||||
android:text="@string/by_date_taken"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyCompatRadioButton
|
||||
android:id="@+id/grouping_dialog_radio_file_type"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/medium_margin"
|
||||
android:paddingTop="@dimen/medium_margin"
|
||||
android:text="@string/by_file_type"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyCompatRadioButton
|
||||
android:id="@+id/grouping_dialog_radio_extension"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/medium_margin"
|
||||
android:paddingTop="@dimen/medium_margin"
|
||||
android:text="@string/by_extension"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyCompatRadioButton
|
||||
android:id="@+id/grouping_dialog_radio_folder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/medium_margin"
|
||||
android:paddingTop="@dimen/medium_margin"
|
||||
android:text="@string/by_folder"/>
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
<include
|
||||
layout="@layout/divider"/>
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/grouping_dialog_radio_order"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:paddingBottom="@dimen/medium_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyCompatRadioButton
|
||||
android:id="@+id/grouping_dialog_radio_ascending"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/medium_margin"
|
||||
android:paddingTop="@dimen/medium_margin"
|
||||
android:text="@string/ascending"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyCompatRadioButton
|
||||
android:id="@+id/grouping_dialog_radio_descending"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/medium_margin"
|
||||
android:paddingTop="@dimen/medium_margin"
|
||||
android:text="@string/descending"/>
|
||||
</RadioGroup>
|
||||
|
||||
<include
|
||||
android:id="@+id/use_for_this_folder_divider"
|
||||
layout="@layout/divider"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/grouping_dialog_use_for_this_folder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/use_for_this_folder"/>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
106
app/src/main/res/layout/dialog_manage_bottom_actions.xml
Normal file
|
@ -0,0 +1,106 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/manage_bottom_actions_scrollview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/manage_bottom_actions_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/medium_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_bottom_actions_toggle_favorite"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/toggle_favorite"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_bottom_actions_edit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/edit"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_bottom_actions_share"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/share"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_bottom_actions_delete"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/delete"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_bottom_actions_rotate"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/rotate"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_bottom_actions_properties"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/properties"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_bottom_actions_change_orientation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/change_orientation"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_bottom_actions_slideshow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/slideshow"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_bottom_actions_show_on_map"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/show_on_map"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_bottom_actions_toggle_visibility"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/toggle_file_visibility"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_bottom_actions_rename"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/rename"/>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
|
@ -18,6 +18,16 @@
|
|||
android:layout_height="match_parent"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<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="@android:color/transparent"
|
||||
android:padding="@dimen/big_margin"
|
||||
android:src="@drawable/ic_panorama"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/photo_details"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -6,12 +6,11 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<SurfaceView
|
||||
<TextureView
|
||||
android:id="@+id/video_surface"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:background="@android:color/transparent"/>
|
||||
android:layout_centerInParent="true"/>
|
||||
|
||||
<com.simplemobiletools.gallery.helpers.MediaSideScroll
|
||||
android:id="@+id/video_volume_controller"
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignRight="@+id/medium_thumbnail"
|
||||
android:background="@drawable/gradient_background"
|
||||
android:ellipsize="end"
|
||||
android:gravity="bottom"
|
||||
android:maxLines="3"
|
||||
android:paddingBottom="@dimen/small_margin"
|
||||
|
|
9
app/src/main/res/layout/thumbnail_section.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/thumbnail_section"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="false"
|
||||
android:padding="@dimen/activity_margin"
|
||||
android:textSize="@dimen/bigger_text_size"/>
|
|
@ -23,7 +23,7 @@
|
|||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/cab_rename"
|
||||
android:icon="@drawable/ic_rename"
|
||||
android:icon="@drawable/ic_rename_new"
|
||||
android:title="@string/rename"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
|
@ -36,6 +36,14 @@
|
|||
android:icon="@drawable/ic_unhide"
|
||||
android:title="@string/unhide_folder"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/cab_empty_recycle_bin"
|
||||
android:title="@string/empty_recycle_bin"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/cab_empty_disable_recycle_bin"
|
||||
android:title="@string/empty_and_disable_recycle_bin"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/cab_exclude"
|
||||
android:title="@string/exclude"
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/cab_rename"
|
||||
android:icon="@drawable/ic_rename"
|
||||
android:icon="@drawable/ic_rename_new"
|
||||
android:title="@string/rename"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
|
@ -46,6 +46,20 @@
|
|||
android:icon="@drawable/ic_select_all"
|
||||
android:title="@string/select_all"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/cab_add_to_favorites"
|
||||
android:icon="@drawable/ic_star_off"
|
||||
android:title="@string/add_to_favorites"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/cab_remove_from_favorites"
|
||||
android:icon="@drawable/ic_star_on"
|
||||
android:title="@string/remove_from_favorites"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/cab_restore_recycle_bin_files"
|
||||
android:title="@string/restore_selected_files"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/cab_open_with"
|
||||
android:title="@string/open_with"
|
||||
|
|
|
@ -22,6 +22,18 @@
|
|||
android:icon="@drawable/ic_filter"
|
||||
android:title="@string/filter_media"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/empty_recycle_bin"
|
||||
android:title="@string/empty_recycle_bin"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/empty_disable_recycle_bin"
|
||||
android:title="@string/empty_and_disable_recycle_bin"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/restore_all_files"
|
||||
android:title="@string/restore_all_files"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/folder_view"
|
||||
android:title="@string/folder_view"
|
||||
|
@ -31,6 +43,10 @@
|
|||
android:icon="@drawable/ic_camera"
|
||||
android:title="@string/open_camera"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/group"
|
||||
android:title="@string/group_by"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/change_view_type"
|
||||
android:title="@string/change_view_type"
|
||||
|
|
|
@ -45,13 +45,26 @@
|
|||
android:title="@string/remove_from_favorites"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/menu_lock_orientation"
|
||||
android:title="@string/lock_orientation"
|
||||
android:id="@+id/menu_restore_file"
|
||||
android:title="@string/restore_this_file"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/menu_slideshow"
|
||||
android:title="@string/slideshow"
|
||||
app:showAsAction="never"/>
|
||||
android:id="@+id/menu_change_orientation"
|
||||
android:icon="@drawable/ic_orientation_auto"
|
||||
android:title="@string/change_orientation"
|
||||
app:showAsAction="ifRoom">
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/menu_force_portrait"
|
||||
android:title="@string/force_portrait"/>
|
||||
<item
|
||||
android:id="@+id/menu_force_landscape"
|
||||
android:title="@string/force_landscape"/>
|
||||
<item
|
||||
android:id="@+id/menu_default_orientation"
|
||||
android:title="@string/use_default_orientation"/>
|
||||
</menu>
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/menu_copy_to"
|
||||
android:title="@string/copy_to"
|
||||
|
@ -81,16 +94,21 @@
|
|||
android:icon="@drawable/ic_edit"
|
||||
android:title="@string/edit"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/menu_rename"
|
||||
android:icon="@drawable/ic_rename"
|
||||
android:title="@string/rename"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/menu_properties"
|
||||
android:icon="@drawable/ic_info"
|
||||
android:title="@string/properties"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/menu_slideshow"
|
||||
android:icon="@drawable/ic_slideshow"
|
||||
android:title="@string/slideshow"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/menu_rename"
|
||||
android:icon="@drawable/ic_rename_new"
|
||||
android:title="@string/rename"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/menu_show_on_map"
|
||||
android:title="@string/show_on_map"
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">فلتر الميديا</string>
|
||||
|
@ -158,6 +162,12 @@
|
|||
<string name="thumbnails">المصغرات</string>
|
||||
<string name="fullscreen_media">وسائط ملء الشاشة</string>
|
||||
<string name="extended_details">تفاصيل موسعة</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">كيف يمكنني جعل الاستوديو البسيط معرض الأجهزة الافتراضي؟</string>
|
||||
|
@ -180,6 +190,8 @@
|
|||
<string name="faq_9_text">نعم ، هناك تبديل في الإعدادات يقول \"استبدل صورًا ذات زووم عميق بجودة أفضل منها\" ، يمكنك استخدام ذلك. سيؤدي ذلك إلى تحسين جودة الصور ، ولكن ستظهر بشكل واضح عند محاولة التكبير كثيرًا.</string>
|
||||
<string name="faq_10_title">هل يمكنني قص الصور باستخدام هذا التطبيق؟</string>
|
||||
<string name="faq_10_text">نعم ، يمكنك اقتصاص الصور في المحرر ، عن طريق سحب زوايا الصورة. يمكنك الوصول إلى المحرر إما عن طريق الضغط لفترة طويلة على صورة مصغرة وتحديد تحرير ، أو تحديد تحرير من العرض بملء الشاشة.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Brillantor</string>
|
||||
<string name="lock_orientation">Bloquejar orientació</string>
|
||||
<string name="unlock_orientation">Desbloquejar orientació</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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtre d\'arxius</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Miniatures</string>
|
||||
<string name="fullscreen_media">Mitjans a pantalla completa</string>
|
||||
<string name="extended_details">Detalls estesos</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Com puc fer que Simple Gallery sigui la galeria de dispositius predeterminada?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Sí, hi ha un commutador a la configuració que diu \"Substituïu imatges ampliades i de gran qualitat\", podeu fer-ho. Millora la qualitat de les imatges, però es borraran una vegada que intenteu fer zoom massa.</string>
|
||||
<string name="faq_10_title">Puc retallar imatges amb aquesta aplicació?</string>
|
||||
<string name="faq_10_text">Sí, pots retallar imatges a l\'editor, arrossegant les cantonades de la imatge. Pots accedir a l\'editor prement una miniatura d\'imatge i seleccionant Edita o seleccionant Edita des de la visualització de pantalla completa.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Brightness</string>
|
||||
<string name="lock_orientation">Lock orientation</string>
|
||||
<string name="unlock_orientation">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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filter media</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Thumbnails</string>
|
||||
<string name="fullscreen_media">Fullscreen media</string>
|
||||
<string name="extended_details">Extended details</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">How can I make Simple Gallery the default device gallery?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much.</string>
|
||||
<string name="faq_10_title">Can I crop images with this app?</string>
|
||||
<string name="faq_10_text">Yes, you can crop images in the editor, by dragging the image corners. You can get to the editor either by long pressing an image thumbnail and selecting Edit, or selecting Edit from the fullscreen view.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Brightness</string>
|
||||
<string name="lock_orientation">Lås orientering</string>
|
||||
<string name="unlock_orientation">Lås orientering op</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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtrer medier</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Thumbnails</string>
|
||||
<string name="fullscreen_media">Fullscreen media</string>
|
||||
<string name="extended_details">Flere oplysninger</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">How can I make Simple Gallery the default device gallery?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much.</string>
|
||||
<string name="faq_10_title">Can I crop images with this app?</string>
|
||||
<string name="faq_10_text">Yes, you can crop images in the editor, by dragging the image corners. You can get to the editor either by long pressing an image thumbnail and selecting Edit, or selecting Edit from the fullscreen view.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Helligkeit</string>
|
||||
<string name="lock_orientation">Bildschirmausrichtung sperren</string>
|
||||
<string name="unlock_orientation">Bildschirmausrichtung entsperren</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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filter</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Thumbnails</string>
|
||||
<string name="fullscreen_media">Vollbild-Medien</string>
|
||||
<string name="extended_details">Erweiterte Details</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Wie kann ich Schlichte Galerie als Standardanwendung auswählen?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Ja, es gibt einen Schalter in den Einstellungen gekennzeichnet mit \"Stark zoombare Bilder durch Bilder mit hoher Qualität ersetzen\". Dieser wird die Bildqualität verbessern, aber sie werden bei sehr hoher Zoomstufe unscharf.</string>
|
||||
<string name="faq_10_title">Kann ich mit dieser App Bilder zuschneiden?</string>
|
||||
<string name="faq_10_text">Ja, du kannst Bilder über das Ziehen der Bildecken im Editor zuschneiden. Du gelangst zum Editor indem du lange auf ein Vorschaubild drückst und Bearbeiten auswählst oder durch Auswählen von Bearbeiten in der Vollbildansicht.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Φιλτράρισμα πολυμέσων</string>
|
||||
|
@ -155,6 +159,12 @@
|
|||
<string name="thumbnails">Εικονίδια</string>
|
||||
<string name="fullscreen_media">Πολυμέσα πλήρους οθόνης</string>
|
||||
<string name="extended_details">Περισσότερες λεπτομέρειες</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Πώς μπορώ να κάνω το Simple Gallery προκαθορισμένη εφαρμογή συλλογής πολυμέσων;</string>
|
||||
|
@ -177,6 +187,8 @@
|
|||
Αυτό θα κάνει ορατούς μόνο τους επιλεγμένους φακέλους, καθώς η εξαίρεση και η συμπερίληψη λειτουργούν αναδρομικά και αν ενας φάκελος ανήκει και στα δύο, θα εμφανιστεί.</string>
|
||||
<string name="faq_9_title">Οι εικόνες πλήρους οθόνης έχουν κάποια περίεργα σημάδια. Μπορώ κάπως να βελτιώσω την ποιότητα;</string>
|
||||
<string name="faq_9_text">Ναι. Υπάρχει ένας διακόπτης στις Ρυθμίσεις με το κείμενο \"Αντικατάσταση των φωτογραφιών που απαιτούν ζούμ με άλλες καλύτερης ποιότητας\". Μπορείτε να χρησιμοποιήσετε αυτό. Θα βελτιώσει την ποιότητα των φωτογραφιών, αλλά θα θολώσουν στο μεγάλο ζουμ.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Brillo</string>
|
||||
<string name="lock_orientation">Bloquear orientación</string>
|
||||
<string name="unlock_orientation">Desbloquear orientación</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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtro de medios</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Miniaturas</string>
|
||||
<string name="fullscreen_media">Medios a pantalla compelta</string>
|
||||
<string name="extended_details">Detalles ampliados</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">¿Cómo puedo hacer que Simple Gallery sea la galería de dispositivos predeterminada?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Sí, hay una alternancia en Configuración que dice \"Reemplazar imágenes con zoom profundo con las de mejor calidad\", puedes usar eso. Mejorará la calidad de las imágenes, pero se volverán borrosas una vez que intente ampliar demasiado.</string>
|
||||
<string name="faq_10_title">¿Puedo recortar imágenes con esta aplicación?</string>
|
||||
<string name="faq_10_text">Sí, puede recortar imágenes en el editor arrastrando las esquinas de la imagen. Puede acceder al editor pulsando prolongadamente una imagen en miniatura y seleccionando Editar, o seleccionando Editar en la vista de pantalla completa.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Kirkkaus</string>
|
||||
<string name="lock_orientation">Lukitse näytönkierto</string>
|
||||
<string name="unlock_orientation">Vapauta näytönkierto</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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Suodata media</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Esikatselukuvat</string>
|
||||
<string name="fullscreen_media">Täyden näytön media</string>
|
||||
<string name="extended_details">Yksityiskohtaiset tiedot</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Miten voin tehdä Simple Gallerystä oletusgalleriasovelluksen?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much.</string>
|
||||
<string name="faq_10_title">Can I crop images with this app?</string>
|
||||
<string name="faq_10_text">Yes, you can crop images in the editor, by dragging the image corners. You can get to the editor either by long pressing an image thumbnail and selecting Edit, or selecting Edit from the fullscreen view.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<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">Force landscape</string>
|
||||
<string name="use_default_orientation">Use default orientation</string>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtrer les médias</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Vignettes</string>
|
||||
<string name="fullscreen_media">Média plein écran</string>
|
||||
<string name="extended_details">Détails supplémentaires</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Comment faire de Simple Galerie ma galerie par défaut ?</string>
|
||||
|
@ -177,6 +187,8 @@
|
|||
<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_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">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Brillo</string>
|
||||
<string name="lock_orientation">Fixar orientación</string>
|
||||
<string name="unlock_orientation">Desbloquear orientación</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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtrar medios</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Iconas</string>
|
||||
<string name="fullscreen_media">Medios a pantalla completa</string>
|
||||
<string name="extended_details">Detalles ampliados</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Cómo podo facer que Simple Gallery sexa a galería por omisión no dispositivo?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Si, hai unha opción en Axustes que di \"Substituír imaxes con un gran zoom con imaxes de mellor calidade\", pode usar eso. mellorará a calidade das imaxes, mais farase máis borrosaxa si intenta facer moito zoom.</string>
|
||||
<string name="faq_10_title">Can I crop images with this app?</string>
|
||||
<string name="faq_10_text">Yes, you can crop images in the editor, by dragging the image corners. You can get to the editor either by long pressing an image thumbnail and selecting Edit, or selecting Edit from the fullscreen view.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Svjetlina</string>
|
||||
<string name="lock_orientation">Zaključaj rotaciju</string>
|
||||
<string name="unlock_orientation">Otključaj rotaciju</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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtriranje medija</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Sličice</string>
|
||||
<string name="fullscreen_media">Mediji na cijelom zaslonu</string>
|
||||
<string name="extended_details">Proširene pojedinosti</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Kako mogu postaviti Jednostavnu galeriju kao zadanu galeriju uređaja?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Da, u "Postavkama" postoji opcija "Zamjena duboko zumiranih slika s kvalitetnijim slikama", ali slike će biti zamućene ako zumirate previše.</string>
|
||||
<string name="faq_10_title">Mogu li izrezati slike pomoću ove aplikacije?</string>
|
||||
<string name="faq_10_text">Da, možete obrezati slike u uređivaču povlačenjem uglova. Možete doći do uređivača dugim pritiskom na minijaturu slike i odabirom Uređivanje ili odabirom Uredi iz prikaza preko cijelog zaslona.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Brightness</string>
|
||||
<string name="lock_orientation">Lock orientation</string>
|
||||
<string name="unlock_orientation">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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filter media</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Thumbnails</string>
|
||||
<string name="fullscreen_media">Fullscreen media</string>
|
||||
<string name="extended_details">Extended details</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">How can I make Simple Gallery the default device gallery?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much.</string>
|
||||
<string name="faq_10_title">Can I crop images with this app?</string>
|
||||
<string name="faq_10_text">Yes, you can crop images in the editor, by dragging the image corners. You can get to the editor either by long pressing an image thumbnail and selecting Edit, or selecting Edit from the fullscreen view.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<string name="unpin_folder">Sblocca cartella</string>
|
||||
<string name="pin_to_the_top">Fissa in alto</string>
|
||||
<string name="show_all">Mostra tutti i contenuti</string>
|
||||
<string name="all_folders">Tutti i media</string>
|
||||
<string name="all_folders">Tutte le cartelle</string>
|
||||
<string name="folder_view">Visualizza a cartelle</string>
|
||||
<string name="other_folder">Altra cartella</string>
|
||||
<string name="show_on_map">Mostra sulla mappa</string>
|
||||
|
@ -24,13 +24,17 @@
|
|||
<string name="brightness">Luminosità</string>
|
||||
<string name="lock_orientation">Blocca orientamento</string>
|
||||
<string name="unlock_orientation">Sblocca orientamento</string>
|
||||
<string name="change_orientation">Cambia orientamento</string>
|
||||
<string name="force_portrait">Forza verticale</string>
|
||||
<string name="force_landscape">Forza orizzontale</string>
|
||||
<string name="use_default_orientation">Usa l'orientamento predefinito</string>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtra i media</string>
|
||||
<string name="images">Immagini</string>
|
||||
<string name="videos">Video</string>
|
||||
<string name="gifs">GIF</string>
|
||||
<string name="raw_images">RAW images</string>
|
||||
<string name="raw_images">Immagini RAW</string>
|
||||
<string name="no_media_with_filters">Nessun file trovato per il filtro selezionato.</string>
|
||||
<string name="change_filters_underlined"><u>Cambia filtro</u></string>
|
||||
|
||||
|
@ -111,16 +115,16 @@
|
|||
<string name="change_view_type">Cambia modalità visualizzazione</string>
|
||||
<string name="grid">Griglia</string>
|
||||
<string name="list">Elenco</string>
|
||||
<string name="group_direct_subfolders">Group direct subfolders</string>
|
||||
<string name="group_direct_subfolders">Raggruppa sottocartelle dirette</string>
|
||||
|
||||
<!-- Grouping at media thumbnails -->
|
||||
<string name="group_by">Group by</string>
|
||||
<string name="do_not_group_files">Do not group files</string>
|
||||
<string name="by_folder">Folder</string>
|
||||
<string name="by_last_modified">Last modified</string>
|
||||
<string name="by_date_taken">Date taken</string>
|
||||
<string name="by_file_type">File type</string>
|
||||
<string name="by_extension">Extension</string>
|
||||
<string name="group_by">Raggruppa per</string>
|
||||
<string name="do_not_group_files">Non raggruppare i file</string>
|
||||
<string name="by_folder">Cartella</string>
|
||||
<string name="by_last_modified">Ultima modifica</string>
|
||||
<string name="by_date_taken">Data creazione</string>
|
||||
<string name="by_file_type">Tipo di file</string>
|
||||
<string name="by_extension">Estensione</string>
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="autoplay_videos">Riproduci i video automaticamente</string>
|
||||
|
@ -148,12 +152,18 @@
|
|||
<string name="replace_zoomable_images">Sostituisci le immagini ingrandibili a fondo con altre di migliore qualità</string>
|
||||
<string name="hide_extended_details">Nascondi i dettagli estesi quando la barra di stato è nascosta</string>
|
||||
<string name="do_extra_check">Fai un controllo ulteriore per evitare di mostrare file non validi</string>
|
||||
<string name="show_at_bottom">Show some action buttons at the bottom of the screen</string>
|
||||
<string name="show_at_bottom">Mostra alcuni pulsanti azione in fondo allo schermo</string>
|
||||
|
||||
<!-- Setting sections -->
|
||||
<string name="thumbnails">Miniature</string>
|
||||
<string name="fullscreen_media">Media a schermo intero</string>
|
||||
<string name="extended_details">Dettagli estesi</string>
|
||||
<string name="bottom_actions">Azioni inferiori</string>
|
||||
|
||||
<!-- Bottom actions -->
|
||||
<string name="manage_bottom_actions">Gestisci la visibilità delle azioni</string>
|
||||
<string name="toggle_favorite">Attiva / disattiva preferito</string>
|
||||
<string name="toggle_file_visibility">Attiva / disattiva la visibilità dei file</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Come posso impostare Simple Gallery come galleria predefinita del dispositivo?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Sì, c\'è un\'opzione nelle impostazioni che dice \"Sostituisci le immagini ingrandibili a fondo con altre di migliore qualità\", puoi usare quella. Ciò migliorerà la qualità delle immagini, ma saranno sfuocate quando proverai a ingrandirle troppo.</string>
|
||||
<string name="faq_10_title">Posso ritagliare le immagini con questa app?</string>
|
||||
<string name="faq_10_text">Sì, puoi ritagliare le immagini nell\'editor, trascinando gli angoli dell\'immagine. Puoi usare l\'editor sia premendo a lungo la miniatura di un\'immagine e selezionando Modifica, o selezionando Modifica mentre la vedi a schermo intero.</string>
|
||||
<string name="faq_11_title">Posso raggruppare in qualche modo le miniature dei file?</string>
|
||||
<string name="faq_11_text">Certo, usa il menu \"Raggruppa per\" mentre visualizzi le miniature. Puoi raggruppare i file con diversi criteri, incluso la data di creazione. Se utilizzi la funzione \"Mostra tutti i contenuti\" puoi anche raggrupparli per cartelle.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">表示するメディアの種類</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">サムネイル</string>
|
||||
<string name="fullscreen_media">メディアのみ</string>
|
||||
<string name="extended_details">詳細も表示する</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">How can I make Simple Gallery the default device gallery?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much.</string>
|
||||
<string name="faq_10_title">Can I crop images with this app?</string>
|
||||
<string name="faq_10_text">Yes, you can crop images in the editor, by dragging the image corners. You can get to the editor either by long pressing an image thumbnail and selecting Edit, or selecting Edit from the fullscreen view.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">미디어 필터 설정</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">섬네일</string>
|
||||
<string name="fullscreen_media">미디어 전체화면</string>
|
||||
<string name="extended_details">확장 된 세부 정보</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">How can I make Simple Gallery the default device gallery?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much.</string>
|
||||
<string name="faq_10_title">Can I crop images with this app?</string>
|
||||
<string name="faq_10_text">Yes, you can crop images in the editor, by dragging the image corners. You can get to the editor either by long pressing an image thumbnail and selecting Edit, or selecting Edit from the fullscreen view.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="do_not_ask_again">Šiame seanse daugiau neklausti</string>
|
||||
<string name="lock_orientation">Užrakinti orientaciją</string>
|
||||
<string name="unlock_orientation">Atrakinti orientaciją</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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtruoti mediją</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Miniatiūros</string>
|
||||
<string name="fullscreen_media">Viso ekrano medija</string>
|
||||
<string name="extended_details">Išsami informacija</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Kaip galiu padaryti paprastą galeriją kaip numatytąją įrenginio galeriją?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Taip, "Nustatymuose" perjunkite \ "Pakeisti giliuosius, patobulintus vaizdus geresnės kokybės vaizdais \", galite tai naudoti. Tai pagerins vaizdų kokybę, tačiau kai jūs pabandysite per daug padidinti vaizdą, jie bus neryškūs.</string>
|
||||
<string name="faq_10_title">Ar galiu apkarpyti vaizdus naudojant šią programėlę?</string>
|
||||
<string name="faq_10_text">Taip, redaguodami vaizdus, galite juos apkarpyti, vilkdami vaizdo kampus. Galite patekti į redaktorių ilgai paspaudę vaizdo miniatiūrą ir pasirinkę "Redaguoti" arba iš viso ekrano rodinio pasirinkę "Redaguoti".</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Lysstyrke</string>
|
||||
<string name="lock_orientation">Lås skjermorientering</string>
|
||||
<string name="unlock_orientation">Lås opp skjermorientering</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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtrer media</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Minibilder</string>
|
||||
<string name="fullscreen_media">Mediavisning</string>
|
||||
<string name="extended_details">Utvidede detaljer</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">How can I make Simple Gallery the default device gallery?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much.</string>
|
||||
<string name="faq_10_title">Can I crop images with this app?</string>
|
||||
<string name="faq_10_text">Yes, you can crop images in the editor, by dragging the image corners. You can get to the editor either by long pressing an image thumbnail and selecting Edit, or selecting Edit from the fullscreen view.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Helderheid</string>
|
||||
<string name="lock_orientation">Schermoriëntatie vergrendelen</string>
|
||||
<string name="unlock_orientation">Schermoriëntatie ontgrendelen</string>
|
||||
<string name="change_orientation">Schermoriëntatie wijzigen</string>
|
||||
<string name="force_portrait">Portretmodus forceren</string>
|
||||
<string name="force_landscape">Landschapsmodus forceren</string>
|
||||
<string name="use_default_orientation">Standaardmodus gebruiken</string>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Media filteren</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Miniatuurvoorbeelden</string>
|
||||
<string name="fullscreen_media">Volledig scherm</string>
|
||||
<string name="extended_details">Uitgebreide informatie</string>
|
||||
<string name="bottom_actions">Acties onderaan het scherm</string>
|
||||
|
||||
<!-- Bottom actions -->
|
||||
<string name="manage_bottom_actions">Actieknoppen onderaan beheren</string>
|
||||
<string name="toggle_favorite">Als favoriet instellen</string>
|
||||
<string name="toggle_file_visibility">Bestand tonen/verbergen</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">How can I make Simple Gallery the default device gallery?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much.</string>
|
||||
<string name="faq_10_title">Can I crop images with this app?</string>
|
||||
<string name="faq_10_text">Yes, you can crop images in the editor, by dragging the image corners. You can get to the editor either by long pressing an image thumbnail and selecting Edit, or selecting Edit from the fullscreen view.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<string name="hidden">(ukryty)</string>
|
||||
<string name="excluded">(wykluczony)</string>
|
||||
<string name="pin_folder">Przypnij folder</string>
|
||||
<string name="unpin_folder">Wypakuj folder</string>
|
||||
<string name="unpin_folder">Odepnij folder</string>
|
||||
<string name="pin_to_the_top">Przypnij na górze</string>
|
||||
<string name="show_all">Pokaż wszystko</string>
|
||||
<string name="all_folders">Wszystkie foldery</string>
|
||||
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Jasność</string>
|
||||
<string name="lock_orientation">Zablokuj orientację ekranu</string>
|
||||
<string name="unlock_orientation">Odblokuj orientację ekranu</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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtruj multimedia</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Miniatury</string>
|
||||
<string name="fullscreen_media">Widok pełnoekranowy</string>
|
||||
<string name="extended_details">Dodatkowe szczegóły</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Jak mogę ustawić tą aplikację jako domyślną aplikację galerii?</string>
|
||||
|
@ -173,9 +183,11 @@
|
|||
<string name="faq_8_title">Co jeśli chcę widzieć tylko.wybrane foldery?</string>
|
||||
<string name="faq_8_text">Przejdź do sekcji z wykluczonymi folderami w ustawieniach aplikacji, dodaj tam folder główny (\"/\"), a następnie dodaj pożądane foldery w sekcji z dołączonymi folderami.</string>
|
||||
<string name="faq_9_title">Zdjęcia w widoku pełnoekranowym mają dziwne artefakty. Jak mogę to naprawić?</string>
|
||||
<string name="faq_9_text">U ustawieniach aplikacji włącz opcję \'Zamieniaj powiększalne obrazy na te o lepszej jakości\'. Poprawi ona jakość zdjęć, jednak przy bardzo dużych powiększeniach mogą się stać one zbyt rozmazane.</string>
|
||||
<string name="faq_9_text">W ustawieniach aplikacji włącz opcję \'Zamieniaj powiększalne obrazy na te o lepszej jakości\'. Poprawi ona jakość zdjęć, jednak przy bardzo dużych powiększeniach mogą się stać one zbyt rozmazane.</string>
|
||||
<string name="faq_10_title">Czy mogę w tej aplikacji przycinać obrazy?</string>
|
||||
<string name="faq_10_text">Tak, możesz to zrobić w edytorze, przeciągając krawędzie obrazu. Edytor otworzysz przytrzymując miniaturę obrazu i wybierając opcję \'Edytuj\', bądź wybierając tą samą opcję w menu pełnoekranowym.</string>
|
||||
<string name="faq_11_title">Czy mogę jakoś grupować miniatury plików?</string>
|
||||
<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>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Brilho</string>
|
||||
<string name="lock_orientation">Travar orientação</string>
|
||||
<string name="unlock_orientation">Destravar orientação</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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtrar mídia</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Miniaturas</string>
|
||||
<string name="fullscreen_media">Mídia em tela cheia</string>
|
||||
<string name="extended_details">Detalhes extendidos</string>
|
||||
<string name="bottom_actions">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>v
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">How can I make Simple Gallery the default device gallery?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much.</string>
|
||||
<string name="faq_10_title">Can I crop images with this app?</string>
|
||||
<string name="faq_10_text">Yes, you can crop images in the editor, by dragging the image corners. You can get to the editor either by long pressing an image thumbnail and selecting Edit, or selecting Edit from the fullscreen view.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Brilho</string>
|
||||
<string name="lock_orientation">Bloquear orientação</string>
|
||||
<string name="unlock_orientation">Desbloquear orientação</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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtrar multimédia</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Miniaturas</string>
|
||||
<string name="fullscreen_media">Multimédia em ecrã completo</string>
|
||||
<string name="extended_details">Detalhes extra</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">How can I make Simple Gallery the default device gallery?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much.</string>
|
||||
<string name="faq_10_title">Can I crop images with this app?</string>
|
||||
<string name="faq_10_text">Yes, you can crop images in the editor, by dragging the image corners. You can get to the editor either by long pressing an image thumbnail and selecting Edit, or selecting Edit from the fullscreen view.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Фильтр медиа</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Миниатюры</string>
|
||||
<string name="fullscreen_media">Просмотр медиафайлов</string>
|
||||
<string name="extended_details">Подробности</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Как сделать Simple Gallery галереей по умолчанию?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Да, в настройках есть переключатель \"Заменять масштабируемые изображения высококачественными\", использовуйте его. Это улучшит качество изображений, но они будут размыты, если вы попытаетесь сильно увеличить масштаб отображения.</string>
|
||||
<string name="faq_10_title">Можно ли обрезать изображения с помощью данного приложения?</string>
|
||||
<string name="faq_10_text">Да, вы можете обрезать изображения в редакторе, перетаскивая за углы. К редактированию можно перейти, выбрав соответсвующий пункт в меню, открывающемуся длительным нажатием на миниатюру или изображение в полноэкранном режиме.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Jas</string>
|
||||
<string name="lock_orientation">Uzamknúť otočenie obrazovky</string>
|
||||
<string name="unlock_orientation">Odomknúť otočenie obrazovky</string>
|
||||
<string name="change_orientation">Zmeniť otočenie obrazovky</string>
|
||||
<string name="force_portrait">Vynútiť orientáciu na výšku</string>
|
||||
<string name="force_landscape">Vynútiť orientáciu na šírku</string>
|
||||
<string name="use_default_orientation">Použiť predvolenú orientáciu</string>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filter médií</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Náhľady</string>
|
||||
<string name="fullscreen_media">Celoobrazovkový režim</string>
|
||||
<string name="extended_details">Rozšírené vlastnosti</string>
|
||||
<string name="bottom_actions">Spodné akčné tlačidlá</string>
|
||||
|
||||
<!-- Bottom actions -->
|
||||
<string name="manage_bottom_actions">Upraviť viditeľné spodné akčné tlačidlá</string>
|
||||
<string name="toggle_favorite">Prepnutie obľúbenosti</string>
|
||||
<string name="toggle_file_visibility">Prepnutie viditeľnosti súboru</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Ako viem spraviť Jednoduchú Galériu predvolenou galériou zariadenia?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Áno, v nastaveniach je prepínač s textom \"Nahradiť hlboko priblížiteľné obrázky s obrázkami s lepšou kvalitou\", môžete ho skúsiť. Spôsobí to vyššiu kvalitu obrázkov, po priblížení sa ale budú rozmazávať oveľa skôr.</string>
|
||||
<string name="faq_10_title">Dá sa s touto aplikáciou orezať obrázky?</string>
|
||||
<string name="faq_10_text">Áno, orezanie je možné v editore, potiahnutím rohov obrázkov. Do editoru sa môžete dostať buď dlhým podržaním náhľadu obrázku a zvolením menu položky Upraviť, alebo zvolením Upraviť pri celoobrazovkovom režime.</string>
|
||||
<string name="faq_11_title">Viem nejakým spôsobom zoskupiť náhľady súborov?</string>
|
||||
<string name="faq_11_text">Áno, použitím funkcie \"Zoskupiť podľa\" na menu obrazovky s náhľadmi. Zoskupenie je možné na základe rozličných kritérií vrátane Dátumu vytvorenia. Ak použijete funkciu \"Zobraziť obsah všetkých priečinkov\", viete ich zoskupiť aj podľa priečinkov.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<string name="brightness">Ljusstyrka</string>
|
||||
<string name="lock_orientation">Aktivera rotationslås</string>
|
||||
<string name="unlock_orientation">Inaktivera rotationslås</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>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtrera media</string>
|
||||
|
@ -154,6 +158,12 @@
|
|||
<string name="thumbnails">Miniatyrer</string>
|
||||
<string name="fullscreen_media">Visning av media i helskärmsläge</string>
|
||||
<string name="extended_details">Utökad information</string>
|
||||
<string name="bottom_actions">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>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">How can I make Simple Gallery the default device gallery?</string>
|
||||
|
@ -178,6 +188,8 @@
|
|||
<string name="faq_9_text">Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much.</string>
|
||||
<string name="faq_10_title">Can I crop images with this app?</string>
|
||||
<string name="faq_10_text">Yes, you can crop images in the editor, by dragging the image corners. You can get to the editor either by long pressing an image thumbnail and selecting Edit, or selecting Edit from the fullscreen view.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|