Merge pull request #1 from SimpleMobileTools/master

Get this thing up-to-date
This commit is contained in:
Guillaume 2017-10-31 23:02:01 +01:00 committed by GitHub
commit bc9f62db40
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
52 changed files with 421 additions and 458 deletions

View file

@ -1,6 +1,29 @@
Changelog
==========
Version 2.17.2 *(2017-10-29)*
----------------------------
* Couple more minor fixes
Version 2.17.1 *(2017-10-29)*
----------------------------
* Show "Set As" and "Edit" menu buttons at videos and gifs too
* Couple other smaller issues fixed
Version 2.17.0 *(2017-10-28)*
----------------------------
* Added a toggle for keeping last-modified field at file copy/move/rename
* Improved GIF animation speed
* Implemented fileprovider support to third party intents
* Make rotation by "Device rotation" less sensitive
* Automatically append "_1" to filename after saving through the Editor
* Added support for Adaptive icons for Android 8 (by fiepi)
* Added Dutch translation (by ltGuillaume)
* Many other smaller improvements
Version 2.16.1 *(2017-10-24)*
----------------------------

View file

@ -3,15 +3,15 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
compileSdkVersion 26
buildToolsVersion "26.0.2"
defaultConfig {
applicationId "com.simplemobiletools.gallery"
minSdkVersion 16
targetSdkVersion 23
versionCode 137
versionName "2.16.1"
targetSdkVersion 26
versionCode 140
versionName "2.17.2"
}
signingConfigs {
@ -37,13 +37,13 @@ android {
}
dependencies {
compile 'com.simplemobiletools:commons:2.31.11'
compile 'com.simplemobiletools:commons:2.34.2'
compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.6.0'
compile 'com.theartofdev.edmodo:android-image-cropper:2.4.0'
compile 'com.bignerdranch.android:recyclerview-multiselect:0.2'
compile 'com.google.code.gson:gson:2.8.0'
compile 'com.github.chrisbanes:PhotoView:2.1.2'
compile 'it.sephiroth.android.exif:library:1.0.1'
compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.8'
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'

View file

@ -83,16 +83,16 @@
android:label="@string/third_party_licences"
android:parentActivityName="com.simplemobiletools.commons.activities.AboutActivity"/>
<activity
android:name=".activities.SettingsActivity"
android:label="@string/settings"
android:parentActivityName=".activities.MainActivity"/>
<activity
android:name="com.simplemobiletools.commons.activities.CustomizationActivity"
android:label="@string/customize_colors"
android:parentActivityName=".activities.SettingsActivity"/>
<activity
android:name=".activities.SettingsActivity"
android:label="@string/settings"
android:parentActivityName=".activities.MainActivity"/>
<activity
android:name=".activities.PhotoVideoActivity"
android:configChanges="orientation|keyboardHidden|screenSize"

View file

@ -7,7 +7,6 @@ import android.graphics.Point
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import com.simplemobiletools.commons.extensions.*
@ -20,12 +19,12 @@ import kotlinx.android.synthetic.main.view_crop_image.*
import java.io.*
class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener {
val TAG = EditActivity::class.java.simpleName
val ASPECT_X = "aspectX"
val ASPECT_Y = "aspectY"
val CROP = "crop"
private val ASPECT_X = "aspectX"
private val ASPECT_Y = "aspectY"
private val CROP = "crop"
lateinit var uri: Uri
lateinit var saveUri: Uri
var resizeWidth = 0
var resizeHeight = 0
var isCropIntent = false
@ -48,11 +47,17 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
return
}
saveUri = if (intent.extras?.containsKey(MediaStore.EXTRA_OUTPUT) == true) {
intent.extras!!.get(MediaStore.EXTRA_OUTPUT) as Uri
} else {
uri
}
isCropIntent = intent.extras?.get(CROP) == "true"
crop_image_view.apply {
setOnCropImageCompleteListener(this@EditActivity)
setImageUriAsync(intent.data)
setImageUriAsync(uri)
if (isCropIntent && shouldCropSquare())
setFixedAspectRatio(true)
@ -66,8 +71,9 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
override fun onStop() {
super.onStop()
if (isEditingWithThirdParty)
if (isEditingWithThirdParty) {
finish()
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
@ -124,15 +130,14 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
override fun onCropImageComplete(view: CropImageView, result: CropImageView.CropResult) {
if (result.error == null) {
if (isCropIntent && intent.extras?.containsKey(MediaStore.EXTRA_OUTPUT) == true) {
val targetUri = intent.extras!!.get(MediaStore.EXTRA_OUTPUT) as Uri
if (isCropIntent) {
var inputStream: InputStream? = null
var outputStream: OutputStream? = null
try {
val stream = ByteArrayOutputStream()
result.bitmap.compress(CompressFormat.JPEG, 100, stream)
inputStream = ByteArrayInputStream(stream.toByteArray())
outputStream = contentResolver.openOutputStream(targetUri)
outputStream = contentResolver.openOutputStream(saveUri)
inputStream.copyTo(outputStream)
} finally {
inputStream?.close()
@ -140,23 +145,21 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
}
setResult(RESULT_OK)
finish()
} else if (uri.scheme == "file") {
SaveAsDialog(this, uri.path) {
} else if (saveUri.scheme == "file") {
SaveAsDialog(this, saveUri.path, true) {
saveBitmapToFile(result.bitmap, it)
}
} else if (uri.scheme == "content") {
val newPath = applicationContext.getRealPathFromURI(uri) ?: ""
} else if (saveUri.scheme == "content") {
val newPath = applicationContext.getRealPathFromURI(saveUri) ?: ""
if (!newPath.isEmpty()) {
SaveAsDialog(this, newPath) {
SaveAsDialog(this, newPath, true) {
saveBitmapToFile(result.bitmap, it)
}
} else {
toast(R.string.image_editing_failed)
finish()
}
} else {
toast(R.string.unknown_file_location)
finish()
}
} else {
toast("${getString(R.string.image_editing_failed)}: ${result.error.message}")
@ -175,9 +178,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
}
}
} catch (e: Exception) {
Log.e(TAG, "Crop compressing failed $path $e")
toast(R.string.image_editing_failed)
finish()
showErrorToast(e)
} catch (e: OutOfMemoryError) {
toast(R.string.out_of_memory_error)
}
@ -196,14 +197,15 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
}
private fun flipImage(horizontally: Boolean) {
if (horizontally)
if (horizontally) {
crop_image_view.flipImageHorizontally()
else
} else {
crop_image_view.flipImageVertically()
}
}
private fun editWith() {
openEditor(uri, true)
openEditor(uri)
isEditingWithThirdParty = true
}

View file

@ -125,30 +125,24 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
super.onResume()
config.isThirdPartyIntent = false
if (mStoredAnimateGifs != config.animateGifs) {
directories_grid.adapter?.notifyDataSetChanged()
getDirectoryAdapter()?.updateAnimateGifs(config.animateGifs)
}
if (mStoredCropThumbnails != config.cropThumbnails) {
directories_grid.adapter?.notifyDataSetChanged()
getDirectoryAdapter()?.updateCropThumbnails(config.cropThumbnails)
}
if (mStoredShowMediaCount != config.showMediaCount) {
(directories_grid.adapter as? DirectoryAdapter)?.apply {
showMediaCount = config.showMediaCount
notifyDataSetChanged()
}
getDirectoryAdapter()?.updateShowMediaCount(config.showMediaCount)
}
if (mStoredScrollHorizontally != config.scrollHorizontally) {
(directories_grid.adapter as? DirectoryAdapter)?.apply {
scrollVertically = config.viewTypeFolders == VIEW_TYPE_LIST || !config.scrollHorizontally
notifyDataSetChanged()
}
getDirectoryAdapter()?.updateScrollHorizontally(config.viewTypeFolders != VIEW_TYPE_LIST && config.scrollHorizontally)
setupScrollDirection()
}
if (mStoredTextColor != config.textColor) {
(directories_grid.adapter as? DirectoryAdapter)?.updateTextColor(config.textColor)
getDirectoryAdapter()?.updateTextColor(config.textColor)
}
tryloadGallery()
@ -177,6 +171,8 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
removeTempFolder()
}
private fun getDirectoryAdapter() = directories_grid.adapter as? DirectoryAdapter
private fun storeStateVariables() {
config.apply {
mStoredAnimateGifs = animateGifs
@ -434,7 +430,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
}
} else if ((mIsPickImageIntent || mIsPickVideoIntent)) {
val path = resultData.data.path
val uri = Uri.fromFile(File(path))
val uri = getFilePublicUri(File(path), BuildConfig.APPLICATION_ID)
resultIntent.data = uri
resultIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
}
@ -467,7 +463,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
private fun fillPickedPaths(resultData: Intent, resultIntent: Intent) {
val paths = resultData.extras.getStringArrayList(PICKED_PATHS)
val uris = paths.map { Uri.fromFile(File(it)) } as ArrayList
val uris = paths.map { getFilePublicUri(File(it), BuildConfig.APPLICATION_ID) } as ArrayList
val clipData = ClipData("Attachment", arrayOf("image/*", "video/*"), ClipData.Item(uris.removeAt(0)))
uris.forEach {
@ -479,7 +475,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
private fun fillIntentPath(resultData: Intent, resultIntent: Intent) {
val path = resultData.data.path
val uri = Uri.fromFile(File(path))
val uri = getFilePublicUri(File(path), BuildConfig.APPLICATION_ID)
val type = path.getMimeTypeFromPath()
resultIntent.setDataAndTypeAndNormalize(uri, type)
resultIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
@ -639,6 +635,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
add(Release(133, R.string.release_133))
add(Release(136, R.string.release_136))
add(Release(137, R.string.release_137))
add(Release(138, R.string.release_138))
checkWhatsNew(this, BuildConfig.VERSION_CODE)
}
}

View file

@ -22,6 +22,7 @@ import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
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.gallery.R
@ -89,24 +90,21 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
override fun onResume() {
super.onResume()
if (mShowAll && mStoredAnimateGifs != config.animateGifs) {
media_grid.adapter?.notifyDataSetChanged()
if (mStoredAnimateGifs != config.animateGifs) {
getMediaAdapter()?.updateAnimateGifs(config.animateGifs)
}
if (mStoredCropThumbnails != config.cropThumbnails) {
media_grid.adapter?.notifyDataSetChanged()
getMediaAdapter()?.updateCropThumbnails(config.cropThumbnails)
}
if (mStoredScrollHorizontally != config.scrollHorizontally) {
(media_grid.adapter as? MediaAdapter)?.apply {
scrollVertically = config.viewTypeFiles == VIEW_TYPE_LIST || !config.scrollHorizontally
notifyDataSetChanged()
}
getMediaAdapter()?.updateScrollHorizontally(config.viewTypeFiles != VIEW_TYPE_LIST || !config.scrollHorizontally)
setupScrollDirection()
}
if (mStoredTextColor != config.textColor) {
(media_grid.adapter as? MediaAdapter)?.updateTextColor(config.textColor)
getMediaAdapter()?.updateTextColor(config.textColor)
}
tryloadGallery()
@ -153,6 +151,8 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
}
}
private fun getMediaAdapter() = media_grid.adapter as? MediaAdapter
private fun checkIfColorChanged() {
if (media_grid.adapter != null && getRecyclerAdapter().primaryColor != config.primaryColor) {
getRecyclerAdapter().primaryColor = config.primaryColor
@ -504,10 +504,10 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
val file = File(path)
val isVideo = file.isVideoFast()
if (isVideo) {
openWith(file, false)
openFile(Uri.fromFile(file), false)
} else {
Intent(this, ViewPagerActivity::class.java).apply {
putExtra(MEDIUM, path)
putExtra(PATH, path)
putExtra(SHOW_ALL, mShowAll)
startActivity(this)
}

View file

@ -4,7 +4,7 @@ import android.os.Bundle
class PhotoActivity : PhotoVideoActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
PhotoVideoActivity.mIsVideo = false
mIsVideo = false
super.onCreate(savedInstanceState)
}
}

View file

@ -1,27 +1,29 @@
package com.simplemobiletools.gallery.activities
import android.content.Intent
import android.database.Cursor
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
import android.view.Menu
import android.view.MenuItem
import android.view.View
import com.simplemobiletools.commons.dialogs.PropertiesDialog
import com.simplemobiletools.commons.extensions.getFilenameFromUri
import com.simplemobiletools.commons.extensions.getRealPathFromURI
import com.simplemobiletools.commons.extensions.scanPath
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.helpers.IS_FROM_GALLERY
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE
import com.simplemobiletools.commons.helpers.REAL_FILE_PATH
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.extensions.*
import com.simplemobiletools.gallery.fragments.PhotoFragment
import com.simplemobiletools.gallery.fragments.VideoFragment
import com.simplemobiletools.gallery.fragments.ViewPagerFragment
import com.simplemobiletools.gallery.helpers.IS_FROM_GALLERY
import com.simplemobiletools.gallery.helpers.IS_VIEW_INTENT
import com.simplemobiletools.gallery.helpers.MEDIUM
import com.simplemobiletools.gallery.helpers.PATH
import com.simplemobiletools.gallery.models.Medium
import kotlinx.android.synthetic.main.fragment_holder.*
import java.io.File
@ -31,12 +33,9 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
private var mIsFullScreen = false
private var mIsFromGallery = false
private var mFragment: ViewPagerFragment? = null
private var mUri: Uri? = null
lateinit var mUri: Uri
companion object {
var mIsVideo = false
}
var mIsVideo = false
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -53,17 +52,21 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
private fun checkIntent(savedInstanceState: Bundle? = null) {
mUri = intent.data ?: return
if (intent.extras?.containsKey(REAL_FILE_PATH) == true) {
mUri = intent.extras.get(REAL_FILE_PATH) as Uri
}
mIsFromGallery = intent.getBooleanExtra(IS_FROM_GALLERY, false)
if (mUri.scheme == "file") {
scanPath(mUri.path) {}
sendViewPagerIntent(mUri.path)
if (mUri!!.scheme == "file") {
scanPath(mUri!!.path) {}
sendViewPagerIntent(mUri!!.path)
finish()
return
} else {
val path = applicationContext.getRealPathFromURI(mUri) ?: ""
val path = applicationContext.getRealPathFromURI(mUri!!) ?: ""
if (path != mUri.toString()) {
scanPath(mUri.path) {}
scanPath(mUri!!.path) {}
if (path.isNotEmpty()) {
sendViewPagerIntent(path)
finish()
@ -75,7 +78,8 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
showSystemUI()
val bundle = Bundle()
val file = File(mUri.toString())
mMedium = Medium(file.name, mUri.toString(), mIsVideo, 0, 0, file.length())
mMedium = Medium(getFilenameFromUri(mUri!!), mUri.toString(), mIsVideo, 0, 0, file.length())
title = mMedium!!.name
bundle.putSerializable(MEDIUM, mMedium)
if (savedInstanceState == null) {
@ -85,22 +89,8 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
supportFragmentManager.beginTransaction().replace(R.id.fragment_holder, mFragment).commit()
}
if (config.darkBackground)
if (config.darkBackground) {
fragment_holder.background = ColorDrawable(Color.BLACK)
val proj = arrayOf(MediaStore.Images.Media.TITLE)
var cursor: Cursor? = null
try {
cursor = contentResolver.query(mUri, proj, null, null, null)
if (cursor != null && cursor.count != 0) {
val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.TITLE)
cursor.moveToFirst()
title = cursor.getString(columnIndex)
}
} catch (e: Exception) {
title = mMedium?.name ?: ""
} finally {
cursor?.close()
}
window.decorView.setOnSystemUiVisibilityChangeListener { visibility ->
@ -118,7 +108,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
Intent(this, ViewPagerActivity::class.java).apply {
putExtra(IS_VIEW_INTENT, true)
putExtra(IS_FROM_GALLERY, mIsFromGallery)
putExtra(MEDIUM, path)
putExtra(PATH, path)
startActivity(this)
}
}
@ -127,7 +117,8 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
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
menu.findItem(R.id.menu_edit).isVisible = mMedium?.isImage() == true && mUri?.scheme == "file"
menu.findItem(R.id.menu_properties).isVisible = mUri?.scheme == "file"
return true
}
@ -137,15 +128,20 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
return true
when (item.itemId) {
R.id.menu_set_as -> trySetAs(File(mMedium!!.path))
R.id.menu_open_with -> openWith(File(mMedium!!.path))
R.id.menu_share -> shareUri(mMedium!!, mUri)
R.id.menu_edit -> openFileEditor(File(mMedium!!.path))
R.id.menu_set_as -> setAs(mUri!!)
R.id.menu_open_with -> openFile(mUri!!, true)
R.id.menu_share -> shareUri(mUri!!)
R.id.menu_edit -> openEditor(mUri!!)
R.id.menu_properties -> showProperties()
else -> return super.onOptionsItemSelected(item)
}
return true
}
private fun showProperties() {
PropertiesDialog(this, mUri!!.path)
}
override fun fragmentClicked() {
mIsFullScreen = !mIsFullScreen
if (mIsFullScreen) {

View file

@ -50,6 +50,7 @@ class SettingsActivity : SimpleActivity() {
setupDeleteEmptyFolders()
setupAllowVideoGestures()
setupShowMediaCount()
setupKeepLastModified()
setupShowExtendedDetails()
setupManageExtendedDetails()
updateTextColors(settings_holder)
@ -207,6 +208,14 @@ class SettingsActivity : SimpleActivity() {
}
}
private fun setupKeepLastModified() {
settings_keep_last_modified.isChecked = config.keepLastModified
settings_keep_last_modified_holder.setOnClickListener {
settings_keep_last_modified.toggle()
config.keepLastModified = settings_keep_last_modified.isChecked
}
}
private fun setupScreenRotation() {
settings_screen_rotation.text = getScreenRotationText()
settings_screen_rotation_holder.setOnClickListener {

View file

@ -5,7 +5,7 @@ import android.os.Bundle
class VideoActivity : PhotoVideoActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
PhotoVideoActivity.mIsVideo = true
mIsVideo = true
super.onCreate(savedInstanceState)
}
}

View file

@ -26,7 +26,10 @@ import android.view.animation.DecelerateInterpolator
import com.simplemobiletools.commons.dialogs.PropertiesDialog
import com.simplemobiletools.commons.dialogs.RenameItemDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.IS_FROM_GALLERY
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE
import com.simplemobiletools.commons.helpers.REQUEST_EDIT_IMAGE
import com.simplemobiletools.commons.helpers.REQUEST_SET_AS
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.MediaActivity.Companion.mMedia
import com.simplemobiletools.gallery.adapters.MyPagerAdapter
@ -85,6 +88,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
}
private fun initViewPager() {
setupOrientationEventListener()
measureScreen()
val uri = intent.data
if (uri != null) {
@ -100,7 +104,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
}
} else {
try {
mPath = intent.getStringExtra(MEDIUM)
mPath = intent.getStringExtra(PATH)
mShowAll = config.showAll
} catch (e: Exception) {
showErrorToast(e)
@ -140,7 +144,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
reloadViewPager()
scanPath(mPath) {}
setupOrientationEventListener()
if (config.darkBackground)
view_pager.background = ColorDrawable(Color.BLACK)
@ -176,8 +179,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 45..134 -> ORIENT_LANDSCAPE_RIGHT
in 225..314 -> ORIENT_LANDSCAPE_LEFT
in 75..134 -> ORIENT_LANDSCAPE_RIGHT
in 225..289 -> ORIENT_LANDSCAPE_LEFT
else -> ORIENT_PORTRAIT
}
@ -230,8 +233,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
menu.apply {
findItem(R.id.menu_share_1).isVisible = !config.replaceShare
findItem(R.id.menu_share_2).isVisible = config.replaceShare
findItem(R.id.menu_set_as).isVisible = currentMedium.isImage()
findItem(R.id.menu_edit).isVisible = currentMedium.isImage()
findItem(R.id.menu_rotate).isVisible = currentMedium.isImage()
findItem(R.id.menu_save_as).isVisible = mRotationDegrees != 0f
findItem(R.id.menu_hide).isVisible = !currentMedium.name.startsWith('.')
@ -246,18 +247,18 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
return true
when (item.itemId) {
R.id.menu_set_as -> trySetAs(getCurrentFile())
R.id.menu_set_as -> setAs(Uri.fromFile(getCurrentFile()))
R.id.slideshow -> initSlideshow()
R.id.menu_copy_to -> copyMoveTo(true)
R.id.menu_move_to -> copyMoveTo(false)
R.id.menu_open_with -> openWith(getCurrentFile())
R.id.menu_open_with -> openFile(Uri.fromFile(getCurrentFile()), true)
R.id.menu_hide -> toggleFileVisibility(true)
R.id.menu_unhide -> toggleFileVisibility(false)
R.id.menu_share_1 -> shareMedium(getCurrentMedium()!!)
R.id.menu_share_2 -> shareMedium(getCurrentMedium()!!)
R.id.menu_delete -> checkDeleteConfirmation()
R.id.menu_rename -> renameFile()
R.id.menu_edit -> openFileEditor(getCurrentFile())
R.id.menu_edit -> openEditor(Uri.fromFile(getCurrentFile()))
R.id.menu_properties -> showProperties()
R.id.show_on_map -> showOnMap()
R.id.menu_rotate -> rotateImage()
@ -327,10 +328,12 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
animator.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener {
var oldDragPosition = 0
override fun onAnimationUpdate(animation: ValueAnimator) {
val dragPosition = animation.animatedValue as Int
val dragOffset = dragPosition - oldDragPosition
oldDragPosition = dragPosition
view_pager?.fakeDragBy(dragOffset * (if (forward) 1f else -1f))
if (view_pager?.isFakeDragging == true) {
val dragPosition = animation.animatedValue as Int
val dragOffset = dragPosition - oldDragPosition
oldDragPosition = dragPosition
view_pager.fakeDragBy(dragOffset * (if (forward) 1f else -1f))
}
}
})
@ -446,7 +449,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
private fun saveImageAs() {
val currPath = getCurrentPath()
SaveAsDialog(this, currPath) {
SaveAsDialog(this, currPath, false) {
Thread({
toast(R.string.saving)
val selectedFile = File(it)
@ -515,8 +518,9 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
private fun getCurrentFragment() = (view_pager.adapter as MyPagerAdapter).getCurrentFragment(view_pager.currentItem)
private fun showProperties() {
if (getCurrentMedium() != null)
if (getCurrentMedium() != null) {
PropertiesDialog(this, getCurrentPath(), false)
}
}
private fun showOnMap() {

View file

@ -30,11 +30,9 @@ 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>() {
val config = activity.config
private val config = activity.config
var actMode: ActionMode? = null
var primaryColor = config.primaryColor
var scrollVertically = !config.scrollHorizontally
var showMediaCount = config.showMediaCount
private val multiSelector = MultiSelector()
private val isListViewType = config.viewTypeFolders == VIEW_TYPE_LIST
@ -42,6 +40,10 @@ class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList<Direc
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) {
@ -353,7 +355,7 @@ class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList<Direc
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val dir = dirs[position]
itemViews.put(position, holder.bindView(dir, pinnedFolders.contains(dir.path), scrollVertically, isListViewType, textColor, showMediaCount))
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
}
@ -371,6 +373,26 @@ class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList<Direc
actMode?.finish()
}
fun updateAnimateGifs(animateGifs: Boolean) {
this.animateGifs = animateGifs
notifyDataSetChanged()
}
fun updateCropThumbnails(cropThumbnails: Boolean) {
this.cropThumbnails = cropThumbnails
notifyDataSetChanged()
}
fun updateShowMediaCount(showMediaCount: Boolean) {
this.showMediaCount = showMediaCount
notifyDataSetChanged()
}
fun updateScrollHorizontally(scrollHorizontally: Boolean) {
this.scrollHorizontally = scrollHorizontally
notifyDataSetChanged()
}
fun updateTextColor(textColor: Int) {
this.textColor = textColor
notifyDataSetChanged()
@ -418,12 +440,13 @@ class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList<Direc
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, scrollVertically: Boolean, isListView: Boolean, textColor: Int, showMediaCount: Boolean): View {
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, scrollVertically)
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)

View file

@ -1,6 +1,7 @@
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
@ -27,18 +28,21 @@ import java.util.*
class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>, val listener: MediaOperationsListener?, val isPickIntent: Boolean,
val allowMultiplePicks: Boolean, val itemClick: (Medium) -> Unit) : RecyclerView.Adapter<MediaAdapter.ViewHolder>() {
val multiSelector = MultiSelector()
val config = activity.config
val isListViewType = config.viewTypeFiles == VIEW_TYPE_LIST
var skipConfirmationDialog = false
private val config = activity.config
var actMode: ActionMode? = null
var itemViews = SparseArray<View>()
val selectedPositions = HashSet<Int>()
var primaryColor = config.primaryColor
var textColor = config.textColor
var displayFilenames = config.displayFileNames
var scrollVertically = !config.scrollHorizontally
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) {
@ -86,6 +90,8 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>,
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
}
@ -100,8 +106,8 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>,
}
override fun onPrepareActionMode(actionMode: ActionMode?, menu: Menu): Boolean {
menu.findItem(R.id.cab_rename).isVisible = selectedPositions.size <= 1
menu.findItem(R.id.cab_edit).isVisible = selectedPositions.size == 1 && media.size > selectedPositions.first() && media[selectedPositions.first()].isImage()
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 = isPickIntent && allowMultiplePicks && selectedPositions.size > 0
checkHideBtnVisibility(menu)
@ -159,7 +165,7 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>,
}
private fun editFile() {
activity.openFileEditor(getCurrentFile())
activity.openEditor(Uri.fromFile(getCurrentFile()))
actMode?.finish()
}
@ -277,7 +283,7 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>,
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
itemViews.put(position, holder.bindView(media[position], displayFilenames, scrollVertically, isListViewType, textColor))
itemViews.put(position, holder.bindView(media[position], displayFilenames, scrollHorizontally, isListViewType, textColor, animateGifs, cropThumbnails))
toggleItemSelection(selectedPositions.contains(position), position)
holder.itemView.tag = holder
}
@ -300,6 +306,21 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>,
notifyDataSetChanged()
}
fun updateAnimateGifs(animateGifs: Boolean) {
this.animateGifs = animateGifs
notifyDataSetChanged()
}
fun updateCropThumbnails(cropThumbnails: Boolean) {
this.cropThumbnails = cropThumbnails
notifyDataSetChanged()
}
fun updateScrollHorizontally(scrollHorizontally: Boolean) {
this.scrollHorizontally = scrollHorizontally
notifyDataSetChanged()
}
fun updateTextColor(textColor: Int) {
this.textColor = textColor
notifyDataSetChanged()
@ -348,12 +369,13 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList<Medium>,
val multiSelector: MultiSelector, val listener: MediaOperationsListener?, val allowMultiplePicks: Boolean,
val itemClick: (Medium) -> (Unit)) :
SwappingHolder(view, MultiSelector()) {
fun bindView(medium: Medium, displayFilenames: Boolean, scrollVertically: Boolean, isListViewType: Boolean, textColor: Int): View {
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, scrollVertically)
activity.loadImage(medium.path, medium_thumbnail, scrollHorizontally, animateGifs, cropThumbnails)
if (isListViewType) {
photo_name.setTextColor(textColor)

View file

@ -23,10 +23,10 @@ class MyPagerAdapter(val activity: ViewPagerActivity, fm: FragmentManager, val m
bundle.putSerializable(MEDIUM, medium)
val fragment: ViewPagerFragment
if (medium.video) {
fragment = VideoFragment()
fragment = if (medium.video) {
VideoFragment()
} else {
fragment = PhotoFragment()
PhotoFragment()
}
fragment.arguments = bundle

View file

@ -11,7 +11,7 @@ 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 callback: (savePath: String) -> Unit) {
class SaveAsDialog(val activity: SimpleActivity, val path: String, val appendFilename: Boolean, val callback: (savePath: String) -> Unit) {
init {
var realPath = File(path).parent.trimEnd('/')
@ -28,6 +28,10 @@ class SaveAsDialog(val activity: SimpleActivity, val path: String, val callback:
save_as_extension.setText(extension)
}
if (appendFilename) {
name += "_1"
}
save_as_name.setText(name)
save_as_path.setOnClickListener {
FilePickerDialog(activity, realPath, false, false, true) {

View file

@ -2,16 +2,11 @@ package com.simplemobiletools.gallery.extensions
import android.app.Activity
import android.content.Intent
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import android.support.v7.app.AppCompatActivity
import android.util.DisplayMetrics
import android.view.KeyCharacterMap
import android.view.KeyEvent
import android.view.View
import android.view.ViewConfiguration
import android.widget.ImageView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.load.engine.DiskCacheStrategy
@ -24,165 +19,42 @@ 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.helpers.IS_FROM_GALLERY
import com.simplemobiletools.gallery.helpers.NOMEDIA
import com.simplemobiletools.gallery.helpers.REQUEST_EDIT_IMAGE
import com.simplemobiletools.gallery.helpers.REQUEST_SET_AS
import com.simplemobiletools.gallery.models.Directory
import com.simplemobiletools.gallery.models.Medium
import com.simplemobiletools.gallery.views.MySquareImageView
import pl.droidsonroids.gif.GifDrawable
import java.io.File
import java.util.*
fun Activity.shareUri(medium: Medium, uri: Uri) {
val shareTitle = resources.getString(R.string.share_via)
Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_STREAM, uri)
type = medium.getMimeType()
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivity(Intent.createChooser(this, shareTitle))
}
fun Activity.shareUri(uri: Uri) {
shareUri(uri, BuildConfig.APPLICATION_ID)
}
fun Activity.shareUris(uris: ArrayList<Uri>) {
shareUris(uris, BuildConfig.APPLICATION_ID)
}
fun Activity.shareMedium(medium: Medium) {
val shareTitle = resources.getString(R.string.share_via)
val file = File(medium.path)
val uri = Uri.fromFile(file)
Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_STREAM, uri)
type = medium.getMimeType()
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivity(Intent.createChooser(this, shareTitle))
}
shareUri(Uri.fromFile(file))
}
fun Activity.shareMedia(media: List<Medium>) {
val shareTitle = resources.getString(R.string.share_via)
val uris = media.map { Uri.fromFile(File(it.path)) } as ArrayList
Intent().apply {
action = Intent.ACTION_SEND_MULTIPLE
type = uris.getMimeType()
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris)
startActivity(Intent.createChooser(this, shareTitle))
}
val uris = media.map { getFilePublicUri(File(it.path), BuildConfig.APPLICATION_ID) } as ArrayList
shareUris(uris)
}
fun Activity.trySetAs(file: File) {
try {
var uri = Uri.fromFile(file)
if (!setAs(uri, file)) {
uri = getFileContentUri(file)
setAs(uri, file, false)
}
} catch (e: Exception) {
toast(R.string.unknown_error_occurred)
}
fun Activity.setAs(uri: Uri) {
setAs(uri, BuildConfig.APPLICATION_ID)
}
fun Activity.setAs(uri: Uri, file: File, showToast: Boolean = true): Boolean {
var success = false
Intent().apply {
action = Intent.ACTION_ATTACH_DATA
setDataAndType(uri, file.getMimeType())
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
val chooser = Intent.createChooser(this, getString(R.string.set_as))
success = if (resolveActivity(packageManager) != null) {
startActivityForResult(chooser, REQUEST_SET_AS)
true
} else {
if (showToast) {
toast(R.string.no_capable_app_found)
}
false
}
}
return success
fun Activity.openFile(uri: Uri, forceChooser: Boolean) {
openFile(uri, forceChooser, BuildConfig.APPLICATION_ID)
}
fun Activity.getFileContentUri(file: File): Uri? {
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Images.Media._ID)
val selection = "${MediaStore.Images.Media.DATA} = ?"
val selectionArgs = arrayOf(file.absolutePath)
var cursor: Cursor? = null
try {
cursor = contentResolver.query(uri, projection, selection, selectionArgs, null)
if (cursor?.moveToFirst() == true) {
val id = cursor.getIntValue(MediaStore.Images.Media._ID)
return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "$id")
}
} finally {
cursor?.close()
}
return null
}
fun Activity.openWith(file: File, forceChooser: Boolean = true) {
val uri = Uri.fromFile(file)
Intent().apply {
action = Intent.ACTION_VIEW
setDataAndType(uri, file.getMimeType())
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
putExtra(IS_FROM_GALLERY, true)
if (resolveActivity(packageManager) != null) {
val chooser = Intent.createChooser(this, getString(R.string.open_with))
startActivity(if (forceChooser) chooser else this)
} else {
toast(R.string.no_app_found)
}
}
}
fun Activity.openFileEditor(file: File) {
openEditor(Uri.fromFile(file))
}
fun Activity.openEditor(uri: Uri, forceChooser: Boolean = false) {
Intent().apply {
action = Intent.ACTION_EDIT
setDataAndType(uri, "image/*")
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
if (resolveActivity(packageManager) != null) {
val chooser = Intent.createChooser(this, getString(R.string.edit_image_with))
startActivityForResult(if (forceChooser) chooser else this, REQUEST_EDIT_IMAGE)
} else {
toast(R.string.no_editor_found)
}
}
}
fun Activity.hasNavBar(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
val display = windowManager.defaultDisplay
val realDisplayMetrics = DisplayMetrics()
display.getRealMetrics(realDisplayMetrics)
val realHeight = realDisplayMetrics.heightPixels
val realWidth = realDisplayMetrics.widthPixels
val displayMetrics = DisplayMetrics()
display.getMetrics(displayMetrics)
val displayHeight = displayMetrics.heightPixels
val displayWidth = displayMetrics.widthPixels
realWidth - displayWidth > 0 || realHeight - displayHeight > 0
} else {
val hasMenuKey = ViewConfiguration.get(applicationContext).hasPermanentMenuKey()
val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK)
!hasMenuKey && !hasBackKey
}
fun Activity.openEditor(uri: Uri) {
openEditor(uri, BuildConfig.APPLICATION_ID)
}
fun Activity.launchCamera() {
@ -196,7 +68,7 @@ fun Activity.launchCamera() {
fun SimpleActivity.launchAbout() {
startAboutActivity(R.string.app_name, LICENSE_KOTLIN or LICENSE_GLIDE or LICENSE_CROPPER or LICENSE_MULTISELECT or LICENSE_RTL
or LICENSE_PHOTOVIEW or LICENSE_SUBSAMPLING or LICENSE_PATTERN, BuildConfig.VERSION_NAME)
or LICENSE_SUBSAMPLING or LICENSE_PATTERN or LICENSE_REPRINT or LICENSE_GIF_DRAWABLE, BuildConfig.VERSION_NAME)
}
fun AppCompatActivity.showSystemUI() {
@ -265,24 +137,28 @@ fun SimpleActivity.toggleFileVisibility(oldFile: File, hide: Boolean, callback:
}
}
fun Activity.loadImage(path: String, target: MySquareImageView, verticalScroll: Boolean) {
target.isVerticalScrolling = verticalScroll
fun Activity.loadImage(path: String, target: MySquareImageView, horizontalScroll: Boolean, animateGifs: Boolean, cropThumbnails: Boolean) {
target.isHorizontalScrolling = horizontalScroll
if (path.isImageFast() || path.isVideoFast()) {
if (path.isPng()) {
loadPng(path, target)
loadPng(path, target, cropThumbnails)
} else {
loadJpg(path, target)
loadJpg(path, target, cropThumbnails)
}
} else if (path.isGif()) {
if (config.animateGifs) {
loadAnimatedGif(path, target)
val gifDrawable = GifDrawable(path)
target.setImageDrawable(gifDrawable)
if (animateGifs) {
gifDrawable.start()
} else {
loadStaticGif(path, target)
gifDrawable.stop()
}
target.scaleType = if (cropThumbnails) ImageView.ScaleType.CENTER_CROP else ImageView.ScaleType.FIT_CENTER
}
}
fun Activity.loadPng(path: String, target: MySquareImageView) {
fun Activity.loadPng(path: String, target: MySquareImageView, cropThumbnails: Boolean) {
val options = RequestOptions()
.signature(path.getFileSignature())
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
@ -292,11 +168,11 @@ fun Activity.loadPng(path: String, target: MySquareImageView) {
.asBitmap()
.load(path)
if (config.cropThumbnails) options.centerCrop() else options.fitCenter()
if (cropThumbnails) options.centerCrop() else options.fitCenter()
builder.apply(options).into(target)
}
fun Activity.loadJpg(path: String, target: MySquareImageView) {
fun Activity.loadJpg(path: String, target: MySquareImageView, cropThumbnails: Boolean) {
val options = RequestOptions()
.signature(path.getFileSignature())
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
@ -304,36 +180,10 @@ fun Activity.loadJpg(path: String, target: MySquareImageView) {
val builder = Glide.with(applicationContext)
.load(path)
if (config.cropThumbnails) options.centerCrop() else options.fitCenter()
if (cropThumbnails) options.centerCrop() else options.fitCenter()
builder.apply(options).transition(DrawableTransitionOptions.withCrossFade()).into(target)
}
fun Activity.loadAnimatedGif(path: String, target: MySquareImageView) {
val options = RequestOptions()
.signature(path.getFileSignature())
.diskCacheStrategy(DiskCacheStrategy.NONE)
val builder = Glide.with(applicationContext)
.asGif()
.load(path)
if (config.cropThumbnails) options.centerCrop() else options.fitCenter()
builder.apply(options).transition(DrawableTransitionOptions.withCrossFade()).into(target)
}
fun Activity.loadStaticGif(path: String, target: MySquareImageView) {
val options = RequestOptions()
.signature(path.getFileSignature())
.diskCacheStrategy(DiskCacheStrategy.DATA)
val builder = Glide.with(applicationContext)
.asBitmap()
.load(path)
if (config.cropThumbnails) options.centerCrop() else options.fitCenter()
builder.apply(options).into(target)
}
fun Activity.getCachedDirectories(): ArrayList<Directory> {
val token = object : TypeToken<List<Directory>>() {}.type
return Gson().fromJson<ArrayList<Directory>>(config.directories, token) ?: ArrayList<Directory>(1)

View file

@ -5,12 +5,17 @@ import android.content.Intent
import android.content.res.Configuration
import android.graphics.Point
import android.media.AudioManager
import android.net.Uri
import android.os.Build
import android.view.WindowManager
import com.simplemobiletools.commons.extensions.getFilePublicUri
import com.simplemobiletools.commons.extensions.getMimeTypeFromPath
import com.simplemobiletools.commons.extensions.humanizePath
import com.simplemobiletools.gallery.BuildConfig
import com.simplemobiletools.gallery.activities.SettingsActivity
import com.simplemobiletools.gallery.helpers.Config
import com.simplemobiletools.gallery.models.Directory
import java.io.File
val Context.portrait get() = resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT
val Context.audioManager get() = getSystemService(Context.AUDIO_SERVICE) as AudioManager

View file

@ -13,12 +13,10 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.bumptech.glide.Glide
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
@ -26,6 +24,7 @@ import com.davemorrissey.labs.subscaleview.ImageSource
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import com.simplemobiletools.commons.extensions.*
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.GlideRotateTransformation
@ -33,15 +32,16 @@ import com.simplemobiletools.gallery.helpers.MEDIUM
import com.simplemobiletools.gallery.models.Medium
import it.sephiroth.android.library.exif2.ExifInterface
import kotlinx.android.synthetic.main.pager_photo_item.view.*
import pl.droidsonroids.gif.GifDrawable
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
class PhotoFragment : ViewPagerFragment() {
private var isFragmentVisible = false
private var wasInit = false
private var storedShowExtendedDetails = false
private var storedExtendedDetails = 0
private var gifDrawable: GifDrawable? = null
lateinit var view: ViewGroup
lateinit var medium: Medium
@ -49,11 +49,14 @@ class PhotoFragment : ViewPagerFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
view = inflater.inflate(R.layout.pager_photo_item, container, false) as ViewGroup
medium = arguments.getSerializable(MEDIUM) as Medium
if (!isFragmentVisible && activity is PhotoActivity) {
isFragmentVisible = true
}
medium = arguments.getSerializable(MEDIUM) as Medium
if (medium.path.startsWith("content://")) {
val originalPath = medium.path
medium.path = context.getRealPathFromURI(Uri.parse(medium.path)) ?: ""
medium.path = context.getRealPathFromURI(Uri.parse(originalPath)) ?: medium.path
if (medium.path.isEmpty()) {
var out: FileOutputStream? = null
@ -63,7 +66,6 @@ class PhotoFragment : ViewPagerFragment() {
exif.readExif(inputStream, ExifInterface.Options.OPTION_ALL)
val tag = exif.getTag(ExifInterface.TAG_ORIENTATION)
val orientation = tag?.getValueAsInt(-1) ?: -1
inputStream = context.contentResolver.openInputStream(Uri.parse(originalPath))
val original = BitmapFactory.decodeStream(inputStream)
val rotated = rotateViaMatrix(original, orientation)
@ -78,26 +80,13 @@ class PhotoFragment : ViewPagerFragment() {
activity.toast(R.string.unknown_error_occurred)
return view
} finally {
try {
out?.close()
} catch (e: IOException) {
}
out?.close()
}
}
}
view.subsampling_view.setOnClickListener({ photoClicked() })
view.photo_view.apply {
maximumScale = 8f
mediumScale = 3f
setOnOutsidePhotoTapListener {
photoClicked()
}
setOnPhotoTapListener { view, x, y ->
photoClicked()
}
}
view.subsampling_view.setOnClickListener { photoClicked() }
view.gif_view.setOnClickListener { photoClicked() }
loadImage()
checkExtendedDetails()
@ -123,14 +112,30 @@ class PhotoFragment : ViewPagerFragment() {
super.setMenuVisibility(menuVisible)
isFragmentVisible = menuVisible
if (wasInit) {
if (menuVisible) {
addZoomableView()
if (medium.isGif()) {
gifFragmentVisibilityChanged(menuVisible)
} else {
view.subsampling_view.apply {
recycle()
beGone()
background = ColorDrawable(Color.TRANSPARENT)
}
photoFragmentVisibilityChanged(menuVisible)
}
}
}
private fun gifFragmentVisibilityChanged(isVisible: Boolean) {
if (isVisible) {
gifDrawable?.start()
} else {
gifDrawable?.stop()
}
}
private fun photoFragmentVisibilityChanged(isVisible: Boolean) {
if (isVisible) {
addZoomableView()
} else {
view.subsampling_view.apply {
recycle()
beGone()
background = ColorDrawable(Color.TRANSPARENT)
}
}
}
@ -155,16 +160,17 @@ class PhotoFragment : ViewPagerFragment() {
private fun loadImage() {
if (medium.isGif()) {
val options = RequestOptions()
.priority(if (isFragmentVisible) Priority.IMMEDIATE else Priority.LOW)
.diskCacheStrategy(DiskCacheStrategy.DATA)
gifDrawable = if (medium.path.startsWith("content://") || medium.path.startsWith("file://")) {
GifDrawable(context.contentResolver, Uri.parse(medium.path))
} else {
GifDrawable(medium.path)
}
Glide.with(this)
.asGif()
.load(medium.path)
.transition(DrawableTransitionOptions.withCrossFade())
.apply(options)
.into(view.photo_view)
if (!isFragmentVisible) {
gifDrawable!!.stop()
}
view.gif_view.setImageDrawable(gifDrawable)
} else {
loadBitmap()
}
@ -193,7 +199,7 @@ class PhotoFragment : ViewPagerFragment() {
addZoomableView()
return false
}
}).into(view.photo_view)
}).into(view.gif_view)
} else {
val options = RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.NONE)
@ -204,7 +210,7 @@ class PhotoFragment : ViewPagerFragment() {
.load(medium.path)
.thumbnail(0.2f)
.apply(options)
.into(view.photo_view)
.into(view.gif_view)
}
}
@ -292,7 +298,7 @@ class PhotoFragment : ViewPagerFragment() {
super.onDestroyView()
context.isKitkatPlus()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && !activity.isDestroyed) {
Glide.with(context).clear(view.photo_view)
Glide.with(context).clear(view.gif_view)
}
}

View file

@ -15,6 +15,7 @@ import android.widget.SeekBar
import android.widget.TextView
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.activities.VideoActivity
import com.simplemobiletools.gallery.activities.ViewPagerActivity
import com.simplemobiletools.gallery.extensions.*
import com.simplemobiletools.gallery.helpers.MEDIUM
@ -64,6 +65,11 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
mTimeHolder = mView.video_time_holder
medium = arguments.getSerializable(MEDIUM) as Medium
// setMenuVisibility is not called at VideoActivity (third party intent)
if (!mIsFragmentVisible && activity is VideoActivity) {
mIsFragmentVisible = true
}
setupPlayer()
if (savedInstanceState != null) {
mCurrTime = savedInstanceState.getInt(PROGRESS)
@ -90,7 +96,6 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
override fun onPause() {
super.onPause()
pauseVideo()
mIsFragmentVisible = false
mStoredShowExtendedDetails = context.config.showExtendedDetails
mStoredExtendedDetails = context.config.extendedDetails
}
@ -285,7 +290,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
var right = res.getDimension(R.dimen.timer_padding).toInt()
var bottom = 0
if (activity.hasNavBar()) {
if (hasNavBar()) {
if (res.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
bottom += height
} else {
@ -303,6 +308,30 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
mTimeHolder.beInvisible()
}
private fun hasNavBar(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
val display = context.windowManager.defaultDisplay
val realDisplayMetrics = DisplayMetrics()
display.getRealMetrics(realDisplayMetrics)
val realHeight = realDisplayMetrics.heightPixels
val realWidth = realDisplayMetrics.widthPixels
val displayMetrics = DisplayMetrics()
display.getMetrics(displayMetrics)
val displayHeight = displayMetrics.heightPixels
val displayWidth = displayMetrics.widthPixels
realWidth - displayWidth > 0 || realHeight - displayHeight > 0
} else {
val hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey()
val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK)
!hasMenuKey && !hasBackKey
}
}
private fun setupTimeHolder() {
mSeekBar!!.max = mDuration
mView.video_duration.text = mDuration.getFormattedDuration()
@ -435,6 +464,10 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
}
private fun videoCompleted() {
if (!isAdded) {
return
}
if (listener?.videoEnded() == false && context.config.loopVideos) {
playVideo()
} else {

View file

@ -20,6 +20,10 @@ abstract class ViewPagerFragment : Fragment() {
fun getMediumExtendedDetails(medium: Medium): String {
val file = File(medium.path)
if (!file.exists()) {
return ""
}
val path = "${file.parent.trimEnd('/')}/"
val exif = android.media.ExifInterface(medium.path)
val details = StringBuilder()

View file

@ -59,18 +59,15 @@ val NOMEDIA = ".nomedia"
val DIRECTORY = "directory"
val MEDIUM = "medium"
val PATH = "path"
val GET_IMAGE_INTENT = "get_image_intent"
val GET_VIDEO_INTENT = "get_video_intent"
val GET_ANY_INTENT = "get_any_intent"
val SET_WALLPAPER_INTENT = "set_wallpaper_intent"
val DIRECTORIES = "directories2"
val IS_VIEW_INTENT = "is_view_intent"
val IS_FROM_GALLERY = "is_from_gallery"
val PICKED_PATHS = "picked_paths"
val REQUEST_EDIT_IMAGE = 1
val REQUEST_SET_AS = 2
// rotations
val ROTATE_BY_SYSTEM_SETTING = 0
val ROTATE_BY_DEVICE_ROTATION = 1

View file

@ -5,7 +5,7 @@ import android.util.AttributeSet
import android.widget.ImageView
class MySquareImageView : ImageView {
var isVerticalScrolling = true
var isHorizontalScrolling = false
constructor(context: Context) : super(context)
@ -14,7 +14,7 @@ class MySquareImageView : ImageView {
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val spec = if (isVerticalScrolling) widthMeasureSpec else heightMeasureSpec
val spec = if (isHorizontalScrolling) heightMeasureSpec else widthMeasureSpec
super.onMeasure(spec, spec)
}
}

View file

@ -348,6 +348,26 @@
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_keep_last_modified_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/medium_margin"
android:background="?attr/selectableItemBackground"
android:padding="@dimen/activity_margin">
<com.simplemobiletools.commons.views.MySwitchCompat
android:id="@+id/settings_keep_last_modified"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:clickable="false"
android:paddingLeft="@dimen/medium_margin"
android:paddingStart="@dimen/medium_margin"
android:text="@string/keep_last_modified"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_show_extended_details_holder"
android:layout_width="match_parent"

View file

@ -6,10 +6,11 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.chrisbanes.photoview.PhotoView
android:id="@+id/photo_view"
<ImageView
android:id="@+id/gif_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
android:layout_height="match_parent"
android:scaleType="fitCenter"/>
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
android:id="@+id/subsampling_view"

View file

@ -46,6 +46,14 @@
android:icon="@drawable/ic_select_all"
android:title="@string/select_all"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/cab_open_with"
android:title="@string/open_with"
app:showAsAction="never"/>
<item
android:id="@+id/cab_set_as"
android:title="@string/set_as"
app:showAsAction="never"/>
<item
android:id="@+id/cab_copy_to"
android:title="@string/copy_to"

View file

@ -6,6 +6,11 @@
android:icon="@drawable/ic_share"
android:title="@string/share"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/menu_properties"
android:icon="@drawable/ic_info"
android:title="@string/properties"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/menu_edit"
android:icon="@drawable/ic_edit"

View file

@ -0,0 +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"/>
</adaptive-icon>

View file

@ -0,0 +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"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Gallery</string>
<string name="edit">Edit</string>
<string name="open_camera">Open camera</string>
<string name="open_with">Open with</string>
<string name="no_app_found">No valid app found</string>
<string name="hidden">(hidden)</string>
<string name="pin_folder">Pin folder</string>
<string name="unpin_folder">Unpin folder</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">Change cover image</string>
<string name="select_photo">Select photo</string>
<string name="use_default">Use default</string>
<string name="set_as">Set as</string>
<string name="volume">Volume</string>
<string name="brightness">Brightness</string>
<string name="do_not_ask_again">Do not ask again in this session</string>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Galerie</string>
<string name="edit">Upravit</string>
<string name="open_camera">Spustit fotoaparát</string>
<string name="open_with">Otevřít pomocí</string>
<string name="no_app_found">Nebyla nalezena žádná vhodná aplikace</string>
<string name="hidden">(skryté)</string>
<string name="pin_folder">Připnout složku</string>
<string name="unpin_folder">Odepnout složku</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">Change cover image</string>
<string name="select_photo">Select photo</string>
<string name="use_default">Use default</string>
<string name="set_as">Nastavit jako</string>
<string name="volume">Volume</string>
<string name="brightness">Brightness</string>
<string name="do_not_ask_again">Do not ask again in this session</string>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Galerie</string>
<string name="edit">Bearbeiten</string>
<string name="open_camera">Kamera öffnen</string>
<string name="open_with">Öffnen mit</string>
<string name="no_app_found">Keine passende App gefunden</string>
<string name="hidden">(versteckt)</string>
<string name="pin_folder">Ordner anheften</string>
<string name="unpin_folder">Ordner loslösen</string>
@ -14,7 +12,7 @@
<string name="folder_view">Ansicht: Als Ordner</string>
<string name="other_folder">Ordner wählen</string>
<string name="show_on_map">Auf Karte zeigen</string>
<string name="unknown_location">Unbekannter Ort</string>
<string name="unknown_location">Unbekannter Pfad</string>
<string name="no_map_application">Keine Karten-App gefunden</string>
<string name="no_camera_app_found">Keine Kamera-App gefunden</string>
<string name="increase_column_count">Kacheln verkleinern</string>
@ -22,10 +20,9 @@
<string name="change_cover_image">Coverbild ändern</string>
<string name="select_photo">Auswählen</string>
<string name="use_default">Standard</string>
<string name="set_as">Festlegen als</string>
<string name="volume">Lautstärke</string>
<string name="brightness">Helligkeit</string>
<string name="do_not_ask_again">Nicht erneut fragen (in dieser Session)</string>
<string name="do_not_ask_again">Nicht erneut fragen (in dieser Sitzung)</string>
<!-- Filter -->
<string name="filter_media">Filter</string>
@ -69,7 +66,7 @@
<string name="image_editing_failed">Bildbearbeitung fehlgeschlagen</string>
<string name="edit_image_with">Bild bearbeiten mit</string>
<string name="no_editor_found">Keine Bildeditor-App gefunden</string>
<string name="unknown_file_location">Unbekannter Dateiort</string>
<string name="unknown_file_location">Unbekannter Dateipfad</string>
<string name="error_saving_file">Konnte Quelldatei nicht überschreiben</string>
<string name="rotate_left">Nach links drehen</string>
<string name="rotate_right">Nach rechts drehen</string>
@ -125,7 +122,7 @@
<string name="hide_system_ui_at_fullscreen">Systemleisten ausblenden im Vollbild</string>
<string name="delete_empty_folders">Nach Löschen leere Ordner löschen</string>
<string name="allow_video_gestures">Gesten für Videolautstärke/Helligkeit</string>
<string name="show_media_count">Show folder media count on the main view</string>
<string name="show_media_count">Medienanzahl bei Ordnern anzeigen</string>
<string name="replace_share_with_rotate">Teilen/Drehen im Vollbild-Menü vertauschen</string>
<string name="show_extended_details">Eigenschaften anzeigen im Vollbild</string>
<string name="manage_extended_details">Eigenschaften auswählen</string>
@ -134,11 +131,11 @@
<!-- Short description has to have less than 80 chars -->
<string name="app_short_description">Eine schlichte Galerie zum Betrachten von Bildern und Videos ohne Werbung.</string>
<string name="app_long_description">
Ein schlichtes Tool zum Betrachten von Bildern und Videos. Die Medien können nach Datum, Größe, Name sowie auf- oder absteigend sortiert angezeigt werden, in Bilder kann hineingezoomt werden. Die Vorschau-Kacheln werden in mehreren Spalten abhängig von der Displaygröße angezeigt, die Spaltenanzahl ist mit Zweifingergesten änderbar. Die Medien können umbenannt, geteilt, gelöscht, kopiert, verschoben werden. Bilder können zugeschnitten, gedreht oder als Hintergrund festgelegt werden, direkt aus der App heraus.
Eine schlichte App zum Betrachten von Bildern und Videos. Die Medien können nach Datum, Größe, Name sowie auf- oder absteigend sortiert werden, in Bilder kann auch hineingezoomt werden. Die Vorschau-Kacheln werden in mehreren Spalten abhängig von der Displaygröße angezeigt, die Spaltenanzahl ist mit Zweifingergesten änderbar. Die Medien können umbenannt, geteilt, gelöscht, kopiert und verschoben werden. Bilder können direkt aus der App heraus zugeschnitten, gedreht oder als Hintergrund festgelegt werden.
Die Galerie bietet auch für Drittparteien einige Funktionen an: zum Vorschauen von Bildern / Videos, zum Hinzufügen von Anhängen bei eMail-Clients, etc. Sie ist perfekt für den täglichen Gebrauch.
Diese Galerie bietet auch für Drittanbieter einige Funktionen an: zum Vorschauen von Bildern / Videos, zum Hinzufügen von Anhängen bei Email-Apps, etc. Sie ist perfekt für den täglichen Gebrauch.
Beinhaltet keine Werbung oder unnötige Berechtigungen. Sie ist komplett Open Source, verwendete Farben sind anpassbar.
Beinhaltet keine Werbung oder unnötigen Berechtigungen. Sie ist komplett Open Source, verwendete Farben sind anpassbar.
Diese App ist nur eine aus einer größeren Serie von schlichten Apps. Der Rest davon findet sich auf http://www.simplemobiletools.com
</string>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Galería</string>
<string name="edit">Editar</string>
<string name="open_camera">Abrir cámara</string>
<string name="open_with">Abrir con&#8230;</string>
<string name="no_app_found">No se encontró una aplicación válida</string>
<string name="hidden">(oculto)</string>
<string name="pin_folder">Fijar carpeta</string>
<string name="unpin_folder">No fijar carpeta</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">Cambiar imagen de portada</string>
<string name="select_photo">Seleccionar imagen</string>
<string name="use_default">Uso por defecto</string>
<string name="set_as">Establecer como</string>
<string name="volume">Volume</string>
<string name="brightness">Brightness</string>
<string name="do_not_ask_again">Do not ask again in this session</string>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Galleria</string>
<string name="edit">Muokkaa</string>
<string name="open_camera">Avaa kamera</string>
<string name="open_with">Avaa</string>
<string name="no_app_found">Sovelluksia ei löydetty</string>
<string name="hidden">(piilotettu)</string>
<string name="pin_folder">Kiinnitä kansio</string>
<string name="unpin_folder">Poista kiinnitys</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">Vaihda kansikuva</string>
<string name="select_photo">Valitse kuva</string>
<string name="use_default">Käytä oletuksia</string>
<string name="set_as">Aseta</string>
<string name="volume">Äänenvoimakkuus</string>
<string name="brightness">Kirkkaus</string>
<string name="do_not_ask_again">Do not ask again in this session</string>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Galerie</string>
<string name="edit">Édition</string>
<string name="open_camera">Ouvrir appareil photo</string>
<string name="open_with">Ouvrir avec</string>
<string name="no_app_found">Aucune application valide trouvée</string>
<string name="hidden">(caché)</string>
<string name="pin_folder">Épingler le dossier</string>
<string name="unpin_folder">Désépingler le dossier</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">Changer l\'image de couverture</string>
<string name="select_photo">Sélectionner une photo</string>
<string name="use_default">Utiliser par défaut</string>
<string name="set_as">Définir comme</string>
<string name="volume">Volume</string>
<string name="brightness">Luminosité</string>
<string name="do_not_ask_again">Ne pas redemander pour cette session</string>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Gallery</string>
<string name="edit">Edit</string>
<string name="open_camera">Open camera</string>
<string name="open_with">Open with</string>
<string name="no_app_found">No valid app found</string>
<string name="hidden">(hidden)</string>
<string name="pin_folder">Pin folder</string>
<string name="unpin_folder">Unpin folder</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">Change cover image</string>
<string name="select_photo">Select photo</string>
<string name="use_default">Use default</string>
<string name="set_as">Set as</string>
<string name="volume">Volume</string>
<string name="brightness">Brightness</string>
<string name="do_not_ask_again">Do not ask again in this session</string>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Galleria</string>
<string name="edit">Modifica</string>
<string name="open_camera">Apri fotocamera</string>
<string name="open_with">Apri con</string>
<string name="no_app_found">Nessun app valida trovata</string>
<string name="hidden">(nascosta)</string>
<string name="pin_folder">Blocca cartella</string>
<string name="unpin_folder">Sblocca cartella</string>
@ -22,10 +20,9 @@
<string name="change_cover_image">Cambia immagine copertina</string>
<string name="select_photo">Seleziona foto</string>
<string name="use_default">Usa predefinita</string>
<string name="set_as">Imposta come</string>
<string name="volume">Volume</string>
<string name="brightness">Luminosità</string>
<string name="do_not_ask_again">Do not ask again in this session</string>
<string name="do_not_ask_again">Non chiedere nuovamente in questa sessione</string>
<!-- Filter -->
<string name="filter_media">Filtra i media</string>
@ -125,10 +122,10 @@
<string name="hide_system_ui_at_fullscreen">Nascondi UI di sistema con media a schermo intero</string>
<string name="delete_empty_folders">Elimina cartelle vuote dopo averne eliminato il contenuto</string>
<string name="allow_video_gestures">Gestisci il volume e la luminosità dei video con gesti verticali</string>
<string name="show_media_count">Show folder media count on the main view</string>
<string name="show_media_count">Mostra numero elementi nella cartella</string>
<string name="replace_share_with_rotate">Sostituisci Condividi con Ruota a schermo intero</string>
<string name="show_extended_details">Show extended details over fullscreen media</string>
<string name="manage_extended_details">Manage extended details</string>
<string name="show_extended_details">Mostra informazioni estese su media a schermo intero</string>
<string name="manage_extended_details">Gestisci le informazioni estese</string>
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
<!-- Short description has to have less than 80 chars -->

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">ギャラリー</string>
<string name="edit">編集</string>
<string name="open_camera">カメラを開く</string>
<string name="open_with">別のアプリで開く</string>
<string name="no_app_found">有効なアプリが見つかりません</string>
<string name="hidden">(非表示)</string>
<string name="pin_folder">フォルダーをピン留めする</string>
<string name="unpin_folder">フォルダーのピン留めを外す</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">カバー画像を変更</string>
<string name="select_photo">写真を選択</string>
<string name="use_default">デフォルトに戻す</string>
<string name="set_as">他で使う</string>
<string name="volume">音量</string>
<string name="brightness">明るさ</string>
<string name="do_not_ask_again">Do not ask again in this session</string>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Gallerij</string>
<string name="edit">Bewerken</string>
<string name="open_camera">Camera</string>
<string name="open_with">Openen met</string>
<string name="no_app_found">Geen app gevonden om dit bestand mee te openen</string>
<string name="hidden">(verborgen)</string>
<string name="pin_folder">Map vastzetten</string>
<string name="unpin_folder">Map losmaken</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">Afbeelding voor omslag veranderen</string>
<string name="select_photo">Foto selecteren</string>
<string name="use_default">Standaard gebruiken</string>
<string name="set_as">Instellen als</string>
<string name="volume">Volume</string>
<string name="brightness">Helderheid</string>
<string name="do_not_ask_again">Onthouden voor deze sessie</string>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Simple Gallery</string>
<string name="edit">Edytuj</string>
<string name="open_camera">Uruchom aplikację aparatu</string>
<string name="open_with">Otwórz w</string>
<string name="no_app_found">Nie znaleziono danych aplikacji</string>
<string name="hidden">(ukryty)</string>
<string name="pin_folder">Przypnij folder</string>
<string name="unpin_folder">Wypakuj folder</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">Zmień okładkę</string>
<string name="select_photo">Wybierz obraz</string>
<string name="use_default">Użyj domyślnej</string>
<string name="set_as">Ustaw jako</string>
<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>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Galeria</string>
<string name="edit">Editar</string>
<string name="open_camera">Abrir câmera</string>
<string name="open_with">Abrir com</string>
<string name="no_app_found">Nenhum aplicativo encontrado</string>    
<string name="hidden">(oculto)</string>
<string name="pin_folder">Fixar pasta</string>
<string name="unpin_folder">Desfixar pasta</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">Trocar imagem de capa</string>
<string name="select_photo">Selecionar foto</string>
<string name="use_default">Usar padrão</string>
<string name="set_as">Definir como</string>
<string name="volume">Volume</string>
<string name="brightness">Brilho</string>
<string name="do_not_ask_again">Não perguntar novamente por enquanto</string>
@ -125,7 +122,7 @@
<string name="hide_system_ui_at_fullscreen">Esconder interface do sistema automaticamente quando em tela cheia</string>
<string name="delete_empty_folders">Apagar pastas vazias após deleter seu conteúdo</string>
<string name="allow_video_gestures">Permitir controle do volume e brilho com gestos na vertical</string>
<string name="show_media_count">Show folder media count on the main view</string>
<string name="show_media_count">Mostrar quantidade de arquivos das pastas</string>
<string name="replace_share_with_rotate">Substituir botão "Compartilhar" por "Rotação de tela" quando em tela cheia</string>
<string name="show_extended_details">Exibir detalhes extendidos quando em tela cheia</string>
<string name="manage_extended_details">Gerenciar detalhes extendidos</string>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Galeria</string>
<string name="edit">Editar</string>
<string name="open_camera">Abrir câmara</string>
<string name="open_with">Abrir com</string>
<string name="no_app_found">Nenhuma aplicação encontrada</string>
<string name="hidden">(oculta)</string>
<string name="pin_folder">Fixar pasta</string>
<string name="unpin_folder">Desafixar pasta</string>
@ -22,10 +20,9 @@
<string name="change_cover_image">Alterar imagem de capa</string>
<string name="select_photo">Selecionar foto</string>
<string name="use_default">Predefinição</string>
<string name="set_as">Definir como</string>
<string name="volume">Volume</string>
<string name="brightness">Brilho</string>
<string name="do_not_ask_again">Do not ask again in this session</string>
<string name="do_not_ask_again">Não perguntar de novo para esta sessão</string>
<!-- Filter -->
<string name="filter_media">Filtrar multimédia</string>
@ -127,8 +124,8 @@
<string name="allow_video_gestures">Permitir controlo do volume e brilho dos vídeos através de gestos verticais</string>
<string name="show_media_count">Show folder media count on the main view</string>
<string name="replace_share_with_rotate">Substituir a opção Partilhar pela opção Rodar se em ecrã completo</string>
<string name="show_extended_details">Show extended details over fullscreen media</string>
<string name="manage_extended_details">Manage extended details</string>
<string name="show_extended_details">Mostrar detalhes se em ecrã completo</string>
<string name="manage_extended_details">Gerir detalhes exibidos</string>
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
<!-- Short description has to have less than 80 chars -->

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Галерея</string>
<string name="edit">Редактировать</string>
<string name="open_camera">Открыть камеру</string>
<string name="open_with">Открыть в</string>
<string name="no_app_found">Приложение не найдено</string>
<string name="hidden">(Скрытый)</string>
<string name="pin_folder">Закрепить папку</string>
<string name="unpin_folder">Открепить папку</string>
@ -17,15 +15,14 @@
<string name="unknown_location">Место съёмки не указано</string>
<string name="no_map_application">Не найдено приложений с картами</string>
<string name="no_camera_app_found">Не найдено приложения камеры</string>
<string name="increase_column_count">Добавить 1 столбец</string>
<string name="reduce_column_count">Убрать 1 столбец</string>
<string name="increase_column_count">Добавить столбец</string>
<string name="reduce_column_count">Убрать столбец</string>
<string name="change_cover_image">Изменить обложку</string>
<string name="select_photo">Выбрать изображение</string>
<string name="use_default">Использовать по умолчанию</string>
<string name="set_as">Установить как…</string>
<string name="volume">Громкость</string>
<string name="brightness">Яркость</string>
<string name="do_not_ask_again">Do not ask again in this session</string>
<string name="do_not_ask_again">Не спрашивать снова (до следующего запуска)</string>
<!-- Filter -->
<string name="filter_media">Фильтр медиа</string>
@ -87,8 +84,8 @@
<string name="no_capable_app_found">Приложение не найдено</string>
<string name="setting_wallpaper">Установка обоев…</string>
<string name="wallpaper_set_successfully">Обои успешно установлены</string>
<string name="portrait_aspect_ratio">Формат изображения</string>
<string name="landscape_aspect_ratio">Пейзажное соотношение сторон</string>
<string name="portrait_aspect_ratio">Портрет</string>
<string name="landscape_aspect_ratio">Ландшафт</string>
<!-- Slideshow -->
<string name="slideshow">Слайдшоу</string>
@ -125,10 +122,10 @@
<string name="hide_system_ui_at_fullscreen">Автоматически скрывать системный интерфейс в полноэкранном режиме</string>
<string name="delete_empty_folders">Удалять пустые папки после удаления их содержимого</string>
<string name="allow_video_gestures">Управлять громкостью и яркостью видео с помощью вертикальных жестов</string>
<string name="show_media_count">Show folder media count on the main view</string>
<string name="show_media_count">Показывать количество файлов в папках</string>
<string name="replace_share_with_rotate">Заменить \'Поделиться\' на \'Повернуть\' в меню полноэкранного режима</string>
<string name="show_extended_details">Show extended details over fullscreen media</string>
<string name="manage_extended_details">Manage extended details</string>
<string name="show_extended_details">Показывать детали файла</string>
<string name="manage_extended_details">Выбрать детали файла</string>
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
<!-- Short description has to have less than 80 chars -->

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Galéria</string>
<string name="edit">Upraviť</string>
<string name="open_camera">Otvoriť fotoaparát</string>
<string name="open_with">Otvoriť pomocou</string>
<string name="no_app_found">Nenašla sa žiadna vhodná aplikácia</string>
<string name="hidden">(skryté)</string>
<string name="pin_folder">Pripnúť priečinok</string>
<string name="unpin_folder">Odopnúť priečinok</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">Zmeniť obal albumu</string>
<string name="select_photo">Zvoliť foto</string>
<string name="use_default">Použiť predvolený</string>
<string name="set_as">Nastaviť ako</string>
<string name="volume">Hlasitosť</string>
<string name="brightness">Jas</string>
<string name="do_not_ask_again">Nepýtať sa už v tomto spustení</string>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Galleri</string>
<string name="edit">Redigera</string>
<string name="open_camera">Starta kameran</string>
<string name="open_with">Öppna med</string>
<string name="no_app_found">Hittade ingen giltig app</string>
<string name="hidden">(dold)</string>
<string name="pin_folder">Fäst mappen</string>
<string name="unpin_folder">Släpp mappen</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">Byt omslagsbild</string>
<string name="select_photo">Välj foto</string>
<string name="use_default">Använd standard</string>
<string name="set_as">Ange som</string>
<string name="volume">Volym</string>
<string name="brightness">Ljusstyrka</string>
<string name="do_not_ask_again">Do not ask again in this session</string>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Galeri</string>
<string name="edit">Düzenle</string>
<string name="open_camera">Kamerayı</string>
<string name="open_with">Bununla aç</string>
<string name="no_app_found">Geçerli bir uygulama bulunamadı</string>
<string name="hidden">(gizli)</string>
<string name="pin_folder">Pin klasör</string>
<string name="unpin_folder">Klasörü çöz</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">Change cover image</string>
<string name="select_photo">Select photo</string>
<string name="use_default">Use default</string>
<string name="set_as">Set as</string>
<string name="volume">Volume</string>
<string name="brightness">Brightness</string>
<string name="do_not_ask_again">Do not ask again in this session</string>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">简约图库</string>
<string name="edit">编辑</string>
<string name="open_camera">打开相机</string>
<string name="open_with">打开方式</string>
<string name="no_app_found">未找到可用应用</string>
<string name="hidden">(隐藏)</string>
<string name="pin_folder">锁定目录</string>
<string name="unpin_folder">解除锁定目录</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">更改封面图片</string>
<string name="select_photo">选择图片</string>
<string name="use_default">使用默认</string>
<string name="set_as">设置为</string>
<string name="volume">音量</string>
<string name="brightness">亮度</string>
<string name="do_not_ask_again">不再提醒</string>
@ -30,7 +27,7 @@
<!-- Filter -->
<string name="filter_media">要显示的媒体文件</string>
<string name="images">图片</string>
<string name="videos">适配</string>
<string name="videos">视频</string>
<string name="gifs">GIFs</string>
<string name="no_media_with_filters">所选的过滤器没有找到媒体文件。</string>
<string name="change_filters_underlined"><u>更改过滤器</u></string>
@ -44,7 +41,7 @@
<string name="exclude_folder_parent">是否排除父目录?</string>
<string name="excluded_activity_placeholder">此目录及其子目录中的媒体将不会在“简约图库”中显示,但是其它应用可以访问。如果您想对其它应用隐藏,请使用隐藏功能。</string>
<string name="remove_all">移除全部</string>
<string name="remove_all_description">是否删除排除列表中的所有文件夹?此操作不会删除文件夹</string>
<string name="remove_all_description">是否删除排除列表中的所有项目?此操作不会删除文件夹本身</string>
<!-- Include folders -->
<string name="include_folders">包含目录</string>
@ -116,7 +113,7 @@
<string name="animate_gifs">GIF 缩略图</string>
<string name="max_brightness">浏览时最大亮度</string>
<string name="crop_thumbnails">裁剪缩略图</string>
<string name="screen_rotation_by">全屏方向</string>
<string name="screen_rotation_by">全屏方向</string>
<string name="screen_rotation_system_setting">系统设置</string>
<string name="screen_rotation_device_rotation">设备方向</string>
<string name="screen_rotation_aspect_ratio">根据长宽比</string>

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">簡易相簿</string>
<string name="edit">編輯</string>
<string name="open_camera">開啟相機</string>
<string name="open_with">以其他應用程式開啟</string>
<string name="no_app_found">找不到應用程式</string>
<string name="hidden">(隱藏)</string>
<string name="pin_folder">釘選資料夾</string>
<string name="unpin_folder">取消釘選資料夾</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">更換封面圖片</string>
<string name="select_photo">選擇相片</string>
<string name="use_default">使用預設</string>
<string name="set_as">設為</string>
<string name="volume">音量</string>
<string name="brightness">亮度</string>
<string name="do_not_ask_again">Do not ask again in this session</string>

View file

@ -7,4 +7,6 @@
<!-- 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,7 @@
<resources>
<!-- Release notes -->
<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>
<string name="release_133">

View file

@ -4,8 +4,6 @@
<string name="app_launcher_name">Gallery</string>
<string name="edit">Edit</string>
<string name="open_camera">Open camera</string>
<string name="open_with">Open with</string>
<string name="no_app_found">No valid app found</string>
<string name="hidden">(hidden)</string>
<string name="pin_folder">Pin folder</string>
<string name="unpin_folder">Unpin folder</string>
@ -22,7 +20,6 @@
<string name="change_cover_image">Change cover image</string>
<string name="select_photo">Select photo</string>
<string name="use_default">Use default</string>
<string name="set_as">Set as</string>
<string name="volume">Volume</string>
<string name="brightness">Brightness</string>
<string name="do_not_ask_again">Do not ask again in this session</string>

View file

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
<root-path name="external_files" path="/storage/" />
</paths>