21
CHANGELOG.md
|
@ -1,6 +1,27 @@
|
|||
Changelog
|
||||
==========
|
||||
|
||||
Version 4.3.5 *(2018-07-17)*
|
||||
----------------------------
|
||||
|
||||
* Fixed some Recycle bin related issues
|
||||
* A few more UX and stability improvements
|
||||
|
||||
Version 4.3.4 *(2018-07-15)*
|
||||
----------------------------
|
||||
|
||||
* Fixed disappearing launcher icon after changing its color on some devices
|
||||
* Fixed some video related errors
|
||||
* Added "Set as" as an available action at the fullscreen bottom actions
|
||||
* Do the appropriate actions at trying to delete the Recycle Bin or Favorites folders
|
||||
* Fixed a glitch with some panorama images not recognized properly
|
||||
* Avoid blank screen at toggling "Temporarily show hidden"
|
||||
|
||||
Version 4.3.3 *(2018-07-06)*
|
||||
----------------------------
|
||||
|
||||
* Couple stability improvements and glitch fixes
|
||||
|
||||
Version 4.3.2 *(2018-07-04)*
|
||||
----------------------------
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ android {
|
|||
applicationId "com.simplemobiletools.gallery"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 27
|
||||
versionCode 184
|
||||
versionName "4.3.2"
|
||||
versionCode 187
|
||||
versionName "4.3.5"
|
||||
multiDexEnabled true
|
||||
setProperty("archivesBaseName", "gallery")
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ ext {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.simplemobiletools:commons:4.3.27'
|
||||
implementation 'com.simplemobiletools:commons:4.5.3'
|
||||
implementation 'com.theartofdev.edmodo:android-image-cropper:2.7.0'
|
||||
implementation 'com.android.support:multidex:1.0.3'
|
||||
implementation 'it.sephiroth.android.exif:library:1.0.1'
|
||||
|
@ -57,6 +57,7 @@ dependencies {
|
|||
implementation 'com.google.android.exoplayer:exoplayer-core:2.8.2'
|
||||
implementation 'com.google.vr:sdk-panowidget:1.150.0'
|
||||
implementation 'org.apache.sanselan:sanselan:0.97-incubator'
|
||||
implementation 'info.androidhive:imagefilters:1.0.7'
|
||||
|
||||
kapt "android.arch.persistence.room:compiler:1.1.1"
|
||||
implementation "android.arch.persistence.room:runtime:1.1.1"
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.SET_WALLPAPER"/>
|
||||
<uses-permission
|
||||
android:name="android.permission.ACCESS_NETWORK_STATE"
|
||||
tools:node="remove"/>
|
||||
|
||||
<uses-sdk
|
||||
tools:overrideLibrary="com.google.vr.widgets.common, com.google.vr.sdk.widgets.pano"/>
|
||||
|
@ -18,17 +21,12 @@
|
|||
android:label="@string/app_launcher_name"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
android:theme="@style/AppTheme"
|
||||
tools:replace="android:label">
|
||||
|
||||
<activity
|
||||
android:name=".activities.SplashActivity"
|
||||
android:theme="@style/SplashTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
android:theme="@style/SplashTheme"/>
|
||||
|
||||
<activity
|
||||
android:name=".activities.MainActivity"
|
||||
|
@ -222,19 +220,6 @@
|
|||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- Do not append ".Orange" to the default alias "name", it would remove the old homescreen launcher of users at upgrade -->
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity"
|
||||
android:enabled="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Red"
|
||||
android:enabled="false"
|
||||
|
@ -417,6 +402,18 @@
|
|||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Orange"
|
||||
android:enabled="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Deep_orange"
|
||||
android:enabled="false"
|
||||
|
|
|
@ -4,40 +4,83 @@ import android.app.Activity
|
|||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Bitmap.CompressFormat
|
||||
import android.graphics.Color
|
||||
import android.graphics.Point
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.widget.RelativeLayout
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.DataSource
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.load.engine.GlideException
|
||||
import com.bumptech.glide.request.RequestListener
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.bumptech.glide.request.target.Target
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.OTG_PATH
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE
|
||||
import com.simplemobiletools.commons.helpers.REAL_FILE_PATH
|
||||
import com.simplemobiletools.commons.models.FileDirItem
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.adapters.FiltersAdapter
|
||||
import com.simplemobiletools.gallery.dialogs.ResizeDialog
|
||||
import com.simplemobiletools.gallery.dialogs.SaveAsDialog
|
||||
import com.simplemobiletools.gallery.extensions.config
|
||||
import com.simplemobiletools.gallery.extensions.openEditor
|
||||
import com.simplemobiletools.gallery.helpers.FilterThumbnailsManager
|
||||
import com.simplemobiletools.gallery.models.FilterItem
|
||||
import com.theartofdev.edmodo.cropper.CropImageView
|
||||
import kotlinx.android.synthetic.main.view_crop_image.*
|
||||
import com.zomato.photofilters.FilterPack
|
||||
import com.zomato.photofilters.imageprocessors.Filter
|
||||
import kotlinx.android.synthetic.main.activity_edit.*
|
||||
import kotlinx.android.synthetic.main.bottom_actions_aspect_ratio.*
|
||||
import kotlinx.android.synthetic.main.bottom_editor_actions_filter.*
|
||||
import kotlinx.android.synthetic.main.bottom_editor_crop_rotate_actions.*
|
||||
import kotlinx.android.synthetic.main.bottom_editor_primary_actions.*
|
||||
import java.io.*
|
||||
|
||||
class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("NativeImageProcessor")
|
||||
}
|
||||
}
|
||||
|
||||
private val ASPECT_X = "aspectX"
|
||||
private val ASPECT_Y = "aspectY"
|
||||
private val CROP = "crop"
|
||||
|
||||
private val ASPECT_RATIO_FREE = 0
|
||||
private val ASPECT_RATIO_ONE_ONE = 1
|
||||
private val ASPECT_RATIO_FOUR_THREE = 2
|
||||
private val ASPECT_RATIO_SIXTEEN_NINE = 3
|
||||
|
||||
// constants for bottom primary action groups
|
||||
private val PRIMARY_ACTION_NONE = 0
|
||||
private val PRIMARY_ACTION_FILTER = 1
|
||||
private val PRIMARY_ACTION_CROP_ROTATE = 2
|
||||
|
||||
private val CROP_ROTATE_NONE = 0
|
||||
private val CROP_ROTATE_ASPECT_RATIO = 1
|
||||
|
||||
private lateinit var uri: Uri
|
||||
private lateinit var saveUri: Uri
|
||||
private var resizeWidth = 0
|
||||
private var resizeHeight = 0
|
||||
private var currPrimaryAction = PRIMARY_ACTION_NONE
|
||||
private var currCropRotateAction = CROP_ROTATE_NONE
|
||||
private var currAspectRatio = ASPECT_RATIO_FREE
|
||||
private var isCropIntent = false
|
||||
private var isEditingWithThirdParty = false
|
||||
|
||||
private var initialBitmap: Bitmap? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.view_crop_image)
|
||||
setContentView(R.layout.activity_edit)
|
||||
|
||||
handlePermission(PERMISSION_WRITE_STORAGE) {
|
||||
if (it) {
|
||||
|
@ -82,14 +125,13 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
|||
}
|
||||
|
||||
isCropIntent = intent.extras?.get(CROP) == "true"
|
||||
|
||||
crop_image_view.apply {
|
||||
setOnCropImageCompleteListener(this@EditActivity)
|
||||
setImageUriAsync(uri)
|
||||
|
||||
if (isCropIntent && shouldCropSquare())
|
||||
setFixedAspectRatio(true)
|
||||
if (isCropIntent) {
|
||||
bottom_editor_primary_actions.beGone()
|
||||
(bottom_editor_crop_rotate_actions.layoutParams as RelativeLayout.LayoutParams).addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, 1)
|
||||
}
|
||||
|
||||
loadDefaultImageView()
|
||||
setupBottomActions()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -106,23 +148,288 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
|||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_editor, menu)
|
||||
menu.findItem(R.id.resize).isVisible = !isCropIntent
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.save_as -> crop_image_view.getCroppedImageAsync()
|
||||
R.id.rotate -> crop_image_view.rotateImage(90)
|
||||
R.id.resize -> resizeImage()
|
||||
R.id.flip_horizontally -> flipImage(true)
|
||||
R.id.flip_vertically -> flipImage(false)
|
||||
R.id.save_as -> saveImage()
|
||||
R.id.edit -> editWith()
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun loadDefaultImageView() {
|
||||
default_image_view.beVisible()
|
||||
crop_image_view.beGone()
|
||||
|
||||
val options = RequestOptions()
|
||||
.skipMemoryCache(true)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
.load(uri)
|
||||
.apply(options)
|
||||
.listener(object : RequestListener<Bitmap> {
|
||||
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Bitmap>?, isFirstResource: Boolean) = false
|
||||
|
||||
override fun onResourceReady(bitmap: Bitmap?, model: Any?, target: Target<Bitmap>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
|
||||
val currentFilter = getFiltersAdapter()?.getCurrentFilter()
|
||||
if (initialBitmap != null && currentFilter != null && currentFilter.filter.name != getString(R.string.none)) {
|
||||
default_image_view.onGlobalLayout {
|
||||
applyFilter(currentFilter)
|
||||
}
|
||||
} else {
|
||||
initialBitmap = bitmap
|
||||
}
|
||||
|
||||
if (isCropIntent) {
|
||||
loadCropImageView()
|
||||
bottom_primary_filter.beGone()
|
||||
bottomCropRotateClicked()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}).into(default_image_view)
|
||||
}
|
||||
|
||||
private fun loadCropImageView() {
|
||||
default_image_view.beGone()
|
||||
crop_image_view.apply {
|
||||
beVisible()
|
||||
setOnCropImageCompleteListener(this@EditActivity)
|
||||
setImageUriAsync(uri)
|
||||
guidelines = CropImageView.Guidelines.ON
|
||||
|
||||
if (isCropIntent && shouldCropSquare()) {
|
||||
currAspectRatio = ASPECT_RATIO_ONE_ONE
|
||||
setFixedAspectRatio(true)
|
||||
bottom_aspect_ratio.beGone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveImage() {
|
||||
if (crop_image_view.isVisible()) {
|
||||
crop_image_view.getCroppedImageAsync()
|
||||
} else {
|
||||
val currentFilter = getFiltersAdapter()?.getCurrentFilter() ?: return
|
||||
val filePathGetter = getNewFilePath()
|
||||
SaveAsDialog(this, filePathGetter.first, filePathGetter.second) {
|
||||
toast(R.string.saving)
|
||||
|
||||
// clean up everything to free as much memory as possible
|
||||
default_image_view.setImageResource(0)
|
||||
crop_image_view.setImageBitmap(null)
|
||||
bottom_actions_filter_list.adapter = null
|
||||
bottom_actions_filter_list.beGone()
|
||||
|
||||
Thread {
|
||||
val originalBitmap = Glide.with(applicationContext).asBitmap().load(uri).submit(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL).get()
|
||||
currentFilter.filter.processFilter(originalBitmap)
|
||||
saveBitmapToFile(originalBitmap, it, false)
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFiltersAdapter() = bottom_actions_filter_list.adapter as? FiltersAdapter
|
||||
|
||||
private fun setupBottomActions() {
|
||||
setupPrimaryActionButtons()
|
||||
setupCropRotateActionButtons()
|
||||
setupAspectRatioButtons()
|
||||
}
|
||||
|
||||
private fun setupPrimaryActionButtons() {
|
||||
bottom_primary_filter.setOnClickListener {
|
||||
bottomFilterClicked()
|
||||
}
|
||||
|
||||
bottom_primary_crop_rotate.setOnClickListener {
|
||||
bottomCropRotateClicked()
|
||||
}
|
||||
}
|
||||
|
||||
private fun bottomFilterClicked() {
|
||||
currPrimaryAction = if (currPrimaryAction == PRIMARY_ACTION_FILTER) {
|
||||
PRIMARY_ACTION_NONE
|
||||
} else {
|
||||
PRIMARY_ACTION_FILTER
|
||||
}
|
||||
updatePrimaryActionButtons()
|
||||
}
|
||||
|
||||
private fun bottomCropRotateClicked() {
|
||||
currPrimaryAction = if (currPrimaryAction == PRIMARY_ACTION_CROP_ROTATE) {
|
||||
PRIMARY_ACTION_NONE
|
||||
} else {
|
||||
PRIMARY_ACTION_CROP_ROTATE
|
||||
}
|
||||
updatePrimaryActionButtons()
|
||||
}
|
||||
|
||||
private fun setupCropRotateActionButtons() {
|
||||
bottom_rotate.setOnClickListener {
|
||||
crop_image_view.rotateImage(90)
|
||||
}
|
||||
|
||||
bottom_resize.beGoneIf(isCropIntent)
|
||||
bottom_resize.setOnClickListener {
|
||||
resizeImage()
|
||||
}
|
||||
|
||||
bottom_flip_horizontally.setOnClickListener {
|
||||
crop_image_view.flipImageHorizontally()
|
||||
}
|
||||
|
||||
bottom_flip_vertically.setOnClickListener {
|
||||
crop_image_view.flipImageVertically()
|
||||
}
|
||||
|
||||
bottom_aspect_ratio.setOnClickListener {
|
||||
currCropRotateAction = if (currCropRotateAction == CROP_ROTATE_ASPECT_RATIO) {
|
||||
crop_image_view.guidelines = CropImageView.Guidelines.OFF
|
||||
bottom_aspect_ratios.beGone()
|
||||
CROP_ROTATE_NONE
|
||||
} else {
|
||||
crop_image_view.guidelines = CropImageView.Guidelines.ON
|
||||
bottom_aspect_ratios.beVisible()
|
||||
CROP_ROTATE_ASPECT_RATIO
|
||||
}
|
||||
updateCropRotateActionButtons()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupAspectRatioButtons() {
|
||||
bottom_aspect_ratio_free.setOnClickListener {
|
||||
updateAspectRatio(ASPECT_RATIO_FREE)
|
||||
}
|
||||
|
||||
bottom_aspect_ratio_one_one.setOnClickListener {
|
||||
updateAspectRatio(ASPECT_RATIO_ONE_ONE)
|
||||
}
|
||||
|
||||
bottom_aspect_ratio_four_three.setOnClickListener {
|
||||
updateAspectRatio(ASPECT_RATIO_FOUR_THREE)
|
||||
}
|
||||
|
||||
bottom_aspect_ratio_sixteen_nine.setOnClickListener {
|
||||
updateAspectRatio(ASPECT_RATIO_SIXTEEN_NINE)
|
||||
}
|
||||
updateAspectRatioButtons()
|
||||
}
|
||||
|
||||
private fun updatePrimaryActionButtons() {
|
||||
if (crop_image_view.isGone() && currPrimaryAction == PRIMARY_ACTION_CROP_ROTATE) {
|
||||
loadCropImageView()
|
||||
} else if (default_image_view.isGone() && currPrimaryAction == PRIMARY_ACTION_FILTER) {
|
||||
loadDefaultImageView()
|
||||
}
|
||||
|
||||
arrayOf(bottom_primary_filter, bottom_primary_crop_rotate).forEach {
|
||||
it.applyColorFilter(Color.WHITE)
|
||||
}
|
||||
|
||||
val currentPrimaryActionButton = when (currPrimaryAction) {
|
||||
PRIMARY_ACTION_FILTER -> bottom_primary_filter
|
||||
PRIMARY_ACTION_CROP_ROTATE -> bottom_primary_crop_rotate
|
||||
else -> null
|
||||
}
|
||||
|
||||
currentPrimaryActionButton?.applyColorFilter(config.primaryColor)
|
||||
bottom_editor_filter_actions.beVisibleIf(currPrimaryAction == PRIMARY_ACTION_FILTER)
|
||||
bottom_editor_crop_rotate_actions.beVisibleIf(currPrimaryAction == PRIMARY_ACTION_CROP_ROTATE)
|
||||
|
||||
if (currPrimaryAction == PRIMARY_ACTION_FILTER && bottom_actions_filter_list.adapter == null) {
|
||||
Thread {
|
||||
val size = resources.getDimension(R.dimen.bottom_filters_thumbnail_height).toInt()
|
||||
val bitmap = Glide.with(this).asBitmap().load(uri).submit(size, size).get()
|
||||
runOnUiThread {
|
||||
val filterThumbnailsManager = FilterThumbnailsManager()
|
||||
filterThumbnailsManager.clearThumbs()
|
||||
|
||||
val noFilter = Filter(getString(R.string.none))
|
||||
filterThumbnailsManager.addThumb(FilterItem(bitmap, noFilter))
|
||||
|
||||
FilterPack.getFilterPack(this).forEach {
|
||||
val filterItem = FilterItem(bitmap, it)
|
||||
filterThumbnailsManager.addThumb(filterItem)
|
||||
}
|
||||
|
||||
val filterItems = filterThumbnailsManager.processThumbs()
|
||||
val adapter = FiltersAdapter(applicationContext, filterItems) {
|
||||
applyFilter(it)
|
||||
}
|
||||
|
||||
bottom_actions_filter_list.adapter = adapter
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
if (currPrimaryAction != PRIMARY_ACTION_CROP_ROTATE) {
|
||||
bottom_aspect_ratios.beGone()
|
||||
currCropRotateAction = CROP_ROTATE_NONE
|
||||
updateCropRotateActionButtons()
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyFilter(filterItem: FilterItem) {
|
||||
val newBitmap = Bitmap.createBitmap(initialBitmap)
|
||||
default_image_view.setImageBitmap(filterItem.filter.processFilter(newBitmap))
|
||||
}
|
||||
|
||||
private fun updateAspectRatio(aspectRatio: Int) {
|
||||
currAspectRatio = aspectRatio
|
||||
updateAspectRatioButtons()
|
||||
|
||||
crop_image_view.apply {
|
||||
if (aspectRatio == ASPECT_RATIO_FREE) {
|
||||
setFixedAspectRatio(false)
|
||||
} else {
|
||||
val newAspectRatio = when (aspectRatio) {
|
||||
ASPECT_RATIO_ONE_ONE -> Pair(1, 1)
|
||||
ASPECT_RATIO_FOUR_THREE -> Pair(4, 3)
|
||||
else -> Pair(16, 9)
|
||||
}
|
||||
|
||||
setAspectRatio(newAspectRatio.first, newAspectRatio.second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateAspectRatioButtons() {
|
||||
arrayOf(bottom_aspect_ratio_free, bottom_aspect_ratio_one_one, bottom_aspect_ratio_four_three, bottom_aspect_ratio_sixteen_nine).forEach {
|
||||
it.setTextColor(Color.WHITE)
|
||||
}
|
||||
|
||||
val currentAspectRatioButton = when (currAspectRatio) {
|
||||
ASPECT_RATIO_FREE -> bottom_aspect_ratio_free
|
||||
ASPECT_RATIO_ONE_ONE -> bottom_aspect_ratio_one_one
|
||||
ASPECT_RATIO_FOUR_THREE -> bottom_aspect_ratio_four_three
|
||||
else -> bottom_aspect_ratio_sixteen_nine
|
||||
}
|
||||
|
||||
currentAspectRatioButton.setTextColor(config.primaryColor)
|
||||
}
|
||||
|
||||
private fun updateCropRotateActionButtons() {
|
||||
arrayOf(bottom_aspect_ratio).forEach {
|
||||
it.applyColorFilter(Color.WHITE)
|
||||
}
|
||||
|
||||
val primaryActionView = when (currCropRotateAction) {
|
||||
CROP_ROTATE_ASPECT_RATIO -> bottom_aspect_ratio
|
||||
else -> null
|
||||
}
|
||||
|
||||
primaryActionView?.applyColorFilter(config.primaryColor)
|
||||
}
|
||||
|
||||
private fun resizeImage() {
|
||||
val point = getAreaSize()
|
||||
if (point == null) {
|
||||
|
@ -160,7 +467,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
|||
if (result.error == null) {
|
||||
if (isCropIntent) {
|
||||
if (saveUri.scheme == "file") {
|
||||
saveBitmapToFile(result.bitmap, saveUri.path)
|
||||
saveBitmapToFile(result.bitmap, saveUri.path, true)
|
||||
} else {
|
||||
var inputStream: InputStream? = null
|
||||
var outputStream: OutputStream? = null
|
||||
|
@ -184,27 +491,12 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
|||
}
|
||||
} else if (saveUri.scheme == "file") {
|
||||
SaveAsDialog(this, saveUri.path, true) {
|
||||
saveBitmapToFile(result.bitmap, it)
|
||||
saveBitmapToFile(result.bitmap, it, true)
|
||||
}
|
||||
} else if (saveUri.scheme == "content") {
|
||||
var newPath = applicationContext.getRealPathFromURI(saveUri) ?: ""
|
||||
var shouldAppendFilename = true
|
||||
if (newPath.isEmpty()) {
|
||||
val filename = applicationContext.getFilenameFromContentUri(saveUri) ?: ""
|
||||
if (filename.isNotEmpty()) {
|
||||
val path = if (intent.extras?.containsKey(REAL_FILE_PATH) == true) intent.getStringExtra(REAL_FILE_PATH).getParentPath() else internalStoragePath
|
||||
newPath = "$path/$filename"
|
||||
shouldAppendFilename = false
|
||||
}
|
||||
}
|
||||
|
||||
if (newPath.isEmpty()) {
|
||||
newPath = "$internalStoragePath/${getCurrentFormattedDateTime()}.${saveUri.toString().getFilenameExtension()}"
|
||||
shouldAppendFilename = false
|
||||
}
|
||||
|
||||
SaveAsDialog(this, newPath, shouldAppendFilename) {
|
||||
saveBitmapToFile(result.bitmap, it)
|
||||
val filePathGetter = getNewFilePath()
|
||||
SaveAsDialog(this, filePathGetter.first, filePathGetter.second) {
|
||||
saveBitmapToFile(result.bitmap, it, true)
|
||||
}
|
||||
} else {
|
||||
toast(R.string.unknown_file_location)
|
||||
|
@ -214,14 +506,34 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
|||
}
|
||||
}
|
||||
|
||||
private fun saveBitmapToFile(bitmap: Bitmap, path: String) {
|
||||
private fun getNewFilePath(): Pair<String, Boolean> {
|
||||
var newPath = applicationContext.getRealPathFromURI(saveUri) ?: ""
|
||||
var shouldAppendFilename = true
|
||||
if (newPath.isEmpty()) {
|
||||
val filename = applicationContext.getFilenameFromContentUri(saveUri) ?: ""
|
||||
if (filename.isNotEmpty()) {
|
||||
val path = if (intent.extras?.containsKey(REAL_FILE_PATH) == true) intent.getStringExtra(REAL_FILE_PATH).getParentPath() else internalStoragePath
|
||||
newPath = "$path/$filename"
|
||||
shouldAppendFilename = false
|
||||
}
|
||||
}
|
||||
|
||||
if (newPath.isEmpty()) {
|
||||
newPath = "$internalStoragePath/${getCurrentFormattedDateTime()}.${saveUri.toString().getFilenameExtension()}"
|
||||
shouldAppendFilename = false
|
||||
}
|
||||
|
||||
return Pair(newPath, shouldAppendFilename)
|
||||
}
|
||||
|
||||
private fun saveBitmapToFile(bitmap: Bitmap, path: String, showSavingToast: Boolean) {
|
||||
try {
|
||||
Thread {
|
||||
val file = File(path)
|
||||
val fileDirItem = FileDirItem(path, path.getFilenameFromPath())
|
||||
getFileOutputStream(fileDirItem, true) {
|
||||
if (it != null) {
|
||||
saveBitmap(file, bitmap, it)
|
||||
saveBitmap(file, bitmap, it, showSavingToast)
|
||||
} else {
|
||||
toast(R.string.image_editing_failed)
|
||||
}
|
||||
|
@ -234,8 +546,11 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
|||
}
|
||||
}
|
||||
|
||||
private fun saveBitmap(file: File, bitmap: Bitmap, out: OutputStream) {
|
||||
toast(R.string.saving)
|
||||
private fun saveBitmap(file: File, bitmap: Bitmap, out: OutputStream, showSavingToast: Boolean) {
|
||||
if (showSavingToast) {
|
||||
toast(R.string.saving)
|
||||
}
|
||||
|
||||
if (resizeWidth > 0 && resizeHeight > 0) {
|
||||
val resized = Bitmap.createScaledBitmap(bitmap, resizeWidth, resizeHeight, false)
|
||||
resized.compress(file.absolutePath.getCompressionFormat(), 90, out)
|
||||
|
@ -247,14 +562,6 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
|||
out.close()
|
||||
}
|
||||
|
||||
private fun flipImage(horizontally: Boolean) {
|
||||
if (horizontally) {
|
||||
crop_image_view.flipImageHorizontally()
|
||||
} else {
|
||||
crop_image_view.flipImageVertically()
|
||||
}
|
||||
}
|
||||
|
||||
private fun editWith() {
|
||||
openEditor(uri.toString())
|
||||
isEditingWithThirdParty = true
|
||||
|
|
|
@ -58,6 +58,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
|||
private var mLoadedInitialPhotos = false
|
||||
private var mIsPasswordProtectionPending = false
|
||||
private var mWasProtectionHandled = false
|
||||
private var mShouldStopFetching = false
|
||||
private var mLatestMediaId = 0L
|
||||
private var mLatestMediaDateId = 0L
|
||||
private var mLastMediaHandler = Handler()
|
||||
|
@ -323,6 +324,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
|||
return
|
||||
}
|
||||
|
||||
mShouldStopFetching = true
|
||||
mIsGettingDirs = true
|
||||
val getImagesOnly = mIsPickImageIntent || mIsGetImageContentIntent
|
||||
val getVideosOnly = mIsPickVideoIntent || mIsGetVideoContentIntent
|
||||
|
@ -347,7 +349,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
|||
|
||||
private fun showFilterMediaDialog() {
|
||||
FilterMediaDialog(this) {
|
||||
mLoadedInitialPhotos = false
|
||||
mShouldStopFetching = true
|
||||
directories_refresh_layout.isRefreshing = true
|
||||
directories_grid.adapter = null
|
||||
getDirectories()
|
||||
|
@ -662,6 +664,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
|||
|
||||
private fun gotDirectories(newDirs: ArrayList<Directory>) {
|
||||
// if hidden item showing is disabled but all Favorite items are hidden, hide the Favorites folder
|
||||
mIsGettingDirs = false
|
||||
mShouldStopFetching = false
|
||||
if (!config.shouldShowHidden) {
|
||||
val favoritesFolder = newDirs.firstOrNull { it.areFavorites() }
|
||||
if (favoritesFolder != null && favoritesFolder.tmb.getFilenameFromPath().startsWith('.')) {
|
||||
|
@ -696,6 +700,10 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
|||
|
||||
try {
|
||||
for (directory in dirs) {
|
||||
if (mShouldStopFetching) {
|
||||
return
|
||||
}
|
||||
|
||||
val curMedia = mediaFetcher.getFilesFrom(directory.path, getImagesOnly, getVideosOnly, getProperDateTaken, favoritePaths)
|
||||
val newDir = if (curMedia.isEmpty()) {
|
||||
directory
|
||||
|
@ -741,13 +749,22 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
|||
|
||||
val foldersToScan = mediaFetcher.getFoldersToScan()
|
||||
foldersToScan.add(FAVORITES)
|
||||
foldersToScan.add(RECYCLE_BIN)
|
||||
if (config.showRecycleBinAtFolders) {
|
||||
foldersToScan.add(RECYCLE_BIN)
|
||||
} else {
|
||||
foldersToScan.remove(RECYCLE_BIN)
|
||||
}
|
||||
|
||||
dirs.forEach {
|
||||
foldersToScan.remove(it.path)
|
||||
}
|
||||
|
||||
// check the remaining folders which were not cached at all yet
|
||||
for (folder in foldersToScan) {
|
||||
if (mShouldStopFetching) {
|
||||
return
|
||||
}
|
||||
|
||||
val newMedia = mediaFetcher.getFilesFrom(folder, getImagesOnly, getVideosOnly, getProperDateTaken, favoritePaths)
|
||||
if (newMedia.isEmpty()) {
|
||||
continue
|
||||
|
@ -771,7 +788,6 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
|||
}
|
||||
}
|
||||
|
||||
mIsGettingDirs = false
|
||||
mLoadedInitialPhotos = true
|
||||
checkLastMediaChanged()
|
||||
|
||||
|
@ -798,7 +814,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
|||
}
|
||||
|
||||
private fun showSortedDirs(dirs: ArrayList<Directory>) {
|
||||
var sortedDirs = getSortedDirectories(dirs).clone() as ArrayList<Directory>
|
||||
var sortedDirs = getSortedDirectories(dirs)
|
||||
sortedDirs = sortedDirs.distinctBy { it.path.getDistinctPath() } as ArrayList<Directory>
|
||||
|
||||
runOnUiThread {
|
||||
|
@ -836,11 +852,10 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
|||
|
||||
private fun setupAdapter(dirs: ArrayList<Directory>) {
|
||||
val currAdapter = directories_grid.adapter
|
||||
val directories = dirs.clone() as ArrayList<Directory>
|
||||
if (currAdapter == null) {
|
||||
initZoomListener()
|
||||
val fastscroller = if (config.scrollHorizontally) directories_horizontal_fastscroller else directories_vertical_fastscroller
|
||||
DirectoryAdapter(this, directories, this, directories_grid, isPickIntent(intent) || isGetAnyContentIntent(intent), fastscroller) {
|
||||
DirectoryAdapter(this, dirs.clone() as ArrayList<Directory>, this, directories_grid, isPickIntent(intent) || isGetAnyContentIntent(intent), fastscroller) {
|
||||
val path = (it as Directory).path
|
||||
if (path != config.tempFolderPath) {
|
||||
itemClicked(path)
|
||||
|
@ -850,7 +865,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
|||
directories_grid.adapter = this
|
||||
}
|
||||
} else {
|
||||
(currAdapter as DirectoryAdapter).updateDirs(directories)
|
||||
(currAdapter as DirectoryAdapter).updateDirs(dirs)
|
||||
}
|
||||
|
||||
getRecyclerAdapter()?.dirs?.apply {
|
||||
|
|
|
@ -261,7 +261,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
|||
private fun setupSearch(menu: Menu) {
|
||||
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
|
||||
mSearchMenuItem = menu.findItem(R.id.search)
|
||||
(mSearchMenuItem!!.actionView as SearchView).apply {
|
||||
(mSearchMenuItem?.actionView as? SearchView)?.apply {
|
||||
setSearchableInfo(searchManager.getSearchableInfo(componentName))
|
||||
isSubmitButtonEnabled = false
|
||||
setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
|
@ -317,7 +317,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
|||
mPath.startsWith(OTG_PATH) -> mPath.trimEnd('/').substringAfterLast('/')
|
||||
else -> getHumanizedFilename(mPath)
|
||||
}
|
||||
supportActionBar?.title = if (mShowAll) resources.getString(R.string.all_folders) else dirName
|
||||
updateActionBarTitle(if (mShowAll) resources.getString(R.string.all_folders) else dirName)
|
||||
getMedia()
|
||||
setupLayoutManager()
|
||||
} else {
|
||||
|
@ -338,7 +338,8 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
|||
if (currAdapter == null) {
|
||||
initZoomListener()
|
||||
val fastscroller = if (config.scrollHorizontally) media_horizontal_fastscroller else media_vertical_fastscroller
|
||||
MediaAdapter(this, mMedia, this, mIsGetImageIntent || mIsGetVideoIntent || mIsGetAnyIntent, mAllowPickingMultiple, media_grid, fastscroller) {
|
||||
MediaAdapter(this, mMedia.clone() as ArrayList<ThumbnailItem>, this, mIsGetImageIntent || mIsGetVideoIntent || mIsGetAnyIntent,
|
||||
mAllowPickingMultiple, media_grid, fastscroller) {
|
||||
if (it is Medium) {
|
||||
itemClicked(it.path)
|
||||
}
|
||||
|
@ -806,7 +807,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
|||
mLatestMediaId = getLatestMediaId()
|
||||
mLatestMediaDateId = getLatestMediaByDateId()
|
||||
if (!isFromCache) {
|
||||
val mediaToInsert = (mMedia.clone() as ArrayList<ThumbnailItem>).filter { it is Medium && it.deletedTS == 0L }.map { it as Medium }
|
||||
val mediaToInsert = (mMedia).filter { it is Medium && it.deletedTS == 0L }.map { it as Medium }
|
||||
galleryDB.MediumDao().insertAll(mediaToInsert)
|
||||
}
|
||||
}
|
||||
|
@ -816,7 +817,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
|||
val deletingItems = resources.getQuantityString(R.plurals.deleting_items, filtered.size, filtered.size)
|
||||
toast(deletingItems)
|
||||
|
||||
if (config.useRecycleBin && !filtered.first().path.startsWith(filesDir.toString())) {
|
||||
if (config.useRecycleBin && !filtered.first().path.startsWith(filesDir.absolutePath)) {
|
||||
movePathsInRecycleBin(filtered.map { it.path } as ArrayList<String>) {
|
||||
if (it) {
|
||||
deleteFilteredFiles(filtered)
|
||||
|
|
|
@ -48,8 +48,6 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
|||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
initBottomActions()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -88,14 +86,15 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
|||
showSystemUI(true)
|
||||
val bundle = Bundle()
|
||||
val file = File(mUri.toString())
|
||||
val filename = getFilenameFromUri(mUri!!)
|
||||
val type = when {
|
||||
file.isImageFast() -> TYPE_IMAGES
|
||||
file.isVideoFast() -> TYPE_VIDEOS
|
||||
file.isGif() -> TYPE_GIFS
|
||||
filename.isImageFast() -> TYPE_IMAGES
|
||||
filename.isVideoFast() -> TYPE_VIDEOS
|
||||
filename.isGif() -> TYPE_GIFS
|
||||
else -> TYPE_RAWS
|
||||
}
|
||||
|
||||
mMedium = Medium(null, getFilenameFromUri(mUri!!), mUri.toString(), mUri!!.path.getParentPath(), 0, 0, file.length(), type, false, 0L)
|
||||
mMedium = Medium(null, filename, mUri.toString(), mUri!!.path.getParentPath(), 0, 0, file.length(), type, false, 0L)
|
||||
supportActionBar?.title = mMedium!!.name
|
||||
bundle.putSerializable(MEDIUM, mMedium)
|
||||
|
||||
|
@ -114,6 +113,8 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
|||
val isFullscreen = visibility and View.SYSTEM_UI_FLAG_FULLSCREEN != 0
|
||||
mFragment?.fullscreenToggled(isFullscreen)
|
||||
}
|
||||
|
||||
initBottomActions()
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration?) {
|
||||
|
@ -132,12 +133,13 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
|||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.photo_video_menu, menu)
|
||||
val visibleBottomActions = if (config.bottomActions) config.visibleBottomActions else 0
|
||||
|
||||
menu.apply {
|
||||
findItem(R.id.menu_set_as).isVisible = mMedium?.isImage() == true
|
||||
findItem(R.id.menu_edit).isVisible = mMedium?.isImage() == true && mUri?.scheme == "file" && !config.bottomActions
|
||||
findItem(R.id.menu_properties).isVisible = mUri?.scheme == "file"
|
||||
findItem(R.id.menu_share).isVisible = !config.bottomActions
|
||||
findItem(R.id.menu_set_as).isVisible = mMedium?.isImage() == true && visibleBottomActions and BOTTOM_ACTION_SET_AS == 0
|
||||
findItem(R.id.menu_edit).isVisible = mMedium?.isImage() == true && mUri?.scheme == "file" && visibleBottomActions and BOTTOM_ACTION_EDIT == 0
|
||||
findItem(R.id.menu_properties).isVisible = mUri?.scheme == "file" && visibleBottomActions and BOTTOM_ACTION_PROPERTIES == 0
|
||||
findItem(R.id.menu_share).isVisible = visibleBottomActions and BOTTOM_ACTION_SHARE == 0
|
||||
}
|
||||
|
||||
return true
|
||||
|
@ -183,7 +185,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
|||
}
|
||||
|
||||
val visibleBottomActions = if (config.bottomActions) config.visibleBottomActions else 0
|
||||
bottom_edit.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_EDIT != 0)
|
||||
bottom_edit.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_EDIT != 0 && mMedium?.isImage() == true)
|
||||
bottom_edit.setOnClickListener {
|
||||
if (mUri != null && bottom_actions.alpha == 1f) {
|
||||
openEditor(mUri!!.toString())
|
||||
|
@ -196,6 +198,11 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
|||
sharePath(mUri!!.toString())
|
||||
}
|
||||
}
|
||||
|
||||
bottom_set_as.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_SET_AS != 0 && mMedium?.isImage() == true)
|
||||
bottom_set_as.setOnClickListener {
|
||||
setAs(mUri!!.toString())
|
||||
}
|
||||
}
|
||||
|
||||
override fun fragmentClicked() {
|
||||
|
|
|
@ -16,7 +16,7 @@ import com.simplemobiletools.commons.helpers.isNougatPlus
|
|||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.theartofdev.edmodo.cropper.CropImageView
|
||||
import kotlinx.android.synthetic.main.view_crop_image.*
|
||||
import kotlinx.android.synthetic.main.activity_edit.*
|
||||
|
||||
class SetWallpaperActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener {
|
||||
private val PICK_IMAGE = 1
|
||||
|
@ -28,7 +28,7 @@ class SetWallpaperActivity : SimpleActivity(), CropImageView.OnCropImageComplete
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.view_crop_image)
|
||||
setContentView(R.layout.activity_set_wallpaper)
|
||||
|
||||
if (intent.data == null) {
|
||||
val pickIntent = Intent(applicationContext, MainActivity::class.java)
|
||||
|
|
|
@ -38,6 +38,7 @@ class SettingsActivity : SimpleActivity() {
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
setupPurchaseThankYou()
|
||||
setupCustomizeColors()
|
||||
setupUseEnglish()
|
||||
setupAvoidWhatsNew()
|
||||
|
@ -74,6 +75,7 @@ class SettingsActivity : SimpleActivity() {
|
|||
setupSkipDeleteConfirmation()
|
||||
setupManageBottomActions()
|
||||
setupUseRecycleBin()
|
||||
setupShowRecycleBin()
|
||||
setupEmptyRecycleBin()
|
||||
updateTextColors(settings_holder)
|
||||
setupSectionColors()
|
||||
|
@ -87,6 +89,13 @@ class SettingsActivity : SimpleActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun setupPurchaseThankYou() {
|
||||
settings_purchase_thank_you_holder.beVisibleIf(config.appRunCount > 10 && !isThankYouInstalled())
|
||||
settings_purchase_thank_you_holder.setOnClickListener {
|
||||
launchPurchaseThankYouIntent()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCustomizeColors() {
|
||||
settings_customize_colors_holder.setOnClickListener {
|
||||
startCustomizationActivity()
|
||||
|
@ -433,6 +442,7 @@ class SettingsActivity : SimpleActivity() {
|
|||
|
||||
private fun setupUseRecycleBin() {
|
||||
settings_empty_recycle_bin_holder.beVisibleIf(config.useRecycleBin)
|
||||
settings_show_recycle_bin_holder.beVisibleIf(config.useRecycleBin)
|
||||
settings_use_recycle_bin.isChecked = config.useRecycleBin
|
||||
settings_use_recycle_bin_holder.setOnClickListener {
|
||||
settings_use_recycle_bin.toggle()
|
||||
|
@ -441,6 +451,14 @@ class SettingsActivity : SimpleActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun setupShowRecycleBin() {
|
||||
settings_show_recycle_bin.isChecked = config.showRecycleBinAtFolders
|
||||
settings_show_recycle_bin_holder.setOnClickListener {
|
||||
settings_show_recycle_bin.toggle()
|
||||
config.showRecycleBinAtFolders = settings_show_recycle_bin.isChecked
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupEmptyRecycleBin() {
|
||||
Thread {
|
||||
mRecycleBinContentSize = galleryDB.MediumDao().getDeletedMedia().sumByLong { it.size }
|
||||
|
|
|
@ -230,6 +230,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}
|
||||
|
||||
refreshViewPager()
|
||||
view_pager.offscreenPageLimit = 2
|
||||
|
||||
if (config.blackBackground) {
|
||||
view_pager.background = ColorDrawable(Color.BLACK)
|
||||
|
@ -295,12 +296,13 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
findItem(R.id.menu_edit).isVisible = visibleBottomActions and BOTTOM_ACTION_EDIT == 0
|
||||
findItem(R.id.menu_rename).isVisible = visibleBottomActions and BOTTOM_ACTION_RENAME == 0
|
||||
findItem(R.id.menu_rotate).isVisible = currentMedium.isImage() && visibleBottomActions and BOTTOM_ACTION_ROTATE == 0
|
||||
findItem(R.id.menu_set_as).isVisible = visibleBottomActions and BOTTOM_ACTION_SET_AS == 0
|
||||
findItem(R.id.menu_save_as).isVisible = mRotationDegrees != 0
|
||||
findItem(R.id.menu_hide).isVisible = !currentMedium.isHidden() && visibleBottomActions and BOTTOM_ACTION_TOGGLE_VISIBILITY == 0
|
||||
findItem(R.id.menu_unhide).isVisible = currentMedium.isHidden() && visibleBottomActions and BOTTOM_ACTION_TOGGLE_VISIBILITY == 0
|
||||
findItem(R.id.menu_add_to_favorites).isVisible = !currentMedium.isFavorite && visibleBottomActions and BOTTOM_ACTION_TOGGLE_FAVORITE == 0
|
||||
findItem(R.id.menu_remove_from_favorites).isVisible = currentMedium.isFavorite && visibleBottomActions and BOTTOM_ACTION_TOGGLE_FAVORITE == 0
|
||||
findItem(R.id.menu_restore_file).isVisible = currentMedium.path.startsWith(filesDir.toString())
|
||||
findItem(R.id.menu_restore_file).isVisible = currentMedium.path.startsWith(filesDir.absolutePath)
|
||||
findItem(R.id.menu_change_orientation).isVisible = mRotationDegrees == 0 && visibleBottomActions and BOTTOM_ACTION_CHANGE_ORIENTATION == 0
|
||||
findItem(R.id.menu_change_orientation).icon = resources.getDrawable(getChangeOrientationIcon())
|
||||
findItem(R.id.menu_rotate).setShowAsAction(
|
||||
|
@ -585,7 +587,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}
|
||||
}
|
||||
|
||||
val tmpPath = "$filesDir/.tmp_${newPath.getFilenameFromPath()}"
|
||||
val tmpPath = "${filesDir.absolutePath}/.tmp_${newPath.getFilenameFromPath()}"
|
||||
val tmpFileDirItem = FileDirItem(tmpPath, tmpPath.getFilenameFromPath())
|
||||
try {
|
||||
getFileOutputStream(tmpFileDirItem) {
|
||||
|
@ -841,6 +843,11 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
bottom_rename.setOnClickListener {
|
||||
renameFile()
|
||||
}
|
||||
|
||||
bottom_set_as.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_SET_AS != 0)
|
||||
bottom_set_as.setOnClickListener {
|
||||
setAs(getCurrentPath())
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateBottomActionIcons(medium: Medium?) {
|
||||
|
@ -915,7 +922,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
|
||||
private fun deleteConfirmed() {
|
||||
val path = getCurrentMedia().getOrNull(mPos)?.path ?: return
|
||||
if (getIsPathDirectory(path)) {
|
||||
if (getIsPathDirectory(path) || !path.isImageVideoGif()) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1104,10 +1111,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
if (view_pager.offscreenPageLimit == 1) {
|
||||
view_pager.offscreenPageLimit = 2
|
||||
}
|
||||
|
||||
if (mPos != position) {
|
||||
mPos = position
|
||||
updateActionbarTitle()
|
||||
|
|
|
@ -72,6 +72,10 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
override fun getItemCount() = dirs.size
|
||||
|
||||
override fun prepareActionMode(menu: Menu) {
|
||||
if (getSelectedPaths().isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val selectedPaths = getSelectedPaths()
|
||||
menu.apply {
|
||||
findItem(R.id.cab_rename).isVisible = isOneItemSelected() && !selectedPaths.contains(FAVORITES) && !selectedPaths.contains(RECYCLE_BIN)
|
||||
|
@ -95,9 +99,9 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
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_empty_recycle_bin -> emptyRecycleBin()
|
||||
R.id.cab_empty_recycle_bin -> tryEmptyRecycleBin(true)
|
||||
R.id.cab_empty_disable_recycle_bin -> emptyAndDisableRecycleBin()
|
||||
R.id.cab_hide -> toggleFoldersVisibility(true)
|
||||
R.id.cab_unhide -> toggleFoldersVisibility(false)
|
||||
R.id.cab_exclude -> tryExcludeFolder()
|
||||
R.id.cab_copy_to -> copyMoveTo(true)
|
||||
|
@ -214,11 +218,19 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
}
|
||||
}
|
||||
|
||||
private fun emptyRecycleBin() {
|
||||
activity.showRecycleBinEmptyingDialog {
|
||||
activity.emptyTheRecycleBin {
|
||||
listener?.refreshItems()
|
||||
private fun tryEmptyRecycleBin(askConfirmation: Boolean) {
|
||||
if (askConfirmation) {
|
||||
activity.showRecycleBinEmptyingDialog {
|
||||
emptyRecycleBin()
|
||||
}
|
||||
} else {
|
||||
emptyRecycleBin()
|
||||
}
|
||||
}
|
||||
|
||||
private fun emptyRecycleBin() {
|
||||
activity.emptyTheRecycleBin {
|
||||
listener?.refreshItems()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,7 +297,7 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
}
|
||||
|
||||
private fun tryExcludeFolder() {
|
||||
val paths = getSelectedPaths().filter { it != PATH }.toSet()
|
||||
val paths = getSelectedPaths().filter { it != PATH && it != RECYCLE_BIN && it != FAVORITES }.toSet()
|
||||
if (paths.size == 1) {
|
||||
ExcludeFolderDialog(activity, paths.toMutableList()) {
|
||||
listener?.refreshItems()
|
||||
|
@ -346,21 +358,27 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
|
||||
private fun askConfirmDelete() {
|
||||
if (config.skipDeleteConfirmation) {
|
||||
deleteFiles()
|
||||
deleteFolders()
|
||||
} else {
|
||||
val itemsCnt = selectedPositions.size
|
||||
val items = resources.getQuantityString(R.plurals.delete_items, itemsCnt, itemsCnt)
|
||||
val baseString = if (config.useRecycleBin) R.string.move_to_recycle_bin_confirmation else R.string.deletion_confirmation
|
||||
val fileDirItem = dirs.getOrNull(selectedPositions.first()) ?: return
|
||||
val baseString = if (!config.useRecycleBin || (isOneItemSelected() && fileDirItem.isRecycleBin()) || (isOneItemSelected() && fileDirItem.areFavorites())) {
|
||||
R.string.deletion_confirmation
|
||||
} else {
|
||||
R.string.move_to_recycle_bin_confirmation
|
||||
}
|
||||
|
||||
var question = String.format(resources.getString(baseString), items)
|
||||
val warning = resources.getQuantityString(R.plurals.delete_warning, itemsCnt, itemsCnt)
|
||||
question += "\n\n$warning"
|
||||
ConfirmationDialog(activity, question) {
|
||||
deleteFiles()
|
||||
deleteFolders()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteFiles() {
|
||||
private fun deleteFolders() {
|
||||
if (selectedPositions.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
@ -380,17 +398,28 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
|
||||
activity.handleSAFDialog(SAFPath) {
|
||||
selectedPositions.sortedDescending().forEach {
|
||||
val directory = dirs[it]
|
||||
if (directory.areFavorites() || directory.isRecycleBin()) {
|
||||
if (selectedPositions.size == 1) {
|
||||
finishActMode()
|
||||
val directory = dirs.getOrNull(it)
|
||||
if (directory != null) {
|
||||
if (directory.areFavorites() || directory.isRecycleBin()) {
|
||||
if (directory.isRecycleBin()) {
|
||||
tryEmptyRecycleBin(false)
|
||||
} else {
|
||||
Thread {
|
||||
activity.galleryDB.MediumDao().clearFavorites()
|
||||
listener?.refreshItems()
|
||||
}.start()
|
||||
}
|
||||
|
||||
if (selectedPositions.size == 1) {
|
||||
finishActMode()
|
||||
} else {
|
||||
selectedPositions.remove(it)
|
||||
toggleItemSelection(false, it)
|
||||
}
|
||||
} else {
|
||||
selectedPositions.remove(it)
|
||||
toggleItemSelection(false, it)
|
||||
folders.add(File(directory.path))
|
||||
removeFolders.add(directory)
|
||||
}
|
||||
} else {
|
||||
folders.add(File(directory.path))
|
||||
removeFolders.add(directory)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -436,14 +465,19 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
|
||||
private fun getSelectedPaths(): HashSet<String> {
|
||||
val paths = HashSet<String>(selectedPositions.size)
|
||||
selectedPositions.forEach { paths.add(dirs[it].path) }
|
||||
selectedPositions.forEach {
|
||||
(dirs.getOrNull(it))?.apply {
|
||||
paths.add(path)
|
||||
}
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
fun updateDirs(newDirs: ArrayList<Directory>) {
|
||||
if (newDirs.hashCode() != currentDirectoriesHash) {
|
||||
currentDirectoriesHash = newDirs.hashCode()
|
||||
dirs = newDirs
|
||||
val directories = newDirs.clone() as ArrayList<Directory>
|
||||
if (directories.hashCode() != currentDirectoriesHash) {
|
||||
currentDirectoriesHash = directories.hashCode()
|
||||
dirs = directories
|
||||
notifyDataSetChanged()
|
||||
finishActMode()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package com.simplemobiletools.gallery.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.interfaces.FilterAdapterListener
|
||||
import com.simplemobiletools.gallery.models.FilterItem
|
||||
import kotlinx.android.synthetic.main.editor_filter_item.view.*
|
||||
import java.util.*
|
||||
|
||||
class FiltersAdapter(val context: Context, val filterItems: ArrayList<FilterItem>, val itemClick: (FilterItem) -> Unit) : RecyclerView.Adapter<FiltersAdapter.ViewHolder>(),
|
||||
FilterAdapterListener {
|
||||
|
||||
private var currentSelection = filterItems.first()
|
||||
private var strokeBackground = context.resources.getDrawable(R.drawable.stroke_background)
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bindView(filterItems[position], strokeBackground)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val view = LayoutInflater.from(parent.context).inflate(R.layout.editor_filter_item, parent, false)
|
||||
return ViewHolder(view, this)
|
||||
}
|
||||
|
||||
override fun getItemCount() = filterItems.size
|
||||
|
||||
override fun getCurrentFilter() = currentSelection
|
||||
|
||||
override fun setCurrentFilter(filterItem: FilterItem) {
|
||||
if (currentSelection != filterItem) {
|
||||
currentSelection = filterItem
|
||||
notifyDataSetChanged()
|
||||
itemClick.invoke(filterItem)
|
||||
}
|
||||
}
|
||||
|
||||
class ViewHolder(view: View, val filterAdapterListener: FilterAdapterListener) : RecyclerView.ViewHolder(view) {
|
||||
fun bindView(filterItem: FilterItem, strokeBackground: Drawable): View {
|
||||
itemView.apply {
|
||||
editor_filter_item_label.text = filterItem.filter.name
|
||||
editor_filter_item_thumbnail.setImageBitmap(filterItem.bitmap)
|
||||
editor_filter_item_thumbnail.background = if (filterAdapterListener.getCurrentFilter() == filterItem) {
|
||||
strokeBackground
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
setOnClickListener {
|
||||
filterAdapterListener.setCurrentFilter(filterItem)
|
||||
}
|
||||
}
|
||||
return itemView
|
||||
}
|
||||
}
|
||||
}
|
|
@ -109,7 +109,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
|
|||
findItem(R.id.cab_rename).isVisible = isOneItemSelected()
|
||||
findItem(R.id.cab_open_with).isVisible = isOneItemSelected()
|
||||
findItem(R.id.cab_confirm_selection).isVisible = isAGetIntent && allowMultiplePicks && selectedPositions.size > 0
|
||||
findItem(R.id.cab_restore_recycle_bin_files).isVisible = getSelectedPaths().all { it.startsWith(activity.filesDir.toString()) }
|
||||
findItem(R.id.cab_restore_recycle_bin_files).isVisible = getSelectedPaths().all { it.startsWith(activity.filesDir.absolutePath) }
|
||||
|
||||
checkHideBtnVisibility(this)
|
||||
checkFavoriteBtnVisibility(this)
|
||||
|
@ -289,7 +289,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
|
|||
|
||||
private fun askConfirmDelete() {
|
||||
val items = resources.getQuantityString(R.plurals.delete_items, selectedPositions.size, selectedPositions.size)
|
||||
val isRecycleBin = getSelectedPaths().first().startsWith(activity.filesDir.toString())
|
||||
val isRecycleBin = getSelectedPaths().first().startsWith(activity.filesDir.absolutePath)
|
||||
val baseString = if (config.useRecycleBin && !isRecycleBin) R.string.move_to_recycle_bin_confirmation else R.string.deletion_confirmation
|
||||
val question = String.format(resources.getString(baseString), items)
|
||||
DeleteWithRememberDialog(activity, question) {
|
||||
|
@ -316,7 +316,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
|
|||
val SAFPath = (media[selectedPositions.first()] as Medium).path
|
||||
activity.handleSAFDialog(SAFPath) {
|
||||
selectedPositions.sortedDescending().forEach {
|
||||
val thumbnailItem = media[it]
|
||||
val thumbnailItem = media.getOrNull(it)
|
||||
if (thumbnailItem is Medium) {
|
||||
fileDirItems.add(FileDirItem(thumbnailItem.path, thumbnailItem.name))
|
||||
removeMedia.add(thumbnailItem)
|
||||
|
@ -342,10 +342,11 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
|
|||
private fun getSelectedPaths() = getSelectedMedia().map { it.path } as ArrayList<String>
|
||||
|
||||
fun updateMedia(newMedia: ArrayList<ThumbnailItem>) {
|
||||
if (newMedia.hashCode() != currentMediaHash) {
|
||||
currentMediaHash = newMedia.hashCode()
|
||||
val thumbnailItems = newMedia.clone() as ArrayList<ThumbnailItem>
|
||||
if (thumbnailItems.hashCode() != currentMediaHash) {
|
||||
currentMediaHash = thumbnailItems.hashCode()
|
||||
Handler().postDelayed({
|
||||
media = newMedia
|
||||
media = thumbnailItems
|
||||
enableInstantLoad()
|
||||
notifyDataSetChanged()
|
||||
finishActMode()
|
||||
|
|
|
@ -5,7 +5,9 @@ import android.os.AsyncTask
|
|||
import com.simplemobiletools.commons.helpers.SORT_BY_DATE_TAKEN
|
||||
import com.simplemobiletools.gallery.extensions.config
|
||||
import com.simplemobiletools.gallery.extensions.getFavoritePaths
|
||||
import com.simplemobiletools.gallery.helpers.FAVORITES
|
||||
import com.simplemobiletools.gallery.helpers.MediaFetcher
|
||||
import com.simplemobiletools.gallery.helpers.RECYCLE_BIN
|
||||
import com.simplemobiletools.gallery.helpers.SHOW_ALL
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import com.simplemobiletools.gallery.models.ThumbnailItem
|
||||
|
@ -21,7 +23,7 @@ class GetMediaAsynctask(val context: Context, val mPath: String, val isPickImage
|
|||
val getProperDateTaken = context.config.getFileSorting(pathToUse) and SORT_BY_DATE_TAKEN != 0
|
||||
val favoritePaths = context.getFavoritePaths()
|
||||
val media = if (showAll) {
|
||||
val foldersToScan = mediaFetcher.getFoldersToScan()
|
||||
val foldersToScan = mediaFetcher.getFoldersToScan().filter { it != RECYCLE_BIN && it != FAVORITES }
|
||||
val media = ArrayList<Medium>()
|
||||
foldersToScan.forEach {
|
||||
val newMedia = mediaFetcher.getFilesFrom(it, isPickImage, isPickVideo, getProperDateTaken, favoritePaths)
|
||||
|
|
|
@ -25,6 +25,7 @@ class ManageBottomActionsDialog(val activity: BaseSimpleActivity, val callback:
|
|||
manage_bottom_actions_show_on_map.isChecked = actions and BOTTOM_ACTION_SHOW_ON_MAP != 0
|
||||
manage_bottom_actions_toggle_visibility.isChecked = actions and BOTTOM_ACTION_TOGGLE_VISIBILITY != 0
|
||||
manage_bottom_actions_rename.isChecked = actions and BOTTOM_ACTION_RENAME != 0
|
||||
manage_bottom_actions_set_as.isChecked = actions and BOTTOM_ACTION_SET_AS != 0
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
|
@ -60,6 +61,8 @@ class ManageBottomActionsDialog(val activity: BaseSimpleActivity, val callback:
|
|||
result += BOTTOM_ACTION_TOGGLE_VISIBILITY
|
||||
if (manage_bottom_actions_rename.isChecked)
|
||||
result += BOTTOM_ACTION_RENAME
|
||||
if (manage_bottom_actions_set_as.isChecked)
|
||||
result += BOTTOM_ACTION_SET_AS
|
||||
}
|
||||
|
||||
activity.config.visibleBottomActions = result
|
||||
|
|
|
@ -61,7 +61,7 @@ class PickDirectoryDialog(val activity: BaseSimpleActivity, val sourcePath: Stri
|
|||
return
|
||||
|
||||
shownDirectories = dirs
|
||||
val adapter = DirectoryAdapter(activity, dirs, null, view.directories_grid, true) {
|
||||
val adapter = DirectoryAdapter(activity, dirs.clone() as ArrayList<Directory>, null, view.directories_grid, true) {
|
||||
if ((it as Directory).path.trimEnd('/') == sourcePath) {
|
||||
activity.toast(R.string.source_and_destination_same)
|
||||
return@DirectoryAdapter
|
||||
|
|
|
@ -64,7 +64,7 @@ class PickMediumDialog(val activity: BaseSimpleActivity, val path: String, val c
|
|||
return
|
||||
|
||||
shownMedia = media
|
||||
val adapter = MediaAdapter(activity, shownMedia, null, true, false, view.media_grid, null) {
|
||||
val adapter = MediaAdapter(activity, shownMedia.clone() as ArrayList<ThumbnailItem>, null, true, false, view.media_grid, null) {
|
||||
if (it is Medium) {
|
||||
callback(it.path)
|
||||
dialog.dismiss()
|
||||
|
|
|
@ -151,6 +151,11 @@ fun BaseSimpleActivity.removeNoMedia(path: String, callback: (() -> Unit)? = nul
|
|||
fun BaseSimpleActivity.toggleFileVisibility(oldPath: String, hide: Boolean, callback: ((newPath: String) -> Unit)? = null) {
|
||||
val path = oldPath.getParentPath()
|
||||
var filename = oldPath.getFilenameFromPath()
|
||||
if ((hide && filename.startsWith('.')) || (!hide && !filename.startsWith('.'))) {
|
||||
callback?.invoke(oldPath)
|
||||
return
|
||||
}
|
||||
|
||||
filename = if (hide) {
|
||||
".${filename.trimStart('.')}"
|
||||
} else {
|
||||
|
@ -196,14 +201,16 @@ fun BaseSimpleActivity.tryDeleteFileDirItem(fileDirItem: FileDirItem, allowDelet
|
|||
|
||||
fun BaseSimpleActivity.movePathsInRecycleBin(paths: ArrayList<String>, callback: ((wasSuccess: Boolean) -> Unit)?) {
|
||||
Thread {
|
||||
val mediumDao = galleryDB.MediumDao()
|
||||
var pathsCnt = paths.size
|
||||
paths.forEach {
|
||||
val file = File(it)
|
||||
val internalFile = File(filesDir, it)
|
||||
val internalFile = File(filesDir.absolutePath, it)
|
||||
try {
|
||||
file.copyRecursively(internalFile, true)
|
||||
galleryDB.MediumDao().updateDeleted(it, System.currentTimeMillis())
|
||||
pathsCnt--
|
||||
if (file.copyRecursively(internalFile, true)) {
|
||||
mediumDao.updateDeleted(it, System.currentTimeMillis())
|
||||
pathsCnt--
|
||||
}
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
}
|
||||
|
@ -220,7 +227,7 @@ fun BaseSimpleActivity.restoreRecycleBinPaths(paths: ArrayList<String>, callback
|
|||
val mediumDao = galleryDB.MediumDao()
|
||||
paths.forEach {
|
||||
val source = it
|
||||
val destination = it.removePrefix(filesDir.toString())
|
||||
val destination = it.removePrefix(filesDir.absolutePath)
|
||||
|
||||
var inputStream: InputStream? = null
|
||||
var out: OutputStream? = null
|
||||
|
|
|
@ -288,6 +288,11 @@ fun Context.getCachedDirectories(getVideosOnly: Boolean = false, getImagesOnly:
|
|||
} catch (e: SQLiteException) {
|
||||
ArrayList<Directory>()
|
||||
}
|
||||
|
||||
if (!config.showRecycleBinAtFolders) {
|
||||
directories.removeAll { it.isRecycleBin() }
|
||||
}
|
||||
|
||||
val shouldShowHidden = config.shouldShowHidden
|
||||
val excludedPaths = config.excludedFolders
|
||||
val includedPaths = config.includedFolders
|
||||
|
@ -365,7 +370,7 @@ fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImag
|
|||
val grouped = mediaFetcher.groupMedia(media, pathToUse)
|
||||
callback(grouped.clone() as ArrayList<ThumbnailItem>)
|
||||
|
||||
val recycleBinPath = filesDir.toString()
|
||||
val recycleBinPath = filesDir.absolutePath
|
||||
media.filter { !getDoesFilePathExist(it.path) }.forEach {
|
||||
if (it.path.startsWith(recycleBinPath)) {
|
||||
mediumDao.deleteMediumPath(it.path.removePrefix(recycleBinPath))
|
||||
|
@ -402,7 +407,7 @@ fun Context.getFavoritePaths() = galleryDB.MediumDao().getFavoritePaths() as Arr
|
|||
fun Context.getUpdatedDeletedMedia(mediumDao: MediumDao): ArrayList<Medium> {
|
||||
val media = mediumDao.getDeletedMedia() as ArrayList<Medium>
|
||||
media.forEach {
|
||||
it.path = File(filesDir, it.path).toString()
|
||||
it.path = File(filesDir.absolutePath, it.path).toString()
|
||||
}
|
||||
return media
|
||||
}
|
||||
|
|
|
@ -47,7 +47,9 @@ import java.io.File
|
|||
import java.io.FileOutputStream
|
||||
|
||||
class PhotoFragment : ViewPagerFragment() {
|
||||
private var DEFAULT_DOUBLE_TAP_ZOOM = 2f
|
||||
private val DEFAULT_DOUBLE_TAP_ZOOM = 2f
|
||||
private val ZOOMABLE_VIEW_LOAD_DELAY = 1500L
|
||||
|
||||
private var isFragmentVisible = false
|
||||
private var isFullscreen = false
|
||||
private var wasInit = false
|
||||
|
@ -55,6 +57,7 @@ class PhotoFragment : ViewPagerFragment() {
|
|||
private var isPanorama = false
|
||||
private var imageOrientation = -1
|
||||
private var gifDrawable: GifDrawable? = null
|
||||
private var loadZoomableViewHandler = Handler()
|
||||
|
||||
private var storedShowExtendedDetails = false
|
||||
private var storedHideExtendedDetails = false
|
||||
|
@ -184,7 +187,9 @@ class PhotoFragment : ViewPagerFragment() {
|
|||
|
||||
private fun photoFragmentVisibilityChanged(isVisible: Boolean) {
|
||||
if (isVisible) {
|
||||
addZoomableView()
|
||||
scheduleZoomableView()
|
||||
} else {
|
||||
loadZoomableViewHandler.removeCallbacksAndMessages(null)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,8 +281,9 @@ class PhotoFragment : ViewPagerFragment() {
|
|||
}
|
||||
|
||||
override fun onResourceReady(resource: Bitmap?, model: Any?, target: Target<Bitmap>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
|
||||
if (isFragmentVisible)
|
||||
addZoomableView()
|
||||
if (isFragmentVisible) {
|
||||
scheduleZoomableView()
|
||||
}
|
||||
return false
|
||||
}
|
||||
}).into(view.photo_view)
|
||||
|
@ -302,46 +308,53 @@ class PhotoFragment : ViewPagerFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun addZoomableView() {
|
||||
if (!context!!.config.replaceZoomableImages && medium.isImage() && isFragmentVisible && view.subsampling_view.isGone()) {
|
||||
ViewPagerActivity.wasDecodedByGlide = false
|
||||
view.subsampling_view.apply {
|
||||
maxScale = 10f
|
||||
beVisible()
|
||||
isQuickScaleEnabled = context.config.oneFingerZoom
|
||||
setResetScaleOnSizeChange(context.config.screenRotation != ROTATE_BY_ASPECT_RATIO)
|
||||
setImage(ImageSource.uri(getPathToLoad(medium)))
|
||||
orientation = if (imageOrientation == -1) SubsamplingScaleImageView.ORIENTATION_USE_EXIF else degreesForRotation(imageOrientation)
|
||||
setEagerLoadingEnabled(false)
|
||||
setExecutor(AsyncTask.SERIAL_EXECUTOR)
|
||||
setOnImageEventListener(object : SubsamplingScaleImageView.OnImageEventListener {
|
||||
override fun onImageLoaded() {
|
||||
}
|
||||
|
||||
override fun onReady() {
|
||||
background = ColorDrawable(if (context.config.blackBackground) Color.BLACK else context.config.backgroundColor)
|
||||
val useWidth = if (imageOrientation == ORIENTATION_ROTATE_90 || imageOrientation == ORIENTATION_ROTATE_270) sHeight else sWidth
|
||||
val useHeight = if (imageOrientation == ORIENTATION_ROTATE_90 || imageOrientation == ORIENTATION_ROTATE_270) sWidth else sHeight
|
||||
setDoubleTapZoomScale(getDoubleTapZoomScale(useWidth, useHeight))
|
||||
}
|
||||
|
||||
override fun onTileLoadError(e: Exception?) {
|
||||
}
|
||||
|
||||
override fun onPreviewReleased() {
|
||||
}
|
||||
|
||||
override fun onImageLoadError(e: Exception) {
|
||||
background = ColorDrawable(Color.TRANSPARENT)
|
||||
beGone()
|
||||
}
|
||||
|
||||
override fun onPreviewLoadError(e: Exception?) {
|
||||
background = ColorDrawable(Color.TRANSPARENT)
|
||||
beGone()
|
||||
}
|
||||
})
|
||||
private fun scheduleZoomableView() {
|
||||
loadZoomableViewHandler.removeCallbacksAndMessages(null)
|
||||
loadZoomableViewHandler.postDelayed({
|
||||
if (isFragmentVisible && !context!!.config.replaceZoomableImages && medium.isImage() && view.subsampling_view.isGone()) {
|
||||
addZoomableView()
|
||||
}
|
||||
}, ZOOMABLE_VIEW_LOAD_DELAY)
|
||||
}
|
||||
|
||||
private fun addZoomableView() {
|
||||
ViewPagerActivity.wasDecodedByGlide = false
|
||||
view.subsampling_view.apply {
|
||||
maxScale = 10f
|
||||
beVisible()
|
||||
isQuickScaleEnabled = context.config.oneFingerZoom
|
||||
setResetScaleOnSizeChange(context.config.screenRotation != ROTATE_BY_ASPECT_RATIO)
|
||||
setImage(ImageSource.uri(getPathToLoad(medium)))
|
||||
orientation = if (imageOrientation == -1) SubsamplingScaleImageView.ORIENTATION_USE_EXIF else degreesForRotation(imageOrientation)
|
||||
setEagerLoadingEnabled(false)
|
||||
setExecutor(AsyncTask.SERIAL_EXECUTOR)
|
||||
setOnImageEventListener(object : SubsamplingScaleImageView.OnImageEventListener {
|
||||
override fun onImageLoaded() {
|
||||
}
|
||||
|
||||
override fun onReady() {
|
||||
background = ColorDrawable(if (context.config.blackBackground) Color.BLACK else context.config.backgroundColor)
|
||||
val useWidth = if (imageOrientation == ORIENTATION_ROTATE_90 || imageOrientation == ORIENTATION_ROTATE_270) sHeight else sWidth
|
||||
val useHeight = if (imageOrientation == ORIENTATION_ROTATE_90 || imageOrientation == ORIENTATION_ROTATE_270) sWidth else sHeight
|
||||
setDoubleTapZoomScale(getDoubleTapZoomScale(useWidth, useHeight))
|
||||
}
|
||||
|
||||
override fun onTileLoadError(e: Exception?) {
|
||||
}
|
||||
|
||||
override fun onPreviewReleased() {
|
||||
}
|
||||
|
||||
override fun onImageLoadError(e: Exception) {
|
||||
background = ColorDrawable(Color.TRANSPARENT)
|
||||
beGone()
|
||||
}
|
||||
|
||||
override fun onPreviewLoadError(e: Exception?) {
|
||||
background = ColorDrawable(Color.TRANSPARENT)
|
||||
beGone()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -349,7 +362,7 @@ class PhotoFragment : ViewPagerFragment() {
|
|||
isPanorama = try {
|
||||
val inputStream = if (medium.path.startsWith("content:/")) context!!.contentResolver.openInputStream(Uri.parse(medium.path)) else File(medium.path).inputStream()
|
||||
val imageParser = JpegImageParser().getXmpXml(ByteSourceInputStream(inputStream, medium.name), HashMap<String, Any>())
|
||||
imageParser.contains("GPano:UsePanoramaViewer=\"True\"", true)
|
||||
imageParser.contains("GPano:UsePanoramaViewer=\"True\"", true) || imageParser.contains("<GPano:UsePanoramaViewer>True</GPano:UsePanoramaViewer>", true)
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
|
@ -431,6 +444,7 @@ class PhotoFragment : ViewPagerFragment() {
|
|||
Glide.with(context!!).clear(view.photo_view)
|
||||
view.subsampling_view.recycle()
|
||||
}
|
||||
loadZoomableViewHandler.removeCallbacksAndMessages(null)
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.content.res.Configuration
|
|||
import android.graphics.Point
|
||||
import android.graphics.SurfaceTexture
|
||||
import android.media.AudioManager
|
||||
import android.media.MediaMetadataRetriever
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
|
@ -14,6 +15,7 @@ import android.view.*
|
|||
import android.view.animation.AnimationUtils
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.google.android.exoplayer2.*
|
||||
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory
|
||||
import com.google.android.exoplayer2.source.ExtractorMediaSource
|
||||
|
@ -56,7 +58,8 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
|||
private var mIsDragged = false
|
||||
private var mIsFullscreen = false
|
||||
private var mIsFragmentVisible = false
|
||||
private var mWasInit = false
|
||||
private var mWasFragmentInit = false
|
||||
private var mIsExoPlayerInitialized = false
|
||||
private var mCurrTime = 0
|
||||
private var mDuration = 0
|
||||
|
||||
|
@ -94,7 +97,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
|||
}
|
||||
|
||||
checkFullscreen()
|
||||
mWasInit = true
|
||||
mWasFragmentInit = true
|
||||
|
||||
mView!!.apply {
|
||||
brightnessSideScroll = video_brightness_controller
|
||||
|
@ -109,76 +112,35 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
|||
|
||||
video_curr_time.setOnClickListener { skip(false) }
|
||||
video_duration.setOnClickListener { skip(true) }
|
||||
Glide.with(context!!).load(medium.path).into(video_preview)
|
||||
}
|
||||
|
||||
mExoPlayer = ExoPlayerFactory.newSimpleInstance(context, DefaultTrackSelector())
|
||||
mExoPlayer!!.addListener(object : Player.EventListener {
|
||||
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) {}
|
||||
initExoPlayerListeners()
|
||||
|
||||
override fun onSeekProcessed() {}
|
||||
|
||||
override fun onTracksChanged(trackGroups: TrackGroupArray?, trackSelections: TrackSelectionArray?) {}
|
||||
|
||||
override fun onPlayerError(error: ExoPlaybackException?) {
|
||||
activity?.showErrorToast(error.toString())
|
||||
}
|
||||
|
||||
override fun onLoadingChanged(isLoading: Boolean) {}
|
||||
|
||||
override fun onPositionDiscontinuity(reason: Int) {}
|
||||
|
||||
override fun onRepeatModeChanged(repeatMode: Int) {}
|
||||
|
||||
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {}
|
||||
|
||||
override fun onTimelineChanged(timeline: Timeline?, manifest: Any?, reason: Int) {}
|
||||
|
||||
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
|
||||
when (playbackState) {
|
||||
Player.STATE_READY -> videoPrepared()
|
||||
Player.STATE_ENDED -> videoCompleted()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
mExoPlayer!!.addVideoListener(object : VideoListener {
|
||||
override fun onVideoSizeChanged(width: Int, height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float) {
|
||||
mVideoSize.x = width
|
||||
mVideoSize.y = height
|
||||
setVideoSize()
|
||||
}
|
||||
|
||||
override fun onRenderedFirstFrame() {}
|
||||
})
|
||||
|
||||
val isContentUri = medium.path.startsWith("content://")
|
||||
val uri = if (isContentUri) Uri.parse(medium.path) else Uri.fromFile(File(medium.path))
|
||||
val dataSpec = DataSpec(uri)
|
||||
val fileDataSource = if (isContentUri) ContentDataSource(context) else FileDataSource()
|
||||
try {
|
||||
fileDataSource.open(dataSpec)
|
||||
} catch (e: Exception) {
|
||||
activity?.showErrorToast(e)
|
||||
}
|
||||
|
||||
val factory = DataSource.Factory { fileDataSource }
|
||||
val audioSource = ExtractorMediaSource(fileDataSource.uri, factory, DefaultExtractorsFactory(), null, null)
|
||||
mExoPlayer!!.audioStreamType = AudioManager.STREAM_MUSIC
|
||||
mExoPlayer!!.prepare(audioSource)
|
||||
medium.path.getVideoResolution()?.apply {
|
||||
mVideoSize.x = x
|
||||
mVideoSize.y = y
|
||||
setVideoSize()
|
||||
}
|
||||
|
||||
setupVideoDuration()
|
||||
|
||||
mView!!.video_surface.onGlobalLayout {
|
||||
if (mIsFragmentVisible && context?.config?.autoplayVideos == true) {
|
||||
playVideo()
|
||||
}
|
||||
}
|
||||
|
||||
return mView
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
activity!!.updateTextColors(mView!!.video_holder)
|
||||
val allowVideoGestures = context!!.config.allowVideoGestures
|
||||
val allowInstantChange = context!!.config.allowInstantChange
|
||||
val config = context!!.config
|
||||
val allowVideoGestures = config.allowVideoGestures
|
||||
val allowInstantChange = config.allowInstantChange
|
||||
mView!!.apply {
|
||||
video_volume_controller.beVisibleIf(allowVideoGestures)
|
||||
video_brightness_controller.beVisibleIf(allowVideoGestures)
|
||||
|
@ -187,14 +149,15 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
|||
instant_next_item.beVisibleIf(allowInstantChange)
|
||||
}
|
||||
|
||||
if (context!!.config.showExtendedDetails != mStoredShowExtendedDetails || context!!.config.extendedDetails != mStoredExtendedDetails) {
|
||||
if (config.showExtendedDetails != mStoredShowExtendedDetails || config.extendedDetails != mStoredExtendedDetails) {
|
||||
checkExtendedDetails()
|
||||
}
|
||||
|
||||
if (context!!.config.bottomActions != mStoredBottomActions) {
|
||||
if (config.bottomActions != mStoredBottomActions) {
|
||||
initTimeHolder()
|
||||
}
|
||||
|
||||
mView!!.video_time_holder.setBackgroundResource(if (config.bottomActions) 0 else R.drawable.gradient_background)
|
||||
storeStateVariables()
|
||||
}
|
||||
|
||||
|
@ -211,6 +174,25 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
|||
}
|
||||
}
|
||||
|
||||
override fun setMenuVisibility(menuVisible: Boolean) {
|
||||
super.setMenuVisibility(menuVisible)
|
||||
if (mIsFragmentVisible && !menuVisible) {
|
||||
pauseVideo()
|
||||
}
|
||||
|
||||
mIsFragmentVisible = menuVisible
|
||||
if (mWasFragmentInit && menuVisible && context?.config?.autoplayVideos == true) {
|
||||
playVideo()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
setVideoSize()
|
||||
initTimeHolder()
|
||||
checkExtendedDetails()
|
||||
}
|
||||
|
||||
private fun storeStateVariables() {
|
||||
context!!.config.apply {
|
||||
mStoredShowExtendedDetails = showExtendedDetails
|
||||
|
@ -235,25 +217,63 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
|||
checkExtendedDetails()
|
||||
}
|
||||
|
||||
override fun setMenuVisibility(menuVisible: Boolean) {
|
||||
super.setMenuVisibility(menuVisible)
|
||||
if (mIsFragmentVisible && !menuVisible) {
|
||||
pauseVideo()
|
||||
private fun initExoPlayer() {
|
||||
val isContentUri = medium.path.startsWith("content://")
|
||||
val uri = if (isContentUri) Uri.parse(medium.path) else Uri.fromFile(File(medium.path))
|
||||
val dataSpec = DataSpec(uri)
|
||||
val fileDataSource = if (isContentUri) ContentDataSource(context) else FileDataSource()
|
||||
try {
|
||||
fileDataSource.open(dataSpec)
|
||||
} catch (e: Exception) {
|
||||
activity?.showErrorToast(e)
|
||||
}
|
||||
|
||||
mIsFragmentVisible = menuVisible
|
||||
if (menuVisible && mWasInit) {
|
||||
if (context?.config?.autoplayVideos == true) {
|
||||
playVideo()
|
||||
}
|
||||
}
|
||||
val factory = DataSource.Factory { fileDataSource }
|
||||
val audioSource = ExtractorMediaSource(fileDataSource.uri, factory, DefaultExtractorsFactory(), null, null)
|
||||
mExoPlayer!!.audioStreamType = AudioManager.STREAM_MUSIC
|
||||
mExoPlayer!!.prepare(audioSource)
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
setVideoSize()
|
||||
initTimeHolder()
|
||||
checkExtendedDetails()
|
||||
private fun initExoPlayerListeners() {
|
||||
mExoPlayer!!.addListener(object : Player.EventListener {
|
||||
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) {}
|
||||
|
||||
override fun onSeekProcessed() {}
|
||||
|
||||
override fun onTracksChanged(trackGroups: TrackGroupArray?, trackSelections: TrackSelectionArray?) {}
|
||||
|
||||
override fun onPlayerError(error: ExoPlaybackException?) {
|
||||
mIsExoPlayerInitialized = false
|
||||
}
|
||||
|
||||
override fun onLoadingChanged(isLoading: Boolean) {}
|
||||
|
||||
override fun onPositionDiscontinuity(reason: Int) {}
|
||||
|
||||
override fun onRepeatModeChanged(repeatMode: Int) {}
|
||||
|
||||
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {}
|
||||
|
||||
override fun onTimelineChanged(timeline: Timeline?, manifest: Any?, reason: Int) {}
|
||||
|
||||
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
|
||||
mIsExoPlayerInitialized = playbackState == Player.STATE_READY || playbackState == Player.STATE_ENDED
|
||||
when (playbackState) {
|
||||
Player.STATE_READY -> videoPrepared()
|
||||
Player.STATE_ENDED -> videoCompleted()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
mExoPlayer!!.addVideoListener(object : VideoListener {
|
||||
override fun onVideoSizeChanged(width: Int, height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float) {
|
||||
mVideoSize.x = width
|
||||
mVideoSize.y = height
|
||||
setVideoSize()
|
||||
}
|
||||
|
||||
override fun onRenderedFirstFrame() {}
|
||||
})
|
||||
}
|
||||
|
||||
private fun toggleFullscreen() {
|
||||
|
@ -378,13 +398,18 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
|||
return
|
||||
}
|
||||
|
||||
if (mView!!.video_preview.isVisible()) {
|
||||
mView!!.video_preview.beGone()
|
||||
initExoPlayer()
|
||||
}
|
||||
|
||||
if (videoEnded()) {
|
||||
setProgress(0)
|
||||
}
|
||||
|
||||
mIsPlaying = true
|
||||
mExoPlayer?.playWhenReady = true
|
||||
mView!!.video_play_outline.setImageDrawable(resources.getDrawable(R.drawable.img_pause_outline_big))
|
||||
mView!!.video_play_outline.setImageResource(R.drawable.ic_pause)
|
||||
activity!!.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
mHidePauseHandler.postDelayed({
|
||||
mView!!.video_play_outline.animate().alpha(0f).start()
|
||||
|
@ -401,13 +426,12 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
|||
mExoPlayer?.playWhenReady = false
|
||||
}
|
||||
|
||||
mView?.video_play_outline?.setImageDrawable(resources.getDrawable(R.drawable.img_play_outline_big))
|
||||
mView!!.video_play_outline.alpha = PLAY_PAUSE_VISIBLE_ALPHA
|
||||
activity!!.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
|
||||
mView?.video_play_outline?.setImageResource(R.drawable.ic_play)
|
||||
mView?.video_play_outline?.alpha = PLAY_PAUSE_VISIBLE_ALPHA
|
||||
activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
}
|
||||
|
||||
private fun videoEnded() = mExoPlayer!!.currentPosition >= mExoPlayer!!.duration
|
||||
private fun videoEnded() = mExoPlayer?.currentPosition ?: 0 >= mExoPlayer?.duration ?: 0
|
||||
|
||||
private fun setProgress(seconds: Int) {
|
||||
mExoPlayer!!.seekTo(seconds * 1000L)
|
||||
|
@ -415,6 +439,18 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
|||
mCurrTimeView!!.text = seconds.getFormattedDuration()
|
||||
}
|
||||
|
||||
private fun setupVideoDuration() {
|
||||
try {
|
||||
val retriever = MediaMetadataRetriever()
|
||||
retriever.setDataSource(medium.path)
|
||||
mDuration = Math.round(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION).toInt() / 1000f)
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
|
||||
setupTimeHolder()
|
||||
setProgress(0)
|
||||
}
|
||||
|
||||
private fun videoPrepared() {
|
||||
if (mDuration == 0) {
|
||||
mDuration = (mExoPlayer!!.duration / 1000).toInt()
|
||||
|
@ -454,15 +490,15 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
|||
|
||||
private fun releaseExoPlayer() {
|
||||
mExoPlayer?.stop()
|
||||
mExoPlayer?.release()
|
||||
mExoPlayer = null
|
||||
Thread {
|
||||
mExoPlayer?.release()
|
||||
mExoPlayer = null
|
||||
}.start()
|
||||
}
|
||||
|
||||
override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) {
|
||||
}
|
||||
override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) {}
|
||||
|
||||
override fun onSurfaceTextureUpdated(surface: SurfaceTexture?) {
|
||||
}
|
||||
override fun onSurfaceTextureUpdated(surface: SurfaceTexture?) {}
|
||||
|
||||
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture?): Boolean {
|
||||
releaseExoPlayer()
|
||||
|
@ -559,6 +595,9 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
|||
}
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar) {
|
||||
if (mExoPlayer == null)
|
||||
return
|
||||
|
||||
if (!mIsPlaying) {
|
||||
togglePlayPause()
|
||||
} else {
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.simplemobiletools.gallery.helpers
|
|||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.os.Environment
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.simplemobiletools.commons.helpers.BaseConfig
|
||||
|
@ -367,6 +368,16 @@ class Config(context: Context) : BaseConfig(context) {
|
|||
|
||||
// if a user hides a folder, then enables temporary hidden folder displaying, make sure we show it properly
|
||||
var everShownFolders: Set<String>
|
||||
get() = prefs.getStringSet(EVER_SHOWN_FOLDERS, HashSet<String>())
|
||||
get() = prefs.getStringSet(EVER_SHOWN_FOLDERS, getEverShownFolders())
|
||||
set(everShownFolders) = prefs.edit().putStringSet(EVER_SHOWN_FOLDERS, everShownFolders).apply()
|
||||
|
||||
fun getEverShownFolders() = hashSetOf(
|
||||
internalStoragePath,
|
||||
Environment.DIRECTORY_DCIM,
|
||||
Environment.DIRECTORY_PICTURES
|
||||
)
|
||||
|
||||
var showRecycleBinAtFolders: Boolean
|
||||
get() = prefs.getBoolean(SHOW_RECYCLE_BIN_AT_FOLDERS, true)
|
||||
set(showRecycleBinAtFolders) = prefs.edit().putBoolean(SHOW_RECYCLE_BIN_AT_FOLDERS, showRecycleBinAtFolders).apply()
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ const val WAS_RECYCLE_BIN_PINNED = "was_recycle_bin_pinned"
|
|||
const val USE_RECYCLE_BIN = "use_recycle_bin"
|
||||
const val GROUP_BY = "group_by"
|
||||
const val EVER_SHOWN_FOLDERS = "ever_shown_folders"
|
||||
const val SHOW_RECYCLE_BIN_AT_FOLDERS = "show_recycle_bin_at_folders"
|
||||
|
||||
// slideshow
|
||||
const val SLIDESHOW_INTERVAL = "slideshow_interval"
|
||||
|
@ -144,5 +145,6 @@ const val BOTTOM_ACTION_SLIDESHOW = 128
|
|||
const val BOTTOM_ACTION_SHOW_ON_MAP = 256
|
||||
const val BOTTOM_ACTION_TOGGLE_VISIBILITY = 512
|
||||
const val BOTTOM_ACTION_RENAME = 1024
|
||||
const val BOTTOM_ACTION_SET_AS = 2048
|
||||
|
||||
const val DEFAULT_BOTTOM_ACTIONS = BOTTOM_ACTION_TOGGLE_FAVORITE or BOTTOM_ACTION_EDIT or BOTTOM_ACTION_SHARE or BOTTOM_ACTION_DELETE
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package com.simplemobiletools.gallery.helpers
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import com.simplemobiletools.gallery.models.FilterItem
|
||||
import java.util.*
|
||||
|
||||
class FilterThumbnailsManager {
|
||||
private var filterThumbnails = ArrayList<FilterItem>(10)
|
||||
private var processedThumbnails = ArrayList<FilterItem>(10)
|
||||
|
||||
fun addThumb(filterItem: FilterItem) {
|
||||
filterThumbnails.add(filterItem)
|
||||
}
|
||||
|
||||
fun processThumbs(): ArrayList<FilterItem> {
|
||||
for (filterItem in filterThumbnails) {
|
||||
filterItem.bitmap = filterItem.filter.processFilter(Bitmap.createBitmap(filterItem.bitmap))
|
||||
processedThumbnails.add(filterItem)
|
||||
}
|
||||
return processedThumbnails
|
||||
}
|
||||
|
||||
fun clearThumbs() {
|
||||
filterThumbnails = ArrayList()
|
||||
processedThumbnails = ArrayList()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.simplemobiletools.gallery.interfaces
|
||||
|
||||
import com.simplemobiletools.gallery.models.FilterItem
|
||||
|
||||
interface FilterAdapterListener {
|
||||
fun getCurrentFilter(): FilterItem
|
||||
|
||||
fun setCurrentFilter(filterItem: FilterItem)
|
||||
}
|
|
@ -40,4 +40,7 @@ interface MediumDao {
|
|||
|
||||
@Query("DELETE FROM media WHERE deleted_ts != 0")
|
||||
fun clearRecycleBin()
|
||||
|
||||
@Query("UPDATE media SET is_favorite = 0")
|
||||
fun clearFavorites()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package com.simplemobiletools.gallery.models
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import com.zomato.photofilters.imageprocessors.Filter
|
||||
|
||||
data class FilterItem(var bitmap: Bitmap, val filter: Filter)
|
BIN
app/src/main/res/drawable-hdpi/ic_aspect_ratio.png
Normal file
After Width: | Height: | Size: 198 B |
Before Width: | Height: | Size: 203 B After Width: | Height: | Size: 203 B |
BIN
app/src/main/res/drawable-hdpi/ic_flip_vertically.png
Normal file
After Width: | Height: | Size: 344 B |
Before Width: | Height: | Size: 877 B |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 520 B |
BIN
app/src/main/res/drawable-hdpi/ic_pause.png
Normal file
After Width: | Height: | Size: 140 B |
BIN
app/src/main/res/drawable-hdpi/ic_photo_filter.png
Normal file
After Width: | Height: | Size: 292 B |
BIN
app/src/main/res/drawable-hdpi/ic_play.png
Normal file
After Width: | Height: | Size: 214 B |
BIN
app/src/main/res/drawable-hdpi/ic_set_as.png
Normal file
After Width: | Height: | Size: 301 B |
Before Width: | Height: | Size: 682 B |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 5.3 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_aspect_ratio.png
Normal file
After Width: | Height: | Size: 174 B |
Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 187 B |
BIN
app/src/main/res/drawable-xhdpi/ic_flip_vertically.png
Normal file
After Width: | Height: | Size: 297 B |
Before Width: | Height: | Size: 917 B |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 622 B |
BIN
app/src/main/res/drawable-xhdpi/ic_pause.png
Normal file
After Width: | Height: | Size: 92 B |
BIN
app/src/main/res/drawable-xhdpi/ic_photo_filter.png
Normal file
After Width: | Height: | Size: 324 B |
BIN
app/src/main/res/drawable-xhdpi/ic_play.png
Normal file
After Width: | Height: | Size: 246 B |
BIN
app/src/main/res/drawable-xhdpi/ic_set_as.png
Normal file
After Width: | Height: | Size: 413 B |
Before Width: | Height: | Size: 810 B |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 4.6 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_aspect_ratio.png
Normal file
After Width: | Height: | Size: 221 B |
Before Width: | Height: | Size: 259 B After Width: | Height: | Size: 259 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_flip_vertically.png
Normal file
After Width: | Height: | Size: 442 B |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 940 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_pause.png
Normal file
After Width: | Height: | Size: 143 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_photo_filter.png
Normal file
After Width: | Height: | Size: 473 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_play.png
Normal file
After Width: | Height: | Size: 320 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_set_as.png
Normal file
After Width: | Height: | Size: 509 B |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 7 KiB |
Before Width: | Height: | Size: 10 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_aspect_ratio.png
Normal file
After Width: | Height: | Size: 289 B |
Before Width: | Height: | Size: 324 B After Width: | Height: | Size: 324 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_flip_vertically.png
Normal file
After Width: | Height: | Size: 684 B |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_pause.png
Normal file
After Width: | Height: | Size: 110 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_photo_filter.png
Normal file
After Width: | Height: | Size: 585 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_play.png
Normal file
After Width: | Height: | Size: 361 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_set_as.png
Normal file
After Width: | Height: | Size: 670 B |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 6 KiB |
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<inset xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:drawable="@drawable/circle_black_background"
|
||||
android:insetBottom="@dimen/activity_margin"
|
||||
android:insetLeft="@dimen/activity_margin"
|
||||
android:insetRight="@dimen/activity_margin"
|
||||
android:insetTop="@dimen/activity_margin"/>
|
8
app/src/main/res/drawable/stroke_background.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<stroke android:width="1dp" android:color="#FFFFFFFF"/>
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
52
app/src/main/res/layout/activity_edit.xml
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?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/fragment_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/default_image_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="@dimen/activity_margin"/>
|
||||
|
||||
<com.theartofdev.edmodo.cropper.CropImageView
|
||||
android:id="@+id/crop_image_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="@dimen/activity_margin"
|
||||
android:visibility="gone"
|
||||
app:cropBackgroundColor="@color/crop_image_view_background"
|
||||
app:cropInitialCropWindowPaddingRatio="0"/>
|
||||
|
||||
<include
|
||||
android:id="@+id/bottom_aspect_ratios"
|
||||
layout="@layout/bottom_actions_aspect_ratio"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/bottom_editor_crop_rotate_actions"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<include
|
||||
android:id="@+id/bottom_editor_filter_actions"
|
||||
layout="@layout/bottom_editor_actions_filter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/bottom_editor_primary_actions"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<include
|
||||
android:id="@+id/bottom_editor_crop_rotate_actions"
|
||||
layout="@layout/bottom_editor_crop_rotate_actions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/bottom_editor_primary_actions"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<include
|
||||
android:id="@+id/bottom_editor_primary_actions"
|
||||
layout="@layout/bottom_editor_primary_actions"/>
|
||||
|
||||
</RelativeLayout>
|
|
@ -11,6 +11,28 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_purchase_thank_you_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/settings_purchase_thank_you"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/purchase_simple_thank_you"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_customize_colors_holder"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -1023,6 +1045,29 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_show_recycle_bin_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_show_recycle_bin"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/show_recycle_bin"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_empty_recycle_bin_holder"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -126,8 +126,19 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_rename_new"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@+id/bottom_set_as"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_toggle_file_visibility"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_set_as"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_set_as"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_rename"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
|
63
app/src/main/res/layout/bottom_actions_aspect_ratio.xml
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/bottom_aspect_ratios_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_actions_height"
|
||||
android:paddingTop="@dimen/medium_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bottom_aspect_ratio_free"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/activity_margin"
|
||||
android:text="@string/free_aspect_ratio"
|
||||
android:textAllCaps="true"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="@dimen/big_text_size"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_aspect_ratio_one_one"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bottom_aspect_ratio_one_one"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/activity_margin"
|
||||
android:text="1:1"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="@dimen/big_text_size"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_aspect_ratio_four_three"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_aspect_ratio_free"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bottom_aspect_ratio_four_three"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/activity_margin"
|
||||
android:text="4:3"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="@dimen/big_text_size"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_aspect_ratio_sixteen_nine"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_aspect_ratio_one_one"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bottom_aspect_ratio_sixteen_nine"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/activity_margin"
|
||||
android:text="16:9"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="@dimen/big_text_size"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_aspect_ratio_four_three"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
19
app/src/main/res/layout/bottom_editor_actions_filter.xml
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?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/bottom_actions_filter_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_filters_height"
|
||||
android:paddingTop="@dimen/medium_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyRecyclerView
|
||||
android:id="@+id/bottom_actions_filter_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_filters_height"
|
||||
android:background="@color/crop_image_view_background"
|
||||
android:orientation="horizontal"
|
||||
android:overScrollMode="never"
|
||||
app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager"/>
|
||||
|
||||
</RelativeLayout>
|
|
@ -0,0 +1,75 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/bottom_editor_actions_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_actions_height"
|
||||
android:layout_alignParentBottom="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_rotate"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_rotate_right"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_resize"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_resize"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_minimize"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_aspect_ratio"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_rotate"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_aspect_ratio"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_aspect_ratio"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_flip_horizontally"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_resize"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_flip_horizontally"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_flip_horizontally"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_flip_vertically"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_aspect_ratio"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_flip_vertically"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_flip_vertically"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_flip_horizontally"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
37
app/src/main/res/layout/bottom_editor_primary_actions.xml
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/bottom_editor_primary_actions_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_actions_height"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="@drawable/gradient_background_lighter">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_primary_filter"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_photo_filter"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bottom_primary_crop_rotate"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_primary_crop_rotate"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_crop_rotate"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/bottom_primary_filter"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
|
@ -102,5 +102,13 @@
|
|||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/rename"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_bottom_actions_set_as"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/set_as"/>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
|
28
app/src/main/res/layout/editor_filter_item.xml
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/editor_filter_item_holder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/editor_filter_item_thumbnail"
|
||||
android:layout_width="@dimen/bottom_filters_thumbnail_height"
|
||||
android:layout_height="@dimen/bottom_filters_thumbnail_height"
|
||||
android:layout_above="@+id/editor_filter_item_label"
|
||||
android:background="@drawable/stroke_background"
|
||||
android:padding="1dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/editor_filter_item_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:gravity="center_horizontal"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="@dimen/smaller_text_size"
|
||||
tools:text="Filter"/>
|
||||
|
||||
</RelativeLayout>
|
|
@ -23,8 +23,8 @@
|
|||
android:layout_width="@dimen/play_outline_size_big"
|
||||
android:layout_height="@dimen/play_outline_size_big"
|
||||
android:layout_centerInParent="true"
|
||||
android:background="@android:color/transparent"
|
||||
android:padding="@dimen/big_margin"
|
||||
android:background="@drawable/circle_black_background_with_inset"
|
||||
android:padding="28dp"
|
||||
android:src="@drawable/ic_panorama"
|
||||
android:visibility="gone"/>
|
||||
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/video_preview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<TextureView
|
||||
android:id="@+id/video_surface"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -41,9 +46,9 @@
|
|||
android:layout_width="@dimen/play_outline_size_big"
|
||||
android:layout_height="@dimen/play_outline_size_big"
|
||||
android:layout_centerInParent="true"
|
||||
android:background="@android:color/transparent"
|
||||
android:padding="@dimen/big_margin"
|
||||
android:src="@drawable/img_play_outline_big"/>
|
||||
android:background="@drawable/circle_black_background_with_inset"
|
||||
android:padding="26dp"
|
||||
android:src="@drawable/ic_play"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/slide_info"
|
||||
|
@ -80,8 +85,7 @@
|
|||
android:id="@+id/video_time_holder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="@drawable/gradient_background">
|
||||
android:layout_alignParentBottom="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/video_curr_time"
|
||||
|
|
|
@ -5,33 +5,10 @@
|
|||
android:id="@+id/save_as"
|
||||
android:icon="@drawable/ic_check"
|
||||
android:title="@string/save_as"
|
||||
app:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/rotate"
|
||||
android:icon="@drawable/ic_rotate_right"
|
||||
android:title="@string/rotate"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/resize"
|
||||
android:icon="@drawable/ic_minimize"
|
||||
android:title="@string/resize"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/flip"
|
||||
android:icon="@drawable/ic_flip"
|
||||
android:title="@string/flip"
|
||||
app:showAsAction="ifRoom">
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/flip_horizontally"
|
||||
android:title="@string/flip_horizontally"/>
|
||||
<item
|
||||
android:id="@+id/flip_vertically"
|
||||
android:title="@string/flip_vertically"/>
|
||||
</menu>
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/edit"
|
||||
android:icon="@drawable/ic_edit"
|
||||
android:title="@string/edit_with"
|
||||
app:showAsAction="never"/>
|
||||
app:showAsAction="ifRoom"/>
|
||||
</menu>
|
||||
|
|
|
@ -73,10 +73,6 @@
|
|||
android:id="@+id/menu_move_to"
|
||||
android:title="@string/move_to"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/menu_set_as"
|
||||
android:title="@string/set_as"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/menu_open_with"
|
||||
android:title="@string/open_with"
|
||||
|
@ -104,6 +100,11 @@
|
|||
android:icon="@drawable/ic_slideshow"
|
||||
android:title="@string/slideshow"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/menu_set_as"
|
||||
android:icon="@drawable/ic_set_as"
|
||||
android:title="@string/set_as"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/menu_rename"
|
||||
android:icon="@drawable/ic_rename_new"
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/menu_set_as"
|
||||
android:icon="@drawable/ic_set_as"
|
||||
android:title="@string/set_as"
|
||||
app:showAsAction="never"/>
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/menu_open_with"
|
||||
android:title="@string/open_with"
|
||||
|
|
|
@ -88,13 +88,14 @@
|
|||
<string name="flip_horizontally">قلب أفقيا</string>
|
||||
<string name="flip_vertically">قلب عموديا</string>
|
||||
<string name="edit_with">تعديل باستخدام</string>
|
||||
<string name="free_aspect_ratio">Free</string> <!-- available as an option: 1:1, 4:3, 16:9, free -->
|
||||
|
||||
<!-- Set wallpaper -->
|
||||
<string name="simple_wallpaper">خلفية بسيطة</string>
|
||||
<string name="set_as_wallpaper">تعيين كخلفية الشاشة</string>
|
||||
<string name="set_as_wallpaper_failed">فشل الإعداد كخلفية</string>
|
||||
<string name="set_as_wallpaper_with">تعيين كخلفية بواسطة:</string>
|
||||
<string name="setting_wallpaper">... جار تعيين الخلفية ...</string>
|
||||
<string name="setting_wallpaper">… جار تعيين الخلفية ...</string>
|
||||
<string name="wallpaper_set_successfully">تم تعيبن الخلفية بنجاح</string>
|
||||
<string name="portrait_aspect_ratio">صورة نسبة العرض إلى الارتفاع</string>
|
||||
<string name="landscape_aspect_ratio">نسبة العرض إلى الارتفاع في المناظر الطبيعية</string>
|
||||
|
@ -157,6 +158,7 @@
|
|||
<string name="hide_extended_details">إخفاء التفاصيل الموسعة عند إخفاء شريط الحالة</string>
|
||||
<string name="do_extra_check">قم بإجراء فحص إضافي لتجنب إظهار الملفات التالفة</string>
|
||||
<string name="show_at_bottom">Show some action buttons at the bottom of the screen</string>
|
||||
<string name="show_recycle_bin">Show the Recycle Bin at the folders screen</string>
|
||||
|
||||
<!-- Setting sections -->
|
||||
<string name="thumbnails">المصغرات</string>
|
||||
|
|
|
@ -24,17 +24,17 @@
|
|||
<string name="brightness">Brillantor</string>
|
||||
<string name="lock_orientation">Bloquejar orientació</string>
|
||||
<string name="unlock_orientation">Desbloquejar orientació</string>
|
||||
<string name="change_orientation">Change orientation</string>
|
||||
<string name="force_portrait">Force portrait</string>
|
||||
<string name="force_landscape">Force landscape</string>
|
||||
<string name="use_default_orientation">Use default orientation</string>
|
||||
<string name="change_orientation">Canviar orientació</string>
|
||||
<string name="force_portrait">Forçar vertical</string>
|
||||
<string name="force_landscape">Forçar horitzontal</string>
|
||||
<string name="use_default_orientation">Fer servir la orientació per defecte</string>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtre d\'arxius</string>
|
||||
<string name="images">Imatges</string>
|
||||
<string name="videos">Vídeos</string>
|
||||
<string name="gifs">GIFs</string>
|
||||
<string name="raw_images">RAW images</string>
|
||||
<string name="raw_images">Imatges RAW</string>
|
||||
<string name="no_media_with_filters">No s\'han tronat arxius amb els filtres seleccionats.</string>
|
||||
<string name="change_filters_underlined"><u>Canviar filtres</u></string>
|
||||
|
||||
|
@ -84,6 +84,7 @@
|
|||
<string name="flip_horizontally">Horizontalment</string>
|
||||
<string name="flip_vertically">Verticalment</string>
|
||||
<string name="edit_with">Editar amb</string>
|
||||
<string name="free_aspect_ratio">Lliure</string> <!-- available as an option: 1:1, 4:3, 16:9, free -->
|
||||
|
||||
<!-- Set wallpaper -->
|
||||
<string name="simple_wallpaper">Fons de pantalla de Simple Gallery</string>
|
||||
|
@ -152,18 +153,19 @@
|
|||
<string name="replace_zoomable_images">Substituïr imatges ampliades per les de millor quialitat</string>
|
||||
<string name="hide_extended_details">Amaga els detalls estesos quan la barra d\'estat està amagada</string>
|
||||
<string name="do_extra_check">Fer una verificació addicional per evitar que es mostrin fitxers no vàlids</string>
|
||||
<string name="show_at_bottom">Show some action buttons at the bottom of the screen</string>
|
||||
<string name="show_at_bottom">Mostra alguns botons d\'acció a la part inferior de la pantalla</string>
|
||||
<string name="show_recycle_bin">Mostra la paperera de reciclatge a la pantalla de carpetes</string>
|
||||
|
||||
<!-- Setting sections -->
|
||||
<string name="thumbnails">Miniatures</string>
|
||||
<string name="fullscreen_media">Mitjans a pantalla completa</string>
|
||||
<string name="extended_details">Detalls estesos</string>
|
||||
<string name="bottom_actions">Bottom actions</string>
|
||||
<string name="bottom_actions">Accions de la part inferior</string>
|
||||
|
||||
<!-- Bottom actions -->
|
||||
<string name="manage_bottom_actions">Manage visible bottom actions</string>
|
||||
<string name="toggle_favorite">Toggle favorite</string>
|
||||
<string name="toggle_file_visibility">Toggle file visibility</string>
|
||||
<string name="manage_bottom_actions">Administra les accions de la part inferior</string>
|
||||
<string name="toggle_favorite">Activa favorits</string>
|
||||
<string name="toggle_file_visibility">Activa la visibilitat del fitxer</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Com puc fer que Simple Gallery sigui la galeria de dispositius predeterminada?</string>
|
||||
|
@ -188,8 +190,8 @@
|
|||
<string name="faq_9_text">Sí, hi ha un commutador a la configuració que diu \"Substituïu imatges ampliades i de gran qualitat\", podeu fer-ho. Millora la qualitat de les imatges, però es borraran una vegada que intenteu fer zoom massa.</string>
|
||||
<string name="faq_10_title">Puc retallar imatges amb aquesta aplicació?</string>
|
||||
<string name="faq_10_text">Sí, pots retallar imatges a l\'editor, arrossegant les cantonades de la imatge. Pots accedir a l\'editor prement una miniatura d\'imatge i seleccionant Edita o seleccionant Edita des de la visualització de pantalla completa.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
<string name="faq_11_title">Puc agrupar d\'alguna manera les miniatures del fitxer multimèdia?</string>
|
||||
<string name="faq_11_text">Si, només heu d\'utilitzar l\'ítem del menú \"Agrupar per\" mentre es troba a la vista en miniatura. Podeu agrupar fitxers amb diversos criteris, inclòs data de presa. Si utilitzeu la funció \"Mostra el contingut de totes les carpetes\", també podeu agrupar-les per carpetes.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
<string name="flip_horizontally">Překlopit vodorovně</string>
|
||||
<string name="flip_vertically">Překlopit svisle</string>
|
||||
<string name="edit_with">Edit with</string>
|
||||
<string name="free_aspect_ratio">Free</string> <!-- available as an option: 1:1, 4:3, 16:9, free -->
|
||||
|
||||
<!-- Set wallpaper -->
|
||||
<string name="simple_wallpaper">Jednoduchá tapeta</string>
|
||||
|
@ -153,6 +154,7 @@
|
|||
<string name="hide_extended_details">Hide extended details when status bar is hidden</string>
|
||||
<string name="do_extra_check">Do an extra check to avoid showing invalid files</string>
|
||||
<string name="show_at_bottom">Show some action buttons at the bottom of the screen</string>
|
||||
<string name="show_recycle_bin">Show the Recycle Bin at the folders screen</string>
|
||||
|
||||
<!-- Setting sections -->
|
||||
<string name="thumbnails">Thumbnails</string>
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
<string name="flip_horizontally">Spejlvend vandret</string>
|
||||
<string name="flip_vertically">Spejlvend lodret</string>
|
||||
<string name="edit_with">Rediger med</string>
|
||||
<string name="free_aspect_ratio">Free</string> <!-- available as an option: 1:1, 4:3, 16:9, free -->
|
||||
|
||||
<!-- Set wallpaper -->
|
||||
<string name="simple_wallpaper">Simple Wallpaper</string>
|
||||
|
@ -153,6 +154,7 @@
|
|||
<string name="hide_extended_details">Skjul udvidede oplysninger når statuslinjen er skjult</string>
|
||||
<string name="do_extra_check">Tjek en ekstra gang for at undgå visning af ugyldige filer</string>
|
||||
<string name="show_at_bottom">Show some action buttons at the bottom of the screen</string>
|
||||
<string name="show_recycle_bin">Show the Recycle Bin at the folders screen</string>
|
||||
|
||||
<!-- Setting sections -->
|
||||
<string name="thumbnails">Thumbnails</string>
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
<string name="lock_orientation">Bildschirmausrichtung sperren</string>
|
||||
<string name="unlock_orientation">Bildschirmausrichtung entsperren</string>
|
||||
<string name="change_orientation">Change orientation</string>
|
||||
<string name="force_portrait">Force portrait</string>
|
||||
<string name="force_landscape">Force landscape</string>
|
||||
<string name="use_default_orientation">Use default orientation</string>
|
||||
<string name="force_portrait">Hochkant erzwingen</string>
|
||||
<string name="force_landscape">Breitbild erzwingen</string>
|
||||
<string name="use_default_orientation">Standard Ausrichtung benutzen</string>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filter</string>
|
||||
|
@ -84,6 +84,7 @@
|
|||
<string name="flip_horizontally">Horizontal spiegeln</string>
|
||||
<string name="flip_vertically">Vertikal spiegeln</string>
|
||||
<string name="edit_with">Bearbeiten mit</string>
|
||||
<string name="free_aspect_ratio">Free</string> <!-- available as an option: 1:1, 4:3, 16:9, free -->
|
||||
|
||||
<!-- Set wallpaper -->
|
||||
<string name="simple_wallpaper">Schlichter Hintergrund</string>
|
||||
|
@ -153,6 +154,7 @@
|
|||
<string name="hide_extended_details">Erweiterte Details nicht anzeigen, wenn die Systemleiste versteckt ist</string>
|
||||
<string name="do_extra_check">Zusätzliche Überprüfung, um ungültige Dateien nicht anzuzeigen</string>
|
||||
<string name="show_at_bottom">Show some action buttons at the bottom of the screen</string>
|
||||
<string name="show_recycle_bin">Show the Recycle Bin at the folders screen</string>
|
||||
|
||||
<!-- Setting sections -->
|
||||
<string name="thumbnails">Thumbnails</string>
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
<string name="flip_horizontally">Οριζόντιο αναποδογύρισμα</string>
|
||||
<string name="flip_vertically">Κατακόρυφο αναποδογύρισμα</string>
|
||||
<string name="edit_with">Επεξεργασία με</string>
|
||||
<string name="free_aspect_ratio">Free</string> <!-- available as an option: 1:1, 4:3, 16:9, free -->
|
||||
|
||||
<!-- Set wallpaper -->
|
||||
<string name="simple_wallpaper">Simple Wallpaper</string>
|
||||
|
@ -154,6 +155,7 @@
|
|||
<string name="hide_extended_details">Απόκρυψη λεπτομερειών όταν η μπάρα κατάστασης είναι κρυμμένη</string>
|
||||
<string name="do_extra_check">Επιπλέον έλεγχος για την αποφυγή εμφάνισης λανθασμένων αρχείων</string>
|
||||
<string name="show_at_bottom">Show some action buttons at the bottom of the screen</string>
|
||||
<string name="show_recycle_bin">Show the Recycle Bin at the folders screen</string>
|
||||
|
||||
<!-- Setting sections -->
|
||||
<string name="thumbnails">Εικονίδια</string>
|
||||
|
|
|
@ -24,17 +24,17 @@
|
|||
<string name="brightness">Brillo</string>
|
||||
<string name="lock_orientation">Bloquear orientación</string>
|
||||
<string name="unlock_orientation">Desbloquear orientación</string>
|
||||
<string name="change_orientation">Change orientation</string>
|
||||
<string name="force_portrait">Force portrait</string>
|
||||
<string name="force_landscape">Force landscape</string>
|
||||
<string name="use_default_orientation">Use default orientation</string>
|
||||
<string name="change_orientation">Cambiar orientación</string>
|
||||
<string name="force_portrait">Forzar retrato</string>
|
||||
<string name="force_landscape">Forzar paisaje</string>
|
||||
<string name="use_default_orientation">Usar la orientación por defecto</string>
|
||||
|
||||
<!-- Filter -->
|
||||
<string name="filter_media">Filtro de medios</string>
|
||||
<string name="images">Imágenes</string>
|
||||
<string name="videos">Vídeos</string>
|
||||
<string name="gifs">GIFs</string>
|
||||
<string name="raw_images">RAW images</string>
|
||||
<string name="raw_images">Imagenes RAW</string>
|
||||
<string name="no_media_with_filters">No se han encontrado ficheros con los filtros seleccionados.</string>
|
||||
<string name="change_filters_underlined"><u>Cambiar filtros</u></string>
|
||||
|
||||
|
@ -84,6 +84,7 @@
|
|||
<string name="flip_horizontally">Horizontalmente</string>
|
||||
<string name="flip_vertically">Verticalmente</string>
|
||||
<string name="edit_with">Editar con</string>
|
||||
<string name="free_aspect_ratio">Libre</string> <!-- available as an option: 1:1, 4:3, 16:9, free -->
|
||||
|
||||
<!-- Set wallpaper -->
|
||||
<string name="simple_wallpaper">Fondos de pantalla Simple Gallery</string>
|
||||
|
@ -152,18 +153,19 @@
|
|||
<string name="replace_zoomable_images">Reemplace las imágenes con mucho zoom por otras de mejor calidad</string>
|
||||
<string name="hide_extended_details">Ocultar detalles ampliados cuando la barra de estado está oculta</string>
|
||||
<string name="do_extra_check">Hacer una comprobación adicional para evitar mostrar archivos inválidos</string>
|
||||
<string name="show_at_bottom">Show some action buttons at the bottom of the screen</string>
|
||||
<string name="show_at_bottom">Mostrar algunos botones de acción en la parte inferior de la pantalla</string>
|
||||
<string name="show_recycle_bin">Muestra la papelera de reciclaje en la pantalla de carpetas</string>
|
||||
|
||||
<!-- Setting sections -->
|
||||
<string name="thumbnails">Miniaturas</string>
|
||||
<string name="fullscreen_media">Medios a pantalla compelta</string>
|
||||
<string name="extended_details">Detalles ampliados</string>
|
||||
<string name="bottom_actions">Bottom actions</string>
|
||||
<string name="bottom_actions">Acciones en la parte inferior</string>
|
||||
|
||||
<!-- Bottom actions -->
|
||||
<string name="manage_bottom_actions">Manage visible bottom actions</string>
|
||||
<string name="toggle_favorite">Toggle favorite</string>
|
||||
<string name="toggle_file_visibility">Toggle file visibility</string>
|
||||
<string name="manage_bottom_actions">Administrar los botones de la parte inferior</string>
|
||||
<string name="toggle_favorite">Activar favoritos</string>
|
||||
<string name="toggle_file_visibility">Activar visibilidad de fichero</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">¿Cómo puedo hacer que Simple Gallery sea la galería de dispositivos predeterminada?</string>
|
||||
|
@ -188,8 +190,8 @@
|
|||
<string name="faq_9_text">Sí, hay una alternancia en Configuración que dice \"Reemplazar imágenes con zoom profundo con las de mejor calidad\", puedes usar eso. Mejorará la calidad de las imágenes, pero se volverán borrosas una vez que intente ampliar demasiado.</string>
|
||||
<string name="faq_10_title">¿Puedo recortar imágenes con esta aplicación?</string>
|
||||
<string name="faq_10_text">Sí, puede recortar imágenes en el editor arrastrando las esquinas de la imagen. Puede acceder al editor pulsando prolongadamente una imagen en miniatura y seleccionando Editar, o seleccionando Editar en la vista de pantalla completa.</string>
|
||||
<string name="faq_11_title">Can I somehow group media file thumbnails?</string>
|
||||
<string name="faq_11_text">Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too.</string>
|
||||
<string name="faq_11_title">¿Puedo de alguna manera agrupar miniaturas de archivos multimedia?</string>
|
||||
<string name="faq_11_text">Claro, solo use el elemento de menú \"Agrupar por \" mientras esté en la vista de miniaturas. Puede agrupar archivos según varios criterios, incluida la Fecha de toma. Si usa la función \"Mostrar todo el contenido de las carpetas\" también puede agruparlas por carpetas.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
<string name="flip_horizontally">Pyöräytä vaakasuoraan</string>
|
||||
<string name="flip_vertically">Pyöräytä pystysuoraan</string>
|
||||
<string name="edit_with">Muokkaa sovelluksella</string>
|
||||
<string name="free_aspect_ratio">Free</string> <!-- available as an option: 1:1, 4:3, 16:9, free -->
|
||||
|
||||
<!-- Set wallpaper -->
|
||||
<string name="simple_wallpaper">Simple Wallpaper</string>
|
||||
|
@ -153,6 +154,7 @@
|
|||
<string name="hide_extended_details">Piilota yksityiskohtaiset tiedot kun tilapalkki on piilotettu</string>
|
||||
<string name="do_extra_check">Tee ylimääräinen tarkistus rikkinäisten tiedostojen varalta</string>
|
||||
<string name="show_at_bottom">Show some action buttons at the bottom of the screen</string>
|
||||
<string name="show_recycle_bin">Show the Recycle Bin at the folders screen</string>
|
||||
|
||||
<!-- Setting sections -->
|
||||
<string name="thumbnails">Esikatselukuvat</string>
|
||||
|
|