Merge pull request #46 from SimpleMobileTools/master

upd
This commit is contained in:
solokot 2019-02-02 13:33:53 +03:00 committed by GitHub
commit 6adff01f30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
69 changed files with 753 additions and 903 deletions

View file

@ -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)*
----------------------------

View file

@ -36,7 +36,7 @@ This app is just one piece of a bigger series of apps. You can find the rest of
<div style="display:flex;">
<img alt="App image" src="fastlane/metadata/android/en-US/images/phoneScreenshots/app.jpg" width="30%">
<img alt="App image" src="fastlane/metadata/android/en-US/images/phoneScreenshots/app_2.jpg" width="30%">
<img alt="App image" src="fastlane/metadata/android/en-US/images/phoneScreenshots/app_5.jpg" width="30%">
<img alt="App image" src="fastlane/metadata/android/en-US/images/phoneScreenshots/app_3.jpg" width="30%">
</div>
License

View file

@ -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'
}

View file

@ -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) {

View file

@ -1177,61 +1177,11 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
private fun checkWhatsNewDialog() {
arrayListOf<Release>().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)
}
}

View file

@ -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 {

View file

@ -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()

View file

@ -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())

View file

@ -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<String, Any>().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<String, Any>()
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()
}
}
}

View file

@ -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)
}
}
}
}

View file

@ -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()

View file

@ -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
}
}
}

View file

