diff --git a/CHANGELOG.md b/CHANGELOG.md index 11500d8ac..856703a75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,29 @@ Changelog ========== +Version 2.17.2 *(2017-10-29)* +---------------------------- + + * Couple more minor fixes + +Version 2.17.1 *(2017-10-29)* +---------------------------- + + * Show "Set As" and "Edit" menu buttons at videos and gifs too + * Couple other smaller issues fixed + +Version 2.17.0 *(2017-10-28)* +---------------------------- + + * Added a toggle for keeping last-modified field at file copy/move/rename + * Improved GIF animation speed + * Implemented fileprovider support to third party intents + * Make rotation by "Device rotation" less sensitive + * Automatically append "_1" to filename after saving through the Editor + * Added support for Adaptive icons for Android 8 (by fiepi) + * Added Dutch translation (by ltGuillaume) + * Many other smaller improvements + Version 2.16.1 *(2017-10-24)* ---------------------------- diff --git a/app/build.gradle b/app/build.gradle index f63fcf375..79f122486 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,15 +3,15 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { - compileSdkVersion 25 - buildToolsVersion "25.0.3" + compileSdkVersion 26 + buildToolsVersion "26.0.2" defaultConfig { applicationId "com.simplemobiletools.gallery" minSdkVersion 16 - targetSdkVersion 23 - versionCode 137 - versionName "2.16.1" + targetSdkVersion 26 + versionCode 140 + versionName "2.17.2" } signingConfigs { @@ -37,13 +37,13 @@ android { } dependencies { - compile 'com.simplemobiletools:commons:2.31.11' + compile 'com.simplemobiletools:commons:2.34.2' compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.6.0' compile 'com.theartofdev.edmodo:android-image-cropper:2.4.0' compile 'com.bignerdranch.android:recyclerview-multiselect:0.2' compile 'com.google.code.gson:gson:2.8.0' - compile 'com.github.chrisbanes:PhotoView:2.1.2' compile 'it.sephiroth.android.exif:library:1.0.1' + compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.8' compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fb8ba91aa..ff7ff3399 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -83,16 +83,16 @@ android:label="@string/third_party_licences" android:parentActivityName="com.simplemobiletools.commons.activities.AboutActivity"/> - - + + @@ -118,7 +108,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList Intent(this, ViewPagerActivity::class.java).apply { putExtra(IS_VIEW_INTENT, true) putExtra(IS_FROM_GALLERY, mIsFromGallery) - putExtra(MEDIUM, path) + putExtra(PATH, path) startActivity(this) } } @@ -127,7 +117,8 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList menuInflater.inflate(R.menu.photo_video_menu, menu) menu.findItem(R.id.menu_set_as).isVisible = mMedium?.isImage() == true - menu.findItem(R.id.menu_edit).isVisible = mMedium?.isImage() == true + menu.findItem(R.id.menu_edit).isVisible = mMedium?.isImage() == true && mUri?.scheme == "file" + menu.findItem(R.id.menu_properties).isVisible = mUri?.scheme == "file" return true } @@ -137,15 +128,20 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList return true when (item.itemId) { - R.id.menu_set_as -> trySetAs(File(mMedium!!.path)) - R.id.menu_open_with -> openWith(File(mMedium!!.path)) - R.id.menu_share -> shareUri(mMedium!!, mUri) - R.id.menu_edit -> openFileEditor(File(mMedium!!.path)) + R.id.menu_set_as -> setAs(mUri!!) + R.id.menu_open_with -> openFile(mUri!!, true) + R.id.menu_share -> shareUri(mUri!!) + R.id.menu_edit -> openEditor(mUri!!) + R.id.menu_properties -> showProperties() else -> return super.onOptionsItemSelected(item) } return true } + private fun showProperties() { + PropertiesDialog(this, mUri!!.path) + } + override fun fragmentClicked() { mIsFullScreen = !mIsFullScreen if (mIsFullScreen) { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/SettingsActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/SettingsActivity.kt index 7c0b7b60b..6e988b0e3 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/SettingsActivity.kt @@ -50,6 +50,7 @@ class SettingsActivity : SimpleActivity() { setupDeleteEmptyFolders() setupAllowVideoGestures() setupShowMediaCount() + setupKeepLastModified() setupShowExtendedDetails() setupManageExtendedDetails() updateTextColors(settings_holder) @@ -207,6 +208,14 @@ class SettingsActivity : SimpleActivity() { } } + private fun setupKeepLastModified() { + settings_keep_last_modified.isChecked = config.keepLastModified + settings_keep_last_modified_holder.setOnClickListener { + settings_keep_last_modified.toggle() + config.keepLastModified = settings_keep_last_modified.isChecked + } + } + private fun setupScreenRotation() { settings_screen_rotation.text = getScreenRotationText() settings_screen_rotation_holder.setOnClickListener { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/VideoActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/VideoActivity.kt index fa38734e3..7ca92e902 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/VideoActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/VideoActivity.kt @@ -5,7 +5,7 @@ import android.os.Bundle class VideoActivity : PhotoVideoActivity() { override fun onCreate(savedInstanceState: Bundle?) { - PhotoVideoActivity.mIsVideo = true + mIsVideo = true super.onCreate(savedInstanceState) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt index e9af326b0..ae02f2a66 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt @@ -26,7 +26,10 @@ import android.view.animation.DecelerateInterpolator import com.simplemobiletools.commons.dialogs.PropertiesDialog import com.simplemobiletools.commons.dialogs.RenameItemDialog import com.simplemobiletools.commons.extensions.* +import com.simplemobiletools.commons.helpers.IS_FROM_GALLERY import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE +import com.simplemobiletools.commons.helpers.REQUEST_EDIT_IMAGE +import com.simplemobiletools.commons.helpers.REQUEST_SET_AS import com.simplemobiletools.gallery.R import com.simplemobiletools.gallery.activities.MediaActivity.Companion.mMedia import com.simplemobiletools.gallery.adapters.MyPagerAdapter @@ -85,6 +88,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } private fun initViewPager() { + setupOrientationEventListener() measureScreen() val uri = intent.data if (uri != null) { @@ -100,7 +104,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } } else { try { - mPath = intent.getStringExtra(MEDIUM) + mPath = intent.getStringExtra(PATH) mShowAll = config.showAll } catch (e: Exception) { showErrorToast(e) @@ -140,7 +144,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View reloadViewPager() scanPath(mPath) {} - setupOrientationEventListener() if (config.darkBackground) view_pager.background = ColorDrawable(Color.BLACK) @@ -176,8 +179,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View mOrientationEventListener = object : OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) { override fun onOrientationChanged(orientation: Int) { val currOrient = when (orientation) { - in 45..134 -> ORIENT_LANDSCAPE_RIGHT - in 225..314 -> ORIENT_LANDSCAPE_LEFT + in 75..134 -> ORIENT_LANDSCAPE_RIGHT + in 225..289 -> ORIENT_LANDSCAPE_LEFT else -> ORIENT_PORTRAIT } @@ -230,8 +233,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View menu.apply { findItem(R.id.menu_share_1).isVisible = !config.replaceShare findItem(R.id.menu_share_2).isVisible = config.replaceShare - findItem(R.id.menu_set_as).isVisible = currentMedium.isImage() - findItem(R.id.menu_edit).isVisible = currentMedium.isImage() findItem(R.id.menu_rotate).isVisible = currentMedium.isImage() findItem(R.id.menu_save_as).isVisible = mRotationDegrees != 0f findItem(R.id.menu_hide).isVisible = !currentMedium.name.startsWith('.') @@ -246,18 +247,18 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View return true when (item.itemId) { - R.id.menu_set_as -> trySetAs(getCurrentFile()) + R.id.menu_set_as -> setAs(Uri.fromFile(getCurrentFile())) R.id.slideshow -> initSlideshow() R.id.menu_copy_to -> copyMoveTo(true) R.id.menu_move_to -> copyMoveTo(false) - R.id.menu_open_with -> openWith(getCurrentFile()) + R.id.menu_open_with -> openFile(Uri.fromFile(getCurrentFile()), true) R.id.menu_hide -> toggleFileVisibility(true) R.id.menu_unhide -> toggleFileVisibility(false) R.id.menu_share_1 -> shareMedium(getCurrentMedium()!!) R.id.menu_share_2 -> shareMedium(getCurrentMedium()!!) R.id.menu_delete -> checkDeleteConfirmation() R.id.menu_rename -> renameFile() - R.id.menu_edit -> openFileEditor(getCurrentFile()) + R.id.menu_edit -> openEditor(Uri.fromFile(getCurrentFile())) R.id.menu_properties -> showProperties() R.id.show_on_map -> showOnMap() R.id.menu_rotate -> rotateImage() @@ -327,10 +328,12 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View animator.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener { var oldDragPosition = 0 override fun onAnimationUpdate(animation: ValueAnimator) { - val dragPosition = animation.animatedValue as Int - val dragOffset = dragPosition - oldDragPosition - oldDragPosition = dragPosition - view_pager?.fakeDragBy(dragOffset * (if (forward) 1f else -1f)) + if (view_pager?.isFakeDragging == true) { + val dragPosition = animation.animatedValue as Int + val dragOffset = dragPosition - oldDragPosition + oldDragPosition = dragPosition + view_pager.fakeDragBy(dragOffset * (if (forward) 1f else -1f)) + } } }) @@ -446,7 +449,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View private fun saveImageAs() { val currPath = getCurrentPath() - SaveAsDialog(this, currPath) { + SaveAsDialog(this, currPath, false) { Thread({ toast(R.string.saving) val selectedFile = File(it) @@ -515,8 +518,9 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View private fun getCurrentFragment() = (view_pager.adapter as MyPagerAdapter).getCurrentFragment(view_pager.currentItem) private fun showProperties() { - if (getCurrentMedium() != null) + if (getCurrentMedium() != null) { PropertiesDialog(this, getCurrentPath(), false) + } } private fun showOnMap() { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/DirectoryAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/DirectoryAdapter.kt index 7f36dfd26..b2f585e07 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/DirectoryAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/DirectoryAdapter.kt @@ -30,11 +30,9 @@ import java.util.* class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList, val listener: DirOperationsListener?, val isPickIntent: Boolean, val itemClick: (Directory) -> Unit) : RecyclerView.Adapter() { - val config = activity.config + private val config = activity.config var actMode: ActionMode? = null var primaryColor = config.primaryColor - var scrollVertically = !config.scrollHorizontally - var showMediaCount = config.showMediaCount private val multiSelector = MultiSelector() private val isListViewType = config.viewTypeFolders == VIEW_TYPE_LIST @@ -42,6 +40,10 @@ class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList() private var textColor = config.textColor private var pinnedFolders = config.pinnedFolders + private var scrollHorizontally = config.scrollHorizontally + private var showMediaCount = config.showMediaCount + private var animateGifs = config.animateGifs + private var cropThumbnails = config.cropThumbnails fun toggleItemSelection(select: Boolean, pos: Int) { if (select) { @@ -353,7 +355,7 @@ class DirectoryAdapter(val activity: SimpleActivity, var dirs: MutableList (Unit)) : SwappingHolder(view, MultiSelector()) { - fun bindView(directory: Directory, isPinned: Boolean, scrollVertically: Boolean, isListView: Boolean, textColor: Int, showMediaCount: Boolean): View { + fun bindView(directory: Directory, isPinned: Boolean, scrollHorizontally: Boolean, isListView: Boolean, textColor: Int, showMediaCount: Boolean, + animateGifs: Boolean, cropThumbnails: Boolean): View { itemView.apply { dir_name.text = directory.name dir_path?.text = "${directory.path.substringBeforeLast("/")}/" photo_cnt.text = directory.mediaCnt.toString() - activity.loadImage(directory.tmb, dir_thumbnail, scrollVertically) + activity.loadImage(directory.tmb, dir_thumbnail, scrollHorizontally, animateGifs, cropThumbnails) dir_pin.beVisibleIf(isPinned) dir_sd_card.beVisibleIf(activity.isPathOnSD(directory.path)) photo_cnt.beVisibleIf(showMediaCount) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/MediaAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/MediaAdapter.kt index d1918aaad..46ff5a7cb 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/MediaAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/MediaAdapter.kt @@ -1,6 +1,7 @@ package com.simplemobiletools.gallery.adapters import android.graphics.PorterDuff +import android.net.Uri import android.os.Build import android.support.v7.view.ActionMode import android.support.v7.widget.RecyclerView @@ -27,18 +28,21 @@ import java.util.* class MediaAdapter(val activity: SimpleActivity, var media: MutableList, val listener: MediaOperationsListener?, val isPickIntent: Boolean, val allowMultiplePicks: Boolean, val itemClick: (Medium) -> Unit) : RecyclerView.Adapter() { - val multiSelector = MultiSelector() - val config = activity.config - val isListViewType = config.viewTypeFiles == VIEW_TYPE_LIST - var skipConfirmationDialog = false - + private val config = activity.config var actMode: ActionMode? = null - var itemViews = SparseArray() - val selectedPositions = HashSet() var primaryColor = config.primaryColor - var textColor = config.textColor - var displayFilenames = config.displayFileNames - var scrollVertically = !config.scrollHorizontally + + private val multiSelector = MultiSelector() + private val isListViewType = config.viewTypeFiles == VIEW_TYPE_LIST + private var skipConfirmationDialog = false + + private var itemViews = SparseArray() + private val selectedPositions = HashSet() + private var scrollHorizontally = config.scrollHorizontally + private var animateGifs = config.animateGifs + private var cropThumbnails = config.cropThumbnails + private var textColor = config.textColor + private var displayFilenames = config.displayFileNames fun toggleItemSelection(select: Boolean, pos: Int) { if (select) { @@ -86,6 +90,8 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList, R.id.cab_copy_to -> copyMoveTo(true) R.id.cab_move_to -> copyMoveTo(false) R.id.cab_select_all -> selectAll() + R.id.cab_open_with -> activity.openFile(Uri.fromFile(getCurrentFile()), true) + R.id.cab_set_as -> activity.setAs(Uri.fromFile(getCurrentFile())) R.id.cab_delete -> checkDeleteConfirmation() else -> return false } @@ -100,8 +106,8 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList, } override fun onPrepareActionMode(actionMode: ActionMode?, menu: Menu): Boolean { - menu.findItem(R.id.cab_rename).isVisible = selectedPositions.size <= 1 - menu.findItem(R.id.cab_edit).isVisible = selectedPositions.size == 1 && media.size > selectedPositions.first() && media[selectedPositions.first()].isImage() + menu.findItem(R.id.cab_rename).isVisible = selectedPositions.size == 1 + menu.findItem(R.id.cab_open_with).isVisible = selectedPositions.size == 1 menu.findItem(R.id.cab_confirm_selection).isVisible = isPickIntent && allowMultiplePicks && selectedPositions.size > 0 checkHideBtnVisibility(menu) @@ -159,7 +165,7 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList, } private fun editFile() { - activity.openFileEditor(getCurrentFile()) + activity.openEditor(Uri.fromFile(getCurrentFile())) actMode?.finish() } @@ -277,7 +283,7 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList, } override fun onBindViewHolder(holder: ViewHolder, position: Int) { - itemViews.put(position, holder.bindView(media[position], displayFilenames, scrollVertically, isListViewType, textColor)) + itemViews.put(position, holder.bindView(media[position], displayFilenames, scrollHorizontally, isListViewType, textColor, animateGifs, cropThumbnails)) toggleItemSelection(selectedPositions.contains(position), position) holder.itemView.tag = holder } @@ -300,6 +306,21 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList, notifyDataSetChanged() } + fun updateAnimateGifs(animateGifs: Boolean) { + this.animateGifs = animateGifs + notifyDataSetChanged() + } + + fun updateCropThumbnails(cropThumbnails: Boolean) { + this.cropThumbnails = cropThumbnails + notifyDataSetChanged() + } + + fun updateScrollHorizontally(scrollHorizontally: Boolean) { + this.scrollHorizontally = scrollHorizontally + notifyDataSetChanged() + } + fun updateTextColor(textColor: Int) { this.textColor = textColor notifyDataSetChanged() @@ -348,12 +369,13 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList, val multiSelector: MultiSelector, val listener: MediaOperationsListener?, val allowMultiplePicks: Boolean, val itemClick: (Medium) -> (Unit)) : SwappingHolder(view, MultiSelector()) { - fun bindView(medium: Medium, displayFilenames: Boolean, scrollVertically: Boolean, isListViewType: Boolean, textColor: Int): View { + fun bindView(medium: Medium, displayFilenames: Boolean, scrollHorizontally: Boolean, isListViewType: Boolean, textColor: Int, + animateGifs: Boolean, cropThumbnails: Boolean): View { itemView.apply { play_outline.visibility = if (medium.video) View.VISIBLE else View.GONE photo_name.beVisibleIf(displayFilenames || isListViewType) photo_name.text = medium.name - activity.loadImage(medium.path, medium_thumbnail, scrollVertically) + activity.loadImage(medium.path, medium_thumbnail, scrollHorizontally, animateGifs, cropThumbnails) if (isListViewType) { photo_name.setTextColor(textColor) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/MyPagerAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/MyPagerAdapter.kt index b7e5640ad..b4be25e37 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/MyPagerAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/MyPagerAdapter.kt @@ -23,10 +23,10 @@ class MyPagerAdapter(val activity: ViewPagerActivity, fm: FragmentManager, val m bundle.putSerializable(MEDIUM, medium) val fragment: ViewPagerFragment - if (medium.video) { - fragment = VideoFragment() + fragment = if (medium.video) { + VideoFragment() } else { - fragment = PhotoFragment() + PhotoFragment() } fragment.arguments = bundle diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/dialogs/SaveAsDialog.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/dialogs/SaveAsDialog.kt index 503e0f741..f97e2fb99 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/dialogs/SaveAsDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/dialogs/SaveAsDialog.kt @@ -11,7 +11,7 @@ import com.simplemobiletools.gallery.activities.SimpleActivity import kotlinx.android.synthetic.main.dialog_save_as.view.* import java.io.File -class SaveAsDialog(val activity: SimpleActivity, val path: String, val callback: (savePath: String) -> Unit) { +class SaveAsDialog(val activity: SimpleActivity, val path: String, val appendFilename: Boolean, val callback: (savePath: String) -> Unit) { init { var realPath = File(path).parent.trimEnd('/') @@ -28,6 +28,10 @@ class SaveAsDialog(val activity: SimpleActivity, val path: String, val callback: save_as_extension.setText(extension) } + if (appendFilename) { + name += "_1" + } + save_as_name.setText(name) save_as_path.setOnClickListener { FilePickerDialog(activity, realPath, false, false, true) { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/extensions/activity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/extensions/activity.kt index 4fe4d6180..5bf08e18d 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/extensions/activity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/extensions/activity.kt @@ -2,16 +2,11 @@ package com.simplemobiletools.gallery.extensions import android.app.Activity import android.content.Intent -import android.database.Cursor import android.net.Uri -import android.os.Build import android.provider.MediaStore import android.support.v7.app.AppCompatActivity -import android.util.DisplayMetrics -import android.view.KeyCharacterMap -import android.view.KeyEvent import android.view.View -import android.view.ViewConfiguration +import android.widget.ImageView import com.bumptech.glide.Glide import com.bumptech.glide.load.DecodeFormat import com.bumptech.glide.load.engine.DiskCacheStrategy @@ -24,165 +19,42 @@ import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.gallery.BuildConfig import com.simplemobiletools.gallery.R import com.simplemobiletools.gallery.activities.SimpleActivity -import com.simplemobiletools.gallery.helpers.IS_FROM_GALLERY import com.simplemobiletools.gallery.helpers.NOMEDIA -import com.simplemobiletools.gallery.helpers.REQUEST_EDIT_IMAGE -import com.simplemobiletools.gallery.helpers.REQUEST_SET_AS import com.simplemobiletools.gallery.models.Directory import com.simplemobiletools.gallery.models.Medium import com.simplemobiletools.gallery.views.MySquareImageView +import pl.droidsonroids.gif.GifDrawable import java.io.File import java.util.* -fun Activity.shareUri(medium: Medium, uri: Uri) { - val shareTitle = resources.getString(R.string.share_via) - Intent().apply { - action = Intent.ACTION_SEND - putExtra(Intent.EXTRA_STREAM, uri) - type = medium.getMimeType() - addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - startActivity(Intent.createChooser(this, shareTitle)) - } +fun Activity.shareUri(uri: Uri) { + shareUri(uri, BuildConfig.APPLICATION_ID) +} + +fun Activity.shareUris(uris: ArrayList) { + shareUris(uris, BuildConfig.APPLICATION_ID) } fun Activity.shareMedium(medium: Medium) { - val shareTitle = resources.getString(R.string.share_via) val file = File(medium.path) - val uri = Uri.fromFile(file) - - Intent().apply { - action = Intent.ACTION_SEND - putExtra(Intent.EXTRA_STREAM, uri) - type = medium.getMimeType() - addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - startActivity(Intent.createChooser(this, shareTitle)) - } + shareUri(Uri.fromFile(file)) } fun Activity.shareMedia(media: List) { - val shareTitle = resources.getString(R.string.share_via) - val uris = media.map { Uri.fromFile(File(it.path)) } as ArrayList - - Intent().apply { - action = Intent.ACTION_SEND_MULTIPLE - type = uris.getMimeType() - addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris) - startActivity(Intent.createChooser(this, shareTitle)) - } + val uris = media.map { getFilePublicUri(File(it.path), BuildConfig.APPLICATION_ID) } as ArrayList + shareUris(uris) } -fun Activity.trySetAs(file: File) { - try { - var uri = Uri.fromFile(file) - if (!setAs(uri, file)) { - uri = getFileContentUri(file) - setAs(uri, file, false) - } - } catch (e: Exception) { - toast(R.string.unknown_error_occurred) - } +fun Activity.setAs(uri: Uri) { + setAs(uri, BuildConfig.APPLICATION_ID) } -fun Activity.setAs(uri: Uri, file: File, showToast: Boolean = true): Boolean { - var success = false - Intent().apply { - action = Intent.ACTION_ATTACH_DATA - setDataAndType(uri, file.getMimeType()) - addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - val chooser = Intent.createChooser(this, getString(R.string.set_as)) - - success = if (resolveActivity(packageManager) != null) { - startActivityForResult(chooser, REQUEST_SET_AS) - true - } else { - if (showToast) { - toast(R.string.no_capable_app_found) - } - false - } - } - - return success +fun Activity.openFile(uri: Uri, forceChooser: Boolean) { + openFile(uri, forceChooser, BuildConfig.APPLICATION_ID) } -fun Activity.getFileContentUri(file: File): Uri? { - val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI - val projection = arrayOf(MediaStore.Images.Media._ID) - val selection = "${MediaStore.Images.Media.DATA} = ?" - val selectionArgs = arrayOf(file.absolutePath) - - var cursor: Cursor? = null - try { - cursor = contentResolver.query(uri, projection, selection, selectionArgs, null) - if (cursor?.moveToFirst() == true) { - val id = cursor.getIntValue(MediaStore.Images.Media._ID) - return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "$id") - } - } finally { - cursor?.close() - } - return null -} - -fun Activity.openWith(file: File, forceChooser: Boolean = true) { - val uri = Uri.fromFile(file) - Intent().apply { - action = Intent.ACTION_VIEW - setDataAndType(uri, file.getMimeType()) - addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - putExtra(IS_FROM_GALLERY, true) - - if (resolveActivity(packageManager) != null) { - val chooser = Intent.createChooser(this, getString(R.string.open_with)) - startActivity(if (forceChooser) chooser else this) - } else { - toast(R.string.no_app_found) - } - } -} - -fun Activity.openFileEditor(file: File) { - openEditor(Uri.fromFile(file)) -} - -fun Activity.openEditor(uri: Uri, forceChooser: Boolean = false) { - Intent().apply { - action = Intent.ACTION_EDIT - setDataAndType(uri, "image/*") - addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - - if (resolveActivity(packageManager) != null) { - val chooser = Intent.createChooser(this, getString(R.string.edit_image_with)) - startActivityForResult(if (forceChooser) chooser else this, REQUEST_EDIT_IMAGE) - } else { - toast(R.string.no_editor_found) - } - } -} - -fun Activity.hasNavBar(): Boolean { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - val display = windowManager.defaultDisplay - - val realDisplayMetrics = DisplayMetrics() - display.getRealMetrics(realDisplayMetrics) - - val realHeight = realDisplayMetrics.heightPixels - val realWidth = realDisplayMetrics.widthPixels - - val displayMetrics = DisplayMetrics() - display.getMetrics(displayMetrics) - - val displayHeight = displayMetrics.heightPixels - val displayWidth = displayMetrics.widthPixels - - realWidth - displayWidth > 0 || realHeight - displayHeight > 0 - } else { - val hasMenuKey = ViewConfiguration.get(applicationContext).hasPermanentMenuKey() - val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK) - !hasMenuKey && !hasBackKey - } +fun Activity.openEditor(uri: Uri) { + openEditor(uri, BuildConfig.APPLICATION_ID) } fun Activity.launchCamera() { @@ -196,7 +68,7 @@ fun Activity.launchCamera() { fun SimpleActivity.launchAbout() { startAboutActivity(R.string.app_name, LICENSE_KOTLIN or LICENSE_GLIDE or LICENSE_CROPPER or LICENSE_MULTISELECT or LICENSE_RTL - or LICENSE_PHOTOVIEW or LICENSE_SUBSAMPLING or LICENSE_PATTERN, BuildConfig.VERSION_NAME) + or LICENSE_SUBSAMPLING or LICENSE_PATTERN or LICENSE_REPRINT or LICENSE_GIF_DRAWABLE, BuildConfig.VERSION_NAME) } fun AppCompatActivity.showSystemUI() { @@ -265,24 +137,28 @@ fun SimpleActivity.toggleFileVisibility(oldFile: File, hide: Boolean, callback: } } -fun Activity.loadImage(path: String, target: MySquareImageView, verticalScroll: Boolean) { - target.isVerticalScrolling = verticalScroll +fun Activity.loadImage(path: String, target: MySquareImageView, horizontalScroll: Boolean, animateGifs: Boolean, cropThumbnails: Boolean) { + target.isHorizontalScrolling = horizontalScroll if (path.isImageFast() || path.isVideoFast()) { if (path.isPng()) { - loadPng(path, target) + loadPng(path, target, cropThumbnails) } else { - loadJpg(path, target) + loadJpg(path, target, cropThumbnails) } } else if (path.isGif()) { - if (config.animateGifs) { - loadAnimatedGif(path, target) + val gifDrawable = GifDrawable(path) + target.setImageDrawable(gifDrawable) + if (animateGifs) { + gifDrawable.start() } else { - loadStaticGif(path, target) + gifDrawable.stop() } + + target.scaleType = if (cropThumbnails) ImageView.ScaleType.CENTER_CROP else ImageView.ScaleType.FIT_CENTER } } -fun Activity.loadPng(path: String, target: MySquareImageView) { +fun Activity.loadPng(path: String, target: MySquareImageView, cropThumbnails: Boolean) { val options = RequestOptions() .signature(path.getFileSignature()) .diskCacheStrategy(DiskCacheStrategy.RESOURCE) @@ -292,11 +168,11 @@ fun Activity.loadPng(path: String, target: MySquareImageView) { .asBitmap() .load(path) - if (config.cropThumbnails) options.centerCrop() else options.fitCenter() + if (cropThumbnails) options.centerCrop() else options.fitCenter() builder.apply(options).into(target) } -fun Activity.loadJpg(path: String, target: MySquareImageView) { +fun Activity.loadJpg(path: String, target: MySquareImageView, cropThumbnails: Boolean) { val options = RequestOptions() .signature(path.getFileSignature()) .diskCacheStrategy(DiskCacheStrategy.RESOURCE) @@ -304,36 +180,10 @@ fun Activity.loadJpg(path: String, target: MySquareImageView) { val builder = Glide.with(applicationContext) .load(path) - if (config.cropThumbnails) options.centerCrop() else options.fitCenter() + if (cropThumbnails) options.centerCrop() else options.fitCenter() builder.apply(options).transition(DrawableTransitionOptions.withCrossFade()).into(target) } -fun Activity.loadAnimatedGif(path: String, target: MySquareImageView) { - val options = RequestOptions() - .signature(path.getFileSignature()) - .diskCacheStrategy(DiskCacheStrategy.NONE) - - val builder = Glide.with(applicationContext) - .asGif() - .load(path) - - if (config.cropThumbnails) options.centerCrop() else options.fitCenter() - builder.apply(options).transition(DrawableTransitionOptions.withCrossFade()).into(target) -} - -fun Activity.loadStaticGif(path: String, target: MySquareImageView) { - val options = RequestOptions() - .signature(path.getFileSignature()) - .diskCacheStrategy(DiskCacheStrategy.DATA) - - val builder = Glide.with(applicationContext) - .asBitmap() - .load(path) - - if (config.cropThumbnails) options.centerCrop() else options.fitCenter() - builder.apply(options).into(target) -} - fun Activity.getCachedDirectories(): ArrayList { val token = object : TypeToken>() {}.type return Gson().fromJson>(config.directories, token) ?: ArrayList(1) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/extensions/context.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/extensions/context.kt index cdda71ab7..d4b01c633 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/extensions/context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/extensions/context.kt @@ -5,12 +5,17 @@ import android.content.Intent import android.content.res.Configuration import android.graphics.Point import android.media.AudioManager +import android.net.Uri import android.os.Build import android.view.WindowManager +import com.simplemobiletools.commons.extensions.getFilePublicUri +import com.simplemobiletools.commons.extensions.getMimeTypeFromPath import com.simplemobiletools.commons.extensions.humanizePath +import com.simplemobiletools.gallery.BuildConfig import com.simplemobiletools.gallery.activities.SettingsActivity import com.simplemobiletools.gallery.helpers.Config import com.simplemobiletools.gallery.models.Directory +import java.io.File val Context.portrait get() = resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT val Context.audioManager get() = getSystemService(Context.AUDIO_SERVICE) as AudioManager diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/fragments/PhotoFragment.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/fragments/PhotoFragment.kt index b865282d3..5852698d2 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/fragments/PhotoFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/fragments/PhotoFragment.kt @@ -13,12 +13,10 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.bumptech.glide.Glide -import com.bumptech.glide.Priority import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.DecodeFormat import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.GlideException -import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.target.Target @@ -26,6 +24,7 @@ import com.davemorrissey.labs.subscaleview.ImageSource import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.gallery.R +import com.simplemobiletools.gallery.activities.PhotoActivity import com.simplemobiletools.gallery.activities.ViewPagerActivity import com.simplemobiletools.gallery.extensions.* import com.simplemobiletools.gallery.helpers.GlideRotateTransformation @@ -33,15 +32,16 @@ import com.simplemobiletools.gallery.helpers.MEDIUM import com.simplemobiletools.gallery.models.Medium import it.sephiroth.android.library.exif2.ExifInterface import kotlinx.android.synthetic.main.pager_photo_item.view.* +import pl.droidsonroids.gif.GifDrawable import java.io.File import java.io.FileOutputStream -import java.io.IOException class PhotoFragment : ViewPagerFragment() { private var isFragmentVisible = false private var wasInit = false private var storedShowExtendedDetails = false private var storedExtendedDetails = 0 + private var gifDrawable: GifDrawable? = null lateinit var view: ViewGroup lateinit var medium: Medium @@ -49,11 +49,14 @@ class PhotoFragment : ViewPagerFragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { view = inflater.inflate(R.layout.pager_photo_item, container, false) as ViewGroup - medium = arguments.getSerializable(MEDIUM) as Medium + if (!isFragmentVisible && activity is PhotoActivity) { + isFragmentVisible = true + } + medium = arguments.getSerializable(MEDIUM) as Medium if (medium.path.startsWith("content://")) { val originalPath = medium.path - medium.path = context.getRealPathFromURI(Uri.parse(medium.path)) ?: "" + medium.path = context.getRealPathFromURI(Uri.parse(originalPath)) ?: medium.path if (medium.path.isEmpty()) { var out: FileOutputStream? = null @@ -63,7 +66,6 @@ class PhotoFragment : ViewPagerFragment() { exif.readExif(inputStream, ExifInterface.Options.OPTION_ALL) val tag = exif.getTag(ExifInterface.TAG_ORIENTATION) val orientation = tag?.getValueAsInt(-1) ?: -1 - inputStream = context.contentResolver.openInputStream(Uri.parse(originalPath)) val original = BitmapFactory.decodeStream(inputStream) val rotated = rotateViaMatrix(original, orientation) @@ -78,26 +80,13 @@ class PhotoFragment : ViewPagerFragment() { activity.toast(R.string.unknown_error_occurred) return view } finally { - try { - out?.close() - } catch (e: IOException) { - } + out?.close() } } } - view.subsampling_view.setOnClickListener({ photoClicked() }) - view.photo_view.apply { - maximumScale = 8f - mediumScale = 3f - setOnOutsidePhotoTapListener { - photoClicked() - } - - setOnPhotoTapListener { view, x, y -> - photoClicked() - } - } + view.subsampling_view.setOnClickListener { photoClicked() } + view.gif_view.setOnClickListener { photoClicked() } loadImage() checkExtendedDetails() @@ -123,14 +112,30 @@ class PhotoFragment : ViewPagerFragment() { super.setMenuVisibility(menuVisible) isFragmentVisible = menuVisible if (wasInit) { - if (menuVisible) { - addZoomableView() + if (medium.isGif()) { + gifFragmentVisibilityChanged(menuVisible) } else { - view.subsampling_view.apply { - recycle() - beGone() - background = ColorDrawable(Color.TRANSPARENT) - } + photoFragmentVisibilityChanged(menuVisible) + } + } + } + + private fun gifFragmentVisibilityChanged(isVisible: Boolean) { + if (isVisible) { + gifDrawable?.start() + } else { + gifDrawable?.stop() + } + } + + private fun photoFragmentVisibilityChanged(isVisible: Boolean) { + if (isVisible) { + addZoomableView() + } else { + view.subsampling_view.apply { + recycle() + beGone() + background = ColorDrawable(Color.TRANSPARENT) } } } @@ -155,16 +160,17 @@ class PhotoFragment : ViewPagerFragment() { private fun loadImage() { if (medium.isGif()) { - val options = RequestOptions() - .priority(if (isFragmentVisible) Priority.IMMEDIATE else Priority.LOW) - .diskCacheStrategy(DiskCacheStrategy.DATA) + gifDrawable = if (medium.path.startsWith("content://") || medium.path.startsWith("file://")) { + GifDrawable(context.contentResolver, Uri.parse(medium.path)) + } else { + GifDrawable(medium.path) + } - Glide.with(this) - .asGif() - .load(medium.path) - .transition(DrawableTransitionOptions.withCrossFade()) - .apply(options) - .into(view.photo_view) + if (!isFragmentVisible) { + gifDrawable!!.stop() + } + + view.gif_view.setImageDrawable(gifDrawable) } else { loadBitmap() } @@ -193,7 +199,7 @@ class PhotoFragment : ViewPagerFragment() { addZoomableView() return false } - }).into(view.photo_view) + }).into(view.gif_view) } else { val options = RequestOptions() .diskCacheStrategy(DiskCacheStrategy.NONE) @@ -204,7 +210,7 @@ class PhotoFragment : ViewPagerFragment() { .load(medium.path) .thumbnail(0.2f) .apply(options) - .into(view.photo_view) + .into(view.gif_view) } } @@ -292,7 +298,7 @@ class PhotoFragment : ViewPagerFragment() { super.onDestroyView() context.isKitkatPlus() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && !activity.isDestroyed) { - Glide.with(context).clear(view.photo_view) + Glide.with(context).clear(view.gif_view) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/fragments/VideoFragment.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/fragments/VideoFragment.kt index e271e0b90..8985628c1 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/fragments/VideoFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/fragments/VideoFragment.kt @@ -15,6 +15,7 @@ import android.widget.SeekBar import android.widget.TextView import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.gallery.R +import com.simplemobiletools.gallery.activities.VideoActivity import com.simplemobiletools.gallery.activities.ViewPagerActivity import com.simplemobiletools.gallery.extensions.* import com.simplemobiletools.gallery.helpers.MEDIUM @@ -64,6 +65,11 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee mTimeHolder = mView.video_time_holder medium = arguments.getSerializable(MEDIUM) as Medium + // setMenuVisibility is not called at VideoActivity (third party intent) + if (!mIsFragmentVisible && activity is VideoActivity) { + mIsFragmentVisible = true + } + setupPlayer() if (savedInstanceState != null) { mCurrTime = savedInstanceState.getInt(PROGRESS) @@ -90,7 +96,6 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee override fun onPause() { super.onPause() pauseVideo() - mIsFragmentVisible = false mStoredShowExtendedDetails = context.config.showExtendedDetails mStoredExtendedDetails = context.config.extendedDetails } @@ -285,7 +290,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee var right = res.getDimension(R.dimen.timer_padding).toInt() var bottom = 0 - if (activity.hasNavBar()) { + if (hasNavBar()) { if (res.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) { bottom += height } else { @@ -303,6 +308,30 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee mTimeHolder.beInvisible() } + private fun hasNavBar(): Boolean { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + val display = context.windowManager.defaultDisplay + + val realDisplayMetrics = DisplayMetrics() + display.getRealMetrics(realDisplayMetrics) + + val realHeight = realDisplayMetrics.heightPixels + val realWidth = realDisplayMetrics.widthPixels + + val displayMetrics = DisplayMetrics() + display.getMetrics(displayMetrics) + + val displayHeight = displayMetrics.heightPixels + val displayWidth = displayMetrics.widthPixels + + realWidth - displayWidth > 0 || realHeight - displayHeight > 0 + } else { + val hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey() + val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK) + !hasMenuKey && !hasBackKey + } + } + private fun setupTimeHolder() { mSeekBar!!.max = mDuration mView.video_duration.text = mDuration.getFormattedDuration() @@ -435,6 +464,10 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee } private fun videoCompleted() { + if (!isAdded) { + return + } + if (listener?.videoEnded() == false && context.config.loopVideos) { playVideo() } else { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/fragments/ViewPagerFragment.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/fragments/ViewPagerFragment.kt index 31a2888c4..20a73b886 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/fragments/ViewPagerFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/fragments/ViewPagerFragment.kt @@ -20,6 +20,10 @@ abstract class ViewPagerFragment : Fragment() { fun getMediumExtendedDetails(medium: Medium): String { val file = File(medium.path) + if (!file.exists()) { + return "" + } + val path = "${file.parent.trimEnd('/')}/" val exif = android.media.ExifInterface(medium.path) val details = StringBuilder() diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/helpers/Constants.kt index 663cf7706..23b5a2673 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/helpers/Constants.kt @@ -59,18 +59,15 @@ val NOMEDIA = ".nomedia" val DIRECTORY = "directory" val MEDIUM = "medium" +val PATH = "path" val GET_IMAGE_INTENT = "get_image_intent" val GET_VIDEO_INTENT = "get_video_intent" val GET_ANY_INTENT = "get_any_intent" val SET_WALLPAPER_INTENT = "set_wallpaper_intent" val DIRECTORIES = "directories2" val IS_VIEW_INTENT = "is_view_intent" -val IS_FROM_GALLERY = "is_from_gallery" val PICKED_PATHS = "picked_paths" -val REQUEST_EDIT_IMAGE = 1 -val REQUEST_SET_AS = 2 - // rotations val ROTATE_BY_SYSTEM_SETTING = 0 val ROTATE_BY_DEVICE_ROTATION = 1 diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/views/MySquareImageView.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/views/MySquareImageView.kt index f254d4183..39a2f74be 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/views/MySquareImageView.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/views/MySquareImageView.kt @@ -5,7 +5,7 @@ import android.util.AttributeSet import android.widget.ImageView class MySquareImageView : ImageView { - var isVerticalScrolling = true + var isHorizontalScrolling = false constructor(context: Context) : super(context) @@ -14,7 +14,7 @@ class MySquareImageView : ImageView { constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - val spec = if (isVerticalScrolling) widthMeasureSpec else heightMeasureSpec + val spec = if (isHorizontalScrolling) heightMeasureSpec else widthMeasureSpec super.onMeasure(spec, spec) } } diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 192ef7050..0090560db 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -348,6 +348,26 @@ + + + + + + - + android:layout_height="match_parent" + android:scaleType="fitCenter"/> + + + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 000000000..f4091292b --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/mipmap-nodpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-nodpi/ic_launcher_foreground.png new file mode 100644 index 000000000..24b7f2986 Binary files /dev/null and b/app/src/main/res/mipmap-nodpi/ic_launcher_foreground.png differ diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index b2b1b6986..209dc0b10 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -4,8 +4,6 @@ Gallery Edit Open camera - Open with - No valid app found (hidden) Pin folder Unpin folder @@ -22,7 +20,6 @@ Change cover image Select photo Use default - Set as Volume Brightness Do not ask again in this session diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 48f819337..d835945cd 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -4,8 +4,6 @@ Galerie Upravit Spustit fotoaparát - Otevřít pomocí - Nebyla nalezena žádná vhodná aplikace (skryté) Připnout složku Odepnout složku @@ -22,7 +20,6 @@ Change cover image Select photo Use default - Nastavit jako Volume Brightness Do not ask again in this session diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index da95fadc3..f216c800e 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -4,8 +4,6 @@ Galerie Bearbeiten Kamera öffnen - Öffnen mit - Keine passende App gefunden (versteckt) Ordner anheften Ordner loslösen @@ -14,7 +12,7 @@ Ansicht: Als Ordner Ordner wählen Auf Karte zeigen - Unbekannter Ort + Unbekannter Pfad Keine Karten-App gefunden Keine Kamera-App gefunden Kacheln verkleinern @@ -22,10 +20,9 @@ Coverbild ändern Auswählen Standard - Festlegen als Lautstärke Helligkeit - Nicht erneut fragen (in dieser Session) + Nicht erneut fragen (in dieser Sitzung) Filter @@ -69,7 +66,7 @@ Bildbearbeitung fehlgeschlagen Bild bearbeiten mit Keine Bildeditor-App gefunden - Unbekannter Dateiort + Unbekannter Dateipfad Konnte Quelldatei nicht überschreiben Nach links drehen Nach rechts drehen @@ -125,7 +122,7 @@ Systemleisten ausblenden im Vollbild Nach Löschen leere Ordner löschen Gesten für Videolautstärke/Helligkeit - Show folder media count on the main view + Medienanzahl bei Ordnern anzeigen Teilen/Drehen im Vollbild-Menü vertauschen Eigenschaften anzeigen im Vollbild Eigenschaften auswählen @@ -134,11 +131,11 @@ Eine schlichte Galerie zum Betrachten von Bildern und Videos ohne Werbung. - Ein schlichtes Tool zum Betrachten von Bildern und Videos. Die Medien können nach Datum, Größe, Name sowie auf- oder absteigend sortiert angezeigt werden, in Bilder kann hineingezoomt werden. Die Vorschau-Kacheln werden in mehreren Spalten abhängig von der Displaygröße angezeigt, die Spaltenanzahl ist mit Zweifingergesten änderbar. Die Medien können umbenannt, geteilt, gelöscht, kopiert, verschoben werden. Bilder können zugeschnitten, gedreht oder als Hintergrund festgelegt werden, direkt aus der App heraus. + Eine schlichte App zum Betrachten von Bildern und Videos. Die Medien können nach Datum, Größe, Name sowie auf- oder absteigend sortiert werden, in Bilder kann auch hineingezoomt werden. Die Vorschau-Kacheln werden in mehreren Spalten abhängig von der Displaygröße angezeigt, die Spaltenanzahl ist mit Zweifingergesten änderbar. Die Medien können umbenannt, geteilt, gelöscht, kopiert und verschoben werden. Bilder können direkt aus der App heraus zugeschnitten, gedreht oder als Hintergrund festgelegt werden. - Die Galerie bietet auch für Drittparteien einige Funktionen an: zum Vorschauen von Bildern / Videos, zum Hinzufügen von Anhängen bei eMail-Clients, etc. Sie ist perfekt für den täglichen Gebrauch. + Diese Galerie bietet auch für Drittanbieter einige Funktionen an: zum Vorschauen von Bildern / Videos, zum Hinzufügen von Anhängen bei Email-Apps, etc. Sie ist perfekt für den täglichen Gebrauch. - Beinhaltet keine Werbung oder unnötige Berechtigungen. Sie ist komplett Open Source, verwendete Farben sind anpassbar. + Beinhaltet keine Werbung oder unnötigen Berechtigungen. Sie ist komplett Open Source, verwendete Farben sind anpassbar. Diese App ist nur eine aus einer größeren Serie von schlichten Apps. Der Rest davon findet sich auf http://www.simplemobiletools.com diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 8f9bb7813..037aa80de 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -4,8 +4,6 @@ Galería Editar Abrir cámara - Abrir con… - No se encontró una aplicación válida (oculto) Fijar carpeta No fijar carpeta @@ -22,7 +20,6 @@ Cambiar imagen de portada Seleccionar imagen Uso por defecto - Establecer como Volume Brightness Do not ask again in this session diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 57e76daec..f6ccd7a8d 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -4,8 +4,6 @@ Galleria Muokkaa Avaa kamera - Avaa - Sovelluksia ei löydetty (piilotettu) Kiinnitä kansio Poista kiinnitys @@ -22,7 +20,6 @@ Vaihda kansikuva Valitse kuva Käytä oletuksia - Aseta Äänenvoimakkuus Kirkkaus Do not ask again in this session diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index efa023339..edf3e5d03 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -4,8 +4,6 @@ Galerie Édition Ouvrir appareil photo - Ouvrir avec - Aucune application valide trouvée (caché) Épingler le dossier Désépingler le dossier @@ -22,7 +20,6 @@ Changer l\'image de couverture Sélectionner une photo Utiliser par défaut - Définir comme Volume Luminosité Ne pas redemander pour cette session diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 2eb9d22d0..89abc717c 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -4,8 +4,6 @@ Gallery Edit Open camera - Open with - No valid app found (hidden) Pin folder Unpin folder @@ -22,7 +20,6 @@ Change cover image Select photo Use default - Set as Volume Brightness Do not ask again in this session diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 66c2fd1f3..3e0b0643f 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -4,8 +4,6 @@ Galleria Modifica Apri fotocamera - Apri con - Nessun app valida trovata (nascosta) Blocca cartella Sblocca cartella @@ -22,10 +20,9 @@ Cambia immagine copertina Seleziona foto Usa predefinita - Imposta come Volume Luminosità - Do not ask again in this session + Non chiedere nuovamente in questa sessione Filtra i media @@ -125,10 +122,10 @@ Nascondi UI di sistema con media a schermo intero Elimina cartelle vuote dopo averne eliminato il contenuto Gestisci il volume e la luminosità dei video con gesti verticali - Show folder media count on the main view + Mostra numero elementi nella cartella Sostituisci Condividi con Ruota a schermo intero - Show extended details over fullscreen media - Manage extended details + Mostra informazioni estese su media a schermo intero + Gestisci le informazioni estese diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index dc2413462..2f9086eb3 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -4,8 +4,6 @@ ギャラリー 編集 カメラを開く - 別のアプリで開く - 有効なアプリが見つかりません (非表示) フォルダーをピン留めする フォルダーのピン留めを外す @@ -22,7 +20,6 @@ カバー画像を変更 写真を選択 デフォルトに戻す - 他で使う 音量 明るさ Do not ask again in this session diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 91e0ca7bf..a7d28d108 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -4,8 +4,6 @@ Gallerij Bewerken Camera - Openen met - Geen app gevonden om dit bestand mee te openen (verborgen) Map vastzetten Map losmaken @@ -22,7 +20,6 @@ Afbeelding voor omslag veranderen Foto selecteren Standaard gebruiken - Instellen als Volume Helderheid Onthouden voor deze sessie diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index c77a32cad..d153c70ba 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -4,8 +4,6 @@ Simple Gallery Edytuj Uruchom aplikację aparatu - Otwórz w - Nie znaleziono danych aplikacji (ukryty) Przypnij folder Wypakuj folder @@ -22,7 +20,6 @@ Zmień okładkę Wybierz obraz Użyj domyślnej - Ustaw jako Głośność Jasność Nie pytaj więcej w tej sesji diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 8c391f4b7..c9e953185 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -4,8 +4,6 @@ Galeria Editar Abrir câmera - Abrir com - Nenhum aplicativo encontrado     (oculto) Fixar pasta Desfixar pasta @@ -22,7 +20,6 @@ Trocar imagem de capa Selecionar foto Usar padrão - Definir como Volume Brilho Não perguntar novamente por enquanto @@ -125,7 +122,7 @@ Esconder interface do sistema automaticamente quando em tela cheia Apagar pastas vazias após deleter seu conteúdo Permitir controle do volume e brilho com gestos na vertical - Show folder media count on the main view + Mostrar quantidade de arquivos das pastas Substituir botão "Compartilhar" por "Rotação de tela" quando em tela cheia Exibir detalhes extendidos quando em tela cheia Gerenciar detalhes extendidos diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index bdbf21597..6242d94c4 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -4,8 +4,6 @@ Galeria Editar Abrir câmara - Abrir com - Nenhuma aplicação encontrada (oculta) Fixar pasta Desafixar pasta @@ -22,10 +20,9 @@ Alterar imagem de capa Selecionar foto Predefinição - Definir como Volume Brilho - Do not ask again in this session + Não perguntar de novo para esta sessão Filtrar multimédia @@ -127,8 +124,8 @@ Permitir controlo do volume e brilho dos vídeos através de gestos verticais Show folder media count on the main view Substituir a opção Partilhar pela opção Rodar se em ecrã completo - Show extended details over fullscreen media - Manage extended details + Mostrar detalhes se em ecrã completo + Gerir detalhes exibidos diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index d62e8711d..f480ce936 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -4,8 +4,6 @@ Галерея Редактировать Открыть камеру - Открыть в - Приложение не найдено (Скрытый) Закрепить папку Открепить папку @@ -17,15 +15,14 @@ Место съёмки не указано Не найдено приложений с картами Не найдено приложения камеры - Добавить 1 столбец - Убрать 1 столбец + Добавить столбец + Убрать столбец Изменить обложку Выбрать изображение Использовать по умолчанию - Установить как… Громкость Яркость - Do not ask again in this session + Не спрашивать снова (до следующего запуска) Фильтр медиа @@ -87,8 +84,8 @@ Приложение не найдено Установка обоев… Обои успешно установлены - Формат изображения - Пейзажное соотношение сторон + Портрет + Ландшафт Слайдшоу @@ -125,10 +122,10 @@ Автоматически скрывать системный интерфейс в полноэкранном режиме Удалять пустые папки после удаления их содержимого Управлять громкостью и яркостью видео с помощью вертикальных жестов - Show folder media count on the main view + Показывать количество файлов в папках Заменить \'Поделиться\' на \'Повернуть\' в меню полноэкранного режима - Show extended details over fullscreen media - Manage extended details + Показывать детали файла + Выбрать детали файла diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index f562dff8d..e4af5b81d 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -4,8 +4,6 @@ Galéria Upraviť Otvoriť fotoaparát - Otvoriť pomocou - Nenašla sa žiadna vhodná aplikácia (skryté) Pripnúť priečinok Odopnúť priečinok @@ -22,7 +20,6 @@ Zmeniť obal albumu Zvoliť foto Použiť predvolený - Nastaviť ako Hlasitosť Jas Nepýtať sa už v tomto spustení diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 106063a54..703575d53 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -4,8 +4,6 @@ Galleri Redigera Starta kameran - Öppna med - Hittade ingen giltig app (dold) Fäst mappen Släpp mappen @@ -22,7 +20,6 @@ Byt omslagsbild Välj foto Använd standard - Ange som Volym Ljusstyrka Do not ask again in this session diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index a9ac2f748..67ea088b9 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -4,8 +4,6 @@ Galeri Düzenle Kamerayı aç - Bununla aç - Geçerli bir uygulama bulunamadı (gizli) Pin klasör Klasörü çöz @@ -22,7 +20,6 @@ Change cover image Select photo Use default - Set as Volume Brightness Do not ask again in this session diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 90412da97..74cfdfe11 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -4,8 +4,6 @@ 简约图库 编辑 打开相机 - 打开方式 - 未找到可用应用 (隐藏) 锁定目录 解除锁定目录 @@ -22,7 +20,6 @@ 更改封面图片 选择图片 使用默认 - 设置为 音量 亮度 不再提醒 @@ -30,7 +27,7 @@ 要显示的媒体文件 图片 - 适配 + 视频 GIFs 所选的过滤器没有找到媒体文件。 更改过滤器 @@ -44,7 +41,7 @@ 是否排除父目录? 此目录及其子目录中的媒体将不会在“简约图库”中显示,但是其它应用可以访问。如果您想对其它应用隐藏,请使用隐藏功能。 移除全部 - 是否删除排除列表中的所有文件夹?此操作不会删除文件夹。 + 是否删除排除列表中的所有项目?此操作不会删除文件夹本身。 包含目录 @@ -116,7 +113,7 @@ GIF 缩略图 浏览时最大亮度 裁剪缩略图 - 全屏时方向 + 全屏方向 系统设置 设备方向 根据长宽比 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index bc5042450..ff138ebbd 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -4,8 +4,6 @@ 簡易相簿 編輯 開啟相機 - 以其他應用程式開啟 - 找不到應用程式 (隱藏) 釘選資料夾 取消釘選資料夾 @@ -22,7 +20,6 @@ 更換封面圖片 選擇相片 使用預設 - 設為 音量 亮度 Do not ask again in this session diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 8cb25a2bb..ee1e5614a 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -7,4 +7,6 @@ @color/default_dark_theme_text_color @color/default_dark_theme_background_color + + @color/color_primary diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index de109b996..a8c998266 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -2,6 +2,7 @@ + Added an option to keep last-modified field at file copy/move/rename Added an option to hide folder media count on the main screen Added an option to show customizable extended details over fullscreen media diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b2b1b6986..209dc0b10 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -4,8 +4,6 @@ Gallery Edit Open camera - Open with - No valid app found (hidden) Pin folder Unpin folder @@ -22,7 +20,6 @@ Change cover image Select photo Use default - Set as Volume Brightness Do not ask again in this session diff --git a/app/src/main/res/xml/provider_paths.xml b/app/src/main/res/xml/provider_paths.xml index 8d13fa177..ad4a8140d 100644 --- a/app/src/main/res/xml/provider_paths.xml +++ b/app/src/main/res/xml/provider_paths.xml @@ -1,4 +1,5 @@ +