Merge pull request #4 from SimpleMobileTools/master

update
This commit is contained in:
solokot 2017-11-19 23:27:38 +03:00 committed by GitHub
commit 5ac1fdb787
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 676 additions and 872 deletions

View file

@ -1,6 +1,22 @@
Changelog
==========
Version 2.18.1 *(2017-11-16)*
----------------------------
* Fixed some double-tap zoom issues
* Misc smaller fixes and improvements here and there
Version 2.18.0 *(2017-11-09)*
----------------------------
* Added an option to use english language on non-english devices
* Added an option to password protect the whole app
* Added an option to lock screen orientation at fullscreen view
* Split the Rotate button to 3 buttons per degrees
* Changed the way fullscreen images are loaded for better quality
* Fixed many memory leaks and smaller issues
Version 2.17.4 *(2017-11-06)*
----------------------------

View file

@ -10,8 +10,10 @@ android {
applicationId "com.simplemobiletools.gallery"
minSdkVersion 16
targetSdkVersion 27
versionCode 142
versionName "2.17.4"
versionCode 144
versionName "2.18.1"
multiDexEnabled true
setProperty("archivesBaseName", "gallery")
}
signingConfigs {
@ -45,10 +47,10 @@ ext {
}
dependencies {
compile 'com.simplemobiletools:commons:2.37.12'
compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.7.2'
compile 'com.simplemobiletools:commons:2.39.10'
compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.8.0'
compile 'com.theartofdev.edmodo:android-image-cropper:2.4.0'
compile 'com.bignerdranch.android:recyclerview-multiselect:0.2'
compile 'com.android.support:multidex:1.0.2'
compile 'com.google.code.gson:gson:2.8.2'
compile 'it.sephiroth.android.exif:library:1.0.1'
compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.8'
@ -59,7 +61,7 @@ dependencies {
}
buildscript {
ext.kotlin_version = '1.1.51'
ext.kotlin_version = '1.1.60'
repositories {
mavenCentral()
}

View file

@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.SET_WALLPAPER"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<application
android:name=".App"

View file

@ -1,13 +1,13 @@
package com.simplemobiletools.gallery
import android.app.Application
import android.support.multidex.MultiDexApplication
import com.github.ajalt.reprint.core.Reprint
import com.simplemobiletools.gallery.BuildConfig.USE_LEAK_CANARY
import com.simplemobiletools.gallery.extensions.config
import com.squareup.leakcanary.LeakCanary
import java.util.*
class App : Application() {
class App : MultiDexApplication() {
override fun onCreate() {
super.onCreate()
if (USE_LEAK_CANARY) {

View file

@ -1,45 +1,33 @@
package com.simplemobiletools.gallery.activities
import android.graphics.PorterDuff
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import com.simplemobiletools.commons.dialogs.FilePickerDialog
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.adapters.ManageFoldersAdapter
import com.simplemobiletools.gallery.extensions.config
import kotlinx.android.synthetic.main.activity_excluded_folders.*
import kotlinx.android.synthetic.main.item_manage_folder.view.*
import kotlinx.android.synthetic.main.activity_manage_folders.*
class ExcludedFoldersActivity : SimpleActivity() {
class ExcludedFoldersActivity : SimpleActivity(), RefreshRecyclerViewListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_excluded_folders)
setContentView(R.layout.activity_manage_folders)
updateExcludedFolders()
}
private fun updateExcludedFolders() {
excluded_folders_holder.removeAllViews()
val folders = config.excludedFolders
excluded_folders_placeholder.beVisibleIf(folders.isEmpty())
excluded_folders_placeholder.setTextColor(config.textColor)
val folders = ArrayList<String>()
config.excludedFolders.mapTo(folders, { it })
manage_folders_placeholder.text = getString(R.string.excluded_activity_placeholder)
manage_folders_placeholder.beVisibleIf(folders.isEmpty())
manage_folders_placeholder.setTextColor(config.textColor)
for (folder in folders) {
layoutInflater.inflate(R.layout.item_manage_folder, null, false).apply {
managed_folder_title.apply {
text = folder
setTextColor(config.textColor)
}
managed_folders_icon.apply {
setColorFilter(config.textColor, PorterDuff.Mode.SRC_IN)
setOnClickListener {
config.removeExcludedFolder(folder)
updateExcludedFolders()
}
}
excluded_folders_holder.addView(this)
}
}
val adapter = ManageFoldersAdapter(this, folders, true, this, manage_folders_list) {}
adapter.setupDragListener(true)
manage_folders_list.adapter = adapter
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
@ -55,6 +43,10 @@ class ExcludedFoldersActivity : SimpleActivity() {
return true
}
override fun refreshItems() {
updateExcludedFolders()
}
private fun addExcludedFolder() {
FilePickerDialog(this, pickFile = false, showHidden = config.shouldShowHidden) {
config.addExcludedFolder(it)

View file

@ -1,46 +1,34 @@
package com.simplemobiletools.gallery.activities
import android.graphics.PorterDuff
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import com.simplemobiletools.commons.dialogs.FilePickerDialog
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.scanPath
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.adapters.ManageFoldersAdapter
import com.simplemobiletools.gallery.extensions.config
import kotlinx.android.synthetic.main.activity_included_folders.*
import kotlinx.android.synthetic.main.item_manage_folder.view.*
import kotlinx.android.synthetic.main.activity_manage_folders.*
class IncludedFoldersActivity : SimpleActivity() {
class IncludedFoldersActivity : SimpleActivity(), RefreshRecyclerViewListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_included_folders)
setContentView(R.layout.activity_manage_folders)
updateIncludedFolders()
}
private fun updateIncludedFolders() {
included_folders_holder.removeAllViews()
val folders = config.includedFolders
included_folders_placeholder.beVisibleIf(folders.isEmpty())
included_folders_placeholder.setTextColor(config.textColor)
val folders = ArrayList<String>()
config.includedFolders.mapTo(folders, { it })
manage_folders_placeholder.text = getString(R.string.included_activity_placeholder)
manage_folders_placeholder.beVisibleIf(folders.isEmpty())
manage_folders_placeholder.setTextColor(config.textColor)
for (folder in folders) {
layoutInflater.inflate(R.layout.item_manage_folder, null, false).apply {
managed_folder_title.apply {
text = folder
setTextColor(config.textColor)
}
managed_folders_icon.apply {
setColorFilter(config.textColor, PorterDuff.Mode.SRC_IN)
setOnClickListener {
config.removeIncludedFolder(folder)
updateIncludedFolders()
}
}
included_folders_holder.addView(this)
}
}
val adapter = ManageFoldersAdapter(this, folders, false, this, manage_folders_list) {}
adapter.setupDragListener(true)
manage_folders_list.adapter = adapter
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
@ -56,11 +44,15 @@ class IncludedFoldersActivity : SimpleActivity() {
return true
}
override fun refreshItems() {
updateIncludedFolders()
}
private fun addIncludedFolder() {
FilePickerDialog(this, pickFile = false, showHidden = config.shouldShowHidden) {
config.addIncludedFolder(it)
updateIncludedFolders()
scanPath(it) {}
scanPath(it)
}
}
}

View file

@ -4,7 +4,6 @@ import android.app.Activity
import android.content.ClipData
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.provider.MediaStore
@ -23,7 +22,7 @@ import com.simplemobiletools.commons.helpers.SORT_BY_DATE_MODIFIED
import com.simplemobiletools.commons.helpers.SORT_BY_DATE_TAKEN
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.models.Release
import com.simplemobiletools.commons.views.MyScalableRecyclerView
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.gallery.BuildConfig
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.adapters.DirectoryAdapter
@ -64,6 +63,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
private var mLatestMediaId = 0L
private var mLastMediaHandler = Handler()
private var mCurrAsyncTask: GetDirectoriesAsynctask? = null
private var mZoomListener: MyRecyclerView.MyZoomListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -178,7 +178,6 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
directories_refresh_layout.isRefreshing = false
mIsGettingDirs = false
storeStateVariables()
directories_grid.listener = null
mLastMediaHandler.removeCallbacksAndMessages(null)
if (!mDirs.isEmpty()) {
@ -209,7 +208,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
val newFolder = File(config.tempFolderPath)
if (newFolder.exists() && newFolder.isDirectory) {
if (newFolder.list()?.isEmpty() == true) {
deleteFileBg(newFolder, true) { }
deleteFileBg(newFolder, true)
}
}
config.tempFolderPath = ""
@ -341,6 +340,11 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
} else {
setupListLayoutManager()
}
getDirectoryAdapter()?.apply {
setupZoomListener(mZoomListener)
setupDragListener(true)
}
}
private fun setupGridLayoutManager() {
@ -353,42 +357,30 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
directories_refresh_layout.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
directories_grid.isDragSelectionEnabled = true
directories_grid.isZoomingEnabled = true
layoutManager.spanCount = config.dirColumnCnt
directories_grid.listener = object : MyScalableRecyclerView.MyScalableRecyclerViewListener {
mZoomListener = object : MyRecyclerView.MyZoomListener {
override fun zoomIn() {
if (layoutManager.spanCount > 1) {
reduceColumnCount()
getRecyclerAdapter().actMode?.finish()
getRecyclerAdapter().finishActMode()
}
}
override fun zoomOut() {
if (layoutManager.spanCount < MAX_COLUMN_COUNT) {
increaseColumnCount()
getRecyclerAdapter().actMode?.finish()
getRecyclerAdapter().finishActMode()
}
}
override fun selectItem(position: Int) {
getRecyclerAdapter().selectItem(position)
}
override fun selectRange(initialSelection: Int, lastDraggedIndex: Int, minReached: Int, maxReached: Int) {
getRecyclerAdapter().selectRange(initialSelection, lastDraggedIndex, minReached, maxReached)
}
}
}
private fun setupListLayoutManager() {
directories_grid.isDragSelectionEnabled = true
directories_grid.isZoomingEnabled = false
val layoutManager = directories_grid.layoutManager as GridLayoutManager
layoutManager.spanCount = 1
layoutManager.orientation = GridLayoutManager.VERTICAL
directories_refresh_layout.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
mZoomListener = null
}
private fun createNewFolder() {
@ -451,7 +443,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
else -> fillIntentPath(resultData, resultIntent)
}
} else if ((mIsPickImageIntent || mIsPickVideoIntent)) {
val path = resultData.data.path
val path = resultData.data?.path
val uri = getFilePublicUri(File(path), BuildConfig.APPLICATION_ID)
resultIntent.data = uri
resultIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
@ -560,8 +552,8 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
private fun setupAdapter() {
val currAdapter = directories_grid.adapter
if (currAdapter == null) {
directories_grid.adapter = DirectoryAdapter(this, mDirs, this, isPickIntent(intent) || isGetAnyContentIntent(intent)) {
itemClicked(it.path)
directories_grid.adapter = DirectoryAdapter(this, mDirs, this, directories_grid, isPickIntent(intent) || isGetAnyContentIntent(intent)) {
itemClicked((it as Directory).path)
}
} else {
(currAdapter as DirectoryAdapter).updateDirs(mDirs)
@ -587,7 +579,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
}
private fun checkLastMediaChanged() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && isDestroyed)
if (isActivityDestroyed())
return
mLastMediaHandler.removeCallbacksAndMessages(null)
@ -610,10 +602,6 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
getDirectories()
}
override fun itemLongClicked(position: Int) {
directories_grid.setDragSelectActive(position)
}
override fun recheckPinnedFolders() {
gotDirectories(movePinnedDirectoriesToFront(mDirs), true)
}
@ -659,6 +647,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
add(Release(136, R.string.release_136))
add(Release(137, R.string.release_137))
add(Release(138, R.string.release_138))
add(Release(143, R.string.release_143))
checkWhatsNew(this, BuildConfig.VERSION_CODE)
}
}

View file

@ -5,7 +5,6 @@ import android.app.WallpaperManager
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.support.v7.widget.GridLayoutManager
@ -24,7 +23,7 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE
import com.simplemobiletools.commons.helpers.REQUEST_EDIT_IMAGE
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.views.MyScalableRecyclerView
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.adapters.MediaAdapter
import com.simplemobiletools.gallery.asynctasks.GetMediaAsynctask
@ -59,6 +58,7 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
private var mLatestMediaId = 0L
private var mLastMediaHandler = Handler()
private var mCurrAsyncTask: GetMediaAsynctask? = null
private var mZoomListener: MyRecyclerView.MyZoomListener? = null
companion object {
var mMedia = ArrayList<Medium>()
@ -120,7 +120,6 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
mIsGettingMedia = false
media_refresh_layout.isRefreshing = false
storeStateVariables()
media_grid.listener = null
mLastMediaHandler.removeCallbacksAndMessages(null)
if (!mMedia.isEmpty()) {
@ -177,8 +176,8 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
val currAdapter = media_grid.adapter
if (currAdapter == null) {
media_grid.adapter = MediaAdapter(this, mMedia, this, mIsGetImageIntent || mIsGetVideoIntent || mIsGetAnyIntent, mAllowPickingMultiple) {
itemClicked(it.path)
media_grid.adapter = MediaAdapter(this, mMedia, this, mIsGetImageIntent || mIsGetVideoIntent || mIsGetAnyIntent, mAllowPickingMultiple, media_grid) {
itemClicked((it as Medium).path)
}
} else {
(currAdapter as MediaAdapter).updateMedia(mMedia)
@ -204,7 +203,7 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
}
private fun checkLastMediaChanged() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && isDestroyed)
if (isActivityDestroyed())
return
mLastMediaHandler.removeCallbacksAndMessages(null)
@ -347,7 +346,7 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
private fun deleteDirectoryIfEmpty() {
val file = File(mPath)
if (config.deleteEmptyFolders && !file.isDownloadsFolder() && file.isDirectory && file.listFiles()?.isEmpty() == true) {
deleteFile(file, true) {}
deleteFile(file, true)
}
}
@ -398,10 +397,16 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
private fun getRecyclerAdapter() = (media_grid.adapter as MediaAdapter)
private fun setupLayoutManager() {
if (config.viewTypeFiles == VIEW_TYPE_GRID)
if (config.viewTypeFiles == VIEW_TYPE_GRID) {
setupGridLayoutManager()
else
} else {
setupListLayoutManager()
}
getMediaAdapter()?.apply {
setupZoomListener(mZoomListener)
setupDragListener(true)
}
}
private fun setupGridLayoutManager() {
@ -414,42 +419,30 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
media_refresh_layout.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
media_grid.isDragSelectionEnabled = true
media_grid.isZoomingEnabled = true
layoutManager.spanCount = config.mediaColumnCnt
media_grid.listener = object : MyScalableRecyclerView.MyScalableRecyclerViewListener {
mZoomListener = object : MyRecyclerView.MyZoomListener {
override fun zoomIn() {
if (layoutManager.spanCount > 1) {
reduceColumnCount()
getRecyclerAdapter().actMode?.finish()
getRecyclerAdapter().finishActMode()
}
}
override fun zoomOut() {
if (layoutManager.spanCount < MAX_COLUMN_COUNT) {
increaseColumnCount()
getRecyclerAdapter().actMode?.finish()
getRecyclerAdapter().finishActMode()
}
}
override fun selectItem(position: Int) {
getRecyclerAdapter().selectItem(position)
}
override fun selectRange(initialSelection: Int, lastDraggedIndex: Int, minReached: Int, maxReached: Int) {
getRecyclerAdapter().selectRange(initialSelection, lastDraggedIndex, minReached, maxReached)
}
}
}
private fun setupListLayoutManager() {
media_grid.isDragSelectionEnabled = true
media_grid.isZoomingEnabled = false
val layoutManager = media_grid.layoutManager as GridLayoutManager
layoutManager.spanCount = 1
layoutManager.orientation = GridLayoutManager.VERTICAL
media_refresh_layout.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
mZoomListener = null
}
private fun increaseColumnCount() {
@ -575,10 +568,6 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
}, 1000)
}
override fun itemLongClicked(position: Int) {
media_grid.setDragSelectActive(position)
}
override fun selectedPaths(paths: ArrayList<String>) {
Intent().apply {
putExtra(PICKED_PATHS, paths)

View file

@ -59,14 +59,14 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
mIsFromGallery = intent.getBooleanExtra(IS_FROM_GALLERY, false)
if (mUri!!.scheme == "file") {
scanPath(mUri!!.path) {}
scanPath(mUri!!.path)
sendViewPagerIntent(mUri!!.path)
finish()
return
} else {
val path = applicationContext.getRealPathFromURI(mUri!!) ?: ""
if (path != mUri.toString() && path.isNotEmpty()) {
scanPath(mUri!!.path) {}
scanPath(mUri!!.path)
sendViewPagerIntent(path)
finish()
return
@ -114,9 +114,11 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.photo_video_menu, menu)
menu.findItem(R.id.menu_set_as).isVisible = mMedium?.isImage() == true
menu.findItem(R.id.menu_edit).isVisible = mMedium?.isImage() == true && mUri?.scheme == "file"
menu.findItem(R.id.menu_properties).isVisible = mUri?.scheme == "file"
menu.apply {
findItem(R.id.menu_set_as).isVisible = mMedium?.isImage() == true
findItem(R.id.menu_edit).isVisible = mMedium?.isImage() == true && mUri?.scheme == "file"
findItem(R.id.menu_properties).isVisible = mUri?.scheme == "file"
}
return true
}

View file

@ -5,10 +5,10 @@ import android.app.WallpaperManager
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import com.simplemobiletools.commons.extensions.isActivityDestroyed
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.gallery.R
import com.theartofdev.edmodo.cropper.CropImageView
@ -61,8 +61,10 @@ class SetWallpaperActivity : SimpleActivity(), CropImageView.OnCropImageComplete
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_set_wallpaper, menu)
menu.findItem(R.id.portrait_aspect_ratio).isVisible = isLandscapeRatio
menu.findItem(R.id.landscape_aspect_ratio).isVisible = !isLandscapeRatio
menu.apply {
findItem(R.id.portrait_aspect_ratio).isVisible = isLandscapeRatio
findItem(R.id.landscape_aspect_ratio).isVisible = !isLandscapeRatio
}
return true
}
@ -84,7 +86,7 @@ class SetWallpaperActivity : SimpleActivity(), CropImageView.OnCropImageComplete
}
override fun onCropImageComplete(view: CropImageView?, result: CropImageView.CropResult) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && isDestroyed)
if (isActivityDestroyed())
return
if (result.error == null) {

View file

@ -67,7 +67,7 @@ class SettingsActivity : SimpleActivity() {
}
private fun setupUseEnglish() {
settings_use_english_holder.beVisibleIf(Locale.getDefault().language != "en")
settings_use_english_holder.beVisibleIf(config.wasUseEnglishToggled || Locale.getDefault().language != "en")
settings_use_english.isChecked = config.useEnglish
settings_use_english_holder.setOnClickListener {
settings_use_english.toggle()

View file

@ -1,36 +1,5 @@
package com.simplemobiletools.gallery.activities
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.getFilenameFromPath
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.dialogs.PickDirectoryDialog
import com.simplemobiletools.gallery.extensions.config
import com.simplemobiletools.gallery.models.Directory
import java.io.File
import java.util.*
open class SimpleActivity : BaseSimpleActivity() {
fun tryCopyMoveFilesTo(files: ArrayList<File>, isCopyOperation: Boolean, callback: () -> Unit) {
if (files.isEmpty()) {
toast(R.string.unknown_error_occurred)
return
}
val source = if (files[0].isFile) files[0].parent else files[0].absolutePath
PickDirectoryDialog(this, source) {
copyMoveFilesTo(files, source.trimEnd('/'), it, isCopyOperation, true, callback)
}
}
fun addTempFolderIfNeeded(dirs: ArrayList<Directory>): ArrayList<Directory> {
val directories = ArrayList<Directory>()
val tempFolderPath = config.tempFolderPath
if (tempFolderPath.isNotEmpty()) {
val newFolder = Directory(tempFolderPath, "", tempFolderPath.getFilenameFromPath(), 0, 0, 0, 0L)
directories.add(newFolder)
}
directories.addAll(dirs)
return directories
}
}
open class SimpleActivity : BaseSimpleActivity()

View file

@ -23,6 +23,7 @@ import android.support.v4.view.ViewPager
import android.util.DisplayMetrics
import android.view.*
import android.view.animation.DecelerateInterpolator
import com.bumptech.glide.Glide
import com.simplemobiletools.commons.dialogs.PropertiesDialog
import com.simplemobiletools.commons.dialogs.RenameItemDialog
import com.simplemobiletools.commons.extensions.*
@ -73,6 +74,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
companion object {
var screenWidth = 0
var screenHeight = 0
var wasDecodedByGlide = false
}
override fun onCreate(savedInstanceState: Bundle?) {
@ -185,7 +187,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
title = mPath.getFilenameFromPath()
view_pager.onGlobalLayout {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 || !isDestroyed) {
if (!isActivityDestroyed()) {
if (mMedia.isNotEmpty()) {
gotMedia(mMedia)
}
@ -193,7 +195,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
}
reloadViewPager()
scanPath(mPath) {}
scanPath(mPath)
if (config.darkBackground)
view_pager.background = ColorDrawable(Color.BLACK)
@ -226,8 +228,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
mOrientationEventListener = object : OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {
override fun onOrientationChanged(orientation: Int) {
val currOrient = when (orientation) {
in 60..134 -> ORIENT_LANDSCAPE_RIGHT
in 225..299 -> ORIENT_LANDSCAPE_LEFT
in 75..134 -> ORIENT_LANDSCAPE_RIGHT
in 225..285 -> ORIENT_LANDSCAPE_LEFT
else -> ORIENT_PORTRAIT
}
@ -303,7 +305,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
private fun updatePagerItems(media: MutableList<Medium>) {
val pagerAdapter = MyPagerAdapter(this, supportFragmentManager, media)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 || !isDestroyed) {
if (!isActivityDestroyed()) {
view_pager.apply {
adapter = pagerAdapter
currentItem = mPos
@ -321,7 +323,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
private fun startSlideshow() {
if (getMediaForSlideshow()) {
view_pager.onGlobalLayout {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 || !isDestroyed) {
if (!isActivityDestroyed()) {
hideSystemUI()
mSlideshowInterval = config.slideshowInterval
mSlideshowMoveBackwards = config.slideshowMoveBackwards
@ -401,7 +403,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
if (mIsSlideshowActive) {
if (getCurrentMedium()!!.isImage() || getCurrentMedium()!!.isGif()) {
mSlideshowHandler.postDelayed({
if (mIsSlideshowActive && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && !isDestroyed) {
if (mIsSlideshowActive && !isActivityDestroyed()) {
swipeToNextMedium()
}
}, mSlideshowInterval * 1000L)
@ -494,52 +496,64 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
private fun saveImageAs() {
val currPath = getCurrentPath()
SaveAsDialog(this, currPath, false) {
Thread({
val selectedFile = File(it)
handleSAFDialog(selectedFile) {
toast(R.string.saving)
val tmpFile = File(filesDir, ".tmp_${it.getFilenameFromPath()}")
try {
val bitmap = BitmapFactory.decodeFile(currPath)
getFileOutputStream(tmpFile) {
if (it == null) {
toast(R.string.unknown_error_occurred)
return@getFileOutputStream
}
val selectedFile = File(it)
handleSAFDialog(selectedFile) {
Thread({
saveImageToFile(currPath, it)
}).start()
}
}
}
val oldLastModified = getCurrentFile().lastModified()
if (currPath.isJpg()) {
saveRotation(getCurrentFile(), tmpFile)
} else {
saveFile(tmpFile, bitmap, it as FileOutputStream)
}
if (tmpFile.length() > 0 && selectedFile.exists()) {
deleteFile(selectedFile) {}
}
copyFile(tmpFile, selectedFile)
scanFile(selectedFile) {}
toast(R.string.file_saved)
if (config.keepLastModified) {
selectedFile.setLastModified(oldLastModified)
updateLastModified(selectedFile, oldLastModified)
}
it.flush()
it.close()
mRotationDegrees = 0f
invalidateOptionsMenu()
}
} catch (e: OutOfMemoryError) {
toast(R.string.out_of_memory_error)
} catch (e: Exception) {
showErrorToast(e)
} finally {
deleteFile(tmpFile) {}
}
private fun saveImageToFile(oldPath: String, newPath: String) {
val newFile = File(newPath)
toast(R.string.saving)
val tmpFile = File(filesDir, ".tmp_${newPath.getFilenameFromPath()}")
try {
val bitmap = BitmapFactory.decodeFile(oldPath)
getFileOutputStream(tmpFile) {
if (it == null) {
toast(R.string.unknown_error_occurred)
return@getFileOutputStream
}
}).start()
val oldLastModified = getCurrentFile().lastModified()
if (oldPath.isJpg()) {
saveRotation(getCurrentFile(), tmpFile)
} else {
saveFile(tmpFile, bitmap, it as FileOutputStream)
}
if (tmpFile.length() > 0 && newFile.exists()) {
deleteFile(newFile)
}
copyFile(tmpFile, newFile)
scanFile(newFile)
toast(R.string.file_saved)
if (config.keepLastModified) {
newFile.setLastModified(oldLastModified)
updateLastModified(newFile, oldLastModified)
}
it.flush()
it.close()
mRotationDegrees = 0f
invalidateOptionsMenu()
// we cannot refresh a specific image in Glide Cache, so just clear it all
val glide = Glide.get(applicationContext)
glide.clearDiskCache()
runOnUiThread {
glide.clearMemory()
}
}
} catch (e: OutOfMemoryError) {
toast(R.string.out_of_memory_error)
} catch (e: Exception) {
showErrorToast(e)
} finally {
deleteFile(tmpFile)
}
}
@ -780,10 +794,10 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
private fun deleteDirectoryIfEmpty() {
val file = File(mDirectory)
if (config.deleteEmptyFolders && !file.isDownloadsFolder() && file.isDirectory && file.listFiles()?.isEmpty() == true) {
deleteFile(file, true) {}
deleteFile(file, true)
}
scanPath(mDirectory) {}
scanPath(mDirectory)
}
private fun checkOrientation() {

View file

@ -1,22 +1,20 @@
package com.simplemobiletools.gallery.adapters
import android.graphics.PorterDuff
import android.os.Build
import android.support.v7.view.ActionMode
import android.support.v7.widget.RecyclerView
import android.util.SparseArray
import android.view.*
import com.bignerdranch.android.multiselector.ModalMultiSelectorCallback
import com.bignerdranch.android.multiselector.MultiSelector
import com.bignerdranch.android.multiselector.SwappingHolder
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import com.bumptech.glide.Glide
import com.google.gson.Gson
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.dialogs.PropertiesDialog
import com.simplemobiletools.commons.dialogs.RenameItemDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.SimpleActivity
import com.simplemobiletools.gallery.dialogs.ExcludeFolderDialog
import com.simplemobiletools.gallery.dialogs.PickMediumDialog
import com.simplemobiletools.gallery.extensions.*
@ -27,134 +25,103 @@ import kotlinx.android.synthetic.main.directory_item_list.view.*
import java.io.File
import java.util.*
class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList<Directory>, val listener: DirOperationsListener?, val isPickIntent: Boolean,
val itemClick: (Directory) -> Unit) : RecyclerView.Adapter<DirectoryAdapter.ViewHolder>() {
class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: MutableList<Directory>, val listener: DirOperationsListener?, recyclerView: MyRecyclerView,
val isPickIntent: Boolean, itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
private val config = activity.config
var actMode: ActionMode? = null
var primaryColor = config.primaryColor
private val multiSelector = MultiSelector()
private val isListViewType = config.viewTypeFolders == VIEW_TYPE_LIST
private var itemViews = SparseArray<View>()
private val selectedPositions = HashSet<Int>()
private var textColor = config.textColor
private var pinnedFolders = config.pinnedFolders
private var scrollHorizontally = config.scrollHorizontally
private var showMediaCount = config.showMediaCount
private var animateGifs = config.animateGifs
private var cropThumbnails = config.cropThumbnails
fun toggleItemSelection(select: Boolean, pos: Int) {
if (select) {
if (itemViews[pos] != null) {
itemViews[pos].dir_check?.background?.setColorFilter(primaryColor, PorterDuff.Mode.SRC_IN)
selectedPositions.add(pos)
}
} else {
selectedPositions.remove(pos)
}
itemViews[pos]?.dir_check?.beVisibleIf(select)
if (selectedPositions.isEmpty()) {
actMode?.finish()
return
}
updateTitle(selectedPositions.size)
init {
selectableItemCount = dirs.count()
}
private fun updateTitle(cnt: Int) {
actMode?.title = "$cnt / ${dirs.size}"
actMode?.invalidate()
override fun getActionMenuId() = R.menu.cab_directories
override fun prepareItemSelection(view: View) {
view.dir_check?.background?.applyColorFilter(primaryColor)
}
private val adapterListener = object : MyAdapterListener {
override fun toggleItemSelectionAdapter(select: Boolean, position: Int) {
toggleItemSelection(select, position)
}
override fun getSelectedPositions(): HashSet<Int> = selectedPositions
override fun markItemSelection(select: Boolean, view: View?) {
view?.dir_check?.beVisibleIf(select)
}
private val multiSelectorMode = object : ModalMultiSelectorCallback(multiSelector) {
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
when (item.itemId) {
R.id.cab_properties -> showProperties()
R.id.cab_rename -> renameDir()
R.id.cab_pin -> pinFolders(true)
R.id.cab_unpin -> pinFolders(false)
R.id.cab_hide -> toggleFoldersVisibility(true)
R.id.cab_unhide -> toggleFoldersVisibility(false)
R.id.cab_exclude -> tryExcludeFolder()
R.id.cab_copy_to -> copyMoveTo(true)
R.id.cab_move_to -> copyMoveTo(false)
R.id.cab_select_all -> selectAll()
R.id.cab_delete -> askConfirmDelete()
R.id.cab_select_photo -> changeAlbumCover(false)
R.id.cab_use_default -> changeAlbumCover(true)
else -> return false
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
val layoutType = if (isListViewType) R.layout.directory_item_list else R.layout.directory_item_grid
return createViewHolder(layoutType, parent)
}
override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) {
val dir = dirs[position]
val view = holder.bindView(dir, !isPickIntent) {
setupView(it, dir)
}
bindViewHolder(holder, position, view)
}
override fun getItemCount() = dirs.size
override fun prepareActionMode(menu: Menu) {
menu.apply {
findItem(R.id.cab_rename).isVisible = selectedPositions.size == 1
findItem(R.id.cab_change_cover_image).isVisible = selectedPositions.size == 1
checkHideBtnVisibility(this)
checkPinBtnVisibility(this)
}
}
override fun actionItemPressed(id: Int) {
when (id) {
R.id.cab_properties -> showProperties()
R.id.cab_rename -> renameDir()
R.id.cab_pin -> pinFolders(true)
R.id.cab_unpin -> pinFolders(false)
R.id.cab_hide -> toggleFoldersVisibility(true)
R.id.cab_unhide -> toggleFoldersVisibility(false)
R.id.cab_exclude -> tryExcludeFolder()
R.id.cab_copy_to -> copyMoveTo(true)
R.id.cab_move_to -> copyMoveTo(false)
R.id.cab_select_all -> selectAll()
R.id.cab_delete -> askConfirmDelete()
R.id.cab_select_photo -> changeAlbumCover(false)
R.id.cab_use_default -> changeAlbumCover(true)
}
}
private fun checkHideBtnVisibility(menu: Menu) {
var hiddenCnt = 0
var unhiddenCnt = 0
selectedPositions.mapNotNull { dirs.getOrNull(it)?.path }.forEach {
if (File(it).containsNoMedia()) {
hiddenCnt++
} else {
unhiddenCnt++
}
return true
}
override fun onCreateActionMode(actionMode: ActionMode?, menu: Menu?): Boolean {
super.onCreateActionMode(actionMode, menu)
actMode = actionMode
activity.menuInflater.inflate(R.menu.cab_directories, menu)
return true
}
menu.findItem(R.id.cab_hide).isVisible = unhiddenCnt > 0
menu.findItem(R.id.cab_unhide).isVisible = hiddenCnt > 0
}
override fun onPrepareActionMode(actionMode: ActionMode?, menu: Menu): Boolean {
menu.findItem(R.id.cab_rename).isVisible = selectedPositions.size <= 1
menu.findItem(R.id.cab_change_cover_image).isVisible = selectedPositions.size <= 1
checkHideBtnVisibility(menu)
checkPinBtnVisibility(menu)
return true
}
override fun onDestroyActionMode(actionMode: ActionMode?) {
super.onDestroyActionMode(actionMode)
selectedPositions.forEach {
itemViews[it]?.dir_check?.beGone()
private fun checkPinBtnVisibility(menu: Menu) {
val pinnedFolders = config.pinnedFolders
var pinnedCnt = 0
var unpinnedCnt = 0
selectedPositions.mapNotNull { dirs.getOrNull(it)?.path }.forEach {
if (pinnedFolders.contains(it)) {
pinnedCnt++
} else {
unpinnedCnt++
}
selectedPositions.clear()
actMode = null
}
fun checkHideBtnVisibility(menu: Menu) {
var hiddenCnt = 0
var unhiddenCnt = 0
selectedPositions.mapNotNull { dirs.getOrNull(it)?.path }.forEach {
if (File(it).containsNoMedia()) {
hiddenCnt++
} else {
unhiddenCnt++
}
}
menu.findItem(R.id.cab_hide).isVisible = unhiddenCnt > 0
menu.findItem(R.id.cab_unhide).isVisible = hiddenCnt > 0
}
fun checkPinBtnVisibility(menu: Menu) {
val pinnedFolders = config.pinnedFolders
var pinnedCnt = 0
var unpinnedCnt = 0
selectedPositions.mapNotNull { dirs.getOrNull(it)?.path }.forEach {
if (pinnedFolders.contains(it)) {
pinnedCnt++
} else {
unpinnedCnt++
}
}
menu.findItem(R.id.cab_pin).isVisible = unpinnedCnt > 0
menu.findItem(R.id.cab_unpin).isVisible = pinnedCnt > 0
}
menu.findItem(R.id.cab_pin).isVisible = unpinnedCnt > 0
menu.findItem(R.id.cab_unpin).isVisible = pinnedCnt > 0
}
private fun showProperties() {
@ -178,7 +145,7 @@ class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList<Direc
RenameItemDialog(activity, dir.absolutePath) {
activity.runOnUiThread {
listener?.refreshItems()
actMode?.finish()
finishActMode()
}
}
}
@ -211,14 +178,14 @@ class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList<Direc
private fun tryExcludeFolder() {
ExcludeFolderDialog(activity, getSelectedPaths().toList()) {
listener?.refreshItems()
actMode?.finish()
finishActMode()
}
}
private fun noMediaHandled() {
activity.runOnUiThread {
listener?.refreshItems()
actMode?.finish()
finishActMode()
}
}
@ -232,7 +199,7 @@ class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList<Direc
pinnedFolders = config.pinnedFolders
listener?.recheckPinnedFolders()
notifyDataSetChanged()
actMode?.finish()
finishActMode()
}
private fun copyMoveTo(isCopyOperation: Boolean) {
@ -248,19 +215,10 @@ class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList<Direc
activity.tryCopyMoveFilesTo(files, isCopyOperation) {
config.tempFolderPath = ""
listener?.refreshItems()
actMode?.finish()
finishActMode()
}
}
fun selectAll() {
val cnt = dirs.size
for (i in 0 until cnt) {
selectedPositions.add(i)
notifyItemChanged(i)
}
updateTitle(cnt)
}
private fun askConfirmDelete() {
ConfirmationDialog(activity) {
deleteFiles()
@ -302,7 +260,8 @@ class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList<Direc
.forEachIndexed { curIndex, i -> newItems.put(curIndex, itemViews[i]) }
itemViews = newItems
actMode?.finish()
selectableItemCount = dirs.size
finishActMode()
}
}
@ -337,7 +296,7 @@ class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList<Direc
private fun storeCovers(albumCovers: ArrayList<AlbumCover>) {
activity.config.albumCovers = Gson().toJson(albumCovers)
actMode?.finish()
finishActMode()
listener?.refreshItems()
}
@ -347,30 +306,18 @@ class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList<Direc
return paths
}
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
val layoutType = if (isListViewType) R.layout.directory_item_list else R.layout.directory_item_grid
val view = LayoutInflater.from(parent?.context).inflate(layoutType, parent, false)
return ViewHolder(view, adapterListener, activity, multiSelectorMode, multiSelector, listener, isPickIntent, itemClick)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val dir = dirs[position]
itemViews.put(position, holder.bindView(dir, pinnedFolders.contains(dir.path), scrollHorizontally, isListViewType, textColor, showMediaCount, animateGifs, cropThumbnails))
toggleItemSelection(selectedPositions.contains(position), position)
holder.itemView.tag = holder
}
override fun onViewRecycled(holder: ViewHolder?) {
super.onViewRecycled(holder)
holder?.stopLoad()
if (!activity.isActivityDestroyed()) {
Glide.with(activity).clear(holder?.itemView?.dir_thumbnail)
}
}
override fun getItemCount() = dirs.size
fun updateDirs(newDirs: ArrayList<Directory>) {
dirs = newDirs
selectableItemCount = dirs.size
notifyDataSetChanged()
actMode?.finish()
finishActMode()
}
fun updateAnimateGifs(animateGifs: Boolean) {
@ -393,117 +340,31 @@ class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList<Direc
notifyDataSetChanged()
}
fun updateTextColor(textColor: Int) {
this.textColor = textColor
notifyDataSetChanged()
}
private fun setupView(view: View, directory: Directory) {
view.apply {
dir_name.text = directory.name
dir_path?.text = "${directory.path.substringBeforeLast("/")}/"
photo_cnt.text = directory.mediaCnt.toString()
activity.loadImage(directory.tmb, dir_thumbnail, scrollHorizontally, animateGifs, cropThumbnails)
dir_pin.beVisibleIf(pinnedFolders.contains(directory.path))
dir_sd_card.beVisibleIf(activity.isPathOnSD(directory.path))
photo_cnt.beVisibleIf(showMediaCount)
fun selectItem(pos: Int) {
toggleItemSelection(true, pos)
}
fun selectRange(from: Int, to: Int, min: Int, max: Int) {
if (from == to) {
(min..max).filter { it != from }
.forEach { toggleItemSelection(false, it) }
return
}
if (to < from) {
for (i in to..from)
toggleItemSelection(true, i)
if (min > -1 && min < to) {
(min until to).filter { it != from }
.forEach { toggleItemSelection(false, it) }
}
if (max > -1) {
for (i in from + 1..max)
toggleItemSelection(false, i)
}
} else {
for (i in from..to)
toggleItemSelection(true, i)
if (max > -1 && max > to) {
(to + 1..max).filter { it != from }
.forEach { toggleItemSelection(false, it) }
}
if (min > -1) {
for (i in min until from)
toggleItemSelection(false, i)
if (isListViewType) {
dir_name.setTextColor(textColor)
dir_path.setTextColor(textColor)
photo_cnt.setTextColor(textColor)
dir_pin.setColorFilter(textColor, PorterDuff.Mode.SRC_IN)
dir_sd_card.setColorFilter(textColor, PorterDuff.Mode.SRC_IN)
}
}
}
class ViewHolder(val view: View, val adapterListener: MyAdapterListener, val activity: SimpleActivity, val multiSelectorCallback: ModalMultiSelectorCallback,
val multiSelector: MultiSelector, val listener: DirOperationsListener?, val isPickIntent: Boolean, val itemClick: (Directory) -> (Unit)) :
SwappingHolder(view, MultiSelector()) {
fun bindView(directory: Directory, isPinned: Boolean, scrollHorizontally: Boolean, isListView: Boolean, textColor: Int, showMediaCount: Boolean,
animateGifs: Boolean, cropThumbnails: Boolean): View {
itemView.apply {
dir_name.text = directory.name
dir_path?.text = "${directory.path.substringBeforeLast("/")}/"
photo_cnt.text = directory.mediaCnt.toString()
activity.loadImage(directory.tmb, dir_thumbnail, scrollHorizontally, animateGifs, cropThumbnails)
dir_pin.beVisibleIf(isPinned)
dir_sd_card.beVisibleIf(activity.isPathOnSD(directory.path))
photo_cnt.beVisibleIf(showMediaCount)
if (isListView) {
dir_name.setTextColor(textColor)
dir_path.setTextColor(textColor)
photo_cnt.setTextColor(textColor)
dir_pin.setColorFilter(textColor, PorterDuff.Mode.SRC_IN)
dir_sd_card.setColorFilter(textColor, PorterDuff.Mode.SRC_IN)
}
setOnClickListener { viewClicked(directory) }
setOnLongClickListener { if (isPickIntent) viewClicked(directory) else viewLongClicked(); true }
}
return itemView
}
private fun viewClicked(directory: Directory) {
if (multiSelector.isSelectable) {
val isSelected = adapterListener.getSelectedPositions().contains(adapterPosition)
adapterListener.toggleItemSelectionAdapter(!isSelected, adapterPosition)
} else {
itemClick(directory)
}
}
private fun viewLongClicked() {
if (listener != null) {
if (!multiSelector.isSelectable) {
activity.startSupportActionMode(multiSelectorCallback)
adapterListener.toggleItemSelectionAdapter(true, adapterPosition)
}
listener.itemLongClicked(adapterPosition)
}
}
fun stopLoad() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 || !activity.isDestroyed)
Glide.with(activity).clear(view.dir_thumbnail)
}
}
interface MyAdapterListener {
fun toggleItemSelectionAdapter(select: Boolean, position: Int)
fun getSelectedPositions(): HashSet<Int>
}
interface DirOperationsListener {
fun refreshItems()
fun tryDeleteFolders(folders: ArrayList<File>)
fun itemLongClicked(position: Int)
fun recheckPinnedFolders()
}
}

View file

@ -0,0 +1,99 @@
package com.simplemobiletools.gallery.adapters
import android.util.SparseArray
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.extensions.config
import kotlinx.android.synthetic.main.item_manage_folder.view.*
import java.util.*
class ManageFoldersAdapter(activity: BaseSimpleActivity, var folders: ArrayList<String>, val isShowingExcludedFolders: Boolean, val listener: RefreshRecyclerViewListener?,
recyclerView: MyRecyclerView, itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
private val config = activity.config
init {
selectableItemCount = folders.size
}
override fun getActionMenuId() = R.menu.cab_delete_only
override fun prepareActionMode(menu: Menu) {}
override fun prepareItemSelection(view: View) {}
override fun markItemSelection(select: Boolean, view: View?) {
view?.manage_folder_holder?.isSelected = select
}
override fun actionItemPressed(id: Int) {
when (id) {
R.id.cab_delete -> askConfirmDelete()
}
}
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) {
setupView(it, folder)
}
bindViewHolder(holder, position, view)
}
override fun getItemCount() = folders.size
private fun setupView(view: View, folder: String) {
view.apply {
manage_folder_title.apply {
text = folder
setTextColor(config.textColor)
}
}
}
private fun askConfirmDelete() {
ConfirmationDialog(activity) {
deleteSelection()
}
}
private fun deleteSelection() {
val removeFolders = ArrayList<String>(selectedPositions.size)
selectedPositions.sortedDescending().forEach {
val folder = folders[it]
removeFolders.add(folder)
notifyItemRemoved(it)
itemViews.put(it, null)
if (isShowingExcludedFolders) {
config.removeExcludedFolder(folder)
} else {
config.removeIncludedFolder(folder)
}
}
folders.removeAll(removeFolders)
selectedPositions.clear()
val newItems = SparseArray<View>()
(0 until itemViews.size())
.filter { itemViews[it] != null }
.forEachIndexed { curIndex, i -> newItems.put(curIndex, itemViews[i]) }
itemViews = newItems
selectableItemCount = folders.size
finishActMode()
if (folders.isEmpty()) {
listener?.refreshItems()
}
}
}

View file

@ -2,21 +2,20 @@ package com.simplemobiletools.gallery.adapters
import android.graphics.PorterDuff
import android.net.Uri
import android.os.Build
import android.support.v7.view.ActionMode
import android.support.v7.widget.RecyclerView
import android.util.SparseArray
import android.view.*
import com.bignerdranch.android.multiselector.ModalMultiSelectorCallback
import com.bignerdranch.android.multiselector.MultiSelector
import com.bignerdranch.android.multiselector.SwappingHolder
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import com.bumptech.glide.Glide
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.dialogs.PropertiesDialog
import com.simplemobiletools.commons.dialogs.RenameItemDialog
import com.simplemobiletools.commons.extensions.beGone
import com.simplemobiletools.commons.extensions.applyColorFilter
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.isActivityDestroyed
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.SimpleActivity
import com.simplemobiletools.gallery.dialogs.DeleteWithRememberDialog
import com.simplemobiletools.gallery.extensions.*
import com.simplemobiletools.gallery.helpers.VIEW_TYPE_LIST
@ -25,119 +24,88 @@ import kotlinx.android.synthetic.main.photo_video_item_grid.view.*
import java.io.File
import java.util.*
class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>, val listener: MediaOperationsListener?, val isAGetIntent: Boolean,
val allowMultiplePicks: Boolean, val itemClick: (Medium) -> Unit) : RecyclerView.Adapter<MediaAdapter.ViewHolder>() {
class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>, val listener: MediaOperationsListener?, val isAGetIntent: Boolean,
val allowMultiplePicks: Boolean, recyclerView: MyRecyclerView, itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
private val config = activity.config
var actMode: ActionMode? = null
var primaryColor = config.primaryColor
private val multiSelector = MultiSelector()
private val isListViewType = config.viewTypeFiles == VIEW_TYPE_LIST
private var skipConfirmationDialog = false
private var itemViews = SparseArray<View>()
private val selectedPositions = HashSet<Int>()
private var scrollHorizontally = config.scrollHorizontally
private var animateGifs = config.animateGifs
private var cropThumbnails = config.cropThumbnails
private var textColor = config.textColor
private var displayFilenames = config.displayFileNames
fun toggleItemSelection(select: Boolean, pos: Int) {
if (select) {
if (itemViews[pos] != null) {
itemViews[pos].medium_check?.background?.setColorFilter(primaryColor, PorterDuff.Mode.SRC_IN)
selectedPositions.add(pos)
}
} else {
selectedPositions.remove(pos)
}
itemViews[pos]?.medium_check?.beVisibleIf(select)
if (selectedPositions.isEmpty()) {
actMode?.finish()
return
}
updateTitle(selectedPositions.size)
init {
selectableItemCount = media.count()
}
private fun updateTitle(cnt: Int) {
actMode?.title = "$cnt / ${media.size}"
actMode?.invalidate()
override fun getActionMenuId() = R.menu.cab_media
override fun prepareItemSelection(view: View) {
view.medium_check?.background?.applyColorFilter(primaryColor)
}
private val adapterListener = object : MyAdapterListener {
override fun toggleItemSelectionAdapter(select: Boolean, position: Int) {
toggleItemSelection(select, position)
}
override fun getSelectedPositions(): HashSet<Int> = selectedPositions
override fun markItemSelection(select: Boolean, view: View?) {
view?.medium_check?.beVisibleIf(select)
}
private val multiSelectorMode = object : ModalMultiSelectorCallback(multiSelector) {
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
when (item.itemId) {
R.id.cab_confirm_selection -> confirmSelection()
R.id.cab_properties -> showProperties()
R.id.cab_rename -> renameFile()
R.id.cab_edit -> editFile()
R.id.cab_hide -> toggleFileVisibility(true)
R.id.cab_unhide -> toggleFileVisibility(false)
R.id.cab_share -> shareMedia()
R.id.cab_copy_to -> copyMoveTo(true)
R.id.cab_move_to -> copyMoveTo(false)
R.id.cab_select_all -> selectAll()
R.id.cab_open_with -> activity.openFile(Uri.fromFile(getCurrentFile()), true)
R.id.cab_set_as -> activity.setAs(Uri.fromFile(getCurrentFile()))
R.id.cab_delete -> checkDeleteConfirmation()
else -> return false
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
return createViewHolder(layoutType, parent)
}
override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) {
val medium = media[position]
val view = holder.bindView(medium, !allowMultiplePicks) {
setupView(it, medium)
}
bindViewHolder(holder, position, view)
}
override fun getItemCount() = media.size
override fun prepareActionMode(menu: Menu) {
menu.apply {
findItem(R.id.cab_rename).isVisible = selectedPositions.size == 1
findItem(R.id.cab_open_with).isVisible = selectedPositions.size == 1
findItem(R.id.cab_confirm_selection).isVisible = isAGetIntent && allowMultiplePicks && selectedPositions.size > 0
checkHideBtnVisibility(this)
}
}
override fun actionItemPressed(id: Int) {
when (id) {
R.id.cab_confirm_selection -> confirmSelection()
R.id.cab_properties -> showProperties()
R.id.cab_rename -> renameFile()
R.id.cab_edit -> editFile()
R.id.cab_hide -> toggleFileVisibility(true)
R.id.cab_unhide -> toggleFileVisibility(false)
R.id.cab_share -> shareMedia()
R.id.cab_copy_to -> copyMoveTo(true)
R.id.cab_move_to -> copyMoveTo(false)
R.id.cab_select_all -> selectAll()
R.id.cab_open_with -> activity.openFile(Uri.fromFile(getCurrentFile()), true)
R.id.cab_set_as -> activity.setAs(Uri.fromFile(getCurrentFile()))
R.id.cab_delete -> checkDeleteConfirmation()
}
}
private fun checkHideBtnVisibility(menu: Menu) {
var hiddenCnt = 0
var unhiddenCnt = 0
selectedPositions.mapNotNull { media.getOrNull(it) }.forEach {
if (it.name.startsWith('.')) {
hiddenCnt++
} else {
unhiddenCnt++
}
return true
}
override fun onCreateActionMode(actionMode: ActionMode?, menu: Menu?): Boolean {
super.onCreateActionMode(actionMode, menu)
actMode = actionMode
activity.menuInflater.inflate(R.menu.cab_media, menu)
return true
}
override fun onPrepareActionMode(actionMode: ActionMode?, menu: Menu): Boolean {
menu.findItem(R.id.cab_rename).isVisible = selectedPositions.size == 1
menu.findItem(R.id.cab_open_with).isVisible = selectedPositions.size == 1
menu.findItem(R.id.cab_confirm_selection).isVisible = isAGetIntent && allowMultiplePicks && selectedPositions.size > 0
checkHideBtnVisibility(menu)
return true
}
override fun onDestroyActionMode(actionMode: ActionMode?) {
super.onDestroyActionMode(actionMode)
selectedPositions.forEach {
itemViews[it]?.medium_check?.beGone()
}
selectedPositions.clear()
actMode = null
}
fun checkHideBtnVisibility(menu: Menu) {
var hiddenCnt = 0
var unhiddenCnt = 0
selectedPositions.mapNotNull { media.getOrNull(it) }.forEach {
if (it.name.startsWith('.')) {
hiddenCnt++
} else {
unhiddenCnt++
}
}
menu.findItem(R.id.cab_hide).isVisible = unhiddenCnt > 0
menu.findItem(R.id.cab_unhide).isVisible = hiddenCnt > 0
}
menu.findItem(R.id.cab_hide).isVisible = unhiddenCnt > 0
menu.findItem(R.id.cab_unhide).isVisible = hiddenCnt > 0
}
private fun confirmSelection() {
@ -159,25 +127,25 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>,
RenameItemDialog(activity, getCurrentFile().absolutePath) {
activity.runOnUiThread {
listener?.refreshItems()
actMode?.finish()
finishActMode()
}
}
}
private fun editFile() {
activity.openEditor(Uri.fromFile(getCurrentFile()))
actMode?.finish()
finishActMode()
}
private fun toggleFileVisibility(hide: Boolean) {
Thread({
getSelectedMedia().forEach {
val oldFile = File(it.path)
activity.toggleFileVisibility(oldFile, hide) {}
activity.toggleFileVisibility(oldFile, hide)
}
activity.runOnUiThread {
listener?.refreshItems()
actMode?.finish()
finishActMode()
}
}).start()
}
@ -199,20 +167,10 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>,
if (!isCopyOperation) {
listener?.refreshItems()
}
actMode?.finish()
finishActMode()
}
}
fun selectAll() {
val cnt = media.size
for (i in 0 until cnt) {
selectedPositions.add(i)
multiSelector.setSelected(i, 0, true)
notifyItemChanged(i)
}
updateTitle(cnt)
}
private fun checkDeleteConfirmation() {
if (skipConfirmationDialog) {
deleteConfirmed()
@ -243,7 +201,7 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>,
val removeMedia = ArrayList<Medium>(selectedPositions.size)
if (media.size <= selectedPositions.first()) {
actMode?.finish()
finishActMode()
return
}
@ -257,7 +215,6 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>,
}
media.removeAll(removeMedia)
selectedPositions.clear()
listener?.deleteFiles(files)
val newItems = SparseArray<View>()
@ -266,7 +223,8 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>,
.forEachIndexed { curIndex, i -> newItems.put(curIndex, itemViews[i]) }
itemViews = newItems
actMode?.finish()
selectableItemCount = media.size
finishActMode()
}
}
@ -276,29 +234,18 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>,
return selectedMedia
}
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 view = LayoutInflater.from(parent?.context).inflate(layoutType, parent, false)
return ViewHolder(view, adapterListener, activity, multiSelectorMode, multiSelector, listener, allowMultiplePicks || !isAGetIntent, itemClick)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
itemViews.put(position, holder.bindView(media[position], displayFilenames, scrollHorizontally, isListViewType, textColor, animateGifs, cropThumbnails))
toggleItemSelection(selectedPositions.contains(position), position)
holder.itemView.tag = holder
}
override fun onViewRecycled(holder: ViewHolder?) {
super.onViewRecycled(holder)
holder?.stopLoad()
if (!activity.isActivityDestroyed()) {
Glide.with(activity).clear(holder?.itemView?.medium_thumbnail)
}
}
override fun getItemCount() = media.size
fun updateMedia(newMedia: ArrayList<Medium>) {
media = newMedia
selectableItemCount = media.size
notifyDataSetChanged()
actMode?.finish()
finishActMode()
}
fun updateDisplayFilenames(displayFilenames: Boolean) {
@ -321,112 +268,25 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>,
notifyDataSetChanged()
}
fun updateTextColor(textColor: Int) {
this.textColor = textColor
notifyDataSetChanged()
}
private fun setupView(view: View, medium: Medium) {
view.apply {
play_outline.beVisibleIf(medium.video)
photo_name.beVisibleIf(displayFilenames || isListViewType)
photo_name.text = medium.name
activity.loadImage(medium.path, medium_thumbnail, scrollHorizontally, animateGifs, cropThumbnails)
fun selectItem(pos: Int) {
toggleItemSelection(true, pos)
}
fun selectRange(from: Int, to: Int, min: Int, max: Int) {
if (from == to) {
(min..max).filter { it != from }
.forEach { toggleItemSelection(false, it) }
return
}
if (to < from) {
for (i in to..from)
toggleItemSelection(true, i)
if (min > -1 && min < to) {
(min until to).filter { it != from }
.forEach { toggleItemSelection(false, it) }
}
if (max > -1) {
for (i in from + 1..max)
toggleItemSelection(false, i)
}
} else {
for (i in from..to)
toggleItemSelection(true, i)
if (max > -1 && max > to) {
(to + 1..max).filter { it != from }
.forEach { toggleItemSelection(false, it) }
}
if (min > -1) {
for (i in min until from)
toggleItemSelection(false, i)
if (isListViewType) {
photo_name.setTextColor(textColor)
play_outline.setColorFilter(textColor, PorterDuff.Mode.SRC_IN)
}
}
}
class ViewHolder(val view: View, val adapterListener: MyAdapterListener, val activity: SimpleActivity, val multiSelectorCallback: ModalMultiSelectorCallback,
val multiSelector: MultiSelector, val listener: MediaOperationsListener?, val allowMultiplePicks: Boolean,
val itemClick: (Medium) -> (Unit)) :
SwappingHolder(view, MultiSelector()) {
fun bindView(medium: Medium, displayFilenames: Boolean, scrollHorizontally: Boolean, isListViewType: Boolean, textColor: Int,
animateGifs: Boolean, cropThumbnails: Boolean): View {
itemView.apply {
play_outline.visibility = if (medium.video) View.VISIBLE else View.GONE
photo_name.beVisibleIf(displayFilenames || isListViewType)
photo_name.text = medium.name
activity.loadImage(medium.path, medium_thumbnail, scrollHorizontally, animateGifs, cropThumbnails)
if (isListViewType) {
photo_name.setTextColor(textColor)
play_outline.setColorFilter(textColor, PorterDuff.Mode.SRC_IN)
}
setOnClickListener { viewClicked(medium) }
setOnLongClickListener { if (allowMultiplePicks) viewLongClicked() else viewClicked(medium); true }
}
return itemView
}
private fun viewClicked(medium: Medium) {
if (multiSelector.isSelectable) {
val isSelected = adapterListener.getSelectedPositions().contains(adapterPosition)
adapterListener.toggleItemSelectionAdapter(!isSelected, adapterPosition)
} else {
itemClick(medium)
}
}
private fun viewLongClicked() {
if (listener != null) {
if (!multiSelector.isSelectable) {
activity.startSupportActionMode(multiSelectorCallback)
adapterListener.toggleItemSelectionAdapter(true, adapterPosition)
}
listener.itemLongClicked(adapterPosition)
}
}
fun stopLoad() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 || !activity.isDestroyed)
Glide.with(activity).clear(view.medium_thumbnail)
}
}
interface MyAdapterListener {
fun toggleItemSelectionAdapter(select: Boolean, position: Int)
fun getSelectedPositions(): HashSet<Int>
}
interface MediaOperationsListener {
fun refreshItems()
fun deleteFiles(files: ArrayList<File>)
fun itemLongClicked(position: Int)
fun selectedPaths(paths: ArrayList<String>)
}
}

View file

@ -4,15 +4,15 @@ import android.content.DialogInterface
import android.support.v7.app.AlertDialog
import android.view.LayoutInflater
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.commons.helpers.*
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.SimpleActivity
import com.simplemobiletools.gallery.extensions.config
import kotlinx.android.synthetic.main.dialog_change_sorting.view.*
class ChangeSortingDialog(val activity: SimpleActivity, val isDirectorySorting: Boolean, showFolderCheckbox: Boolean,
class ChangeSortingDialog(val activity: BaseSimpleActivity, val isDirectorySorting: Boolean, showFolderCheckbox: Boolean,
val path: String = "", val callback: () -> Unit) :
DialogInterface.OnClickListener {
private var currSorting = 0

View file

@ -5,15 +5,15 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.RadioButton
import android.widget.RadioGroup
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.getBasePath
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.SimpleActivity
import com.simplemobiletools.gallery.extensions.config
import kotlinx.android.synthetic.main.dialog_exclude_folder.view.*
class ExcludeFolderDialog(val activity: SimpleActivity, val selectedPaths: List<String>, val callback: () -> Unit) {
class ExcludeFolderDialog(val activity: BaseSimpleActivity, val selectedPaths: List<String>, val callback: () -> Unit) {
val alternativePaths = getAlternativePathsList()
var radioGroup: RadioGroup? = null

View file

@ -3,16 +3,16 @@ package com.simplemobiletools.gallery.dialogs
import android.support.v7.app.AlertDialog
import android.view.LayoutInflater
import android.view.View
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.SimpleActivity
import com.simplemobiletools.gallery.extensions.config
import com.simplemobiletools.gallery.helpers.GIFS
import com.simplemobiletools.gallery.helpers.IMAGES
import com.simplemobiletools.gallery.helpers.VIDEOS
import kotlinx.android.synthetic.main.dialog_filter_media.view.*
class FilterMediaDialog(val activity: SimpleActivity, val callback: (result: Int) -> Unit) {
class FilterMediaDialog(val activity: BaseSimpleActivity, val callback: (result: Int) -> Unit) {
private var view: View = LayoutInflater.from(activity).inflate(R.layout.dialog_filter_media, null)
init {

View file

@ -3,6 +3,7 @@ package com.simplemobiletools.gallery.dialogs
import android.support.v7.app.AlertDialog
import android.view.LayoutInflater
import android.view.View
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.SimpleActivity
@ -10,7 +11,7 @@ import com.simplemobiletools.gallery.extensions.config
import com.simplemobiletools.gallery.helpers.*
import kotlinx.android.synthetic.main.dialog_manage_extended_details.view.*
class ManageExtendedDetailsDialog(val activity: SimpleActivity, val callback: (result: Int) -> Unit) {
class ManageExtendedDetailsDialog(val activity: BaseSimpleActivity, val callback: (result: Int) -> Unit) {
private var view: View = LayoutInflater.from(activity).inflate(R.layout.dialog_manage_extended_details, null)
init {

View file

@ -3,15 +3,16 @@ package com.simplemobiletools.gallery.dialogs
import android.support.v7.app.AlertDialog
import android.support.v7.widget.GridLayoutManager
import android.view.LayoutInflater
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.dialogs.FilePickerDialog
import com.simplemobiletools.commons.extensions.beGoneIf
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.SimpleActivity
import com.simplemobiletools.gallery.adapters.DirectoryAdapter
import com.simplemobiletools.gallery.asynctasks.GetDirectoriesAsynctask
import com.simplemobiletools.gallery.extensions.addTempFolderIfNeeded
import com.simplemobiletools.gallery.extensions.config
import com.simplemobiletools.gallery.extensions.getCachedDirectories
import com.simplemobiletools.gallery.extensions.getSortedDirectories
@ -19,7 +20,7 @@ import com.simplemobiletools.gallery.helpers.VIEW_TYPE_GRID
import com.simplemobiletools.gallery.models.Directory
import kotlinx.android.synthetic.main.dialog_directory_picker.view.*
class PickDirectoryDialog(val activity: SimpleActivity, val sourcePath: String, val callback: (path: String) -> Unit) {
class PickDirectoryDialog(val activity: BaseSimpleActivity, val sourcePath: String, val callback: (path: String) -> Unit) {
var dialog: AlertDialog
var shownDirectories = ArrayList<Directory>()
var view = LayoutInflater.from(activity).inflate(R.layout.dialog_directory_picker, null)
@ -62,8 +63,8 @@ class PickDirectoryDialog(val activity: SimpleActivity, val sourcePath: String,
return
shownDirectories = dirs
val adapter = DirectoryAdapter(activity, dirs, null, true) {
if (it.path.trimEnd('/') == sourcePath) {
val adapter = DirectoryAdapter(activity, dirs, null, view.directories_grid, true) {
if ((it as Directory).path.trimEnd('/') == sourcePath) {
activity.toast(R.string.source_and_destination_same)
return@DirectoryAdapter
} else {

View file

@ -3,11 +3,11 @@ package com.simplemobiletools.gallery.dialogs
import android.support.v7.app.AlertDialog
import android.support.v7.widget.GridLayoutManager
import android.view.LayoutInflater
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.beGoneIf
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.SimpleActivity
import com.simplemobiletools.gallery.adapters.MediaAdapter
import com.simplemobiletools.gallery.asynctasks.GetMediaAsynctask
import com.simplemobiletools.gallery.extensions.config
@ -16,7 +16,7 @@ import com.simplemobiletools.gallery.helpers.VIEW_TYPE_GRID
import com.simplemobiletools.gallery.models.Medium
import kotlinx.android.synthetic.main.dialog_medium_picker.view.*
class PickMediumDialog(val activity: SimpleActivity, val path: String, val callback: (path: String) -> Unit) {
class PickMediumDialog(val activity: BaseSimpleActivity, val path: String, val callback: (path: String) -> Unit) {
var dialog: AlertDialog
var shownMedia = ArrayList<Medium>()
val view = LayoutInflater.from(activity).inflate(R.layout.dialog_medium_picker, null)
@ -58,8 +58,8 @@ class PickMediumDialog(val activity: SimpleActivity, val path: String, val callb
return
shownMedia = media
val adapter = MediaAdapter(activity, media, null, true, false) {
callback(it.path)
val adapter = MediaAdapter(activity, media, null, true, false, view.media_grid) {
callback((it as Medium).path)
dialog.dismiss()
}

View file

@ -7,14 +7,14 @@ import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.WindowManager
import android.widget.EditText
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.extensions.value
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.SimpleActivity
import kotlinx.android.synthetic.main.resize_image.view.*
class ResizeDialog(val activity: SimpleActivity, val size: Point, val callback: (newSize: Point) -> Unit) {
class ResizeDialog(val activity: BaseSimpleActivity, val size: Point, val callback: (newSize: Point) -> Unit) {
init {
val view = LayoutInflater.from(activity).inflate(R.layout.resize_image, null)
val widthView = view.image_width

View file

@ -3,15 +3,15 @@ package com.simplemobiletools.gallery.dialogs
import android.support.v7.app.AlertDialog
import android.view.LayoutInflater
import android.view.WindowManager
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.dialogs.FilePickerDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.SimpleActivity
import kotlinx.android.synthetic.main.dialog_save_as.view.*
import java.io.File
class SaveAsDialog(val activity: SimpleActivity, val path: String, val appendFilename: Boolean, val callback: (savePath: String) -> Unit) {
class SaveAsDialog(val activity: BaseSimpleActivity, val path: String, val appendFilename: Boolean, val callback: (savePath: String) -> Unit) {
init {
var realPath = File(path).parent.trimEnd('/')

View file

@ -4,16 +4,16 @@ import android.support.v7.app.AlertDialog
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.hideKeyboard
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.SimpleActivity
import com.simplemobiletools.gallery.extensions.config
import com.simplemobiletools.gallery.helpers.SLIDESHOW_DEFAULT_INTERVAL
import kotlinx.android.synthetic.main.dialog_slideshow.view.*
class SlideshowDialog(val activity: SimpleActivity, val callback: () -> Unit) {
class SlideshowDialog(val activity: BaseSimpleActivity, val callback: () -> Unit) {
val view: View
init {

View file

@ -14,11 +14,13 @@ import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestOptions
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.gallery.BuildConfig
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.Directory
import com.simplemobiletools.gallery.models.Medium
@ -89,7 +91,7 @@ fun AppCompatActivity.hideSystemUI() {
View.SYSTEM_UI_FLAG_IMMERSIVE
}
fun SimpleActivity.addNoMedia(path: String, callback: () -> Unit) {
fun BaseSimpleActivity.addNoMedia(path: String, callback: () -> Unit) {
val file = File(path, NOMEDIA)
if (file.exists())
return
@ -116,14 +118,14 @@ fun SimpleActivity.addNoMedia(path: String, callback: () -> Unit) {
}
}
fun SimpleActivity.removeNoMedia(path: String, callback: () -> Unit) {
fun BaseSimpleActivity.removeNoMedia(path: String, callback: (() -> Unit)? = null) {
val file = File(path, NOMEDIA)
deleteFile(file) {
callback()
callback?.invoke()
}
}
fun SimpleActivity.toggleFileVisibility(oldFile: File, hide: Boolean, callback: (newFile: File) -> Unit) {
fun BaseSimpleActivity.toggleFileVisibility(oldFile: File, hide: Boolean, callback: ((newFile: File) -> Unit)? = null) {
val path = oldFile.parent
var filename = oldFile.name
filename = if (hide) {
@ -133,7 +135,7 @@ fun SimpleActivity.toggleFileVisibility(oldFile: File, hide: Boolean, callback:
}
val newFile = File(path, filename)
renameFile(oldFile, newFile) {
callback(newFile)
callback?.invoke(newFile)
}
}
@ -158,10 +160,35 @@ fun Activity.loadImage(path: String, target: MySquareImageView, horizontalScroll
target.scaleType = if (cropThumbnails) ImageView.ScaleType.CENTER_CROP else ImageView.ScaleType.FIT_CENTER
} catch (e: Exception) {
loadJpg(path, target, cropThumbnails)
} catch (e: OutOfMemoryError) {
loadJpg(path, target, cropThumbnails)
}
}
}
fun BaseSimpleActivity.tryCopyMoveFilesTo(files: ArrayList<File>, isCopyOperation: Boolean, callback: () -> Unit) {
if (files.isEmpty()) {
toast(R.string.unknown_error_occurred)
return
}
val source = if (files[0].isFile) files[0].parent else files[0].absolutePath
PickDirectoryDialog(this, source) {
copyMoveFilesTo(files, source.trimEnd('/'), it, isCopyOperation, true, callback)
}
}
fun BaseSimpleActivity.addTempFolderIfNeeded(dirs: ArrayList<Directory>): ArrayList<Directory> {
val directories = ArrayList<Directory>()
val tempFolderPath = config.tempFolderPath
if (tempFolderPath.isNotEmpty()) {
val newFolder = Directory(tempFolderPath, "", tempFolderPath.getFilenameFromPath(), 0, 0, 0, 0L)
directories.add(newFolder)
}
directories.addAll(dirs)
return directories
}
fun Activity.loadPng(path: String, target: MySquareImageView, cropThumbnails: Boolean) {
val options = RequestOptions()
.signature(path.getFileSignature())

View file

@ -7,7 +7,6 @@ import android.graphics.Color
import android.graphics.Matrix
import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -27,6 +26,7 @@ import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.PhotoActivity
import com.simplemobiletools.gallery.activities.ViewPagerActivity
import com.simplemobiletools.gallery.extensions.*
import com.simplemobiletools.gallery.helpers.GlideDecoder
import com.simplemobiletools.gallery.helpers.GlideRotateTransformation
import com.simplemobiletools.gallery.helpers.MEDIUM
import com.simplemobiletools.gallery.models.Medium
@ -37,7 +37,9 @@ import java.io.File
import java.io.FileOutputStream
class PhotoFragment : ViewPagerFragment() {
private var DEFAULT_DOUBLE_TAP_ZOOM = 5f
private var isFragmentVisible = false
private var isFullscreen = false
private var wasInit = false
private var storedShowExtendedDetails = false
private var storedExtendedDetails = 0
@ -85,6 +87,7 @@ class PhotoFragment : ViewPagerFragment() {
}
}
isFullscreen = activity!!.window.decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_FULLSCREEN == View.SYSTEM_UI_FLAG_FULLSCREEN
view.subsampling_view.setOnClickListener { photoClicked() }
view.gif_view.setOnClickListener { photoClicked() }
loadImage()
@ -131,12 +134,6 @@ class PhotoFragment : ViewPagerFragment() {
private fun photoFragmentVisibilityChanged(isVisible: Boolean) {
if (isVisible) {
addZoomableView()
} else {
view.subsampling_view.apply {
recycle()
beGone()
background = ColorDrawable(Color.TRANSPARENT)
}
}
}
@ -224,9 +221,10 @@ class PhotoFragment : ViewPagerFragment() {
}
private fun addZoomableView() {
if ((medium.isImage()) && isFragmentVisible && view.subsampling_view.visibility == View.GONE) {
if ((medium.isImage()) && isFragmentVisible && view.subsampling_view.isGone()) {
ViewPagerActivity.wasDecodedByGlide = false
view.subsampling_view.apply {
//setBitmapDecoderClass(GlideDecoder::class.java) // causing random crashes on Android 7+, at rotating
setBitmapDecoderClass(GlideDecoder::class.java)
maxScale = 10f
beVisible()
setImage(ImageSource.uri(medium.path))
@ -268,20 +266,28 @@ class PhotoFragment : ViewPagerFragment() {
val height = bitmapOptions.outHeight
val bitmapAspectRatio = height / (width).toFloat()
if (context == null)
return 2f
return if (context!!.portrait && bitmapAspectRatio <= 1f) {
return if (context == null) {
DEFAULT_DOUBLE_TAP_ZOOM
} else if (ViewPagerActivity.screenHeight / ViewPagerActivity.screenWidth.toFloat() == bitmapAspectRatio) {
DEFAULT_DOUBLE_TAP_ZOOM
} else if (ViewPagerActivity.wasDecodedByGlide) {
1f
} else if (context!!.portrait && bitmapAspectRatio <= 1f) {
ViewPagerActivity.screenHeight / height.toFloat()
} else if (context!!.portrait && bitmapAspectRatio > 1f) {
ViewPagerActivity.screenHeight / width.toFloat()
} else if (!context!!.portrait && bitmapAspectRatio >= 1f) {
ViewPagerActivity.screenWidth / width.toFloat()
} else if (!context!!.portrait && bitmapAspectRatio < 1f) {
ViewPagerActivity.screenWidth / height.toFloat()
} else {
2f
DEFAULT_DOUBLE_TAP_ZOOM
}
}
fun rotateImageViewBy(degrees: Float) {
view.subsampling_view.beGone()
// do not make Subsampling view Gone, because it gets recycled and can crash with "Error, cannot access an invalid/free'd bitmap here!"
view.subsampling_view.beInvisible()
loadBitmap(degrees)
}
@ -292,9 +298,8 @@ class PhotoFragment : ViewPagerFragment() {
setTextColor(context.config.textColor)
beVisibleIf(text.isNotEmpty())
onGlobalLayout {
if (height != 0) {
val smallMargin = resources.getDimension(R.dimen.small_margin)
y = context.usableScreenSize.y - height - if (context.navigationBarHeight == 0) smallMargin else 0f
if (height != 0 && isAdded) {
y = getExtendedDetailsY(height)
}
}
}
@ -305,7 +310,7 @@ class PhotoFragment : ViewPagerFragment() {
override fun onDestroyView() {
super.onDestroyView()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && !activity!!.isDestroyed) {
if (activity?.isActivityDestroyed() == false) {
Glide.with(context).clear(view.gif_view)
}
}
@ -321,13 +326,17 @@ class PhotoFragment : ViewPagerFragment() {
}
override fun fullscreenToggled(isFullscreen: Boolean) {
this.isFullscreen = isFullscreen
view.photo_details.apply {
if (visibility == View.VISIBLE) {
val smallMargin = resources.getDimension(R.dimen.small_margin)
val fullscreenOffset = context.navigationBarHeight.toFloat() - smallMargin
val newY = context.usableScreenSize.y - height + if (isFullscreen) fullscreenOffset else -(if (context.navigationBarHeight == 0) smallMargin else 0f)
animate().y(newY)
if (isVisible()) {
animate().y(getExtendedDetailsY(height))
}
}
}
private fun getExtendedDetailsY(height: Int): Float {
val smallMargin = resources.getDimension(R.dimen.small_margin)
val fullscreenOffset = context!!.navigationBarHeight.toFloat() - smallMargin
return context!!.usableScreenSize.y - height + if (isFullscreen) fullscreenOffset else -(if (context!!.navigationBarHeight == 0) smallMargin else 0f)
}
}

View file

@ -34,6 +34,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
private var mCurrTimeView: TextView? = null
private var mTimerHandler: Handler? = null
private var mSeekBar: SeekBar? = null
private var mTimeHolder: View? = null
private var mIsPlaying = false
private var mIsDragged = false
@ -60,7 +61,6 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
lateinit var mView: View
lateinit var medium: Medium
lateinit var mTimeHolder: View
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mView = inflater.inflate(R.layout.pager_video_item, container, false)
@ -287,8 +287,8 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
private fun initTimeHolder() {
val res = resources
val height = context!!.navigationBarHeight
val left = mTimeHolder.paddingLeft
val top = mTimeHolder.paddingTop
val left = mTimeHolder!!.paddingLeft
val top = mTimeHolder!!.paddingTop
var right = res.getDimension(R.dimen.timer_padding).toInt()
var bottom = 0
@ -299,7 +299,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
right += height
bottom += context!!.navigationBarHeight
}
mTimeHolder.setPadding(left, top, right, bottom)
mTimeHolder!!.setPadding(left, top, right, bottom)
}
mCurrTimeView = mView.video_curr_time
@ -307,7 +307,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
mSeekBar!!.setOnSeekBarChangeListener(this)
if (mIsFullscreen)
mTimeHolder.beInvisible()
mTimeHolder!!.beInvisible()
}
private fun hasNavBar(): Boolean {
@ -375,7 +375,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
AnimationUtils.loadAnimation(activity, anim).apply {
duration = 150
fillAfter = true
mTimeHolder.startAnimation(this)
mTimeHolder?.startAnimation(this)
}
}
@ -457,9 +457,13 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
releaseMediaPlayer()
mSeekBar?.progress = 0
mTimerHandler?.removeCallbacksAndMessages(null)
mSurfaceView = null
mSurfaceHolder?.removeCallback(this)
mSurfaceHolder = null
}
private fun releaseMediaPlayer() {
mMediaPlayer?.setSurface(null)
mMediaPlayer?.release()
mMediaPlayer = null
}
@ -551,10 +555,8 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
setTextColor(context.config.textColor)
beVisibleIf(text.isNotEmpty())
onGlobalLayout {
if (height != 0) {
val smallMargin = resources.getDimension(R.dimen.small_margin)
val timeHolderHeight = mTimeHolder.height - context.navigationBarHeight
y = context.usableScreenSize.y - height - timeHolderHeight - if (context.navigationBarHeight == 0) smallMargin else 0f
if (height != 0 && isAdded) {
y = getExtendedDetailsY(height)
}
}
}
@ -592,13 +594,16 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
mIsFullscreen = isFullscreen
checkFullscreen()
mView.video_details.apply {
if (visibility == View.VISIBLE) {
val smallMargin = resources.getDimension(R.dimen.small_margin)
val timeHolderHeight = mTimeHolder.height - context.navigationBarHeight.toFloat()
val fullscreenOffset = context.navigationBarHeight.toFloat() - smallMargin
val newY = context.usableScreenSize.y - height + if (mIsFullscreen) fullscreenOffset else -(timeHolderHeight + if (context.navigationBarHeight == 0) smallMargin else 0f)
animate().y(newY)
if (isVisible()) {
animate().y(getExtendedDetailsY(height))
}
}
}
private fun getExtendedDetailsY(height: Int): Float {
val smallMargin = resources.getDimension(R.dimen.small_margin)
val timeHolderHeight = mTimeHolder!!.height - context!!.navigationBarHeight.toFloat()
val fullscreenOffset = context!!.navigationBarHeight.toFloat() - smallMargin
return context!!.usableScreenSize.y - height + if (mIsFullscreen) fullscreenOffset else -(timeHolderHeight + if (context!!.navigationBarHeight == 0) smallMargin else 0f)
}
}

View file

@ -23,6 +23,7 @@ class GlideDecoder : ImageDecoder {
val targetWidth = if (ViewPagerActivity.screenWidth == 0) Target.SIZE_ORIGINAL else ViewPagerActivity.screenWidth
val targetHeight = if (ViewPagerActivity.screenHeight == 0) Target.SIZE_ORIGINAL else ViewPagerActivity.screenHeight
ViewPagerActivity.wasDecodedByGlide = true
val options = RequestOptions()
.signature(uri.path.getFileSignature())
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)

View file

@ -247,7 +247,6 @@ class MediaFetcher(val context: Context) {
private fun isThisOrParentExcluded(path: String, excludedPaths: MutableSet<String>, includedPaths: MutableSet<String>) =
includedPaths.none { path.startsWith(it) } && excludedPaths.any { path.startsWith(it) }
private fun getMediaInFolder(folder: String, curMedia: ArrayList<Medium>, isPickImage: Boolean, isPickVideo: Boolean, filterMedia: Int) {
val files = File(folder).listFiles() ?: return
for (file in files) {
@ -282,7 +281,7 @@ class MediaFetcher(val context: Context) {
val isAlreadyAdded = curMedia.any { it.path == file.absolutePath }
if (!isAlreadyAdded) {
curMedia.add(medium)
context.scanPath(file.absolutePath) {}
context.scanPath(file.absolutePath)
}
}
}
@ -296,10 +295,11 @@ class MediaFetcher(val context: Context) {
else -> MediaStore.Images.Media.DATE_TAKEN
}
return if (sorting and SORT_DESCENDING > 0)
return if (sorting and SORT_DESCENDING > 0) {
"$sortValue DESC"
else
} else {
"$sortValue ASC"
}
}
private fun getNoMediaFolders(): ArrayList<String> {

View file

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/excluded_folders_scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="@+id/exclude_folders_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/excluded_folders_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/excluded_folders_placeholder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingLeft="@dimen/big_margin"
android:paddingRight="@dimen/big_margin"
android:paddingTop="@dimen/activity_margin"
android:text="@string/excluded_activity_placeholder"
android:visibility="gone"/>
</RelativeLayout>
</ScrollView>

View file

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/included_folders_scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="@+id/include_folders_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/included_folders_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/included_folders_placeholder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingLeft="@dimen/big_margin"
android:paddingRight="@dimen/big_margin"
android:paddingTop="@dimen/activity_margin"
android:text="@string/included_activity_placeholder"
android:visibility="gone"/>
</RelativeLayout>
</ScrollView>

View file

@ -33,7 +33,7 @@
android:text="@string/change_filters_underlined"
android:visibility="gone"/>
<com.simplemobiletools.commons.views.MyScalableRecyclerView
<com.simplemobiletools.commons.views.MyRecyclerView
android:id="@+id/directories_grid"
android:layout_width="match_parent"
android:layout_height="wrap_content"

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/manage_folders_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.simplemobiletools.commons.views.MyRecyclerView
android:id="@+id/manage_folders_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"/>
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/manage_folders_placeholder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingLeft="@dimen/big_margin"
android:paddingRight="@dimen/big_margin"
android:paddingTop="@dimen/activity_margin"
android:text="@string/excluded_activity_placeholder"
android:visibility="gone"/>
</RelativeLayout>

View file

@ -33,7 +33,7 @@
android:text="@string/change_filters_underlined"
android:visibility="gone"/>
<com.simplemobiletools.commons.views.MyScalableRecyclerView
<com.simplemobiletools.commons.views.MyRecyclerView
android:id="@+id/media_grid"
android:layout_width="match_parent"
android:layout_height="wrap_content"

View file

@ -7,7 +7,7 @@
android:layout_height="wrap_content"
android:paddingTop="@dimen/activity_margin">
<com.simplemobiletools.commons.views.MyScalableRecyclerView
<com.simplemobiletools.commons.views.MyRecyclerView
android:id="@+id/directories_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"

View file

@ -6,7 +6,7 @@
android:layout_height="wrap_content"
android:paddingTop="@dimen/activity_margin">
<com.simplemobiletools.commons.views.MyScalableRecyclerView
<com.simplemobiletools.commons.views.MyRecyclerView
android:id="@+id/media_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"

View file

@ -4,6 +4,8 @@
android:id="@+id/dir_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:padding="1px">
<com.simplemobiletools.gallery.views.MySquareImageView
@ -21,7 +23,8 @@
android:layout_margin="@dimen/small_margin"
android:background="@drawable/circle_background"
android:padding="@dimen/tiny_margin"
android:src="@drawable/ic_check"/>
android:src="@drawable/ic_check"
android:visibility="gone"/>
<ImageView
android:id="@+id/dir_pin"
@ -33,7 +36,8 @@
android:layout_margin="@dimen/small_margin"
android:background="@drawable/circle_black_background"
android:padding="@dimen/small_margin"
android:src="@drawable/ic_pin"/>
android:src="@drawable/ic_pin"
android:visibility="gone"/>
<ImageView
android:id="@+id/dir_shadow_holder"

View file

@ -5,6 +5,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/small_margin"
android:clickable="true"
android:focusable="true"
android:paddingTop="@dimen/small_margin">
<com.simplemobiletools.gallery.views.MySquareImageView
@ -22,7 +24,8 @@
android:layout_margin="@dimen/small_margin"
android:background="@drawable/circle_background"
android:padding="@dimen/tiny_margin"
android:src="@drawable/ic_check"/>
android:src="@drawable/ic_check"
android:visibility="gone"/>
<TextView
android:id="@+id/dir_name"

View file

@ -1,29 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/managed_folder_holder"
android:id="@+id/manage_folder_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:foreground="@drawable/selector"
android:padding="@dimen/activity_margin">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/managed_folder_title"
android:id="@+id/manage_folder_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/medium_margin"
android:layout_marginRight="@dimen/medium_margin"
android:layout_toLeftOf="@+id/managed_folders_icon"
android:layout_toStartOf="@+id/managed_folders_icon"/>
<ImageView
android:id="@+id/managed_folders_icon"
style="@style/MyBorderlessBackgroundStyle"
android:layout_width="@dimen/normal_icon_size"
android:layout_height="@dimen/normal_icon_size"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_cross"/>
android:layout_marginTop="@dimen/medium_margin"/>
</RelativeLayout>

View file

@ -4,6 +4,8 @@
android:id="@+id/media_item_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:padding="1px">
<com.simplemobiletools.gallery.views.MySquareImageView

View file

@ -4,6 +4,8 @@
android:id="@+id/media_item_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:paddingLeft="@dimen/small_margin"
android:paddingTop="@dimen/small_margin">

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<background android:drawable="@color/color_primary"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<background android:drawable="@color/color_primary"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

View file

@ -23,8 +23,8 @@
<string name="volume">Lautstärke</string>
<string name="brightness">Helligkeit</string>
<string name="do_not_ask_again">Nicht erneut fragen (in dieser Sitzung)</string>
<string name="lock_orientation">Lock orientation</string>
<string name="unlock_orientation">Unlock orientation</string>
<string name="lock_orientation">Bildschirmausrichtung sperren</string>
<string name="unlock_orientation">Bildschirmausrichtung entsperren</string>
<!-- Filter -->
<string name="filter_media">Filter</string>

View file

@ -23,8 +23,8 @@
<string name="volume">Volume</string>
<string name="brightness">Luminosità</string>
<string name="do_not_ask_again">Non chiedere nuovamente in questa sessione</string>
<string name="lock_orientation">Lock orientation</string>
<string name="unlock_orientation">Unlock orientation</string>
<string name="lock_orientation">Blocca orientamento</string>
<string name="unlock_orientation">Sblocca orientamento</string>
<!-- Filter -->
<string name="filter_media">Filtra i media</string>
@ -115,7 +115,7 @@
<string name="animate_gifs">Anima le GIF in miniatura</string>
<string name="max_brightness">Luminosità max durante visualizzazione</string>
<string name="crop_thumbnails">Ritaglia le miniature in quadrati</string>
<string name="screen_rotation_by">Ruota a schermo intero per</string>
<string name="screen_rotation_by">Ruota schermo per</string>
<string name="screen_rotation_system_setting">Impostazione di sistema</string>
<string name="screen_rotation_device_rotation">Rotazione dispositivo</string>
<string name="screen_rotation_aspect_ratio">Proporzioni</string>
@ -133,7 +133,7 @@
<!-- Short description has to have less than 80 chars -->
<string name="app_short_description">Una galleria per visualizzare foto e video senza pubblicità.</string>
<string name="app_long_description">
Un semplice strumento per visualizzare foto e video. Gli elementi possono essere ordinati per data, dimensioni, nome sia ascendente che discendente; le foto possono essere ingrandite. I file sono mostrati in colonne multiple a seconda delle dimensioni dello schermo, puoi modificare il numero di colonne con il tocco. Possono essere rinominate, condivise, eliminate, copiate, spostate. Le immagini possono anche essere ritagliate, ruotate o impostate come sfondo direttamente dall\'app.
Un semplice strumento per visualizzare foto e video. Gli elementi possono essere ordinati per data, dimensioni, nome sia ascendente che discendente; le foto possono essere ingrandite. I file sono mostrati in colonne multiple a seconda delle dimensioni dello schermo, puoi modificare il numero di colonne con il tocco. Possono essere rinominate, condivise, eliminate, copiate, spostate. Le immagini possono anche essere ritagliate, ruotate o impostate come sfondo direttamente dalla app.
Simple Gallery è anche offerta per utilizzo di terze parti per anteprime di immagini / video, aggiunta di allegati ai client email, ecc. È perfetta per un uso quotidiano.

View file

@ -27,12 +27,12 @@
<string name="unlock_orientation">Schermrotatie ontgrendelen</string>
<!-- Filter -->
<string name="filter_media">Media kiezen</string>
<string name="filter_media">Filter media</string>
<string name="images">Afbeeldingen</string>
<string name="videos">Video\'s</string>
<string name="gifs">GIF-bestanden</string>
<string name="no_media_with_filters">Geen bestanden gevonden met de huidige filters.</string>
<string name="change_filters_underlined"><u>Media kiezen</u></string>
<string name="change_filters_underlined"><u>Filters aanpassen</u></string>
<!-- Hide / Exclude -->
<string name="hide_folder_description">Deze functie verbergt de map door het bestand \'.nomedia\' toe te voegen. Alle submappen zullen ook worden verborgen. Kies \'Verborgen mappen tonen\' in de instellingen om toch verborgen mappen te kunnen inzien. Doorgaan?</string>
@ -46,8 +46,8 @@
<string name="remove_all_description">Verwijder alles uit de lijst van uitgesloten mappen? Dit zal de mappen zelf niet verwijderen.</string>
<!-- Include folders -->
<string name="include_folders">Ingesloten mappen</string>
<string name="manage_included_folders">Ingesloten mappen beheren</string>
<string name="include_folders">Toegevoegde mappen</string>
<string name="manage_included_folders">Toegevoegde mappen beheren</string>
<string name="add_folder">Map toevoegen</string>
<string name="included_activity_placeholder">Als er mappen zijn die wel media bevatten, maar niet niet door de galerij worden herkend, voeg deze mappen dan hier handmatig toe.\n\nHet hier toevoegen van mappen zal andere mappen niet uitsluiten.</string>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Simple Gallery</string>
<string name="app_launcher_name">Simple Gallery</string>
<string name="app_name">Prosta Galeria</string>
<string name="app_launcher_name">Galeria</string>
<string name="edit">Edytuj</string>
<string name="open_camera">Uruchom aplikację aparatu</string>
<string name="hidden">(ukryty)</string>
@ -23,8 +23,8 @@
<string name="volume">Głośność</string>
<string name="brightness">Jasność</string>
<string name="do_not_ask_again">Nie pytaj więcej w tej sesji</string>
<string name="lock_orientation">Lock orientation</string>
<string name="unlock_orientation">Unlock orientation</string>
<string name="lock_orientation">Zablokuj orientację ekranu</string>
<string name="unlock_orientation">Odblokuj orientację ekranu</string>
<!-- Filter -->
<string name="filter_media">Filtruj multimedia</string>
@ -35,7 +35,7 @@
<string name="change_filters_underlined"><u>Zmień filtry</u></string>
<!-- Hide / Exclude -->
<string name="hide_folder_description">Ta funkcja ukrywa foldery dodając do nich pusty plik .nomedia. Aby móc je zobaczyć, należy włączyć opcję \'Pokazuj ukryte foldery\' w ustawieniach. Kontyntynuować?</string>
<string name="hide_folder_description">Ta funkcja ukrywa foldery, dodając do nich pusty plik .nomedia. Aby móc je zobaczyć, należy włączyć opcję \'Pokazuj ukryte foldery\' w ustawieniach. Kontynuować?</string>
<string name="exclude">Wyklucz</string>
<string name="excluded_folders">Wykluczone foldery</string>
<string name="manage_excluded_folders">Zarządzaj wykluczonymi folderami</string>
@ -49,7 +49,7 @@
<string name="include_folders">Dołączone foldery</string>
<string name="manage_included_folders">Zarządzaj dołączonymi folderami</string>
<string name="add_folder">Dodaj folder</string>
<string name="included_activity_placeholder">Jeśli masz jakieś foldery z multimediami, ale aplikacja ich nie wykryła, możesz je tutaj dodać ręcznie.</string>
<string name="included_activity_placeholder">Jeśli masz jakieś foldery z multimediami, ale aplikacja ich nie wykryła, możesz je dodać ręcznie tutaj.</string>
<!-- Resizing -->
<string name="resize">Zmień rozmiar</string>
@ -131,13 +131,13 @@
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
<!-- Short description has to have less than 80 chars -->
<string name="app_short_description">Darmowa galeria bez reklam do przeglądania obrazów i filmów.</string>
<string name="app_short_description">Prosta galeria bez reklam do przeglądania obrazów i filmów.</string>
<string name="app_long_description">
Prosta aplikacja galerii do oglądania obrazów i filmów. Pliki mogą być sortowane według daty, rozmiaru i nazwy, zarówno w porządku rosnącym, jak i malejącym. W zależności od wielkości ekranu wyświetlane mogą być w wielu kolumnach. Liczbę kolumn można zmieniać za pomocą gestów. Zdjęcia mogą być powiększane, przycinane, obracane lub ustawiane jako tapeta bezpośrednio z poziomu aplikacji. Kolory aplikacji można dowolnie ustawiać.
Prosta aplikacja galerii do oglądania obrazów i filmów. Pliki mogą być sortowane według daty, rozmiaru i nazwy, zarówno w porządku rosnącym, jak i malejącym. W zależności od wielkości ekranu, wyświetlane mogą być w wielu kolumnach. Liczbę kolumn można zmieniać za pomocą gestów, a zdjęcia mogą być powiększane, przycinane, obracane lub ustawiane jako tapeta bezpośrednio z poziomu Prostej Galerii. Kolory aplikacji można dowolnie ustawiać.
Aplikacja nie zawiera żadnych reklam ani niepotrzebnych uprawnień. Jest też w pełni otawrtoźrodłowa.
Nie zawiera natomiast żadnych reklam i nie potrzebuje całej masy uprawnień. Jest w pełni otwartoźródłowa i w pełni podatna na kolorowanie.
Niniejsza aplikacja jest tylko częścią naszego zestawu prostych aplikacji. Znajdziecie je na stronie http://www.simplemobiletools.com.
Niniejsza aplikacja jest tylko częścią naszej kolekcji prostych narzędzi. Ta, jak i pozostałe, dostępne są na stronie http://www.simplemobiletools.com
</string>
<!--

View file

@ -23,8 +23,8 @@
<string name="volume">音量</string>
<string name="brightness">亮度</string>
<string name="do_not_ask_again">不再提醒</string>
<string name="lock_orientation">Lock orientation</string>
<string name="unlock_orientation">Unlock orientation</string>
<string name="lock_orientation">锁定方向</string>
<string name="unlock_orientation">解锁方向</string>
<!-- Filter -->
<string name="filter_media">要显示的媒体文件</string>

View file

@ -7,6 +7,4 @@
<!-- Default colors -->
<color name="default_text_color">@color/default_dark_theme_text_color</color>
<color name="default_background_color">@color/default_dark_theme_background_color</color>
<color name="ic_launcher_background">@color/color_primary</color>
</resources>

View file

@ -2,6 +2,9 @@
<resources>
<!-- Release notes -->
<string name="release_143">
Added new options to use english language on non-english devices, to password protect whole app and to lock screen orientation at fullscreen view
</string>
<string name="release_138">Added an option to keep last-modified field at file copy/move/rename</string>
<string name="release_137">Added an option to hide folder media count on the main screen</string>
<string name="release_136">Added an option to show customizable extended details over fullscreen media</string>