@ -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<Medium>()
private var mFavoritePaths = ArrayList<String>()
@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<ThumbnailItem>).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) {

View file

@ -43,6 +43,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
private val viewType = config.getFolderViewType(if (config.showAll) SHOW_ALL else path)
private val isListViewType = viewType == VIEW_TYPE_LIST
private var visibleItemPaths = ArrayList<String>()
private var rotatedImagePaths = ArrayList<String>()
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<Thumbnai
private fun rotateSelection(degrees: Int) {
activity.toast(R.string.saving)
Thread {
val paths = getSelectedPaths()
val paths = getSelectedPaths().filter { it.isImageFast() }
var fileCnt = paths.size
rotatedImagePaths.clear()
paths.forEach {
activity.saveRotatedImageToFile(it, it, degrees) {
rotatedImagePaths.add(it)
activity.saveRotatedImageToFile(it, it, degrees, true) {
fileCnt--
if (fileCnt == 0) {
activity.runOnUiThread {
@ -375,7 +378,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
activity.handleSAFDialog(SAFPath) {
val fileDirItems = ArrayList<FileDirItem>(selectedKeys.size)
val removeMedia = ArrayList<Medium>(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<Thumbnai
media.removeAll(removeMedia)
listener?.tryDeleteFiles(fileDirItems)
removeSelectedItems(position)
removeSelectedItems(positions)
}
}
@ -460,14 +463,14 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
}
if (loadImageInstantly) {
activity.loadImage(medium.type, path, medium_thumbnail, scrollHorizontally, animateGifs, cropThumbnails)
activity.loadImage(medium.type, path, medium_thumbnail, scrollHorizontally, animateGifs, cropThumbnails, rotatedImagePaths)
} else {
medium_thumbnail.setImageDrawable(null)
medium_thumbnail.isHorizontalScrolling = scrollHorizontally
delayHandler.postDelayed({
val isVisible = visibleItemPaths.contains(medium.path)
if (isVisible) {
activity.loadImage(medium.type, path, medium_thumbnail, scrollHorizontally, animateGifs, cropThumbnails)
activity.loadImage(medium.type, path, medium_thumbnail, scrollHorizontally, animateGifs, cropThumbnails, rotatedImagePaths)
}
}, IMAGE_LOAD_DELAY)
}

View file

@ -74,7 +74,7 @@ fun Activity.launchCamera() {
fun SimpleActivity.launchAbout() {
val licenses = LICENSE_GLIDE or LICENSE_CROPPER or LICENSE_RTL or LICENSE_SUBSAMPLING or LICENSE_PATTERN or LICENSE_REPRINT or LICENSE_GIF_DRAWABLE or
LICENSE_PHOTOVIEW or LICENSE_PICASSO or LICENSE_EXOPLAYER or LICENSE_PANORAMA_VIEW or LICENSE_SANSELAN or LICENSE_FILTERS
LICENSE_PICASSO or LICENSE_EXOPLAYER or LICENSE_PANORAMA_VIEW or LICENSE_SANSELAN or LICENSE_FILTERS or LICENSE_GESTURE_VIEWS
val faqItems = arrayListOf(
FAQItem(R.string.faq_5_title_commons, R.string.faq_5_text_commons),
@ -373,9 +373,9 @@ fun Activity.fixDateTaken(paths: ArrayList<String>, 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) {
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) {
if (showToasts) {
toast(R.string.out_of_memory_error)
}
} catch (e: Exception) {
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()
if (showToasts) {
toast(R.string.file_saved)
}
true
} else {
false
}
} catch (e: Exception) {
if (showToasts) {
showErrorToast(e)
}
false
}
}

View file

@ -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<String>? = 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<String>? = 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<String>? = null) {
val options = RequestOptions()
.signature(path.getFileSignature())
.skipMemoryCache(skipMemoryCacheAtPaths?.contains(path) == true)
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
val builder = Glide.with(applicationContext)

View file

@ -21,9 +21,13 @@ fun String.shouldFolderBeVisible(excludedPaths: MutableSet<String>, 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

View file

@ -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<Drawable> {
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
if (activity != null) {
tryLoadingWithPicasso(degrees)
}
return false
}
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, 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<Bitmap> {
override fun onLoadFailed(e: GlideException?, model: Any?, target: com.bumptech.glide.request.target.Target<Bitmap>?, isFirstResource: Boolean) = false
override fun onResourceReady(resource: Bitmap?, model: Any?, target: Target<Bitmap>?, 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)
}
}

View file

@ -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
}
}
}

View file

@ -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

View file

@ -104,7 +104,7 @@ class Config(context: Context) : BaseConfig(context) {
fun addPinnedFolders(paths: Set<String>) {
val currPinnedFolders = HashSet<String>(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<String>) {
val currExcludedFolders = HashSet<String>(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<String>) {
val currIncludedFolders = HashSet<String>(includedFolders)
currIncludedFolders.addAll(paths)
includedFolders = currIncludedFolders.filter { it.isNotEmpty() }.toHashSet()
}
fun removeIncludedFolder(path: String) {
val currIncludedFolders = HashSet<String>(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()
}

View file

@ -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

View file

@ -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())

View file

@ -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

View file

@ -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

View file

@ -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
}
}
}

View file

@ -694,6 +694,30 @@
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_show_notch_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/medium_margin"
android:background="?attr/selectableItemBackground"
android:paddingLeft="@dimen/normal_margin"
android:paddingTop="@dimen/activity_margin"
android:paddingRight="@dimen/normal_margin"
android:paddingBottom="@dimen/activity_margin">
<com.simplemobiletools.commons.views.MySwitchCompat
android:id="@+id/settings_show_notch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:clickable="false"
android:paddingStart="@dimen/medium_margin"
android:paddingLeft="@dimen/medium_margin"
android:text="@string/show_notch"
app:switchPadding="@dimen/medium_margin"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_screen_rotation_holder"
android:layout_width="match_parent"
@ -1297,5 +1321,67 @@
android:clickable="false"/>
</RelativeLayout>
<View
android:id="@+id/migrating_divider"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/divider_grey"
android:importantForAccessibility="no"/>
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/migrating_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/bigger_margin"
android:layout_marginLeft="@dimen/bigger_margin"
android:layout_marginTop="@dimen/activity_margin"
android:text="@string/migrating"
android:textAllCaps="true"
android:textSize="@dimen/smaller_text_size"/>
<RelativeLayout
android:id="@+id/settings_export_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/medium_margin"
android:background="?attr/selectableItemBackground"
android:paddingLeft="@dimen/normal_margin"
android:paddingTop="@dimen/activity_margin"
android:paddingRight="@dimen/normal_margin"
android:paddingBottom="@dimen/activity_margin">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/settings_export"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:paddingStart="@dimen/medium_margin"
android:paddingLeft="@dimen/medium_margin"
android:text="@string/export_settings"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_import_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/medium_margin"
android:background="?attr/selectableItemBackground"
android:paddingLeft="@dimen/normal_margin"
android:paddingTop="@dimen/activity_margin"
android:paddingRight="@dimen/normal_margin"
android:paddingBottom="@dimen/activity_margin">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/settings_import"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:paddingStart="@dimen/medium_margin"
android:paddingLeft="@dimen/medium_margin"
android:text="@string/import_settings"/>
</RelativeLayout>
</LinearLayout>
</ScrollView>

View file

@ -12,12 +12,19 @@
android:layout_height="@dimen/default_status_action_height"
android:background="@drawable/gradient_background_flipped"/>
<com.alexvasilkov.gestures.GestureFrameLayout
android:id="@+id/video_surface_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextureView
android:id="@+id/video_surface"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"/>
</com.alexvasilkov.gestures.GestureFrameLayout>
<com.simplemobiletools.gallery.pro.views.MediaSideScroll
android:id="@+id/video_volume_controller"
android:layout_width="@dimen/media_side_slider_width"
@ -30,6 +37,17 @@
android:layout_width="@dimen/media_side_slider_width"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/video_bottom_gradient"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignTop="@+id/video_time_holder"
android:layout_alignParentBottom="true"
android:background="@drawable/gradient_background"
tools:ignore="UnknownIdInLayout"/>
<include layout="@layout/bottom_video_time_holder"/>
<TextView
android:id="@+id/slide_info"
android:layout_width="wrap_content"
@ -47,15 +65,4 @@
android:textColor="@android:color/white"
android:textSize="@dimen/extra_big_text_size"/>
<TextView
android:id="@+id/video_bottom_gradient"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignTop="@+id/video_time_holder"
android:layout_alignParentBottom="true"
android:background="@drawable/gradient_background"
tools:ignore="UnknownIdInLayout"/>
<include layout="@layout/bottom_video_time_holder"/>
</RelativeLayout>

View file

@ -6,17 +6,25 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.chrisbanes.photoview.PhotoView
android:id="@+id/photo_view"
<com.alexvasilkov.gestures.GestureImageView
android:id="@+id/gestures_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<com.simplemobiletools.gallery.pro.views.MyZoomableGifTextureView
android:id="@+id/gif_view"
<com.alexvasilkov.gestures.GestureFrameLayout
android:id="@+id/gif_view_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="matrix"
android:visibility="gone"/>
android:layout_centerInParent="true"
android:visibility="gone">
<pl.droidsonroids.gif.GifTextureView
android:id="@+id/gif_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"/>
</com.alexvasilkov.gestures.GestureFrameLayout>
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
android:id="@+id/subsampling_view"

View file

@ -11,12 +11,19 @@
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<com.alexvasilkov.gestures.GestureFrameLayout
android:id="@+id/video_surface_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextureView
android:id="@+id/video_surface"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
</com.alexvasilkov.gestures.GestureFrameLayout>
<com.simplemobiletools.gallery.pro.views.MediaSideScroll
android:id="@+id/video_volume_controller"
android:layout_width="@dimen/media_side_slider_width"
@ -49,23 +56,6 @@
android:padding="20dp"
android:src="@drawable/ic_play_outline"/>
<TextView
android:id="@+id/slide_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="120dp"
android:alpha="0"
android:background="@drawable/black_rounded_background"
android:gravity="center"
android:paddingLeft="@dimen/activity_margin"
android:paddingTop="@dimen/medium_margin"
android:paddingRight="@dimen/activity_margin"
android:paddingBottom="@dimen/medium_margin"
android:textColor="@android:color/white"
android:textSize="@dimen/extra_big_text_size"/>
<ImageView
android:id="@+id/panorama_outline"
android:layout_width="@dimen/play_outline_size_big"
@ -91,4 +81,21 @@
<include layout="@layout/bottom_video_time_holder"/>
<TextView
android:id="@+id/slide_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="120dp"
android:alpha="0"
android:background="@drawable/black_rounded_background"
android:gravity="center"
android:paddingLeft="@dimen/activity_margin"
android:paddingTop="@dimen/medium_margin"
android:paddingRight="@dimen/activity_margin"
android:paddingBottom="@dimen/medium_margin"
android:textColor="@android:color/white"
android:textSize="@dimen/extra_big_text_size"/>
</RelativeLayout>

View file

@ -176,6 +176,7 @@
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">المصغرات</string>

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Thumbnails</string>
@ -198,7 +199,7 @@
<string name="faq_5_text">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.</string>
<string name="faq_6_title">Why do folders with music cover art or stickers show up?</string>
<string name="faq_6_text">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.</string>
<string name="faq_7_title">A folder with images isn\'t showing up, what can I do?</string>
<string name="faq_7_title">A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do?</string>
<string name="faq_7_text">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.</string>
<string name="faq_8_title">What if I want just a few particular folders visible?</string>
<string name="faq_8_text">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.

View file

@ -31,7 +31,7 @@
<string name="fix_date_taken">Fixar la data de presa</string>
<string name="fixing">Fixant…</string>
<string name="dates_fixed_successfully">Data fixada correctament</string>
<string name="share_resized">Share a resized version</string>
<string name="share_resized">Comparteix una versió redimensionada</string>
<!-- Filter -->
<string name="filter_media">Filtre d\'arxius</string>
@ -116,7 +116,7 @@
<string name="loop_slideshow">Presentació de diapositives</string>
<string name="slideshow_ended">S\'ha acabat la presentació de diapositives</string>
<string name="no_media_for_slideshow">No s\'han trobat mitjans per a la presentació de diapositives</string>
<string name="use_crossfade_animation">Use crossfade animations</string>
<string name="use_crossfade_animation">Utilitzeu animacions creuades</string>
<!-- View types -->
<string name="change_view_type">Canviar el tipus de vista</string>
@ -170,8 +170,9 @@
<string name="show_highest_quality">Mostra imatges amb la màxima qualitat possible</string>
<string name="show_recycle_bin_last">Mostra la paperera de reciclatge com a últim element a la pantalla principal</string>
<string name="allow_down_gesture">Permet tancar la vista de pantalla completa amb un gest avall</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="allow_one_to_one_zoom">Permet 1:1 zoom amb dos tocs dobles</string>
<string name="open_videos_on_separate_screen">Obriu sempre vídeos en una pantalla independent amb nous gestos horitzontals</string>
<string name="show_notch">Mostra una osca si està disponible</string>
<!-- Setting sections -->
<string name="thumbnails">Miniatures</string>
@ -193,7 +194,7 @@
<string name="faq_3_title">Com puc fer que un àlbum sempre aparegui a la part superior?</string>
<string name="faq_3_text">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.</string>
<string name="faq_4_title">Com puc fer avançar els vídeos?</string>
<string name="faq_4_text">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.</string>
<string name="faq_4_text">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.</string>
<string name="faq_5_title">Quina és la diferència entre ocultar i excloure una carpeta?</string>
<string name="faq_5_text">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.</string>
<string name="faq_6_title">Per què apareixen les carpetes amb les portades de la música o adhesius?</string>
@ -216,7 +217,7 @@
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
<!-- Short description has to have less than 80 chars -->
<string name="app_short_description">An offline gallery for managing your files without ads, respecting your privacy.</string>
<string name="app_short_description">Una galeria senzilla, sense anuncis i respectant la vostra privadesa.</string>
<string name="app_long_description">
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.

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Povolit zavírání celoobrazovkového režimu tažením prstu dolů</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Náhledy</string>

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Luk fuldskærmsvisning ved at swipe ned</string>
<string name="allow_one_to_one_zoom">Tillad 1:1 zooming med to dobbelttryk</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Miniaturer</string>
@ -198,7 +199,7 @@
<string name="faq_5_text">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.</string>
<string name="faq_6_title">Why do folders with music cover art or stickers show up?</string>
<string name="faq_6_text">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.</string>
<string name="faq_7_title">A folder with images isn\'t showing up, what can I do?</string>
<string name="faq_7_title">A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do?</string>
<string name="faq_7_text">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.</string>
<string name="faq_8_title">What if I want just a few particular folders visible?</string>
<string name="faq_8_text">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.

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Erlaube das Schließen der Vollbildansicht mit einer Abwärtsgeste</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Thumbnails</string>

View file

@ -30,8 +30,8 @@
<string name="use_default_orientation">Χρήση προεπιλογής</string>
<string name="fix_date_taken">Διόρθωση ημερ. λήψης</string>
<string name="fixing">Διορθώνεται…</string>
<string name="dates_fixed_successfully">Ημερ. διορθώθηκε με επιτυχία</string>
<string name="share_resized">Share a resized version</string>
<string name="dates_fixed_successfully">Η Ημερ. διορθώθηκε με επιτυχία</string>
<string name="share_resized">Διαμοιρασμός έκδοσης με αλλαγμένο μέγεθος</string>
<!-- Filter -->
<string name="filter_media">Φιλτράρισμα πολυμέσων</string>
@ -89,7 +89,7 @@
<string name="flip_horizontally">Οριζόντιο αναποδογύρισμα</string>
<string name="flip_vertically">Κατακόρυφο αναποδογύρισμα</string>
<string name="free_aspect_ratio">Ελεύθερο</string> <!-- available as an option: 1:1, 4:3, 16:9, free -->
<string name="other_aspect_ratio">Other</string> <!-- available as an option: 1:1, 4:3, 16:9, free, other -->
<string name="other_aspect_ratio">Άλλο</string> <!-- available as an option: 1:1, 4:3, 16:9, free, other -->
<!-- Set wallpaper -->
<string name="simple_wallpaper">Simple Wallpaper</string>
@ -116,7 +116,7 @@
<string name="loop_slideshow">Επανάληψη εμφάνισης διαφανιών</string>
<string name="slideshow_ended">Η εμφάνιση διαφανειών τελείωσε</string>
<string name="no_media_for_slideshow">Δεν βρέθηκαν πολυμέσα για την εμφάνιση διαφανειών</string>
<string name="use_crossfade_animation">Use crossfade animations</string>
<string name="use_crossfade_animation">Χρήση κίνησης εικόνων με διαγώνιο ξεθώριασμα</string>
<!-- View types -->
<string name="change_view_type">Αλλαγή τύπου εμφάνισης</string>
@ -128,8 +128,8 @@
<string name="group_by">Ομαδοποίηση κατά</string>
<string name="do_not_group_files">Χωρίς</string>
<string name="by_folder">Φάκελο</string>
<string name="by_last_modified">Τελευταία τροποποίηση</string>
<string name="by_date_taken">Ημερομηνία λήψης</string>
<string name="by_last_modified">Τελευταία τροπ/ηση</string>
<string name="by_date_taken">Ημερομ. λήψης</string>
<string name="by_file_type">Τύπο αρχείου</string>
<string name="by_extension">Επέκταση</string>
@ -170,8 +170,9 @@
<string name="show_highest_quality">Εμφάνιση εικόνων με την υψηλότερη δυνατή ποιότητα</string>
<string name="show_recycle_bin_last">Εμφάνιση του Κάδου ως τελευταίο στοιχείο στην κύρια οθόνη</string>
<string name="allow_down_gesture">Επιτρέψτε το κλείσιμο προβολής πλήρους οθόνης με χειρονομία προς τα κάτω</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="allow_one_to_one_zoom">Allow 1:1 μεγένθυση με δύο διπλά χτυπήματα</string>
<string name="open_videos_on_separate_screen">Να ανοίγονται πάντα τα βίντεο σε ξεχωριστή οθόνη με νέες οριζόντιες χειρονομίες</string>
<string name="show_notch">Εμφάνιση μιας εγκοπή αν διατίθεται</string>
<!-- Setting sections -->
<string name="thumbnails">Εικονίδια</string>
@ -193,7 +194,7 @@
<string name="faq_3_title">Πώς μπορώ να κάνω ένα άλμπουμ να φαίνεται στην κορυφή;</string>
<string name="faq_3_text">Μπορείτε να πατήσετε παρατεταμένα στο άλμπουμ και να επιλέξετε το εικονίδιο καρφιτσώματος στο μενού, αυτό θα το καρφιτσώσει στην κορυφή. Επίσης μπορείτε να καρφιτσώσετε πολλαπλούς φακέλους, τα καρφιτσωμένα αντικείμενα θα είναι ταξινομημένα με την προεπιλεγμένη μέθοδο.</string>
<string name="faq_4_title">Πώς μπορώ να τρέξω μπροστά (fast-forward) τα βίντεο;</string>
<string name="faq_4_text">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.</string>
<string name="faq_4_text">Μπορείτε είτε να σύρετε το δάχτυλό σας οριζόντια πάνω από το πρόγραμμα αναπαραγωγής Βίντεο ή να κάνετε κλικ στα γράμματα της τρέχουσας ή της μέγιστης διάρκειας κοντά στο Γραμμή Αναζήτησης. Αυτό θα μετακινήσει το βίντεο προς τα πίσω ή προς τα εμπρός.</string>
<string name="faq_5_title">Ποια είναι διαφορά μεταξύ απόκρυψης και εξαίρεσης ενός φακέλου;</string>
<string name="faq_5_text">Η εξαίρεση δεν επιτρέπει την εμφάνιση του φακέλου μόνο στο Simple Gallery, ενώ η απόκρυψη λειτουργεί σε επίπεδο συστήματος και θα αποκρύψει τον φάκελο και από άλλες εφαρμογές γκάλερι. Λειτουργεί δημιουργώντας ένα άδειο \".nomedia\" αρχείο στον επιλεγμένο φάκελο, το οποίο μπορείτε να το διαγράψετε και με οποιονδήποτε διαχειριστή αρχείων.</string>
<string name="faq_6_title">Γιατί εμφανίζονται φάκελοι με εξώφυλλο μουσικής ή αυτόκολλητα;</string>
@ -216,7 +217,7 @@
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
<!-- Short description has to have less than 80 chars -->
<string name="app_short_description">An offline gallery for managing your files without ads, respecting your privacy.</string>
<string name="app_short_description">Μια offline Gallery χωρίς διαφημίσεις, σεβόμενοι τα προσωπικά σας δεδομένα.</string>
<string name="app_long_description">
Μια εξαιρετικά προσαρμόσιμη Gallery ικανή να εμφανίζει πολλούς διαφορετικούς τύπους εικόνας και βίντεο, όπως SVGs, RAWs, πανοραμικές φωτογραφίες και βίντεο.

View file

@ -31,7 +31,7 @@
<string name="fix_date_taken">Fijar fecha de toma</string>
<string name="fixing">Fijando…</string>
<string name="dates_fixed_successfully">Fecha fijada correctamente</string>
<string name="share_resized">Share a resized version</string>
<string name="share_resized">Comparte una versión redimensionada</string>
<!-- Filter -->
<string name="filter_media">Filtro de medios</string>
@ -116,7 +116,7 @@
<string name="loop_slideshow">Presentación de diapositivas</string>
<string name="slideshow_ended">La diapositiva terminó</string>
<string name="no_media_for_slideshow">No se han encontrado medios para la presentación de diapositivas</string>
<string name="use_crossfade_animation">Use crossfade animations</string>
<string name="use_crossfade_animation">Usa animaciones de crossfade.</string>
<!-- View types -->
<string name="change_view_type">Cambiar tipo de vista</string>
@ -170,8 +170,9 @@
<string name="show_highest_quality">Muestra imágenes con la mayor calidad posible</string>
<string name="show_recycle_bin_last">Mostrar la Papelera de reciclaje como el último elemento en la pantalla principal</string>
<string name="allow_down_gesture">Permite cerrar la vista de pantalla completa con un gesto hacia abajo.</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="allow_one_to_one_zoom">Permitir zoom 1:1 con dos toques dobles</string>
<string name="open_videos_on_separate_screen">Siempre abre videos en una pantalla separada con nuevos gestos horizontales</string>
<string name="show_notch">Mostrar una muesca si está disponible</string>
<!-- Setting sections -->
<string name="thumbnails">Miniaturas</string>
@ -193,7 +194,7 @@
<string name="faq_3_title">¿Cómo puedo hacer que un álbum siempre aparezca en la parte superior?</string>
<string name="faq_3_text">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.</string>
<string name="faq_4_title">¿Cómo puedo avanzar videos?</string>
<string name="faq_4_text">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.</string>
<string name="faq_4_text">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.</string>
<string name="faq_5_title">¿Cuál es la diferencia entre ocultar y excluir una carpeta?</string>
<string name="faq_5_text">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.</string>
<string name="faq_6_title">¿Por qué aparecen las carpetas con la portada de la música o las pegatinas?</string>
@ -216,7 +217,7 @@
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
<!-- Short description has to have less than 80 chars -->
<string name="app_short_description">An offline gallery for managing your files without ads, respecting your privacy.</string>
<string name="app_short_description">Una galería senzilla, sin anuncios y respetando su privacidad.</string>
<string name="app_long_description">
Una galería altamente personalizable capaz de mostrar diferentes tipos de imágenes y videos, incluyendo SVG, RAW, fotos panorámicas y videos.

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Esikatselukuvat</string>
@ -198,7 +199,7 @@
<string name="faq_5_text">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.</string>
<string name="faq_6_title">Why do folders with music cover art or stickers show up?</string>
<string name="faq_6_text">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.</string>
<string name="faq_7_title">A folder with images isn\'t showing up, what can I do?</string>
<string name="faq_7_title">A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do?</string>
<string name="faq_7_text">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.</string>
<string name="faq_8_title">What if I want just a few particular folders visible?</string>
<string name="faq_8_text">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.

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Fermeture de la vue plein écran par un geste vers le bas</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Miniatures</string>

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Iconas</string>

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Omogućite zatvaranje prikaza preko cijelog zaslona pokretom prema dolje</string>
<string name="allow_one_to_one_zoom">Dopusti zumiranje 1: 1 s dva dvostruka dodira</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Sličice</string>

View file

@ -31,7 +31,7 @@
<string name="fix_date_taken">Dátum javítása</string>
<string name="fixing">Javítás…</string>
<string name="dates_fixed_successfully">Sikeres dátum javítás</string>
<string name="share_resized">Share a resized version</string>
<string name="share_resized">Átméretezett verzió megosztása</string>
<!-- Filter -->
<string name="filter_media">Média szűrő</string>
@ -172,7 +172,8 @@
<string name="show_recycle_bin_last">Mutassa a Lomtárat a fő képernyő utolsó elemeként</string>
<string name="allow_down_gesture">Engedélyezi a teljes képernyős nézetet a lefelé mozdulattal</string>
<string name="allow_one_to_one_zoom">Engedélyezi az 1:1 nagyítást két dupla érintéssel</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="open_videos_on_separate_screen">Mindig külön képernyőn nyissa meg a videókat új vízszintes mozdulattal</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Miniatűrök</string>

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Izinkan keluar dari layar penuh dengan menggeser kebawah</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Thumbnail</string>

View file

@ -31,7 +31,7 @@
<string name="fix_date_taken">Correggi valore Data acquisizione</string>
<string name="fixing">Correzione in corso…</string>
<string name="dates_fixed_successfully">Date aggiornate correttamente</string>
<string name="share_resized">Share a resized version</string>
<string name="share_resized">Condividi una versione ridimensionata</string>
<!-- Filter -->
<string name="filter_media">Filtra i file</string>
@ -172,6 +172,7 @@
<string name="allow_down_gesture">Chiudi la visuale a schermo intero con un gesto verso il basso</string>
<string name="allow_one_to_one_zoom">Permetti l\'ingrandimento 1:1 con un doppio tasto</string>
<string name="open_videos_on_separate_screen">Apri sempre i video su uno schermo separato con i nuovi movimenti orizzontali</string>
<string name="show_notch">Mostra un notch se disponibile</string>
<!-- Setting sections -->
<string name="thumbnails">Anteprime</string>

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">サムネイル設定</string>
@ -198,7 +199,7 @@
<string name="faq_5_text">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.</string>
<string name="faq_6_title">Why do folders with music cover art or stickers show up?</string>
<string name="faq_6_text">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.</string>
<string name="faq_7_title">A folder with images isn\'t showing up, what can I do?</string>
<string name="faq_7_title">A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do?</string>
<string name="faq_7_text">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.</string>
<string name="faq_8_title">What if I want just a few particular folders visible?</string>
<string name="faq_8_text">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.

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">섬네일</string>
@ -198,7 +199,7 @@
<string name="faq_5_text">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.</string>
<string name="faq_6_title">Why do folders with music cover art or stickers show up?</string>
<string name="faq_6_text">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.</string>
<string name="faq_7_title">A folder with images isn\'t showing up, what can I do?</string>
<string name="faq_7_title">A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do?</string>
<string name="faq_7_text">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.</string>
<string name="faq_8_title">What if I want just a few particular folders visible?</string>
<string name="faq_8_text">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.

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Miniatiūros</string>

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Tillat lukking av mediavisningen med en nedoverbevegelse</string>
<string name="allow_one_to_one_zoom">Tillat å zoome 1:1 med to dobbeltrykk</string>
<string name="open_videos_on_separate_screen">Åpne alltid videoer på en separat skjerm med nye horisontale bevegelser</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Minibilder</string>
@ -198,7 +199,7 @@
<string name="faq_5_text">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.</string>
<string name="faq_6_title">Why do folders with music cover art or stickers show up?</string>
<string name="faq_6_text">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.</string>
<string name="faq_7_title">A folder with images isn\'t showing up, what can I do?</string>
<string name="faq_7_title">A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do?</string>
<string name="faq_7_text">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.</string>
<string name="faq_8_title">What if I want just a few particular folders visible?</string>
<string name="faq_8_text">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.

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Naar beneden vegen om volledig scherm af te sluiten</string>
<string name="allow_one_to_one_zoom">1:1 zoomen na 2x dubbelklikken</string>
<string name="open_videos_on_separate_screen">Video\'s altijd in apart scherm met horizontale veeggebaren openen</string>
<string name="show_notch">Inkeping scherm tonen indien aanwezig</string>
<!-- Setting sections -->
<string name="thumbnails">Miniatuurvoorbeelden</string>

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Zezwalaj na zamykanie pełnoekranowego widoku gestem pociągnięcia w dół</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
   <string name="thumbnails">Miniatury</string>

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Miniaturas</string>
@ -198,7 +199,7 @@
<string name="faq_5_text">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.</string>
<string name="faq_6_title">Why do folders with music cover art or stickers show up?</string>
<string name="faq_6_text">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.</string>
<string name="faq_7_title">A folder with images isn\'t showing up, what can I do?</string>
<string name="faq_7_title">A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do?</string>
<string name="faq_7_text">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.</string>
<string name="faq_8_title">What if I want just a few particular folders visible?</string>
<string name="faq_8_text">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.

View file

@ -31,7 +31,7 @@
<string name="fix_date_taken">Corrigir data de obtenção</string>
<string name="fixing">A corrigir…</string>
<string name="dates_fixed_successfully">Dados corrigidos com sucesso</string>
<string name="share_resized">Share a resized version</string>
<string name="share_resized">Partilhar foto redimensionada</string>
<!-- Filter -->
<string name="filter_media">Filtrar multimédia</string>
@ -111,7 +111,7 @@
<string name="include_videos">Incluir vídeos</string>
<string name="include_gifs">Incluir GIF</string>
<string name="random_order">Ordem aleatória</string>
<string name="use_fade">Usar animações</string>
<string name="use_fade">Utilizar animações</string>
<string name="move_backwards">Mover para trás</string>
<string name="loop_slideshow">Apresentação em ciclo</string>
<string name="slideshow_ended">Apresentação terminada</string>
@ -172,6 +172,7 @@
<string name="allow_down_gesture">Sair de ecrã completo com um gesto para baixo</string>
<string name="allow_one_to_one_zoom">Permitir ampliação 1:1 com dois toques</string>
<string name="open_videos_on_separate_screen">Abrir vídeos em ecrã distinto com os novos toques horizontais</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Miniaturas</string>
@ -198,7 +199,7 @@
<string name="faq_5_text">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.</string>
<string name="faq_6_title">Why do folders with music cover art or stickers show up?</string>
<string name="faq_6_text">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.</string>
<string name="faq_7_title">A folder with images isn\'t showing up, what can I do?</string>
<string name="faq_7_title">A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do?</string>
<string name="faq_7_text">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.</string>
<string name="faq_8_title">What if I want just a few particular folders visible?</string>
<string name="faq_8_text">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.

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Отключать полноэкранный режим жестом вниз</string>
<string name="allow_one_to_one_zoom">Масштаб 1:1 двумя двойными нажатиями</string>
<string name="open_videos_on_separate_screen">Воспроизводить видео на отдельном экране с управлением позицией горизонтальными жестами</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Миниатюры</string>

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Povoliť zatváranie celoobrazovkového režimu potiahnutím prsta dole</string>
<string name="allow_one_to_one_zoom">Povoliť 1:1 priblíženie dvojnásobným dvojklikom</string>
<string name="open_videos_on_separate_screen">Vždy otvárať videá na vlastnej obrazovke s novými vodorovnými gestami</string>
<string name="show_notch">Zobraziť výrez obrazovky, ak je dostupný</string>
<!-- Setting sections -->
<string name="thumbnails">Náhľady</string>
@ -198,7 +199,7 @@
<string name="faq_5_text">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.</string>
<string name="faq_6_title">Prečo sa mi zobrazujú priečinky s obalmi hudobných albumov, alebo nálepkami?</string>
<string name="faq_6_text">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.</string>
<string name="faq_7_title">Priečinok s fotkami sa mi nezobrazuje, čo môžem urobiť?</string>
<string name="faq_7_title">Priečinok s fotkami sa mi nezobrazuje, alebo priečinok nezobrazuje všetky položky. Čo s tým môžem urobiť?</string>
<string name="faq_7_text">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.</string>
<string name="faq_8_title">Čo v prípade, ak chcem mať zobrazených iba pár priečinkov?</string>
<string name="faq_8_text">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.

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Dovoli zapiranje celozaslonskega načina z gesto navzdol</string>
<string name="allow_one_to_one_zoom">Dovoli 1:1 povečavo z dvojnim pritiskom</string>
<string name="open_videos_on_separate_screen">Vedno odpri videoposnetke na ločenem zaslonu z novimi horizontalnimi gestami</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Sličice</string>

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Miniatyrer</string>
@ -198,7 +199,7 @@
<string name="faq_5_text">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.</string>
<string name="faq_6_title">Why do folders with music cover art or stickers show up?</string>
<string name="faq_6_text">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.</string>
<string name="faq_7_title">A folder with images isn\'t showing up, what can I do?</string>
<string name="faq_7_title">A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do?</string>
<string name="faq_7_text">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.</string>
<string name="faq_8_title">What if I want just a few particular folders visible?</string>
<string name="faq_8_text">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.

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Tam ekran görünümünü aşağı hareketi ile kapatmaya izin ver</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Küçük resimler</string>

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Дозволити закриття повноекранного перегляду свайпом згори вниз</string>
<string name="allow_one_to_one_zoom">Дозволити масштабування до 1:1 подвійним тапом</string>
<string name="open_videos_on_separate_screen">Завжди відкривати відео на окремому екрані з новими горизонтальними жестами</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Ескізи</string>

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">使用下滑手势关闭全屏视图</string>
<string name="allow_one_to_one_zoom">双击两次后 1:1 放大图像</string>
<string name="open_videos_on_separate_screen">使用新的水平手势在独立页面播放视频</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">缩略图</string>

View file

@ -31,7 +31,7 @@
<string name="fix_date_taken">修復拍照日期數值</string>
<string name="fixing">修復中…</string>
<string name="dates_fixed_successfully">日期修復成功</string>
<string name="share_resized">Share a resized version</string>
<string name="share_resized">分享調整大小的版本</string>
<!-- Filter -->
<string name="filter_media">篩選媒體檔案</string>
@ -172,6 +172,7 @@
<string name="allow_down_gesture">允許用下滑手勢來關閉全螢幕檢視</string>
<string name="allow_one_to_one_zoom">允許用兩次雙擊來1:1縮放</string>
<string name="open_videos_on_separate_screen">總是用新的水平手勢在獨立畫面開啟影片</string>
<string name="show_notch">如果可以,顯示瀏海螢幕</string>
<!-- Setting sections -->
<string name="thumbnails">縮圖</string>

View file

@ -2,6 +2,17 @@
<resources>
<!-- Release notes -->
<string name="release_225">
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
</string>
<string name="release_221">
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
</string>
<string name="release_220">Reverted to the old way of opening videos, opening on separate screen can be enabled in the app settings</string>
<string name="release_217">
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
</string>
<string name="release_206">Added a new option for password protecting file deletion/move</string>
<string name="release_202">Added a new option for showing the Recycle Bin as the last folder</string>
<string name="release_201">
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
</string>
<string name="release_184">
Added Panorama photo support\n
Allow forcing portrait/landscape orientation at fullscreen view\n
Allow customizing visible fullscreen bottom actions in the app settings
</string>
<string name="release_182">
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
</string>
<string name="release_181">Allow selecting Favorite items for easy access</string>
<string name="release_180">Allow filtering out RAW images separately</string>
<string name="release_178">Added sorting by Date Taken</string>
<string name="release_177">Allow customizing the app launcher icon color</string>
<string name="release_163">Added toggles for disabling Pull-to-refresh and permanent Delete dialog confirmation skipping</string>
<string name="release_159">
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
</string>
<string name="release_158">Added optional one-finger drag zoom, disabled by default</string>
<string name="release_143">
Added new options to use english language on non-english devices, to password protect whole app and to lock screen orientation at fullscreen view
</string>
<string name="release_138">Added an option to keep last-modified field at file copy/move/rename</string>
<string name="release_137">Added an option to hide folder media count on the main screen</string>
<string name="release_136">Added an option to show customizable extended details over fullscreen media</string>
<string name="release_133">
Added fingerprint to hidden item protection\n
Added a new List view type
</string>
<string name="release_127">
Added a switch for disabling video gestures\n
Added a switch for deleting empty folders after deleting content
</string>
<string name="release_125">Moved media type filter from Settings to the Action menu</string>
<string name="release_123">Allow changing the screen brightness and volume at videos by vertically dragging the screen sides</string>
<string name="release_122">Added slideshow at the fullscreen view</string>
<string name="release_119">Added pattern/pin protection for showing hidden items</string>
<string name="release_118">Added a toggle for replacing Share with Rotate at fullscreen media</string>
<string name="release_115">
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
</string>
<string name="release_114">Added an option for automatically hiding the system UI at entering fullscreen mode</string>
<string name="release_112">Added an option for enabling horizontal scrolling</string>
<string name="release_108">Allow setting custom folder covers</string>
<string name="release_98">
Allow selecting multiple items by finger dragging\n
Added an option to always use black background at fullscreen media
</string>
<string name="release_97">Allow hiding individual files by prepending filenames with a dot</string>
<string name="release_94">Added horizontal and vertical image flipping in the image editor</string>
<string name="release_93">
Allow setting portrait wallpapers\n
Added more fields in photo Properties dialog
</string>
<string name="release_89">
Improved fullscreen image zooming\n
Added more settings related to screen autorotating\n
Split copy and move functions for ease of use
</string>
<string name="release_88">
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
</string>
<string name="release_84">
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
</string>
<string name="release_83">
Fixed some sharing and editor issues\n
Sorry for the frequent updates lately, they should be stopped now.
</string>
<string name="release_77">
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
</string>
<string name="release_76">Added an option to toggle gif animation at thumbnails</string>
<string name="release_74">Allow setting different sorting per folder</string>
<string name="release_72">
Implement proper folder hiding via .nomedia file\n
Allow managing excluded folders in Settings
</string>
<string name="release_70">Added menu items for easy image rotating in fullscreen view</string>
<string name="release_69">Added menu buttons for changing the column count</string>
<string name="release_66">Allow picking colors by hex codes</string>
<string name="release_65">Allow showing the photos and videos on a map, if there are available map coordinates</string>
<string name="release_62">Show some additional Exif data at photo properties</string>
<string name="release_58">
Allow zooming pngs and gifs\n
Allow creating new folders at Copy/Move or Save as dialog destinations
</string>
<string name="release_54">Added an option to loop videos automatically</string>
<string name="release_52">
Added more color customization options\n
Your settings have been cleared, please reset them
</string>
<string name="release_51">Allow changing the column count with pinch gestures</string>
<string name="release_50">Added an option to display images or videos only</string>
<string name="release_49">Added a Select all button at selecting media and folders</string>
<string name="release_47">
Added an image resizer to the editor\n
Allow displaying images and videos from all folders together
</string>
<string name="release_46">Allow pinning folders at the top</string>
</resources>

View file

@ -172,6 +172,7 @@
<string name="allow_down_gesture">Allow closing the fullscreen view with a down gesture</string>
<string name="allow_one_to_one_zoom">Allow 1:1 zooming in with two double taps</string>
<string name="open_videos_on_separate_screen">Always open videos on a separate screen with new horizontal gestures</string>
<string name="show_notch">Show a notch if available</string>
<!-- Setting sections -->
<string name="thumbnails">Thumbnails</string>
@ -198,7 +199,7 @@
<string name="faq_5_text">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.</string>
<string name="faq_6_title">Why do folders with music cover art or stickers show up?</string>
<string name="faq_6_text">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.</string>
<string name="faq_7_title">A folder with images isn\'t showing up, what can I do?</string>
<string name="faq_7_title">A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do?</string>
<string name="faq_7_text">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.</string>
<string name="faq_8_title">What if I want just a few particular folders visible?</string>
<string name="faq_8_text">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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB

After

Width:  |  Height:  |  Size: 581 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 KiB

After

Width:  |  Height:  |  Size: 731 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 KiB

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 378 KiB

After

Width:  |  Height:  |  Size: 592 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB