diff --git a/CHANGELOG.md b/CHANGELOG.md index ca94b74d9..18192daf0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,44 @@ Changelog ========== +Version 6.4.1 *(2019-01-29)* +---------------------------- + + * Fixed some crashes related to zoomable videos + * Disable the Close Down gesture at GIFs and videos, if they are zoomed in + +Version 6.4.0 *(2019-01-29)* +---------------------------- + + * Implemented export/importing for app settings and other preferences, like sorting + * Allow hiding Notch on fullscreen view on Android 9+ + * Some gif/video zoom related improvements + * Autosave images zoomed at the fullscreen view + * Many other UX and stability improvements + +Version 6.3.2 *(2019-01-23)* +---------------------------- + + * Fixed some fullscreen image and gif issues related to zooming + * Show directly included folders even if they contain a .nomedia file + +Version 6.3.1 *(2019-01-22)* +---------------------------- + + * Fixed fullscreen images crashing when the app was installed on an SD card + * A couple other fullscreen image viewer improvements + * Allow batch rotating only images, ignore other file types + +Version 6.3.0 *(2019-01-17)* +---------------------------- + + * Allow zooming GIFs and videos + * Allow sharing images directly from the editor + * Allow drawing in the editor + * If a folder is directly excluded, make it a higher priority than some included parent folder + * Added batch rotating from the thumbnails view + * Many other smaller improvements + Version 6.2.2 *(2019-01-10)* ---------------------------- diff --git a/README.md b/README.md index 473b2ca61..6b7f501ad 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ This app is just one piece of a bigger series of apps. You can find the rest of
App image App image -App image +App image
License diff --git a/app/build.gradle b/app/build.gradle index 8e1c23607..767d127be 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,8 @@ android { applicationId "com.simplemobiletools.gallery.pro" minSdkVersion 21 targetSdkVersion 28 - versionCode 220 - versionName "6.2.2" + versionCode 226 + versionName "6.4.1" multiDexEnabled true setProperty("archivesBaseName", "gallery") } @@ -54,10 +54,14 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + + packagingOptions { + exclude 'META-INF/library_release.kotlin_module' + } } dependencies { - implementation 'com.simplemobiletools:commons:5.6.7' + implementation 'com.simplemobiletools:commons:5.7.5' implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0' implementation 'androidx.multidex:multidex:2.0.1' implementation 'it.sephiroth.android.exif:library:1.0.1' @@ -70,16 +74,11 @@ dependencies { implementation 'info.androidhive:imagefilters:1.0.7' implementation 'com.squareup.picasso:picasso:2.71828' implementation 'com.caverock:androidsvg-aar:1.3' + implementation 'com.github.tibbi:gestureviews:985ba285fb' + implementation 'com.github.tibbi:subsampling-scale-image-view:3ccd2f9c2b' kapt 'com.github.bumptech.glide:compiler:4.8.0' // keep it here too, not just in Commons, else loading SVGs wont work kapt 'androidx.room:room-compiler:2.0.0' implementation 'androidx.room:room-runtime:2.0.0' annotationProcessor 'androidx.room:room-compiler:2.0.0' - - //implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0' - //implementation 'com.github.tibbi:subsampling-scale-image-view:v3.10.1-fork' - implementation 'com.github.tibbi:subsampling-scale-image-view:9e9a393cc3' - - // implementation 'com.github.chrisbanes:PhotoView:2.3.0' - implementation 'com.github.tibbi:PhotoView:2.3.0-fork' } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/EditActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/EditActivity.kt index be4ce6d94..2916e5ce7 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/EditActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/EditActivity.kt @@ -106,6 +106,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener override fun onResume() { super.onResume() isEditingWithThirdParty = false + bottom_draw_width.setColors(config.textColor, getAdjustedPrimaryColor(), config.backgroundColor) } override fun onStop() { @@ -348,6 +349,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener val currentFilter = getFiltersAdapter()?.getCurrentFilter() if (currentFilter == null) { toast(R.string.unknown_error_occurred) + return@Thread } val originalBitmap = Glide.with(applicationContext).asBitmap().load(uri).submit(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL).get() @@ -566,7 +568,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener else -> null } - currentPrimaryActionButton?.applyColorFilter(config.primaryColor) + currentPrimaryActionButton?.applyColorFilter(getAdjustedPrimaryColor()) bottom_editor_filter_actions.beVisibleIf(currPrimaryAction == PRIMARY_ACTION_FILTER) bottom_editor_crop_rotate_actions.beVisibleIf(currPrimaryAction == PRIMARY_ACTION_CROP_ROTATE) bottom_editor_draw_actions.beVisibleIf(currPrimaryAction == PRIMARY_ACTION_DRAW) @@ -656,7 +658,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener else -> bottom_aspect_ratio_other } - currentAspectRatioButton.setTextColor(config.primaryColor) + currentAspectRatioButton.setTextColor(getAdjustedPrimaryColor()) } private fun updateCropRotateActionButtons() { @@ -669,7 +671,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener else -> null } - primaryActionView?.applyColorFilter(config.primaryColor) + primaryActionView?.applyColorFilter(getAdjustedPrimaryColor()) } private fun updateDrawColor(color: Int) { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/MainActivity.kt index 6e4fa3240..38de24828 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/MainActivity.kt @@ -1177,61 +1177,11 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { private fun checkWhatsNewDialog() { arrayListOf().apply { - add(Release(46, R.string.release_46)) - add(Release(47, R.string.release_47)) - add(Release(49, R.string.release_49)) - add(Release(50, R.string.release_50)) - add(Release(51, R.string.release_51)) - add(Release(52, R.string.release_52)) - add(Release(54, R.string.release_54)) - add(Release(58, R.string.release_58)) - add(Release(62, R.string.release_62)) - add(Release(65, R.string.release_65)) - add(Release(66, R.string.release_66)) - add(Release(69, R.string.release_69)) - add(Release(70, R.string.release_70)) - add(Release(72, R.string.release_72)) - add(Release(74, R.string.release_74)) - add(Release(76, R.string.release_76)) - add(Release(77, R.string.release_77)) - add(Release(83, R.string.release_83)) - add(Release(84, R.string.release_84)) - add(Release(88, R.string.release_88)) - add(Release(89, R.string.release_89)) - add(Release(93, R.string.release_93)) - add(Release(94, R.string.release_94)) - add(Release(97, R.string.release_97)) - add(Release(98, R.string.release_98)) - add(Release(108, R.string.release_108)) - add(Release(112, R.string.release_112)) - add(Release(114, R.string.release_114)) - add(Release(115, R.string.release_115)) - add(Release(118, R.string.release_118)) - add(Release(119, R.string.release_119)) - add(Release(122, R.string.release_122)) - add(Release(123, R.string.release_123)) - add(Release(125, R.string.release_125)) - add(Release(127, R.string.release_127)) - add(Release(133, R.string.release_133)) - add(Release(136, R.string.release_136)) - add(Release(137, R.string.release_137)) - add(Release(138, R.string.release_138)) - add(Release(143, R.string.release_143)) - add(Release(158, R.string.release_158)) - add(Release(159, R.string.release_159)) - add(Release(163, R.string.release_163)) - add(Release(177, R.string.release_177)) - add(Release(178, R.string.release_178)) - add(Release(180, R.string.release_180)) - add(Release(181, R.string.release_181)) - add(Release(182, R.string.release_182)) - add(Release(184, R.string.release_184)) - add(Release(201, R.string.release_201)) - add(Release(202, R.string.release_202)) - add(Release(206, R.string.release_206)) add(Release(213, R.string.release_213)) add(Release(217, R.string.release_217)) add(Release(220, R.string.release_220)) + add(Release(221, R.string.release_221)) + add(Release(225, R.string.release_225)) checkWhatsNew(this, BuildConfig.VERSION_CODE) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PanoramaPhotoActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PanoramaPhotoActivity.kt index 0af37fd0b..fa8dcfb54 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PanoramaPhotoActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PanoramaPhotoActivity.kt @@ -7,7 +7,6 @@ import android.graphics.Color import android.os.Bundle import android.view.View import android.view.Window -import android.view.WindowManager import android.widget.RelativeLayout import com.google.vr.sdk.widgets.pano.VrPanoramaEventListener import com.google.vr.sdk.widgets.pano.VrPanoramaView @@ -16,7 +15,6 @@ import com.simplemobiletools.commons.extensions.onGlobalLayout import com.simplemobiletools.commons.extensions.showErrorToast import com.simplemobiletools.commons.extensions.toast import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE -import com.simplemobiletools.commons.helpers.isPiePlus import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.extensions.* import com.simplemobiletools.gallery.pro.helpers.PATH @@ -36,11 +34,7 @@ open class PanoramaPhotoActivity : SimpleActivity() { setContentView(R.layout.activity_panorama_photo) supportActionBar?.hide() - if (isPiePlus()) { - window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES - window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) - } - + checkNotchSupport() setupButtonMargins() cardboard.setOnClickListener { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PanoramaVideoActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PanoramaVideoActivity.kt index c442bd718..e394858d2 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PanoramaVideoActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PanoramaVideoActivity.kt @@ -14,7 +14,6 @@ import com.google.vr.sdk.widgets.video.VrVideoEventListener import com.google.vr.sdk.widgets.video.VrVideoView import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE -import com.simplemobiletools.commons.helpers.isPiePlus import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.extensions.* import com.simplemobiletools.gallery.pro.helpers.MIN_SKIP_LENGTH @@ -44,11 +43,7 @@ open class PanoramaVideoActivity : SimpleActivity(), SeekBar.OnSeekBarChangeList setContentView(R.layout.activity_panorama_video) supportActionBar?.hide() - if (isPiePlus()) { - window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES - window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) - } - + checkNotchSupport() handlePermission(PERMISSION_WRITE_STORAGE) { if (it) { checkIntent() diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PhotoVideoActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PhotoVideoActivity.kt index 02ddad7c1..c9c413caa 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PhotoVideoActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PhotoVideoActivity.kt @@ -9,13 +9,11 @@ import android.os.Bundle import android.view.Menu import android.view.MenuItem import android.view.View -import android.view.WindowManager import com.simplemobiletools.commons.dialogs.PropertiesDialog 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.REAL_FILE_PATH -import com.simplemobiletools.commons.helpers.isPiePlus import com.simplemobiletools.gallery.pro.BuildConfig import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.extensions.* @@ -107,11 +105,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList } } - if (isPiePlus()) { - window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES - window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) - } - + checkNotchSupport() showSystemUI(true) val bundle = Bundle() val file = File(mUri.toString()) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SettingsActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SettingsActivity.kt index df0324e07..169528978 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SettingsActivity.kt @@ -2,13 +2,13 @@ package com.simplemobiletools.gallery.pro.activities import android.content.Intent import android.os.Bundle +import android.text.TextUtils import com.simplemobiletools.commons.dialogs.ConfirmationDialog +import com.simplemobiletools.commons.dialogs.FilePickerDialog import com.simplemobiletools.commons.dialogs.RadioGroupDialog import com.simplemobiletools.commons.dialogs.SecurityDialog import com.simplemobiletools.commons.extensions.* -import com.simplemobiletools.commons.helpers.PROTECTION_FINGERPRINT -import com.simplemobiletools.commons.helpers.SHOW_ALL_TABS -import com.simplemobiletools.commons.helpers.sumByLong +import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.dialogs.ManageBottomActionsDialog @@ -19,6 +19,7 @@ import com.simplemobiletools.gallery.pro.extensions.galleryDB import com.simplemobiletools.gallery.pro.extensions.showRecycleBinEmptyingDialog import com.simplemobiletools.gallery.pro.helpers.* import kotlinx.android.synthetic.main.activity_settings.* +import java.io.File import java.util.* class SettingsActivity : SimpleActivity() { @@ -31,7 +32,10 @@ class SettingsActivity : SimpleActivity() { override fun onResume() { super.onResume() + setupSettingItems() + } + private fun setupSettingItems() { setupCustomizeColors() setupUseEnglish() setupManageIncludedFolders() @@ -57,6 +61,7 @@ class SettingsActivity : SimpleActivity() { setupAllowPhotoGestures() setupAllowVideoGestures() setupAllowDownGesture() + setupShowNotch() setupBottomActions() setupThumbnailVideoDuration() setupShowMediaCount() @@ -79,12 +84,15 @@ class SettingsActivity : SimpleActivity() { setupEmptyRecycleBin() updateTextColors(settings_holder) setupSectionColors() + setupExportSettings() + setupImportSettings() } private fun setupSectionColors() { val adjustedPrimaryColor = getAdjustedPrimaryColor() arrayListOf(visibility_label, videos_label, thumbnails_label, scrolling_label, fullscreen_media_label, security_label, - file_operations_label, deep_zoomable_images_label, extended_details_label, bottom_actions_label, recycle_bin_label).forEach { + file_operations_label, deep_zoomable_images_label, extended_details_label, bottom_actions_label, recycle_bin_label, + migrating_label).forEach { it.setTextColor(adjustedPrimaryColor) } } @@ -342,6 +350,15 @@ class SettingsActivity : SimpleActivity() { } } + private fun setupShowNotch() { + settings_show_notch_holder.beVisibleIf(isPiePlus()) + settings_show_notch.isChecked = config.showNotch + settings_show_notch_holder.setOnClickListener { + settings_show_notch.toggle() + config.showNotch = settings_show_notch.isChecked + } + } + private fun setupShowMediaCount() { settings_show_media_count.isChecked = config.showMediaCount settings_show_media_count_holder.setOnClickListener { @@ -557,4 +574,212 @@ class SettingsActivity : SimpleActivity() { } } } + + private fun setupExportSettings() { + settings_export_holder.setOnClickListener { + val configItems = LinkedHashMap().apply { + put(IS_USING_SHARED_THEME, config.isUsingSharedTheme) + put(TEXT_COLOR, config.textColor) + put(BACKGROUND_COLOR, config.backgroundColor) + put(PRIMARY_COLOR, config.primaryColor) + put(APP_ICON_COLOR, config.appIconColor) + put(USE_ENGLISH, config.useEnglish) + put(WAS_USE_ENGLISH_TOGGLED, config.wasUseEnglishToggled) + put(INCLUDED_FOLDERS, TextUtils.join(",", config.includedFolders)) + put(EXCLUDED_FOLDERS, TextUtils.join(",", config.excludedFolders)) + put(SHOW_HIDDEN_MEDIA, config.showHiddenMedia) + put(DO_EXTRA_CHECK, config.doExtraCheck) + put(AUTOPLAY_VIDEOS, config.autoplayVideos) + put(REMEMBER_LAST_VIDEO_POSITION, config.rememberLastVideoPosition) + put(LAST_VIDEO_PATH, config.lastVideoPath) + put(LOOP_VIDEOS, config.loopVideos) + put(OPEN_VIDEOS_ON_SEPARATE_SCREEN, config.openVideosOnSeparateScreen) + put(ALLOW_VIDEO_GESTURES, config.allowVideoGestures) + put(ANIMATE_GIFS, config.animateGifs) + put(CROP_THUMBNAILS, config.cropThumbnails) + put(SHOW_THUMBNAIL_VIDEO_DURATION, config.showThumbnailVideoDuration) + put(SHOW_MEDIA_COUNT, config.showMediaCount) + put(SHOW_INFO_BUBBLE, config.showInfoBubble) + put(SCROLL_HORIZONTALLY, config.scrollHorizontally) + put(ENABLE_PULL_TO_REFRESH, config.enablePullToRefresh) + put(MAX_BRIGHTNESS, config.maxBrightness) + put(BLACK_BACKGROUND, config.blackBackground) + put(HIDE_SYSTEM_UI, config.hideSystemUI) + put(ALLOW_INSTANT_CHANGE, config.allowInstantChange) + put(ALLOW_PHOTO_GESTURES, config.allowPhotoGestures) + put(ALLOW_DOWN_GESTURE, config.allowDownGesture) + put(SHOW_NOTCH, config.showNotch) + put(SCREEN_ROTATION, config.screenRotation) + put(ALLOW_ZOOMING_IMAGES, config.allowZoomingImages) + put(SHOW_HIGHEST_QUALITY, config.showHighestQuality) + put(ONE_FINGER_ZOOM, config.oneFingerZoom) + put(ALLOW_ONE_TO_ONE_ZOOM, config.allowOneToOneZoom) + put(SHOW_EXTENDED_DETAILS, config.showExtendedDetails) + put(HIDE_EXTENDED_DETAILS, config.hideExtendedDetails) + put(EXTENDED_DETAILS, config.extendedDetails) + put(DELETE_EMPTY_FOLDERS, config.deleteEmptyFolders) + put(KEEP_LAST_MODIFIED, config.keepLastModified) + put(SKIP_DELETE_CONFIRMATION, config.skipDeleteConfirmation) + put(BOTTOM_ACTIONS, config.bottomActions) + put(VISIBLE_BOTTOM_ACTIONS, config.visibleBottomActions) + put(USE_RECYCLE_BIN, config.useRecycleBin) + put(SHOW_RECYCLE_BIN_AT_FOLDERS, config.showRecycleBinAtFolders) + put(SHOW_RECYCLE_BIN_LAST, config.showRecycleBinLast) + put(SORT_ORDER, config.sorting) + put(DIRECTORY_SORT_ORDER, config.directorySorting) + put(GROUP_BY, config.groupBy) + put(GROUP_DIRECT_SUBFOLDERS, config.groupDirectSubfolders) + put(PINNED_FOLDERS, TextUtils.join(",", config.pinnedFolders)) + put(DISPLAY_FILE_NAMES, config.displayFileNames) + put(FILTER_MEDIA, config.filterMedia) + put(DIR_COLUMN_CNT, config.dirColumnCnt) + put(MEDIA_COLUMN_CNT, config.mediaColumnCnt) + put(SHOW_ALL, config.showAll) + put(SHOW_WIDGET_FOLDER_NAME, config.showWidgetFolderName) + put(WIDGET_BG_COLOR, config.widgetBgColor) + put(WIDGET_TEXT_COLOR, config.widgetTextColor) + put(VIEW_TYPE_FILES, config.viewTypeFiles) + put(VIEW_TYPE_FOLDERS, config.viewTypeFolders) + put(SLIDESHOW_INTERVAL, config.slideshowInterval) + put(SLIDESHOW_INCLUDE_VIDEOS, config.slideshowIncludeVideos) + put(SLIDESHOW_INCLUDE_GIFS, config.slideshowIncludeGIFs) + put(SLIDESHOW_RANDOM_ORDER, config.slideshowRandomOrder) + put(SLIDESHOW_MOVE_BACKWARDS, config.slideshowMoveBackwards) + put(SLIDESHOW_LOOP, config.loopSlideshow) + put(LAST_EDITOR_CROP_ASPECT_RATIO, config.lastEditorCropAspectRatio) + put(LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_X, config.lastEditorCropOtherAspectRatioX) + put(LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_Y, config.lastEditorCropOtherAspectRatioY) + put(LAST_EDITOR_DRAW_COLOR, config.lastEditorDrawColor) + put(LAST_EDITOR_BRUSH_SIZE, config.lastEditorBrushSize) + put(LAST_CONFLICT_RESOLUTION, config.lastConflictResolution) + put(LAST_CONFLICT_APPLY_TO_ALL, config.lastConflictApplyToAll) + } + + exportSettings(configItems, "gallery-settings.txt") + } + } + + private fun setupImportSettings() { + settings_import_holder.setOnClickListener { + FilePickerDialog(this) { + Thread { + try { + parseFile(it) + } catch (e: Exception) { + showErrorToast(e) + } + }.start() + } + } + } + + private fun parseFile(path: String) { + val inputStream = File(path).inputStream() + var importedItems = 0 + val configValues = LinkedHashMap() + inputStream.bufferedReader().use { + while (true) { + try { + val line = it.readLine() ?: break + val split = line.split("=".toRegex(), 2) + if (split.size == 2) { + configValues[split[0]] = split[1] + } + importedItems++ + } catch (e: Exception) { + showErrorToast(e) + } + } + } + + for ((key, value) in configValues) { + when (key) { + IS_USING_SHARED_THEME -> config.isUsingSharedTheme = value.toBoolean() + TEXT_COLOR -> config.textColor = value.toInt() + BACKGROUND_COLOR -> config.backgroundColor = value.toInt() + PRIMARY_COLOR -> config.primaryColor = value.toInt() + APP_ICON_COLOR -> { + if (getAppIconColors().contains(value.toInt())) { + config.appIconColor = value.toInt() + checkAppIconColor() + } + } + USE_ENGLISH -> config.useEnglish = value.toBoolean() + WAS_USE_ENGLISH_TOGGLED -> config.wasUseEnglishToggled = value.toBoolean() + INCLUDED_FOLDERS -> config.addIncludedFolders(value.toStringSet()) + EXCLUDED_FOLDERS -> config.addExcludedFolders(value.toStringSet()) + SHOW_HIDDEN_MEDIA -> config.showHiddenMedia = value.toBoolean() + DO_EXTRA_CHECK -> config.doExtraCheck = value.toBoolean() + AUTOPLAY_VIDEOS -> config.autoplayVideos = value.toBoolean() + REMEMBER_LAST_VIDEO_POSITION -> config.rememberLastVideoPosition = value.toBoolean() + LAST_VIDEO_PATH -> config.lastVideoPath = value.toString() + LOOP_VIDEOS -> config.loopVideos = value.toBoolean() + OPEN_VIDEOS_ON_SEPARATE_SCREEN -> config.openVideosOnSeparateScreen = value.toBoolean() + ALLOW_VIDEO_GESTURES -> config.allowVideoGestures = value.toBoolean() + ANIMATE_GIFS -> config.animateGifs = value.toBoolean() + CROP_THUMBNAILS -> config.cropThumbnails = value.toBoolean() + SHOW_THUMBNAIL_VIDEO_DURATION -> config.showThumbnailVideoDuration = value.toBoolean() + SHOW_MEDIA_COUNT -> config.showMediaCount = value.toBoolean() + SHOW_INFO_BUBBLE -> config.showInfoBubble = value.toBoolean() + SCROLL_HORIZONTALLY -> config.scrollHorizontally = value.toBoolean() + ENABLE_PULL_TO_REFRESH -> config.enablePullToRefresh = value.toBoolean() + MAX_BRIGHTNESS -> config.maxBrightness = value.toBoolean() + BLACK_BACKGROUND -> config.blackBackground = value.toBoolean() + HIDE_SYSTEM_UI -> config.hideSystemUI = value.toBoolean() + ALLOW_INSTANT_CHANGE -> config.allowInstantChange = value.toBoolean() + ALLOW_PHOTO_GESTURES -> config.allowPhotoGestures = value.toBoolean() + ALLOW_DOWN_GESTURE -> config.allowDownGesture = value.toBoolean() + SHOW_NOTCH -> config.showNotch = value.toBoolean() + SCREEN_ROTATION -> config.screenRotation = value.toInt() + ALLOW_ZOOMING_IMAGES -> config.allowZoomingImages = value.toBoolean() + SHOW_HIGHEST_QUALITY -> config.showHighestQuality = value.toBoolean() + ONE_FINGER_ZOOM -> config.oneFingerZoom = value.toBoolean() + ALLOW_ONE_TO_ONE_ZOOM -> config.allowOneToOneZoom = value.toBoolean() + SHOW_EXTENDED_DETAILS -> config.showExtendedDetails = value.toBoolean() + HIDE_EXTENDED_DETAILS -> config.hideExtendedDetails = value.toBoolean() + EXTENDED_DETAILS -> config.extendedDetails = value.toInt() + DELETE_EMPTY_FOLDERS -> config.deleteEmptyFolders = value.toBoolean() + KEEP_LAST_MODIFIED -> config.keepLastModified = value.toBoolean() + SKIP_DELETE_CONFIRMATION -> config.skipDeleteConfirmation = value.toBoolean() + BOTTOM_ACTIONS -> config.bottomActions = value.toBoolean() + VISIBLE_BOTTOM_ACTIONS -> config.visibleBottomActions = value.toInt() + USE_RECYCLE_BIN -> config.useRecycleBin = value.toBoolean() + SHOW_RECYCLE_BIN_AT_FOLDERS -> config.showRecycleBinAtFolders = value.toBoolean() + SHOW_RECYCLE_BIN_LAST -> config.showRecycleBinLast = value.toBoolean() + SORT_ORDER -> config.sorting = value.toInt() + DIRECTORY_SORT_ORDER -> config.directorySorting = value.toInt() + GROUP_BY -> config.groupBy = value.toInt() + GROUP_DIRECT_SUBFOLDERS -> config.groupDirectSubfolders = value.toBoolean() + PINNED_FOLDERS -> config.addPinnedFolders(value.toStringSet()) + DISPLAY_FILE_NAMES -> config.displayFileNames = value.toBoolean() + FILTER_MEDIA -> config.filterMedia = value.toInt() + DIR_COLUMN_CNT -> config.dirColumnCnt = value.toInt() + MEDIA_COLUMN_CNT -> config.mediaColumnCnt = value.toInt() + SHOW_ALL -> config.showAll = value.toBoolean() + SHOW_WIDGET_FOLDER_NAME -> config.showWidgetFolderName = value.toBoolean() + WIDGET_BG_COLOR -> config.widgetBgColor = value.toInt() + WIDGET_TEXT_COLOR -> config.widgetTextColor = value.toInt() + VIEW_TYPE_FILES -> config.viewTypeFiles = value.toInt() + VIEW_TYPE_FOLDERS -> config.viewTypeFolders = value.toInt() + SLIDESHOW_INTERVAL -> config.slideshowInterval = value.toInt() + SLIDESHOW_INCLUDE_VIDEOS -> config.slideshowIncludeVideos = value.toBoolean() + SLIDESHOW_INCLUDE_GIFS -> config.slideshowIncludeGIFs = value.toBoolean() + SLIDESHOW_RANDOM_ORDER -> config.slideshowRandomOrder = value.toBoolean() + SLIDESHOW_MOVE_BACKWARDS -> config.slideshowMoveBackwards = value.toBoolean() + SLIDESHOW_LOOP -> config.loopSlideshow = value.toBoolean() + LAST_EDITOR_CROP_ASPECT_RATIO -> config.lastEditorCropAspectRatio = value.toInt() + LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_X -> config.lastEditorCropOtherAspectRatioX = value.toInt() + LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_Y -> config.lastEditorCropOtherAspectRatioY = value.toInt() + LAST_EDITOR_DRAW_COLOR -> config.lastEditorDrawColor = value.toInt() + LAST_EDITOR_BRUSH_SIZE -> config.lastEditorBrushSize = value.toInt() + LAST_CONFLICT_RESOLUTION -> config.lastConflictResolution = value.toInt() + LAST_CONFLICT_APPLY_TO_ALL -> config.lastConflictApplyToAll = value.toBoolean() + } + } + + toast(if (configValues.size > 0) R.string.settings_imported_successfully else R.string.no_entries_for_importing) + runOnUiThread { + setupSettingItems() + } + } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SimpleActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SimpleActivity.kt index 603355ac0..8d0017ff8 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SimpleActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SimpleActivity.kt @@ -1,7 +1,11 @@ package com.simplemobiletools.gallery.pro.activities +import android.annotation.SuppressLint +import android.view.WindowManager import com.simplemobiletools.commons.activities.BaseSimpleActivity +import com.simplemobiletools.commons.helpers.isPiePlus import com.simplemobiletools.gallery.pro.R +import com.simplemobiletools.gallery.pro.extensions.config open class SimpleActivity : BaseSimpleActivity() { override fun getAppIconIDs() = arrayListOf( @@ -27,4 +31,19 @@ open class SimpleActivity : BaseSimpleActivity() { ) override fun getAppLauncherName() = getString(R.string.app_launcher_name) + + @SuppressLint("InlinedApi") + protected fun checkNotchSupport() { + if (isPiePlus()) { + val cutoutMode = when { + config.showNotch -> WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES + else -> WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER + } + + window.attributes.layoutInDisplayCutoutMode = cutoutMode + if (config.showNotch) { + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) + } + } + } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SplashActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SplashActivity.kt index 20c9c9387..611cfe083 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SplashActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SplashActivity.kt @@ -4,6 +4,8 @@ import android.content.Intent import com.simplemobiletools.commons.activities.BaseSplashActivity class SplashActivity : BaseSplashActivity() { + override fun getAppPackageName() = "-1" + override fun initActivity() { startActivity(Intent(this, MainActivity::class.java)) finish() diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/VideoPlayerActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/VideoPlayerActivity.kt index 4c0f3614e..7fc2138c1 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/VideoPlayerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/VideoPlayerActivity.kt @@ -5,7 +5,6 @@ import android.content.Intent import android.content.pm.ActivityInfo import android.content.res.Configuration import android.graphics.Color -import android.graphics.Matrix import android.graphics.Point import android.graphics.SurfaceTexture import android.graphics.drawable.ColorDrawable @@ -26,7 +25,6 @@ import com.google.android.exoplayer2.upstream.DataSpec import com.google.android.exoplayer2.video.VideoListener import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE -import com.simplemobiletools.commons.helpers.isPiePlus import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.extensions.* import com.simplemobiletools.gallery.pro.helpers.* @@ -44,27 +42,18 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen private var mScreenWidth = 0 private var mCurrTime = 0 private var mDuration = 0 - private var mSaveScale = 1f - private var mRight = 0f - private var mBottom = 0f - private var mLastTouchX = 0f - private var mLastTouchY = 0f private var mDragThreshold = 0f private var mTouchDownX = 0f private var mTouchDownY = 0f private var mTouchDownTime = 0L private var mProgressAtDown = 0L private var mCloseDownThreshold = 100f - private var mCurrZoomMode = ZOOM_MODE_NONE private var mUri: Uri? = null private var mExoPlayer: SimpleExoPlayer? = null private var mVideoSize = Point(0, 0) private var mTimerHandler = Handler() private var mPlayWhenReadyHandler = Handler() - private var mScaleDetector: ScaleGestureDetector? = null - private var mMatrices = FloatArray(9) - private val mMatrix = Matrix() private var mIgnoreCloseDown = false @@ -72,6 +61,7 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen super.onCreate(savedInstanceState) setContentView(R.layout.activity_video_player) setupOrientation() + checkNotchSupport() handlePermission(PERMISSION_WRITE_STORAGE) { if (it) { @@ -159,11 +149,6 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen supportActionBar?.title = getFilenameFromUri(mUri!!) initTimeHolder() - if (isPiePlus()) { - window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES - window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) - } - showSystemUI(true) window.decorView.setOnSystemUiVisibilityChangeListener { visibility -> val isFullscreen = visibility and View.SYSTEM_UI_FLAG_FULLSCREEN != 0 @@ -173,6 +158,7 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen video_curr_time.setOnClickListener { skip(false) } video_duration.setOnClickListener { skip(true) } video_toggle_play_pause.setOnClickListener { togglePlayPause() } + video_surface_frame.setOnClickListener { toggleFullscreen() } video_next_file.beVisibleIf(intent.getBooleanExtra(SHOW_NEXT_ITEM, false)) video_next_file.setOnClickListener { handleNextFile() } @@ -180,14 +166,9 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen video_prev_file.beVisibleIf(intent.getBooleanExtra(SHOW_PREV_ITEM, false)) video_prev_file.setOnClickListener { handlePrevFile() } - video_player_holder.setOnTouchListener { view, event -> + video_surface_frame.setOnTouchListener { view, event -> handleEvent(event) - true - } - - video_surface.setOnTouchListener { view, event -> - handleEventWithZooming(event) - true + false } initExoPlayer() @@ -213,7 +194,6 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen } mDragThreshold = DRAG_THRESHOLD * resources.displayMetrics.density - mScaleDetector = ScaleGestureDetector(applicationContext, ScaleListener()) } private fun initExoPlayer() { @@ -515,7 +495,7 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen val diffX = event.x - mTouchDownX val diffY = event.y - mTouchDownY - if (mIsDragged || (Math.abs(diffX) > mDragThreshold && Math.abs(diffX) > Math.abs(diffY))) { + if (mIsDragged || (Math.abs(diffX) > mDragThreshold && Math.abs(diffX) > Math.abs(diffY)) && video_surface_frame.controller.state.zoom == 1f) { if (!mIsDragged) { arrayOf(video_curr_time, video_seekbar, video_duration).forEach { it.animate().alpha(1f).start() @@ -539,7 +519,9 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen val diffY = mTouchDownY - event.y val downGestureDuration = System.currentTimeMillis() - mTouchDownTime - if (config.allowDownGesture && !mIgnoreCloseDown && Math.abs(diffY) > Math.abs(diffX) && diffY < -mCloseDownThreshold && downGestureDuration < MAX_CLOSE_DOWN_GESTURE_DURATION) { + if (config.allowDownGesture && !mIgnoreCloseDown && Math.abs(diffY) > Math.abs(diffX) && diffY < -mCloseDownThreshold && + downGestureDuration < MAX_CLOSE_DOWN_GESTURE_DURATION && + video_surface_frame.controller.state.zoom == 1f) { supportFinishAfterTransition() } @@ -554,10 +536,6 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen if (!mIsPlaying) { togglePlayPause() } - } else { - if (Math.abs(diffX) < CLICK_MAX_DISTANCE && Math.abs(diffY) < CLICK_MAX_DISTANCE && System.currentTimeMillis() - mTouchDownTime < CLICK_MAX_DURATION) { - toggleFullscreen() - } } mIsDragged = false } @@ -632,150 +610,4 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen } override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) {} - - private fun handleEventWithZooming(event: MotionEvent) { - mScaleDetector?.onTouchEvent(event) - - mMatrix.getValues(mMatrices) - val x = mMatrices[Matrix.MTRANS_X] - val y = mMatrices[Matrix.MTRANS_Y] - - when (event.actionMasked) { - MotionEvent.ACTION_DOWN -> { - mTouchDownTime = System.currentTimeMillis() - mCurrZoomMode = ZOOM_MODE_DRAG - mLastTouchX = event.x - mLastTouchY = event.y - - mTouchDownX = event.x - mTouchDownY = event.y - mProgressAtDown = mExoPlayer!!.currentPosition - } - MotionEvent.ACTION_UP -> { - mCurrZoomMode = ZOOM_MODE_NONE - val diffX = mTouchDownX - event.x - val diffY = mTouchDownY - event.y - - val downGestureDuration = System.currentTimeMillis() - mTouchDownTime - if (!mIgnoreCloseDown && Math.abs(diffY) > Math.abs(diffX) && diffY < -mCloseDownThreshold && downGestureDuration < MAX_CLOSE_DOWN_GESTURE_DURATION && mSaveScale == 1f) { - supportFinishAfterTransition() - } - mIgnoreCloseDown = false - - if (mIsDragged) { - if (mIsFullscreen) { - arrayOf(video_curr_time, video_seekbar, video_duration).forEach { - it.animate().alpha(0f).start() - } - } - - if (!mIsPlaying) { - togglePlayPause() - } - } else { - if (Math.abs(diffX) < CLICK_MAX_DISTANCE && Math.abs(diffY) < CLICK_MAX_DISTANCE && System.currentTimeMillis() - mTouchDownTime < CLICK_MAX_DURATION) { - toggleFullscreen() - } - } - - mIsDragged = false - } - MotionEvent.ACTION_POINTER_DOWN -> { - mLastTouchX = event.x - mLastTouchY = event.y - mCurrZoomMode = ZOOM_MODE_ZOOM - mIgnoreCloseDown = true - } - MotionEvent.ACTION_MOVE -> { - val diffX = event.x - mTouchDownX - val diffY = event.y - mTouchDownY - if (mSaveScale == 1f && (mIsDragged || (Math.abs(diffX) > mDragThreshold && Math.abs(diffX) > Math.abs(diffY)))) { - if (!mIsDragged) { - arrayOf(video_curr_time, video_seekbar, video_duration).forEach { - it.animate().alpha(1f).start() - } - } - mIgnoreCloseDown = true - mIsDragged = true - var percent = ((diffX / mScreenWidth) * 100).toInt() - percent = Math.min(100, Math.max(-100, percent)) - - val skipLength = (mDuration * 1000f) * (percent / 100f) - var newProgress = mProgressAtDown + skipLength - newProgress = Math.max(Math.min(mExoPlayer!!.duration.toFloat(), newProgress), 0f) - val newSeconds = (newProgress / 1000).toInt() - setPosition(newSeconds) - resetPlayWhenReady() - } else if (mCurrZoomMode == ZOOM_MODE_ZOOM || mCurrZoomMode == ZOOM_MODE_DRAG && mSaveScale > MIN_VIDEO_ZOOM_SCALE) { - var deltaX = event.x - mLastTouchX - var deltaY = event.y - mLastTouchY - if (y + deltaY > 0) { - deltaY = -y - } else if (y + deltaY < -mBottom) { - deltaY = -(y + mBottom) - } - - if (x + deltaX > 0) { - deltaX = -x - } else if (x + deltaX < -mRight) { - deltaX = -(x + mRight) - } - - mMatrix.postTranslate(deltaX, deltaY) - mLastTouchX = event.x - mLastTouchY = event.y - } - } - MotionEvent.ACTION_POINTER_UP -> { - mCurrZoomMode = ZOOM_MODE_NONE - } - } - - video_surface.setTransform(mMatrix) - video_surface.invalidate() - } - - // taken from https://github.com/Manuiq/ZoomableTextureView - private inner class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener() { - override fun onScaleBegin(detector: ScaleGestureDetector): Boolean { - mCurrZoomMode = ZOOM_MODE_ZOOM - return true - } - - override fun onScale(detector: ScaleGestureDetector): Boolean { - val width = video_surface.width - val height = video_surface.height - if (width <= 0 || height <= 0) { - return true - } - - var scaleFactor = detector.scaleFactor - val origScale = mSaveScale - mSaveScale *= scaleFactor - - if (mSaveScale > MAX_VIDEO_ZOOM_SCALE) { - mSaveScale = MAX_VIDEO_ZOOM_SCALE - scaleFactor = MAX_VIDEO_ZOOM_SCALE / origScale - } else if (mSaveScale < MIN_VIDEO_ZOOM_SCALE) { - mSaveScale = MIN_VIDEO_ZOOM_SCALE - scaleFactor = MIN_VIDEO_ZOOM_SCALE / origScale - } - - mRight = width * mSaveScale - width - mBottom = height * mSaveScale - height - mMatrix.postScale(scaleFactor, scaleFactor, detector.focusX, detector.focusY) - if (scaleFactor < 1) { - mMatrix.getValues(mMatrices) - val y = mMatrices[Matrix.MTRANS_Y] - if (scaleFactor < 1) { - if (y < -mBottom) { - mMatrix.postTranslate(0f, -(y + mBottom)) - } else if (y > 0) { - mMatrix.postTranslate(0f, -y) - } - } - } - return true - } - } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt index 2100ea9ec..681bca548 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt @@ -2,7 +2,6 @@ package com.simplemobiletools.gallery.pro.activities import android.animation.Animator import android.animation.ValueAnimator -import android.annotation.TargetApi import android.app.Activity import android.content.Intent import android.content.pm.ActivityInfo @@ -12,7 +11,6 @@ import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.media.ExifInterface import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.Handler import android.provider.MediaStore @@ -70,17 +68,12 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View private var mMediaFiles = ArrayList() private var mFavoritePaths = ArrayList() - @TargetApi(Build.VERSION_CODES.P) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_medium) top_shadow.layoutParams.height = statusBarHeight + actionBarHeight - if (isPiePlus()) { - window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES - window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) - } - + checkNotchSupport() (MediaActivity.mMedia.clone() as ArrayList).filter { it is Medium }.mapTo(mMediaFiles) { it as Medium } handlePermission(PERMISSION_WRITE_STORAGE) { @@ -149,6 +142,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View currentMedium.isFavorite = mFavoritePaths.contains(currentMedium.path) val visibleBottomActions = if (config.bottomActions) config.visibleBottomActions else 0 + getCurrentPhotoFragment()?.mCurrentRotationDegrees = mRotationDegrees menu.apply { findItem(R.id.menu_show_on_map).isVisible = visibleBottomActions and BOTTOM_ACTION_SHOW_ON_MAP == 0 findItem(R.id.menu_slideshow).isVisible = visibleBottomActions and BOTTOM_ACTION_SLIDESHOW == 0 @@ -558,10 +552,19 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } private fun rotateImage(degrees: Int) { - mRotationDegrees = (mRotationDegrees + degrees) % 360 - getCurrentFragment()?.let { - (it as? PhotoFragment)?.rotateImageViewBy(mRotationDegrees) + val currentPath = getCurrentPath() + if (needsStupidWritePermissions(currentPath)) { + handleSAFDialog(currentPath) { + rotateBy(degrees) + } + } else { + rotateBy(degrees) } + } + + private fun rotateBy(degrees: Int) { + mRotationDegrees = (mRotationDegrees + degrees) % 360 + getCurrentPhotoFragment()?.rotateImageViewBy(mRotationDegrees) supportInvalidateOptionsMenu() } @@ -589,9 +592,10 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View handleSAFDialog(it) { toast(R.string.saving) Thread { - saveRotatedImageToFile(currPath, it, mRotationDegrees) { + saveRotatedImageToFile(currPath, it, mRotationDegrees, true) { toast(R.string.file_saved) mRotationDegrees = 0 + getCurrentPhotoFragment()?.mCurrentRotationDegrees = 0 invalidateOptionsMenu() } }.start() @@ -599,6 +603,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } } + private fun getCurrentPhotoFragment() = getCurrentFragment() as? PhotoFragment + private fun isShowHiddenFlagNeeded(): Boolean { val file = File(mPath) if (file.isHidden) { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt index ef0f82aea..f92a5d01b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt @@ -43,6 +43,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList() + private var rotatedImagePaths = ArrayList() private var loadImageInstantly = false private var delayHandler = Handler(Looper.getMainLooper()) private var currentMediaHash = media.hashCode() @@ -278,10 +279,12 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList(selectedKeys.size) val removeMedia = ArrayList(selectedKeys.size) - val position = getSelectedItemPositions() + val positions = getSelectedItemPositions() getSelectedItems().forEach { fileDirItems.add(FileDirItem(it.path, it.name)) @@ -384,7 +387,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList, callback: (() -> Unit)? = nu } } -fun BaseSimpleActivity.saveRotatedImageToFile(oldPath: String, newPath: String, degrees: Int, callback: () -> Unit) { +fun BaseSimpleActivity.saveRotatedImageToFile(oldPath: String, newPath: String, degrees: Int, showToasts: Boolean, callback: () -> Unit) { if (oldPath == newPath && oldPath.isJpg()) { - if (tryRotateByExif(oldPath, degrees, callback)) { + if (tryRotateByExif(oldPath, degrees, showToasts, callback)) { return } } @@ -385,7 +385,9 @@ fun BaseSimpleActivity.saveRotatedImageToFile(oldPath: String, newPath: String, try { getFileOutputStream(tmpFileDirItem) { if (it == null) { - toast(R.string.unknown_error_occurred) + if (showToasts) { + toast(R.string.unknown_error_occurred) + } return@getFileOutputStream } @@ -412,29 +414,37 @@ fun BaseSimpleActivity.saveRotatedImageToFile(oldPath: String, newPath: String, callback.invoke() } } catch (e: OutOfMemoryError) { - toast(R.string.out_of_memory_error) + if (showToasts) { + toast(R.string.out_of_memory_error) + } } catch (e: Exception) { - showErrorToast(e) + if (showToasts) { + showErrorToast(e) + } } finally { tryDeleteFileDirItem(tmpFileDirItem, false, true) } } @TargetApi(Build.VERSION_CODES.N) -fun Activity.tryRotateByExif(path: String, degrees: Int, callback: () -> Unit): Boolean { +fun Activity.tryRotateByExif(path: String, degrees: Int, showToasts: Boolean, callback: () -> Unit): Boolean { return try { val file = File(path) val oldLastModified = file.lastModified() if (saveImageRotation(path, degrees)) { fileRotatedSuccessfully(path, oldLastModified) callback.invoke() - toast(R.string.file_saved) + if (showToasts) { + toast(R.string.file_saved) + } true } else { false } } catch (e: Exception) { - showErrorToast(e) + if (showToasts) { + showErrorToast(e) + } false } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt index 3f6b336de..9e2ce8af0 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt @@ -387,13 +387,14 @@ fun Context.getFolderNameFromPath(path: String): String { } } -fun Context.loadImage(type: Int, path: String, target: MySquareImageView, horizontalScroll: Boolean, animateGifs: Boolean, cropThumbnails: Boolean) { +fun Context.loadImage(type: Int, path: String, target: MySquareImageView, horizontalScroll: Boolean, animateGifs: Boolean, cropThumbnails: Boolean, + skipMemoryCacheAtPaths: ArrayList? = null) { target.isHorizontalScrolling = horizontalScroll if (type == TYPE_IMAGES || type == TYPE_VIDEOS || type == TYPE_RAWS) { if (type == TYPE_IMAGES && path.isPng()) { - loadPng(path, target, cropThumbnails) + loadPng(path, target, cropThumbnails, skipMemoryCacheAtPaths) } else { - loadJpg(path, target, cropThumbnails) + loadJpg(path, target, cropThumbnails, skipMemoryCacheAtPaths) } } else if (type == TYPE_GIFS) { try { @@ -407,9 +408,9 @@ fun Context.loadImage(type: Int, path: String, target: MySquareImageView, horizo target.scaleType = if (cropThumbnails) ImageView.ScaleType.CENTER_CROP else ImageView.ScaleType.FIT_CENTER } catch (e: Exception) { - loadJpg(path, target, cropThumbnails) + loadJpg(path, target, cropThumbnails, skipMemoryCacheAtPaths) } catch (e: OutOfMemoryError) { - loadJpg(path, target, cropThumbnails) + loadJpg(path, target, cropThumbnails, skipMemoryCacheAtPaths) } } else if (type == TYPE_SVGS) { loadSVG(path, target, cropThumbnails) @@ -435,9 +436,10 @@ fun Context.getPathLocation(path: String): Int { } } -fun Context.loadPng(path: String, target: MySquareImageView, cropThumbnails: Boolean) { +fun Context.loadPng(path: String, target: MySquareImageView, cropThumbnails: Boolean, skipMemoryCacheAtPaths: ArrayList? = null) { val options = RequestOptions() .signature(path.getFileSignature()) + .skipMemoryCache(skipMemoryCacheAtPaths?.contains(path) == true) .diskCacheStrategy(DiskCacheStrategy.RESOURCE) .format(DecodeFormat.PREFER_ARGB_8888) @@ -449,9 +451,10 @@ fun Context.loadPng(path: String, target: MySquareImageView, cropThumbnails: Boo builder.apply(options).into(target) } -fun Context.loadJpg(path: String, target: MySquareImageView, cropThumbnails: Boolean) { +fun Context.loadJpg(path: String, target: MySquareImageView, cropThumbnails: Boolean, skipMemoryCacheAtPaths: ArrayList? = null) { val options = RequestOptions() .signature(path.getFileSignature()) + .skipMemoryCache(skipMemoryCacheAtPaths?.contains(path) == true) .diskCacheStrategy(DiskCacheStrategy.RESOURCE) val builder = Glide.with(applicationContext) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/String.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/String.kt index 3941ba0db..b426c5a61 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/String.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/String.kt @@ -21,9 +21,13 @@ fun String.shouldFolderBeVisible(excludedPaths: MutableSet, includedPath val file = File(this) return if (isEmpty()) { false + } else if (!showHidden && file.isHidden) { + false + } else if (includedPaths.contains(this)) { + true } else if (!showHidden && file.containsNoMedia()) { false - } else if (excludedPaths.contains(this) && !includedPaths.contains(this)) { + } else if (excludedPaths.contains(this)) { false } else if (isThisOrParentIncluded(includedPaths)) { true diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/PhotoFragment.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/PhotoFragment.kt index 49cdabda3..05c6b244d 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/PhotoFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/PhotoFragment.kt @@ -2,8 +2,12 @@ package com.simplemobiletools.gallery.pro.fragments import android.content.Intent import android.content.res.Configuration -import android.graphics.* +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.Color +import android.graphics.Matrix import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.Drawable import android.graphics.drawable.PictureDrawable import android.media.ExifInterface.* import android.net.Uri @@ -14,28 +18,28 @@ import android.util.DisplayMetrics import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import com.alexvasilkov.gestures.GestureController +import com.alexvasilkov.gestures.State import com.bumptech.glide.Glide +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.request.RequestListener import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.target.Target -import com.davemorrissey.labs.subscaleview.ImageSource +import com.davemorrissey.labs.subscaleview.DecoderFactory +import com.davemorrissey.labs.subscaleview.ImageDecoder +import com.davemorrissey.labs.subscaleview.ImageRegionDecoder import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView -import com.davemorrissey.labs.subscaleview.decoder.DecoderFactory -import com.davemorrissey.labs.subscaleview.decoder.ImageDecoder -import com.davemorrissey.labs.subscaleview.decoder.ImageRegionDecoder +import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.OTG_PATH import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.activities.PanoramaPhotoActivity import com.simplemobiletools.gallery.pro.activities.PhotoActivity import com.simplemobiletools.gallery.pro.extensions.* -import com.simplemobiletools.gallery.pro.helpers.MEDIUM -import com.simplemobiletools.gallery.pro.helpers.PATH -import com.simplemobiletools.gallery.pro.helpers.PicassoDecoder -import com.simplemobiletools.gallery.pro.helpers.PicassoRegionDecoder +import com.simplemobiletools.gallery.pro.helpers.* import com.simplemobiletools.gallery.pro.models.Medium import com.simplemobiletools.gallery.pro.svg.SvgSoftwareLayerSetter import com.squareup.picasso.Callback @@ -59,6 +63,7 @@ class PhotoFragment : ViewPagerFragment() { "google nexus 5x" ) + var mCurrentRotationDegrees = 0 private var mIsFragmentVisible = false private var mIsFullscreen = false private var mWasInit = false @@ -66,9 +71,10 @@ class PhotoFragment : ViewPagerFragment() { private var mIsSubsamplingVisible = false // checking view.visibility is unreliable, use an extra variable for it private var mImageOrientation = -1 private var mOriginalSubsamplingScale = 0f - private var mIoadZoomableViewHandler = Handler() + private var mLoadZoomableViewHandler = Handler() private var mScreenWidth = 0 private var mScreenHeight = 0 + private var mCurrentGestureViewZoom = 1f private var mStoredShowExtendedDetails = false private var mStoredHideExtendedDetails = false @@ -83,7 +89,7 @@ class PhotoFragment : ViewPagerFragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { mView = (inflater.inflate(R.layout.pager_photo_item, container, false) as ViewGroup).apply { subsampling_view.setOnClickListener { photoClicked() } - photo_view.setOnClickListener { photoClicked() } + gestures_view.setOnClickListener { photoClicked() } gif_view.setOnClickListener { photoClicked() } instant_prev_item.setOnClickListener { listener?.goToPrevItem() } instant_next_item.setOnClickListener { listener?.goToNextItem() } @@ -97,14 +103,34 @@ class PhotoFragment : ViewPagerFragment() { if (subsampling_view.isVisible()) { subsampling_view.sendFakeClick(x, y) } else { - photo_view.sendFakeClick(x, y) + gestures_view.sendFakeClick(x, y) } } } if (context.config.allowDownGesture) { + gif_view.setOnTouchListener { v, event -> + if (gif_view_frame.controller.state.zoom == 1f) { + handleEvent(event) + } + false + } + + gestures_view.controller.addOnStateChangeListener(object : GestureController.OnStateChangeListener { + override fun onStateChanged(state: State) { + mCurrentGestureViewZoom = state.zoom + } + }) + + gestures_view.setOnTouchListener { v, event -> + if (mCurrentGestureViewZoom == 1f) { + handleEvent(event) + } + false + } + subsampling_view.setOnTouchListener { v, event -> - if (mView.subsampling_view.scale == mOriginalSubsamplingScale) { + if (subsampling_view.scale == mOriginalSubsamplingScale) { handleEvent(event) } false @@ -190,7 +216,6 @@ class PhotoFragment : ViewPagerFragment() { photo_brightness_controller.beVisibleIf(allowPhotoGestures) instant_prev_item.beVisibleIf(allowInstantChange) instant_next_item.beVisibleIf(allowInstantChange) - photo_view.setAllowFingerDragZoom(config.oneFingerZoom) } storeStateVariables() @@ -201,7 +226,14 @@ class PhotoFragment : ViewPagerFragment() { if (activity?.isDestroyed == false) { mView.subsampling_view.recycle() } - mIoadZoomableViewHandler.removeCallbacksAndMessages(null) + + mLoadZoomableViewHandler.removeCallbacksAndMessages(null) + if (mCurrentRotationDegrees != 0) { + Thread { + val path = mMedium.path + (activity as? BaseSimpleActivity)?.saveRotatedImageToFile(path, path, mCurrentRotationDegrees, false) {} + }.start() + } } override fun onConfigurationChanged(newConfig: Configuration) { @@ -210,6 +242,7 @@ class PhotoFragment : ViewPagerFragment() { // avoid GIFs being skewed, played in wrong aspect ratio if (mMedium.isGIF()) { mView.onGlobalLayout { + measureScreen() Handler().postDelayed({ loadGif() }, 50) @@ -302,13 +335,10 @@ class PhotoFragment : ViewPagerFragment() { InputSource.FileSource(pathToLoad) } - mView.photo_view.beGone() - val resolution = mMedium.path.getImageResolution() ?: Point(0, 0) - mView.gif_view.apply { - setInputSource(source) - setupGIFView(resolution.x, resolution.y, mScreenWidth, mScreenHeight) { - activity?.supportFinishAfterTransition() - } + mView.apply { + gestures_view.beGone() + gif_view.setInputSource(source) + gif_view_frame.beVisible() } } catch (e: Exception) { loadBitmap() @@ -322,10 +352,42 @@ class PhotoFragment : ViewPagerFragment() { .`as`(PictureDrawable::class.java) .listener(SvgSoftwareLayerSetter()) .load(mMedium.path) - .into(mView.photo_view) + .into(mView.gestures_view) } - private fun loadBitmap(degrees: Int = 0) { + private fun loadBitmap(degrees: Int = mCurrentRotationDegrees) { + val options = RequestOptions() + .signature(mMedium.path.getFileSignature()) + .format(DecodeFormat.PREFER_ARGB_8888) + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .fitCenter() + + if (degrees != 0) { + options.transform(GlideRotateTransformation(degrees)) + options.diskCacheStrategy(DiskCacheStrategy.NONE) + } + + Glide.with(context!!) + .load(getPathToLoad(mMedium)) + .apply(options) + .listener(object : RequestListener { + override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { + if (activity != null) { + tryLoadingWithPicasso(degrees) + } + return false + } + + override fun onResourceReady(resource: Drawable?, model: Any?, target: Target?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { + if (mIsFragmentVisible && degrees == 0) { + scheduleZoomableView() + } + return false + } + }).into(mView.gestures_view) + } + + private fun tryLoadingWithPicasso(degrees: Int = 0) { var pathToLoad = if (mMedium.path.startsWith("content://")) mMedium.path else "file://${mMedium.path}" pathToLoad = pathToLoad.replace("%", "%25").replace("#", "%23") @@ -338,57 +400,24 @@ class PhotoFragment : ViewPagerFragment() { if (degrees != 0) { picasso.rotate(degrees.toFloat()) + } else { + degreesForRotation(mImageOrientation).toFloat() } - picasso.into(mView.photo_view, object : Callback { + picasso.into(mView.gestures_view, object : Callback { override fun onSuccess() { - mView.photo_view.isZoomable = degrees != 0 || context?.config?.allowZoomingImages == false + mView.gestures_view.controller.settings.isZoomEnabled = degrees != 0 || context?.config?.allowZoomingImages == false if (mIsFragmentVisible && degrees == 0) { scheduleZoomableView() } } - override fun onError(e: Exception) { - if (activity != null) { - tryLoadingWithGlide() - } - } + override fun onError(e: Exception) {} }) } catch (ignored: Exception) { } } - private fun tryLoadingWithGlide() { - var targetWidth = if (mScreenWidth == 0) com.bumptech.glide.request.target.Target.SIZE_ORIGINAL else mScreenWidth - var targetHeight = if (mScreenHeight == 0) com.bumptech.glide.request.target.Target.SIZE_ORIGINAL else mScreenHeight - - if (mImageOrientation == ORIENTATION_ROTATE_90) { - targetWidth = targetHeight - targetHeight = com.bumptech.glide.request.target.Target.SIZE_ORIGINAL - } - - val options = RequestOptions() - .signature(mMedium.path.getFileSignature()) - .format(DecodeFormat.PREFER_ARGB_8888) - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .override(targetWidth, targetHeight) - - Glide.with(context!!) - .asBitmap() - .load(getPathToLoad(mMedium)) - .apply(options) - .listener(object : RequestListener { - override fun onLoadFailed(e: GlideException?, model: Any?, target: com.bumptech.glide.request.target.Target?, isFirstResource: Boolean) = false - - override fun onResourceReady(resource: Bitmap?, model: Any?, target: Target?, dataSource: com.bumptech.glide.load.DataSource?, isFirstResource: Boolean): Boolean { - if (mIsFragmentVisible) { - scheduleZoomableView() - } - return false - } - }).into(mView.photo_view) - } - private fun openPanorama() { Intent(context, PanoramaPhotoActivity::class.java).apply { putExtra(PATH, mMedium.path) @@ -397,9 +426,9 @@ class PhotoFragment : ViewPagerFragment() { } private fun scheduleZoomableView() { - mIoadZoomableViewHandler.removeCallbacksAndMessages(null) - mIoadZoomableViewHandler.postDelayed({ - if (mIsFragmentVisible && context?.config?.allowZoomingImages == true && mMedium.isImage() && !mIsSubsamplingVisible) { + mLoadZoomableViewHandler.removeCallbacksAndMessages(null) + mLoadZoomableViewHandler.postDelayed({ + if (mIsFragmentVisible && context?.config?.allowZoomingImages == true && mMedium.isImage() && !mIsSubsamplingVisible && mCurrentRotationDegrees == 0) { addZoomableView() } }, ZOOMABLE_VIEW_LOAD_DELAY) @@ -423,17 +452,15 @@ class PhotoFragment : ViewPagerFragment() { setMaxTileSize(if (config.showHighestQuality) Integer.MAX_VALUE else 4096) setMinimumTileDpi(if (config.showHighestQuality) -1 else getMinTileDpi()) background = ColorDrawable(Color.TRANSPARENT) - setBitmapDecoderFactory(bitmapDecoder) - setRegionDecoderFactory(regionDecoder) + bitmapDecoderFactory = bitmapDecoder + regionDecoderFactory = regionDecoder maxScale = 10f beVisible() isQuickScaleEnabled = config.oneFingerZoom isOneToOneZoomEnabled = config.allowOneToOneZoom - setResetScaleOnSizeChange(false) - setImage(ImageSource.uri(path)) - setOrientation(rotation) - setEagerLoadingEnabled(false) - setOnImageEventListener(object : SubsamplingScaleImageView.OnImageEventListener { + orientation = rotation + setImage(path) + onImageEventListener = object : SubsamplingScaleImageView.OnImageEventListener { override fun onImageLoaded() { } @@ -441,29 +468,20 @@ class PhotoFragment : ViewPagerFragment() { background = ColorDrawable(if (config.blackBackground) Color.BLACK else config.backgroundColor) val useWidth = if (mImageOrientation == ORIENTATION_ROTATE_90 || mImageOrientation == ORIENTATION_ROTATE_270) sHeight else sWidth val useHeight = if (mImageOrientation == ORIENTATION_ROTATE_90 || mImageOrientation == ORIENTATION_ROTATE_270) sWidth else sHeight - setDoubleTapZoomScale(getDoubleTapZoomScale(useWidth, useHeight)) + doubleTapZoomScale = getDoubleTapZoomScale(useWidth, useHeight) mOriginalSubsamplingScale = scale } override fun onTileLoadError(e: Exception) { } - override fun onPreviewReleased() { - } - override fun onImageLoadError(e: Exception) { - mView.photo_view.isZoomable = true + mView.gestures_view.controller.settings.isZoomEnabled = true background = ColorDrawable(Color.TRANSPARENT) mIsSubsamplingVisible = false beGone() } - - override fun onPreviewLoadError(e: Exception) { - background = ColorDrawable(Color.TRANSPARENT) - mIsSubsamplingVisible = false - beGone() - } - }) + } } } @@ -535,7 +553,8 @@ class PhotoFragment : ViewPagerFragment() { } fun rotateImageViewBy(degrees: Int) { - mIoadZoomableViewHandler.removeCallbacksAndMessages(null) + mCurrentRotationDegrees = degrees + mLoadZoomableViewHandler.removeCallbacksAndMessages(null) mView.subsampling_view.beGone() mIsSubsamplingVisible = false loadBitmap(degrees) @@ -567,7 +586,7 @@ class PhotoFragment : ViewPagerFragment() { mIsSubsamplingVisible = false mView.subsampling_view.recycle() mView.subsampling_view.beGone() - mIoadZoomableViewHandler.removeCallbacksAndMessages(null) + mLoadZoomableViewHandler.removeCallbacksAndMessages(null) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt index beebb1604..0b0258d9a 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt @@ -2,7 +2,6 @@ package com.simplemobiletools.gallery.pro.fragments import android.content.Intent import android.content.res.Configuration -import android.graphics.Matrix import android.graphics.Point import android.graphics.SurfaceTexture import android.net.Uri @@ -29,7 +28,10 @@ import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.activities.PanoramaVideoActivity import com.simplemobiletools.gallery.pro.activities.VideoActivity import com.simplemobiletools.gallery.pro.extensions.* -import com.simplemobiletools.gallery.pro.helpers.* +import com.simplemobiletools.gallery.pro.helpers.Config +import com.simplemobiletools.gallery.pro.helpers.MEDIUM +import com.simplemobiletools.gallery.pro.helpers.MIN_SKIP_LENGTH +import com.simplemobiletools.gallery.pro.helpers.PATH import com.simplemobiletools.gallery.pro.models.Medium import com.simplemobiletools.gallery.pro.views.MediaSideScroll import kotlinx.android.synthetic.main.bottom_video_time_holder.view.* @@ -49,19 +51,10 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S private var mWasVideoStarted = false private var mCurrTime = 0 private var mDuration = 0 - private var mSaveScale = 1f - private var mRight = 0f - private var mBottom = 0f - private var mLastTouchX = 0f - private var mLastTouchY = 0f - private var mCurrZoomMode = ZOOM_MODE_NONE private var mExoPlayer: SimpleExoPlayer? = null private var mVideoSize = Point(0, 0) private var mTimerHandler = Handler() - private var mScaleDetector: ScaleGestureDetector? = null - private var mMatrices = FloatArray(9) - private val mMatrix = Matrix() private var mStoredShowExtendedDetails = false private var mStoredHideExtendedDetails = false @@ -84,7 +77,6 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { mConfig = context!!.config - mScaleDetector = ScaleGestureDetector(context, ScaleListener()) mView = inflater.inflate(R.layout.pager_video_item, container, false).apply { instant_prev_item.setOnClickListener { listener?.goToPrevItem() } instant_next_item.setOnClickListener { listener?.goToNextItem() } @@ -123,9 +115,11 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S false } - video_surface.setOnTouchListener { view, event -> - handleEventWithZooming(event) - true + video_surface_frame.setOnTouchListener { view, event -> + if (video_surface_frame.controller.state.zoom == 1f) { + handleEvent(event) + } + false } } } @@ -204,6 +198,8 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S val allowInstantChange = mConfig.allowInstantChange mTextureView.beGoneIf(mConfig.openVideosOnSeparateScreen || mIsPanorama) mView.apply { + video_surface_frame.beGoneIf(mTextureView.isGone()) + video_volume_controller.beVisibleIf(allowVideoGestures && !mIsPanorama) video_brightness_controller.beVisibleIf(allowVideoGestures && !mIsPanorama) @@ -275,7 +271,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S return } - mTextureView.setOnClickListener { toggleFullscreen() } + mView.video_surface_frame.setOnClickListener { toggleFullscreen() } mTextureView.surfaceTextureListener = this checkExtendedDetails() @@ -348,8 +344,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S override fun onTracksChanged(trackGroups: TrackGroupArray?, trackSelections: TrackSelectionArray?) {} - override fun onPlayerError(error: ExoPlaybackException?) { - } + override fun onPlayerError(error: ExoPlaybackException?) {} override fun onLoadingChanged(isLoading: Boolean) {} @@ -708,116 +703,4 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S mTextureView.layoutParams = this } } - - private fun handleEventWithZooming(event: MotionEvent) { - mScaleDetector?.onTouchEvent(event) - - mMatrix.getValues(mMatrices) - val x = mMatrices[Matrix.MTRANS_X] - val y = mMatrices[Matrix.MTRANS_Y] - - when (event.actionMasked) { - MotionEvent.ACTION_DOWN -> { - mTouchDownTime = System.currentTimeMillis() - mCurrZoomMode = ZOOM_MODE_DRAG - mLastTouchX = event.x - mLastTouchY = event.y - - mTouchDownX = event.x - mTouchDownY = event.y - } - MotionEvent.ACTION_UP -> { - mCurrZoomMode = ZOOM_MODE_NONE - val diffX = mTouchDownX - event.x - val diffY = mTouchDownY - event.y - - if (Math.abs(diffX) < CLICK_MAX_DISTANCE && Math.abs(diffY) < CLICK_MAX_DISTANCE && System.currentTimeMillis() - mTouchDownTime < CLICK_MAX_DURATION) { - mTextureView.performClick() - } else { - val downGestureDuration = System.currentTimeMillis() - mTouchDownTime - if (!mIgnoreCloseDown && Math.abs(diffY) > Math.abs(diffX) && diffY < -mCloseDownThreshold && downGestureDuration < MAX_CLOSE_DOWN_GESTURE_DURATION && mSaveScale == 1f) { - activity?.supportFinishAfterTransition() - } - } - mIgnoreCloseDown = false - } - MotionEvent.ACTION_POINTER_DOWN -> { - mLastTouchX = event.x - mLastTouchY = event.y - mCurrZoomMode = ZOOM_MODE_ZOOM - mIgnoreCloseDown = true - } - MotionEvent.ACTION_MOVE -> { - if (mCurrZoomMode == ZOOM_MODE_ZOOM || mCurrZoomMode == ZOOM_MODE_DRAG && mSaveScale > MIN_VIDEO_ZOOM_SCALE) { - var diffX = event.x - mLastTouchX - var diffY = event.y - mLastTouchY - if (y + diffY > 0) { - diffY = -y - } else if (y + diffY < -mBottom) { - diffY = -(y + mBottom) - } - - if (x + diffX > 0) { - diffX = -x - } else if (x + diffX < -mRight) { - diffX = -(x + mRight) - } - - mMatrix.postTranslate(diffX, diffY) - mLastTouchX = event.x - mLastTouchY = event.y - } - } - MotionEvent.ACTION_POINTER_UP -> { - mCurrZoomMode = ZOOM_MODE_NONE - } - } - - mTextureView.setTransform(mMatrix) - mTextureView.invalidate() - } - - // taken from https://github.com/Manuiq/ZoomableTextureView - private inner class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener() { - override fun onScaleBegin(detector: ScaleGestureDetector): Boolean { - mCurrZoomMode = ZOOM_MODE_ZOOM - return true - } - - override fun onScale(detector: ScaleGestureDetector): Boolean { - val width = mTextureView.width - val height = mTextureView.height - if (width <= 0 || height <= 0) { - return true - } - - var scaleFactor = detector.scaleFactor - val origScale = mSaveScale - mSaveScale *= scaleFactor - - if (mSaveScale > MAX_VIDEO_ZOOM_SCALE) { - mSaveScale = MAX_VIDEO_ZOOM_SCALE - scaleFactor = MAX_VIDEO_ZOOM_SCALE / origScale - } else if (mSaveScale < MIN_VIDEO_ZOOM_SCALE) { - mSaveScale = MIN_VIDEO_ZOOM_SCALE - scaleFactor = MIN_VIDEO_ZOOM_SCALE / origScale - } - - mRight = width * mSaveScale - width - mBottom = height * mSaveScale - height - mMatrix.postScale(scaleFactor, scaleFactor, detector.focusX, detector.focusY) - if (scaleFactor < 1) { - mMatrix.getValues(mMatrices) - val y = mMatrices[Matrix.MTRANS_Y] - if (scaleFactor < 1) { - if (y < -mBottom) { - mMatrix.postTranslate(0f, -(y + mBottom)) - } else if (y > 0) { - mMatrix.postTranslate(0f, -y) - } - } - } - return true - } - } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/ViewPagerFragment.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/ViewPagerFragment.kt index bee1b525b..2cb3cf893 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/ViewPagerFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/ViewPagerFragment.kt @@ -104,7 +104,7 @@ abstract class ViewPagerFragment : Fragment() { mTouchDownY = event.y } MotionEvent.ACTION_POINTER_DOWN -> mIgnoreCloseDown = true - MotionEvent.ACTION_UP -> { + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { val diffX = mTouchDownX - event.x val diffY = mTouchDownY - event.y diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Config.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Config.kt index 29368ae2d..f7d14e261 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Config.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Config.kt @@ -104,7 +104,7 @@ class Config(context: Context) : BaseConfig(context) { fun addPinnedFolders(paths: Set) { val currPinnedFolders = HashSet(pinnedFolders) currPinnedFolders.addAll(paths) - pinnedFolders = currPinnedFolders + pinnedFolders = currPinnedFolders.filter { it.isNotEmpty() }.toHashSet() if (paths.contains(RECYCLE_BIN)) { showRecycleBinLast = false } @@ -123,7 +123,7 @@ class Config(context: Context) : BaseConfig(context) { fun addExcludedFolders(paths: Set) { val currExcludedFolders = HashSet(excludedFolders) currExcludedFolders.addAll(paths) - excludedFolders = currExcludedFolders + excludedFolders = currExcludedFolders.filter { it.isNotEmpty() }.toHashSet() } fun removeExcludedFolder(path: String) { @@ -142,6 +142,12 @@ class Config(context: Context) : BaseConfig(context) { includedFolders = currIncludedFolders } + fun addIncludedFolders(paths: Set) { + val currIncludedFolders = HashSet(includedFolders) + currIncludedFolders.addAll(paths) + includedFolders = currIncludedFolders.filter { it.isNotEmpty() }.toHashSet() + } + fun removeIncludedFolder(path: String) { val currIncludedFolders = HashSet(includedFolders) currIncludedFolders.remove(path) @@ -154,7 +160,7 @@ class Config(context: Context) : BaseConfig(context) { var autoplayVideos: Boolean get() = prefs.getBoolean(AUTOPLAY_VIDEOS, false) - set(autoplay) = prefs.edit().putBoolean(AUTOPLAY_VIDEOS, autoplay).apply() + set(autoplayVideos) = prefs.edit().putBoolean(AUTOPLAY_VIDEOS, autoplayVideos).apply() var animateGifs: Boolean get() = prefs.getBoolean(ANIMATE_GIFS, false) @@ -189,8 +195,8 @@ class Config(context: Context) : BaseConfig(context) { set(display) = prefs.edit().putBoolean(DISPLAY_FILE_NAMES, display).apply() var blackBackground: Boolean - get() = prefs.getBoolean(DARK_BACKGROUND, false) - set(darkBackground) = prefs.edit().putBoolean(DARK_BACKGROUND, darkBackground).apply() + get() = prefs.getBoolean(BLACK_BACKGROUND, false) + set(blackBackground) = prefs.edit().putBoolean(BLACK_BACKGROUND, blackBackground).apply() var filterMedia: Int get() = prefs.getInt(FILTER_MEDIA, TYPE_IMAGES or TYPE_VIDEOS or TYPE_GIFS or TYPE_RAWS or TYPE_SVGS) @@ -398,7 +404,7 @@ class Config(context: Context) : BaseConfig(context) { get() = prefs.getStringSet(EVER_SHOWN_FOLDERS, getEverShownFolders()) set(everShownFolders) = prefs.edit().putStringSet(EVER_SHOWN_FOLDERS, everShownFolders).apply() - fun getEverShownFolders() = hashSetOf( + private fun getEverShownFolders() = hashSetOf( internalStoragePath, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).absolutePath, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath, @@ -461,4 +467,8 @@ class Config(context: Context) : BaseConfig(context) { var lastEditorBrushSize: Int get() = prefs.getInt(LAST_EDITOR_BRUSH_SIZE, 50) set(lastEditorBrushSize) = prefs.edit().putInt(LAST_EDITOR_BRUSH_SIZE, lastEditorBrushSize).apply() + + var showNotch: Boolean + get() = prefs.getBoolean(SHOW_NOTCH, true) + set(showNotch) = prefs.edit().putBoolean(SHOW_NOTCH, showNotch).apply() } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Constants.kt index e775ba452..706a3bb93 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Constants.kt @@ -20,7 +20,7 @@ const val CROP_THUMBNAILS = "crop_thumbnails" const val SHOW_THUMBNAIL_VIDEO_DURATION = "show_thumbnail_video_duration" const val SCREEN_ROTATION = "screen_rotation" const val DISPLAY_FILE_NAMES = "display_file_names" -const val DARK_BACKGROUND = "dark_background" +const val BLACK_BACKGROUND = "dark_background" const val PINNED_FOLDERS = "pinned_folders" const val FILTER_MEDIA = "filter_media" const val DIR_COLUMN_CNT = "dir_column_cnt" @@ -78,6 +78,7 @@ const val SHOW_WIDGET_FOLDER_NAME = "show_widget_folder_name" const val ALLOW_ONE_TO_ONE_ZOOM = "allow_one_to_one_zoom" const val LAST_EDITOR_DRAW_COLOR = "last_editor_draw_color" const val LAST_EDITOR_BRUSH_SIZE = "last_editor_brush_size" +const val SHOW_NOTCH = "show_notch" // slideshow const val SLIDESHOW_INTERVAL = "slideshow_interval" @@ -104,7 +105,7 @@ const val MAX_COLUMN_COUNT = 20 const val SHOW_TEMP_HIDDEN_DURATION = 300000L const val CLICK_MAX_DURATION = 150 const val CLICK_MAX_DISTANCE = 100 -const val MAX_CLOSE_DOWN_GESTURE_DURATION = 400 +const val MAX_CLOSE_DOWN_GESTURE_DURATION = 300 const val DRAG_THRESHOLD = 8 const val MONTH_MILLISECONDS = MONTH_SECONDS * 1000L const val MIN_SKIP_LENGTH = 2000 diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/GlideRotateTransformation.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/GlideRotateTransformation.kt index 619694642..a0dabc09d 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/GlideRotateTransformation.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/GlideRotateTransformation.kt @@ -8,8 +8,9 @@ import java.security.MessageDigest class GlideRotateTransformation(val rotateRotationAngle: Int) : BitmapTransformation() { override fun transform(pool: BitmapPool, bitmap: Bitmap, outWidth: Int, outHeight: Int): Bitmap { - if (rotateRotationAngle % 360 == 0) + if (rotateRotationAngle % 360 == 0) { return bitmap + } val matrix = Matrix() matrix.postRotate(rotateRotationAngle.toFloat()) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/PicassoDecoder.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/PicassoDecoder.kt index 1ff60708d..978106763 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/PicassoDecoder.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/PicassoDecoder.kt @@ -3,7 +3,7 @@ package com.simplemobiletools.gallery.pro.helpers import android.content.Context import android.graphics.Bitmap import android.net.Uri -import com.davemorrissey.labs.subscaleview.decoder.ImageDecoder +import com.davemorrissey.labs.subscaleview.ImageDecoder import com.squareup.picasso.MemoryPolicy import com.squareup.picasso.Picasso diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/PicassoRegionDecoder.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/PicassoRegionDecoder.kt index d0f8a7f41..85b0e1133 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/PicassoRegionDecoder.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/PicassoRegionDecoder.kt @@ -3,7 +3,7 @@ package com.simplemobiletools.gallery.pro.helpers import android.content.Context import android.graphics.* import android.net.Uri -import com.davemorrissey.labs.subscaleview.decoder.ImageRegionDecoder +import com.davemorrissey.labs.subscaleview.ImageRegionDecoder class PicassoRegionDecoder : ImageRegionDecoder { private var decoder: BitmapRegionDecoder? = null diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/MyZoomableGifTextureView.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/MyZoomableGifTextureView.kt deleted file mode 100644 index be6e23a35..000000000 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/MyZoomableGifTextureView.kt +++ /dev/null @@ -1,177 +0,0 @@ -package com.simplemobiletools.gallery.pro.views - -import android.content.Context -import android.graphics.Matrix -import android.graphics.RectF -import android.util.AttributeSet -import android.view.MotionEvent -import android.view.ScaleGestureDetector -import android.widget.ImageView -import com.simplemobiletools.commons.extensions.beVisible -import com.simplemobiletools.gallery.pro.extensions.config -import com.simplemobiletools.gallery.pro.helpers.* -import pl.droidsonroids.gif.GifTextureView - -// allow horizontal swipes through the layout, else it can cause glitches at zoomed in images -class MyZoomableGifTextureView(context: Context, attrs: AttributeSet) : GifTextureView(context, attrs) { - private var mSaveScale = 1f - private var mLastTouchX = 0f - private var mLastTouchY = 0f - private var mTouchDownTime = 0L - private var mTouchDownX = 0f - private var mTouchDownY = 0f - private var mGifWidth = 0f - private var mGifHeight = 0f - private var mScreenWidth = 0f - private var mScreenHeight = 0f - private var mLastFocusX = 0f - private var mLastFocusY = 0f - private var mCloseDownThreshold = 100f - private var mIgnoreCloseDown = false - private var mCurrZoomMode = ZOOM_MODE_NONE - - private var mScaleDetector: ScaleGestureDetector? = null - private var mMatrices = FloatArray(9) - private val mMatrix = Matrix() - private var mCurrentViewport = RectF() - private var mCloseDownCallback: (() -> Unit)? = null - - init { - mScaleDetector = ScaleGestureDetector(context, ScaleListener()) - } - - fun setupGIFView(gifWidth: Int, gifHeight: Int, screenWidth: Int, screenHeight: Int, callback: () -> Unit) { - mCloseDownCallback = callback - // if we don't know the gifs' resolution, just display it and disable zooming - if (gifWidth == 0 || gifHeight == 0) { - scaleType = ImageView.ScaleType.FIT_CENTER - mScaleDetector = null - beVisible() - return - } - - mGifWidth = gifWidth.toFloat() - mGifHeight = gifHeight.toFloat() - mScreenWidth = screenWidth.toFloat() - mScreenHeight = screenHeight.toFloat() - - // we basically want scaleType fitCenter, but we have to use matrices to reach that - val origRect = RectF(0f, 0f, mGifWidth, mGifHeight) - val wantedRect = RectF(0f, 0f, mScreenWidth, mScreenHeight) - mMatrix.setRectToRect(origRect, wantedRect, Matrix.ScaleToFit.CENTER) - mMatrix.getValues(mMatrices) - - val left = mMatrices[Matrix.MTRANS_X] - val top = mMatrices[Matrix.MTRANS_Y] - val right = mScreenWidth - left - val bottom = mScreenHeight - top - mCurrentViewport.set(left, top, right, bottom) - - setTransform(mMatrix) - invalidate() - beVisible() - } - - override fun onTouchEvent(event: MotionEvent): Boolean { - mScaleDetector?.onTouchEvent(event) - - when (event.actionMasked) { - MotionEvent.ACTION_DOWN -> { - mTouchDownTime = System.currentTimeMillis() - mCurrZoomMode = ZOOM_MODE_DRAG - mLastTouchX = event.x - mLastTouchY = event.y - - mTouchDownX = event.x - mTouchDownY = event.y - } - MotionEvent.ACTION_UP -> { - val diffX = mTouchDownX - event.x - val diffY = mTouchDownY - event.y - mCurrZoomMode = ZOOM_MODE_NONE - if (Math.abs(diffX) < CLICK_MAX_DISTANCE && Math.abs(diffY) < CLICK_MAX_DISTANCE && System.currentTimeMillis() - mTouchDownTime < CLICK_MAX_DURATION) { - performClick() - } else { - val downGestureDuration = System.currentTimeMillis() - mTouchDownTime - val areDiffsOK = Math.abs(diffY) > Math.abs(diffX) && diffY < -mCloseDownThreshold - if (mSaveScale == 1f && !mIgnoreCloseDown && areDiffsOK && context.config.allowDownGesture && downGestureDuration < MAX_CLOSE_DOWN_GESTURE_DURATION) { - mCloseDownCallback?.invoke() - } - } - mIgnoreCloseDown = false - } - MotionEvent.ACTION_POINTER_DOWN -> { - mLastTouchX = event.x - mLastTouchY = event.y - mCurrZoomMode = ZOOM_MODE_ZOOM - } - MotionEvent.ACTION_MOVE -> { - if (mCurrZoomMode == ZOOM_MODE_ZOOM || mCurrZoomMode == ZOOM_MODE_DRAG && mSaveScale > MIN_VIDEO_ZOOM_SCALE) { - var diffX = event.x - mLastTouchX - - // horizontal bounds - if (mCurrentViewport.left >= 0) { - diffX = -mCurrentViewport.left - } else if (mCurrentViewport.right + diffX >= mScreenWidth * mSaveScale) { - diffX = -((mScreenWidth * mSaveScale) - mCurrentViewport.right) - } - - mCurrentViewport.left += diffX - mCurrentViewport.right += diffX - - mMatrix.postTranslate(diffX, 0f) - - mCurrentViewport.left = Math.max(mCurrentViewport.left, 0f) - mCurrentViewport.right = Math.min(mCurrentViewport.right, mScreenWidth) - - mLastTouchX = event.x - mLastTouchY = event.y - } - } - MotionEvent.ACTION_POINTER_UP -> { - mCurrZoomMode = ZOOM_MODE_NONE - } - } - - setTransform(mMatrix) - invalidate() - return true - } - - // taken from https://github.com/Manuiq/ZoomableTextureView - private inner class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener() { - override fun onScaleBegin(detector: ScaleGestureDetector): Boolean { - mCurrZoomMode = ZOOM_MODE_ZOOM - return true - } - - override fun onScale(detector: ScaleGestureDetector): Boolean { - if (width <= 0 || height <= 0) { - return true - } - - mLastFocusX = detector.focusX - mLastFocusY = detector.focusY - var scaleFactor = detector.scaleFactor - val origScale = mSaveScale - mSaveScale *= scaleFactor - - if (mSaveScale > MAX_VIDEO_ZOOM_SCALE) { - mSaveScale = MAX_VIDEO_ZOOM_SCALE - scaleFactor = MAX_VIDEO_ZOOM_SCALE / origScale - } else if (mSaveScale < MIN_VIDEO_ZOOM_SCALE) { - mSaveScale = MIN_VIDEO_ZOOM_SCALE - scaleFactor = MIN_VIDEO_ZOOM_SCALE / origScale - } - - mMatrix.postScale(scaleFactor, scaleFactor, detector.focusX, detector.focusY) - mMatrix.getValues(mMatrices) - val left = mMatrices[Matrix.MTRANS_X] - val top = mMatrices[Matrix.MTRANS_Y] - val right = mScreenWidth - left - val bottom = mScreenHeight - top - mCurrentViewport.set(left, top, right, bottom) - return true - } - } -} diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 5a8762ee1..280ea6978 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -694,6 +694,30 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_video_player.xml b/app/src/main/res/layout/activity_video_player.xml index a87ee4cc5..14e0352fc 100644 --- a/app/src/main/res/layout/activity_video_player.xml +++ b/app/src/main/res/layout/activity_video_player.xml @@ -12,11 +12,18 @@ android:layout_height="@dimen/default_status_action_height" android:background="@drawable/gradient_background_flipped"/> - + + + + + + + + + - - - - diff --git a/app/src/main/res/layout/pager_photo_item.xml b/app/src/main/res/layout/pager_photo_item.xml index bc3ec30e8..7484532eb 100644 --- a/app/src/main/res/layout/pager_photo_item.xml +++ b/app/src/main/res/layout/pager_photo_item.xml @@ -6,17 +6,25 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - + android:layout_centerInParent="true" + android:visibility="gone"> + + + + - + + + + + - - + + diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index b489c68b0..d62b37bb8 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -176,6 +176,7 @@ Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available المصغرات diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index 33362f9f1..20302c348 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -172,6 +172,7 @@ Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available Thumbnails @@ -198,7 +199,7 @@ Exclude prevents displaying the folder only in Simple Gallery, while Hide works system-wise and it hides the folder from other galleries too. It works by creating an empty \".nomedia\" file in the given folder, which you can then remove with any file manager too. Why do folders with music cover art or stickers show up? It can happen that you will see some unusual albums show up. You can easily exclude them by long pressing them and selecting Exclude. In the next dialog you can then select the parent folder, chances are it will prevent the other related albums showing up too. - A folder with images isn\'t showing up, what can I do? + A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do? That can have multiple reasons, but solving it is easy. Just go in Settings -> Manage Included Folders, select Plus and navigate to the required folder. What if I want just a few particular folders visible? Adding a folder at the Included Folders doesn\'t automatically exclude anything. What you can do is go in Settings -> Manage Excluded Folders, exclude the root folder \"/\", then add the desired folders at Settings -> Manage Included Folders. diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index d0433fd12..4f400f5e1 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -31,7 +31,7 @@ Fixar la data de presa Fixant… Data fixada correctament - Share a resized version + Comparteix una versió redimensionada Filtre d\'arxius @@ -116,7 +116,7 @@ Presentació de diapositives S\'ha acabat la presentació de diapositives No s\'han trobat mitjans per a la presentació de diapositives - Use crossfade animations + Utilitzeu animacions creuades Canviar el tipus de vista @@ -170,8 +170,9 @@ Mostra imatges amb la màxima qualitat possible Mostra la paperera de reciclatge com a últim element a la pantalla principal Permet tancar la vista de pantalla completa amb un gest avall - Allow 1:1 zooming in with two double taps - Always open videos on a separate screen with new horizontal gestures + Permet 1:1 zoom amb dos tocs dobles + Obriu sempre vídeos en una pantalla independent amb nous gestos horitzontals + Mostra una osca si està disponible Miniatures @@ -193,7 +194,7 @@ Com puc fer que un àlbum sempre aparegui a la part superior? Podeu prémer l\'àlbum desitjat i seleccionar la icona de la xinxeta al menú d\'acció i el fixarà a la part superior. També podeu enganxar diverses carpetes, els elements fixats s\'ordenaran pel mètode de classificació predeterminat. Com puc fer avançar els vídeos? - You can either drag your finger horizontally over the video player, or click on the current or max duration texts near the seekbar. That will move the video either backward, or forward. + Podeu arrossegar el dit horitzontalment al reproductor de vídeo o fer clic als textos actuals o de màxima duració a prop de la barra de cerca. Això mourà el vídeo ja sigui cap enrere o cap endavant. Quina és la diferència entre ocultar i excloure una carpeta? Excloure impedeix mostrar la carpeta només a Simple Galery, mentre que Ocultar també amaga la carpeta a altres galeries. Funciona creant un fitxer \". Nomedia \" buit a la carpeta donada, que podeu eliminar amb qualsevol gestor de fitxers. Per què apareixen les carpetes amb les portades de la música o adhesius? @@ -216,7 +217,7 @@ - An offline gallery for managing your files without ads, respecting your privacy. + Una galeria senzilla, sense anuncis i respectant la vostra privadesa. Una galeria molt personalitzable capaç de mostrar molts tipus d\'imatge i de vídeo diferents, inclosos SVGs, RAWs, fotos panoràmiques i vídeos. diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 1f08bfbd9..772a47e50 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -172,6 +172,7 @@ Povolit zavírání celoobrazovkového režimu tažením prstu dolů Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available Náhledy diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 8f542b363..f2683e5ef 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -172,6 +172,7 @@ Luk fuldskærmsvisning ved at swipe ned Tillad 1:1 zooming med to dobbelttryk Always open videos on a separate screen with new horizontal gestures + Show a notch if available Miniaturer @@ -198,7 +199,7 @@ Exclude prevents displaying the folder only in Simple Gallery, while Hide works system-wise and it hides the folder from other galleries too. It works by creating an empty \".nomedia\" file in the given folder, which you can then remove with any file manager too. Why do folders with music cover art or stickers show up? It can happen that you will see some unusual albums show up. You can easily exclude them by long pressing them and selecting Exclude. In the next dialog you can then select the parent folder, chances are it will prevent the other related albums showing up too. - A folder with images isn\'t showing up, what can I do? + A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do? That can have multiple reasons, but solving it is easy. Just go in Settings -> Manage Included Folders, select Plus and navigate to the required folder. What if I want just a few particular folders visible? Adding a folder at the Included Folders doesn\'t automatically exclude anything. What you can do is go in Settings -> Manage Excluded Folders, exclude the root folder \"/\", then add the desired folders at Settings -> Manage Included Folders. diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 91f8e0e1d..b74782d24 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -172,6 +172,7 @@ Erlaube das Schließen der Vollbildansicht mit einer Abwärtsgeste Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available Thumbnails diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 0a147bc9f..a447f33a0 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -30,8 +30,8 @@ Χρήση προεπιλογής Διόρθωση ημερ. λήψης Διορθώνεται… - Ημερ. διορθώθηκε με επιτυχία - Share a resized version + Η Ημερ. διορθώθηκε με επιτυχία + Διαμοιρασμός έκδοσης με αλλαγμένο μέγεθος Φιλτράρισμα πολυμέσων @@ -89,7 +89,7 @@ Οριζόντιο αναποδογύρισμα Κατακόρυφο αναποδογύρισμα Ελεύθερο - Other + Άλλο Simple Wallpaper @@ -116,7 +116,7 @@ Επανάληψη εμφάνισης διαφανιών Η εμφάνιση διαφανειών τελείωσε Δεν βρέθηκαν πολυμέσα για την εμφάνιση διαφανειών - Use crossfade animations + Χρήση κίνησης εικόνων με διαγώνιο ξεθώριασμα Αλλαγή τύπου εμφάνισης @@ -128,8 +128,8 @@ Ομαδοποίηση κατά Χωρίς Φάκελο - Τελευταία τροποποίηση - Ημερομηνία λήψης + Τελευταία τροπ/ηση + Ημερομ. λήψης Τύπο αρχείου Επέκταση @@ -170,8 +170,9 @@ Εμφάνιση εικόνων με την υψηλότερη δυνατή ποιότητα Εμφάνιση του Κάδου ως τελευταίο στοιχείο στην κύρια οθόνη Επιτρέψτε το κλείσιμο προβολής πλήρους οθόνης με χειρονομία προς τα κάτω - Allow 1:1 zooming in with two double taps - Always open videos on a separate screen with new horizontal gestures + Allow 1:1 μεγένθυση με δύο διπλά χτυπήματα + Να ανοίγονται πάντα τα βίντεο σε ξεχωριστή οθόνη με νέες οριζόντιες χειρονομίες + Εμφάνιση μιας εγκοπή αν διατίθεται Εικονίδια @@ -193,7 +194,7 @@ Πώς μπορώ να κάνω ένα άλμπουμ να φαίνεται στην κορυφή; Μπορείτε να πατήσετε παρατεταμένα στο άλμπουμ και να επιλέξετε το εικονίδιο καρφιτσώματος στο μενού, αυτό θα το καρφιτσώσει στην κορυφή. Επίσης μπορείτε να καρφιτσώσετε πολλαπλούς φακέλους, τα καρφιτσωμένα αντικείμενα θα είναι ταξινομημένα με την προεπιλεγμένη μέθοδο. Πώς μπορώ να τρέξω μπροστά (fast-forward) τα βίντεο; - You can either drag your finger horizontally over the video player, or click on the current or max duration texts near the seekbar. That will move the video either backward, or forward. + Μπορείτε είτε να σύρετε το δάχτυλό σας οριζόντια πάνω από το πρόγραμμα αναπαραγωγής Βίντεο ή να κάνετε κλικ στα γράμματα της τρέχουσας ή της μέγιστης διάρκειας κοντά στο Γραμμή Αναζήτησης. Αυτό θα μετακινήσει το βίντεο προς τα πίσω ή προς τα εμπρός. Ποια είναι διαφορά μεταξύ απόκρυψης και εξαίρεσης ενός φακέλου; Η εξαίρεση δεν επιτρέπει την εμφάνιση του φακέλου μόνο στο Simple Gallery, ενώ η απόκρυψη λειτουργεί σε επίπεδο συστήματος και θα αποκρύψει τον φάκελο και από άλλες εφαρμογές γκάλερι. Λειτουργεί δημιουργώντας ένα άδειο \".nomedia\" αρχείο στον επιλεγμένο φάκελο, το οποίο μπορείτε να το διαγράψετε και με οποιονδήποτε διαχειριστή αρχείων. Γιατί εμφανίζονται φάκελοι με εξώφυλλο μουσικής ή αυτόκολλητα; @@ -216,7 +217,7 @@ - An offline gallery for managing your files without ads, respecting your privacy. + Μια offline Gallery χωρίς διαφημίσεις, σεβόμενοι τα προσωπικά σας δεδομένα. Μια εξαιρετικά προσαρμόσιμη Gallery ικανή να εμφανίζει πολλούς διαφορετικούς τύπους εικόνας και βίντεο, όπως SVGs, RAWs, πανοραμικές φωτογραφίες και βίντεο. diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 89f0bd44e..5b5dff533 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -31,7 +31,7 @@ Fijar fecha de toma Fijando… Fecha fijada correctamente - Share a resized version + Comparte una versión redimensionada Filtro de medios @@ -116,7 +116,7 @@ Presentación de diapositivas La diapositiva terminó No se han encontrado medios para la presentación de diapositivas - Use crossfade animations + Usa animaciones de crossfade. Cambiar tipo de vista @@ -170,8 +170,9 @@ Muestra imágenes con la mayor calidad posible Mostrar la Papelera de reciclaje como el último elemento en la pantalla principal Permite cerrar la vista de pantalla completa con un gesto hacia abajo. - Allow 1:1 zooming in with two double taps - Always open videos on a separate screen with new horizontal gestures + Permitir zoom 1:1 con dos toques dobles + Siempre abre videos en una pantalla separada con nuevos gestos horizontales + Mostrar una muesca si está disponible Miniaturas @@ -193,7 +194,7 @@ ¿Cómo puedo hacer que un álbum siempre aparezca en la parte superior? Puede aguantar pulsado el álbum deseado y seleccionar el ícono Pin en el menú de acción, que lo fijará en la parte superior. También puede anclar varias carpetas, los artículos fijados se ordenarán por el método de clasificación predeterminado. ¿Cómo puedo avanzar videos? - You can either drag your finger horizontally over the video player, or click on the current or max duration texts near the seekbar, that will move the video either backward, or forward. + Puede arrastrar el dedo horizontalmente sobre el reproductor de video, o hacer clic en los textos de duración actual o máxima cerca de la barra de búsqueda, que moverán el video hacia atrás o hacia adelante. ¿Cuál es la diferencia entre ocultar y excluir una carpeta? Excluir evita mostrar la carpeta solo en Simple Gallery, mientras que Ocultar funciona en el sistema y oculta la carpeta de otras galerías también. Funciona al crear un archivo \".nomedia \" vacío en la carpeta determinada, que luego puede eliminar también con cualquier administrador de archivos. ¿Por qué aparecen las carpetas con la portada de la música o las pegatinas? @@ -216,7 +217,7 @@ - An offline gallery for managing your files without ads, respecting your privacy. + Una galería senzilla, sin anuncios y respetando su privacidad. Una galería altamente personalizable capaz de mostrar diferentes tipos de imágenes y videos, incluyendo SVG, RAW, fotos panorámicas y videos. diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index d4410137c..642825ba3 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -172,6 +172,7 @@ Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available Esikatselukuvat @@ -198,7 +199,7 @@ Exclude prevents displaying the folder only in Simple Gallery, while Hide works system-wise and it hides the folder from other galleries too. It works by creating an empty \".nomedia\" file in the given folder, which you can then remove with any file manager too. Why do folders with music cover art or stickers show up? It can happen that you will see some unusual albums show up. You can easily exclude them by long pressing them and selecting Exclude. In the next dialog you can then select the parent folder, chances are it will prevent the other related albums showing up too. - A folder with images isn\'t showing up, what can I do? + A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do? That can have multiple reasons, but solving it is easy. Just go in Settings -> Manage Included Folders, select Plus and navigate to the required folder. What if I want just a few particular folders visible? Adding a folder at the Included Folders doesn\'t automatically exclude anything. What you can do is go in Settings -> Manage Excluded Folders, exclude the root folder \"/\", then add the desired folders at Settings -> Manage Included Folders. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 013a04193..e4500491d 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -172,6 +172,7 @@ Fermeture de la vue plein écran par un geste vers le bas Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available Miniatures diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 1bfcab564..c26670555 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -172,6 +172,7 @@ Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available Iconas diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 87786044b..d53e4db0b 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -172,6 +172,7 @@ Omogućite zatvaranje prikaza preko cijelog zaslona pokretom prema dolje Dopusti zumiranje 1: 1 s dva dvostruka dodira Always open videos on a separate screen with new horizontal gestures + Show a notch if available Sličice diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 2db88f5cf..848e58dc4 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -31,7 +31,7 @@ Dátum javítása Javítás… Sikeres dátum javítás - Share a resized version + Átméretezett verzió megosztása Média szűrő @@ -172,7 +172,8 @@ Mutassa a Lomtárat a fő képernyő utolsó elemeként Engedélyezi a teljes képernyős nézetet a lefelé mozdulattal Engedélyezi az 1:1 nagyítást két dupla érintéssel - Always open videos on a separate screen with new horizontal gestures + Mindig külön képernyőn nyissa meg a videókat új vízszintes mozdulattal + Show a notch if available Miniatűrök diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 7129f35b8..f8b56fa5d 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -172,6 +172,7 @@ Izinkan keluar dari layar penuh dengan menggeser kebawah Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available Thumbnail diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index f5939868a..0d2b39653 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -31,7 +31,7 @@ Correggi valore Data acquisizione Correzione in corso… Date aggiornate correttamente - Share a resized version + Condividi una versione ridimensionata Filtra i file @@ -172,6 +172,7 @@ Chiudi la visuale a schermo intero con un gesto verso il basso Permetti l\'ingrandimento 1:1 con un doppio tasto Apri sempre i video su uno schermo separato con i nuovi movimenti orizzontali + Mostra un notch se disponibile Anteprime diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 9d8334625..8690af96d 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -172,6 +172,7 @@ Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available サムネイル設定 @@ -198,7 +199,7 @@ Exclude prevents displaying the folder only in Simple Gallery, while Hide works system-wise and it hides the folder from other galleries too. It works by creating an empty \".nomedia\" file in the given folder, which you can then remove with any file manager too. Why do folders with music cover art or stickers show up? It can happen that you will see some unusual albums show up. You can easily exclude them by long pressing them and selecting Exclude. In the next dialog you can then select the parent folder, chances are it will prevent the other related albums showing up too. - A folder with images isn\'t showing up, what can I do? + A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do? That can have multiple reasons, but solving it is easy. Just go in Settings -> Manage Included Folders, select Plus and navigate to the required folder. What if I want just a few particular folders visible? Adding a folder at the Included Folders doesn\'t automatically exclude anything. What you can do is go in Settings -> Manage Excluded Folders, exclude the root folder \"/\", then add the desired folders at Settings -> Manage Included Folders. diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index b13747387..4c697cc10 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -172,6 +172,7 @@ Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available 섬네일 @@ -198,7 +199,7 @@ Exclude prevents displaying the folder only in Simple Gallery, while Hide works system-wise and it hides the folder from other galleries too. It works by creating an empty \".nomedia\" file in the given folder, which you can then remove with any file manager too. Why do folders with music cover art or stickers show up? It can happen that you will see some unusual albums show up. You can easily exclude them by long pressing them and selecting Exclude. In the next dialog you can then select the parent folder, chances are it will prevent the other related albums showing up too. - A folder with images isn\'t showing up, what can I do? + A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do? That can have multiple reasons, but solving it is easy. Just go in Settings -> Manage Included Folders, select Plus and navigate to the required folder. What if I want just a few particular folders visible? Adding a folder at the Included Folders doesn\'t automatically exclude anything. What you can do is go in Settings -> Manage Excluded Folders, exclude the root folder \"/\", then add the desired folders at Settings -> Manage Included Folders. diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 00f8dfb82..59a6f176d 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -172,6 +172,7 @@ Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available Miniatiūros diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 153802ae6..ec4b26bc7 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -172,6 +172,7 @@ Tillat lukking av mediavisningen med en nedoverbevegelse Tillat å zoome 1:1 med to dobbeltrykk Åpne alltid videoer på en separat skjerm med nye horisontale bevegelser + Show a notch if available Minibilder @@ -198,7 +199,7 @@ Exclude prevents displaying the folder only in Simple Gallery, while Hide works system-wise and it hides the folder from other galleries too. It works by creating an empty \".nomedia\" file in the given folder, which you can then remove with any file manager too. Why do folders with music cover art or stickers show up? It can happen that you will see some unusual albums show up. You can easily exclude them by long pressing them and selecting Exclude. In the next dialog you can then select the parent folder, chances are it will prevent the other related albums showing up too. - A folder with images isn\'t showing up, what can I do? + A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do? That can have multiple reasons, but solving it is easy. Just go in Settings -> Manage Included Folders, select Plus and navigate to the required folder. What if I want just a few particular folders visible? Adding a folder at the Included Folders doesn\'t automatically exclude anything. What you can do is go in Settings -> Manage Excluded Folders, exclude the root folder \"/\", then add the desired folders at Settings -> Manage Included Folders. diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 77996d5ea..974f83c41 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -172,6 +172,7 @@ Naar beneden vegen om volledig scherm af te sluiten 1:1 zoomen na 2x dubbelklikken Video\'s altijd in apart scherm met horizontale veeggebaren openen + Inkeping scherm tonen indien aanwezig Miniatuurvoorbeelden diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index fa6d862d1..72a6e11ef 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -172,6 +172,7 @@ Zezwalaj na zamykanie pełnoekranowego widoku gestem pociągnięcia w dół Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available    Miniatury diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index b2b49c576..8b23a2780 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -172,6 +172,7 @@ Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available Miniaturas @@ -198,7 +199,7 @@ Exclude prevents displaying the folder only in Simple Gallery, while Hide works system-wise and it hides the folder from other galleries too. It works by creating an empty \".nomedia\" file in the given folder, which you can then remove with any file manager too. Why do folders with music cover art or stickers show up? It can happen that you will see some unusual albums show up. You can easily exclude them by long pressing them and selecting Exclude. In the next dialog you can then select the parent folder, chances are it will prevent the other related albums showing up too. - A folder with images isn\'t showing up, what can I do? + A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do? That can have multiple reasons, but solving it is easy. Just go in Settings -> Manage Included Folders, select Plus and navigate to the required folder. What if I want just a few particular folders visible? Adding a folder at the Included Folders doesn\'t automatically exclude anything. What you can do is go in Settings -> Manage Excluded Folders, exclude the root folder \"/\", then add the desired folders at Settings -> Manage Included Folders. diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 9706ec32d..a5051c540 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -31,7 +31,7 @@ Corrigir data de obtenção A corrigir… Dados corrigidos com sucesso - Share a resized version + Partilhar foto redimensionada Filtrar multimédia @@ -111,7 +111,7 @@ Incluir vídeos Incluir GIF Ordem aleatória - Usar animações + Utilizar animações Mover para trás Apresentação em ciclo Apresentação terminada @@ -172,6 +172,7 @@ Sair de ecrã completo com um gesto para baixo Permitir ampliação 1:1 com dois toques Abrir vídeos em ecrã distinto com os novos toques horizontais + Show a notch if available Miniaturas @@ -198,7 +199,7 @@ Exclude prevents displaying the folder only in Simple Gallery, while Hide works system-wise and it hides the folder from other galleries too. It works by creating an empty \".nomedia\" file in the given folder, which you can then remove with any file manager too. Why do folders with music cover art or stickers show up? It can happen that you will see some unusual albums show up. You can easily exclude them by long pressing them and selecting Exclude. In the next dialog you can then select the parent folder, chances are it will prevent the other related albums showing up too. - A folder with images isn\'t showing up, what can I do? + A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do? That can have multiple reasons, but solving it is easy. Just go in Settings -> Manage Included Folders, select Plus and navigate to the required folder. What if I want just a few particular folders visible? Adding a folder at the Included Folders doesn\'t automatically exclude anything. What you can do is go in Settings -> Manage Excluded Folders, exclude the root folder \"/\", then add the desired folders at Settings -> Manage Included Folders. diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 1a8e5bf56..0ef0d574b 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -172,6 +172,7 @@ Отключать полноэкранный режим жестом вниз Масштаб 1:1 двумя двойными нажатиями Воспроизводить видео на отдельном экране с управлением позицией горизонтальными жестами + Show a notch if available Миниатюры diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index d9b61d146..dbb29c3fe 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -172,6 +172,7 @@ Povoliť zatváranie celoobrazovkového režimu potiahnutím prsta dole Povoliť 1:1 priblíženie dvojnásobným dvojklikom Vždy otvárať videá na vlastnej obrazovke s novými vodorovnými gestami + Zobraziť výrez obrazovky, ak je dostupný Náhľady @@ -198,7 +199,7 @@ Kým vylúčenie predíde zobrazeniu priečinka iba vrámci Jednoduchej Galérie, skrytie ho ukryje vrámci celého systému, teda to ovplyvní aj ostatné galérie. Skrytie funguje pomocou vytvorenia prázdneho \".nomedia\" súboru v danom priečinku, ktorý viete vymazať aj nejakým správcom súborov. Prečo sa mi zobrazujú priečinky s obalmi hudobných albumov, alebo nálepkami? Môže sa stať, že sa vám zobrazia aj nezvyčajné priečinky. Viete ich ale jednoducho ukryť pomocou ich zvolenia dlhým podržaním a zvolením Vylúčiť. Ak na nasledovnom dialógu zvolíte vylúčenie rodičovského priečinka, pravdepodobne budú vylúčené aj ostatné, podobné priečinky. - Priečinok s fotkami sa mi nezobrazuje, čo môžem urobiť? + Priečinok s fotkami sa mi nezobrazuje, alebo priečinok nezobrazuje všetky položky. Čo s tým môžem urobiť? Môže to mať viacero dôvodov, riešenie je ale jednoduché. Choďte do Nastavenia -> Spravovať pridané priečinky, zvoľte Plus a zvoľte vytúžený priečinok. Čo v prípade, ak chcem mať zobrazených iba pár priečinkov? Pridanie priečinka medzi Pridané Priečinky automaticky nevylúči ostatné. Môžete ale ísť do Nastavenia -> Spravovať vylúčené priečinky a zvoliť Koreňový priečinok \"/\", následne pridať žiadané priečinky v Nastavenia -> Spravovať pridané priečinky. diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 6ded38895..d30849de5 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -172,6 +172,7 @@ Dovoli zapiranje celozaslonskega načina z gesto navzdol Dovoli 1:1 povečavo z dvojnim pritiskom Vedno odpri videoposnetke na ločenem zaslonu z novimi horizontalnimi gestami + Show a notch if available Sličice diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 796a5a6c8..322ea5ce1 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -172,6 +172,7 @@ Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available Miniatyrer @@ -198,7 +199,7 @@ Exclude prevents displaying the folder only in Simple Gallery, while Hide works system-wise and it hides the folder from other galleries too. It works by creating an empty \".nomedia\" file in the given folder, which you can then remove with any file manager too. Why do folders with music cover art or stickers show up? It can happen that you will see some unusual albums show up. You can easily exclude them by long pressing them and selecting Exclude. In the next dialog you can then select the parent folder, chances are it will prevent the other related albums showing up too. - A folder with images isn\'t showing up, what can I do? + A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do? That can have multiple reasons, but solving it is easy. Just go in Settings -> Manage Included Folders, select Plus and navigate to the required folder. What if I want just a few particular folders visible? Adding a folder at the Included Folders doesn\'t automatically exclude anything. What you can do is go in Settings -> Manage Excluded Folders, exclude the root folder \"/\", then add the desired folders at Settings -> Manage Included Folders. diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index cab36d290..357a665da 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -172,6 +172,7 @@ Tam ekran görünümünü aşağı hareketi ile kapatmaya izin ver Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available Küçük resimler diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 0099580ab..0248f8939 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -172,6 +172,7 @@ Дозволити закриття повноекранного перегляду свайпом згори вниз Дозволити масштабування до 1:1 подвійним тапом Завжди відкривати відео на окремому екрані з новими горизонтальними жестами + Show a notch if available Ескізи diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 5226ef286..4252b5daf 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -172,6 +172,7 @@ 使用下滑手势关闭全屏视图 双击两次后 1:1 放大图像 使用新的水平手势在独立页面播放视频 + Show a notch if available 缩略图 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 0c3413685..820f22486 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -31,7 +31,7 @@ 修復拍照日期數值 修復中… 日期修復成功 - Share a resized version + 分享調整大小的版本 篩選媒體檔案 @@ -172,6 +172,7 @@ 允許用下滑手勢來關閉全螢幕檢視 允許用兩次雙擊來1:1縮放 總是用新的水平手勢在獨立畫面開啟影片 + 如果可以,顯示瀏海螢幕 縮圖 diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index 0c2e2b267..2d9b27b32 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -2,6 +2,17 @@ + + Implemented export/importing for app settings and other preferences, like sorting\n + Allow hiding Notch on fullscreen view on Android 9+\n + Autosave images zoomed at the fullscreen view + + + Allow drawing in the editor\n + Allow batch rotating images from the thumbnails view (proper thumbnail refreshing might need an app restart)\n + Allow sharing images directly from the editor\n + Allow zooming GIFs and videos + Reverted to the old way of opening videos, opening on separate screen can be enabled in the app settings Rewrote video playback, use a separate screen + added fast-forwarding with horizontal swiping\n @@ -13,119 +24,5 @@ Added an initial widget implementation for creating homescreen folder shortcuts\n Added optional grouping of direct subfolders, as a check at the \"Change view type\" dialog - Added a new option for password protecting file deletion/move - Added a new option for showing the Recycle Bin as the last folder - - Added a new settings toggle \"Show images in the highest possible quality\"\n - Allow faster video seeking by dragging a finger at the bottom seekbar - - - Added Panorama photo support\n - Allow forcing portrait/landscape orientation at fullscreen view\n - Allow customizing visible fullscreen bottom actions in the app settings - - - Allow grouping media thumbnails by some criteria\n - Added a Recycle Bin enabled by default, can be disabled in Settings, or from the Bin itself - - Allow selecting Favorite items for easy access - Allow filtering out RAW images separately - Added sorting by Date Taken - Allow customizing the app launcher icon color - Added toggles for disabling Pull-to-refresh and permanent Delete dialog confirmation skipping - - Added a toggle for replacing deep zoomable images with better quality ones\n - Added a toggle for hiding Extended details when the statusbar is hidden\n - Added a toggle for switching media files by clicking on screen sides - - Added optional one-finger drag zoom, disabled by default - - Added new options to use english language on non-english devices, to password protect whole app and to lock screen orientation at fullscreen view - - 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 - - Added fingerprint to hidden item protection\n - Added a new List view type - - - Added a switch for disabling video gestures\n - Added a switch for deleting empty folders after deleting content - - Moved media type filter from Settings to the Action menu - Allow changing the screen brightness and volume at videos by vertically dragging the screen sides - Added slideshow at the fullscreen view - Added pattern/pin protection for showing hidden items - Added a toggle for replacing Share with Rotate at fullscreen media - - Added an indicator of folders located on SD cards\n - Improved the way of rotating jpg images on the internal storage by modifying the exif tags + added autosave - - Added an option for automatically hiding the system UI at entering fullscreen mode - Added an option for enabling horizontal scrolling - Allow setting custom folder covers - - Allow selecting multiple items by finger dragging\n - Added an option to always use black background at fullscreen media - - Allow hiding individual files by prepending filenames with a dot - Added horizontal and vertical image flipping in the image editor - - Allow setting portrait wallpapers\n - Added more fields in photo Properties dialog - - - Improved fullscreen image zooming\n - Added more settings related to screen autorotating\n - Split copy and move functions for ease of use - - - Added an option to temporarily show hidden folders\n - Added a setting for preventing thumbnail croping to square\n - Added a setting for auto-rotating the screen depending on photo aspect ratio - - - Added an option to use max brightness at viewing fullscreen media\n - Added an option to manually include folders which contain media, but were not recognized by the app - - - Fixed some sharing and editor issues\n - Sorry for the frequent updates lately, they should be stopped now. - - - Exclude the subfolders of excluded folders too\n - Added an easy way of excluding parent folders from the exclude confirmation dialog\n - Added draggable scrollbars\n - Allow setting a third party video player as the default - - Added an option to toggle gif animation at thumbnails - Allow setting different sorting per folder - - Implement proper folder hiding via .nomedia file\n - Allow managing excluded folders in Settings - - Added menu items for easy image rotating in fullscreen view - Added menu buttons for changing the column count - Allow picking colors by hex codes - Allow showing the photos and videos on a map, if there are available map coordinates - Show some additional Exif data at photo properties - - Allow zooming pngs and gifs\n - Allow creating new folders at Copy/Move or Save as dialog destinations - - Added an option to loop videos automatically - - Added more color customization options\n - Your settings have been cleared, please reset them - - Allow changing the column count with pinch gestures - Added an option to display images or videos only - Added a Select all button at selecting media and folders - - Added an image resizer to the editor\n - Allow displaying images and videos from all folders together - - Allow pinning folders at the top diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f6c49d687..3950ffb4a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -172,6 +172,7 @@ Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps Always open videos on a separate screen with new horizontal gestures + Show a notch if available Thumbnails @@ -198,7 +199,7 @@ Exclude prevents displaying the folder only in Simple Gallery, while Hide works system-wise and it hides the folder from other galleries too. It works by creating an empty \".nomedia\" file in the given folder, which you can then remove with any file manager too. Why do folders with music cover art or stickers show up? It can happen that you will see some unusual albums show up. You can easily exclude them by long pressing them and selecting Exclude. In the next dialog you can then select the parent folder, chances are it will prevent the other related albums showing up too. - A folder with images isn\'t showing up, what can I do? + A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do? That can have multiple reasons, but solving it is easy. Just go in Settings -> Manage Included Folders, select Plus and navigate to the required folder. What if I want just a few particular folders visible? Adding a folder at the Included Folders doesn\'t automatically exclude anything. What you can do is go in Settings -> Manage Excluded Folders, exclude the root folder \"/\", then add the desired folders at Settings -> Manage Included Folders. diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/app.jpg b/fastlane/metadata/android/en-US/images/phoneScreenshots/app.jpg old mode 100644 new mode 100755 index e03971236..c8e5f57e9 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/app.jpg and b/fastlane/metadata/android/en-US/images/phoneScreenshots/app.jpg differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_2.jpg b/fastlane/metadata/android/en-US/images/phoneScreenshots/app_2.jpg old mode 100644 new mode 100755 index 3c79bf959..9d14855a2 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_2.jpg and b/fastlane/metadata/android/en-US/images/phoneScreenshots/app_2.jpg differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_3.jpg b/fastlane/metadata/android/en-US/images/phoneScreenshots/app_3.jpg old mode 100644 new mode 100755 index e9778473f..b80672eb4 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_3.jpg and b/fastlane/metadata/android/en-US/images/phoneScreenshots/app_3.jpg differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_4.jpg b/fastlane/metadata/android/en-US/images/phoneScreenshots/app_4.jpg old mode 100644 new mode 100755 index 9cd10f484..20ddf6acf Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_4.jpg and b/fastlane/metadata/android/en-US/images/phoneScreenshots/app_4.jpg differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_5.jpg b/fastlane/metadata/android/en-US/images/phoneScreenshots/app_5.jpg deleted file mode 100644 index 315243832..000000000 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_5.jpg and /dev/null differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_6.jpg b/fastlane/metadata/android/en-US/images/phoneScreenshots/app_6.jpg deleted file mode 100644 index db4b66408..000000000 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_6.jpg and /dev/null differ