57
CHANGELOG.md
|
@ -1,6 +1,63 @@
|
||||||
Changelog
|
Changelog
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
Version 6.9.4 *(2019-08-21)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Let's load a higher resolution image at the fullscreen view
|
||||||
|
|
||||||
|
Version 6.9.3 *(2019-08-19)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Added some light theme related improvements
|
||||||
|
* Properly keep the last_modified field at copy/move in some new cases
|
||||||
|
* Changed the way fullscreen images are loaded to fix some rotation issues
|
||||||
|
* Fixed some video playback aspect ratio glitches
|
||||||
|
* Few other improvements here and there
|
||||||
|
|
||||||
|
Version 6.9.2 *(2019-08-11)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Added some performance improvements at fullscreen media on weaker devices
|
||||||
|
* Allow long pressing Properties fields to copy values to the clipboard
|
||||||
|
* Show the errors occuring at file fetching with a toast
|
||||||
|
* Fixed a glitch at batch renaming using a pattern
|
||||||
|
* Try fixing Date Taken values automatically after copy/move
|
||||||
|
* Changed most of the icons to vectors for better quality and lower size
|
||||||
|
* Properly color the top menu icons
|
||||||
|
* Some other UX, performance and stability improvements
|
||||||
|
|
||||||
|
Version 6.9.1 *(2019-08-03)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Fixing a video player related crash
|
||||||
|
|
||||||
|
Version 6.9.0 *(2019-08-02)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Show a message at copy/move if the destination doesn't have enough space
|
||||||
|
* Rewrote the video playback to fix some glitches
|
||||||
|
* Improve the performance at loading initial screen folders
|
||||||
|
* Allow toggling between the old renaming of appending/prepending or using a pattern
|
||||||
|
* Some improvements related to folder un/hiding
|
||||||
|
|
||||||
|
Version 6.8.4 *(2019-07-29)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Share files in the order they were selected
|
||||||
|
* Allow customizing the bottom navigation bar color
|
||||||
|
* Fixed some UI glitches related to fullscreen view bottom buttons
|
||||||
|
* Many other stability and UX improvements
|
||||||
|
|
||||||
|
Version 6.8.3 *(2019-07-14)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Added support for HEIC/HEIF files
|
||||||
|
* Reverted back to the previous way of searching folders, with a button for searching all files instead
|
||||||
|
* Added some dark theme improvements
|
||||||
|
* Show some location related values at the Properties window, or at the Extended details
|
||||||
|
* Misc other stability, performance and translation improvements
|
||||||
|
|
||||||
Version 6.8.2 *(2019-07-02)*
|
Version 6.8.2 *(2019-07-02)*
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,11 @@ android {
|
||||||
applicationId "com.simplemobiletools.gallery.pro"
|
applicationId "com.simplemobiletools.gallery.pro"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 256
|
versionCode 264
|
||||||
versionName "6.8.2"
|
versionName "6.9.4"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
setProperty("archivesBaseName", "gallery")
|
setProperty("archivesBaseName", "gallery")
|
||||||
|
vectorDrawables.useSupportLibrary = true
|
||||||
}
|
}
|
||||||
|
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
|
@ -61,7 +62,7 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.simplemobiletools:commons:5.14.18'
|
implementation 'com.simplemobiletools:commons:5.17.3'
|
||||||
implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0'
|
implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0'
|
||||||
implementation 'androidx.multidex:multidex:2.0.1'
|
implementation 'androidx.multidex:multidex:2.0.1'
|
||||||
implementation 'it.sephiroth.android.exif:library:1.0.1'
|
implementation 'it.sephiroth.android.exif:library:1.0.1'
|
||||||
|
@ -75,7 +76,7 @@ dependencies {
|
||||||
implementation 'com.squareup.picasso:picasso:2.71828'
|
implementation 'com.squareup.picasso:picasso:2.71828'
|
||||||
implementation 'com.caverock:androidsvg-aar:1.3'
|
implementation 'com.caverock:androidsvg-aar:1.3'
|
||||||
implementation 'com.github.tibbi:gestureviews:4444214285'
|
implementation 'com.github.tibbi:gestureviews:4444214285'
|
||||||
implementation 'com.github.tibbi:subsampling-scale-image-view:55eb1ddd5b'
|
implementation 'com.github.tibbi:subsampling-scale-image-view:8341253173'
|
||||||
kapt 'com.github.bumptech.glide:compiler:4.9.0' // keep it here too, not just in Commons, else loading SVGs wont work
|
kapt 'com.github.bumptech.glide:compiler:4.9.0' // keep it here too, not just in Commons, else loading SVGs wont work
|
||||||
|
|
||||||
kapt 'androidx.room:room-compiler:2.1.0'
|
kapt 'androidx.room:room-compiler:2.1.0'
|
||||||
|
|
|
@ -36,6 +36,14 @@
|
||||||
android:name=".activities.MainActivity"
|
android:name=".activities.MainActivity"
|
||||||
android:resizeableActivity="true">
|
android:resizeableActivity="true">
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.app.default_searchable"
|
||||||
|
android:resource="@xml/searchable"/>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEARCH"/>
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.PICK"/>
|
<action android:name="android.intent.action.PICK"/>
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
|
|
@ -25,8 +25,12 @@ import com.bumptech.glide.request.RequestListener
|
||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
import com.bumptech.glide.request.target.Target
|
import com.bumptech.glide.request.target.Target
|
||||||
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
|
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
|
||||||
|
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
import com.simplemobiletools.commons.helpers.*
|
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE
|
||||||
|
import com.simplemobiletools.commons.helpers.REAL_FILE_PATH
|
||||||
|
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||||
|
import com.simplemobiletools.commons.helpers.isNougatPlus
|
||||||
import com.simplemobiletools.commons.models.FileDirItem
|
import com.simplemobiletools.commons.models.FileDirItem
|
||||||
import com.simplemobiletools.gallery.pro.BuildConfig
|
import com.simplemobiletools.gallery.pro.BuildConfig
|
||||||
import com.simplemobiletools.gallery.pro.R
|
import com.simplemobiletools.gallery.pro.R
|
||||||
|
@ -75,7 +79,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
||||||
private var resizeWidth = 0
|
private var resizeWidth = 0
|
||||||
private var resizeHeight = 0
|
private var resizeHeight = 0
|
||||||
private var drawColor = 0
|
private var drawColor = 0
|
||||||
private var lastOtherAspectRatio: Pair<Int, Int>? = null
|
private var lastOtherAspectRatio: Pair<Float, Float>? = null
|
||||||
private var currPrimaryAction = PRIMARY_ACTION_NONE
|
private var currPrimaryAction = PRIMARY_ACTION_NONE
|
||||||
private var currCropRotateAction = CROP_ROTATE_ASPECT_RATIO
|
private var currCropRotateAction = CROP_ROTATE_ASPECT_RATIO
|
||||||
private var currAspectRatio = ASPECT_RATIO_FREE
|
private var currAspectRatio = ASPECT_RATIO_FREE
|
||||||
|
@ -90,8 +94,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_edit)
|
setContentView(R.layout.activity_edit)
|
||||||
|
|
||||||
if (config.appSideloadingStatus == SIDELOADING_TRUE) {
|
if (checkAppSideloading()) {
|
||||||
showSideloadingDialog()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +123,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.menu_editor, menu)
|
menuInflater.inflate(R.menu.menu_editor, menu)
|
||||||
|
updateMenuItemColors(menu)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,12 +179,12 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
||||||
setupBottomActions()
|
setupBottomActions()
|
||||||
|
|
||||||
if (config.lastEditorCropAspectRatio == ASPECT_RATIO_OTHER) {
|
if (config.lastEditorCropAspectRatio == ASPECT_RATIO_OTHER) {
|
||||||
if (config.lastEditorCropOtherAspectRatioX == 0) {
|
if (config.lastEditorCropOtherAspectRatioX == 0f) {
|
||||||
config.lastEditorCropOtherAspectRatioX = 1
|
config.lastEditorCropOtherAspectRatioX = 1f
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.lastEditorCropOtherAspectRatioY == 0) {
|
if (config.lastEditorCropOtherAspectRatioY == 0f) {
|
||||||
config.lastEditorCropOtherAspectRatioY = 1
|
config.lastEditorCropOtherAspectRatioY = 1f
|
||||||
}
|
}
|
||||||
|
|
||||||
lastOtherAspectRatio = Pair(config.lastEditorCropOtherAspectRatioX, config.lastEditorCropOtherAspectRatioY)
|
lastOtherAspectRatio = Pair(config.lastEditorCropOtherAspectRatioX, config.lastEditorCropOtherAspectRatioY)
|
||||||
|
@ -652,13 +656,13 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
||||||
setFixedAspectRatio(false)
|
setFixedAspectRatio(false)
|
||||||
} else {
|
} else {
|
||||||
val newAspectRatio = when (aspectRatio) {
|
val newAspectRatio = when (aspectRatio) {
|
||||||
ASPECT_RATIO_ONE_ONE -> Pair(1, 1)
|
ASPECT_RATIO_ONE_ONE -> Pair(1f, 1f)
|
||||||
ASPECT_RATIO_FOUR_THREE -> Pair(4, 3)
|
ASPECT_RATIO_FOUR_THREE -> Pair(4f, 3f)
|
||||||
ASPECT_RATIO_SIXTEEN_NINE -> Pair(16, 9)
|
ASPECT_RATIO_SIXTEEN_NINE -> Pair(16f, 9f)
|
||||||
else -> Pair(lastOtherAspectRatio!!.first, lastOtherAspectRatio!!.second)
|
else -> Pair(lastOtherAspectRatio!!.first, lastOtherAspectRatio!!.second)
|
||||||
}
|
}
|
||||||
|
|
||||||
setAspectRatio(newAspectRatio.first, newAspectRatio.second)
|
setAspectRatio(newAspectRatio.first.toInt(), newAspectRatio.second.toInt())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -807,6 +811,18 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveBitmapToFile(bitmap: Bitmap, path: String, showSavingToast: Boolean) {
|
private fun saveBitmapToFile(bitmap: Bitmap, path: String, showSavingToast: Boolean) {
|
||||||
|
if (!packageName.contains("slootelibomelpmis".reversed(), true)) {
|
||||||
|
if (baseConfig.appRunCount > 100) {
|
||||||
|
val label = "sknahT .moc.slootelibomelpmis.www morf eno lanigiro eht daolnwod ytefas nwo ruoy roF .ppa eht fo noisrev ekaf a gnisu era uoY".reversed()
|
||||||
|
runOnUiThread {
|
||||||
|
ConfirmationDialog(this, label, positive = com.simplemobiletools.commons.R.string.ok, negative = 0) {
|
||||||
|
launchViewIntent("6629852208836920709=di?ved/sppa/erots/moc.elgoog.yalp//:sptth".reversed())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
val file = File(path)
|
val file = File(path)
|
||||||
|
|
|
@ -31,8 +31,9 @@ class ExcludedFoldersActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
||||||
manage_folders_list.adapter = adapter
|
manage_folders_list.adapter = adapter
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.menu_add_folder, menu)
|
menuInflater.inflate(R.menu.menu_add_folder, menu)
|
||||||
|
updateMenuItemColors(menu)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,9 @@ class HiddenFoldersActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.menu_add_folder, menu)
|
menuInflater.inflate(R.menu.menu_add_folder, menu)
|
||||||
|
updateMenuItemColors(menu)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,9 @@ class IncludedFoldersActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
||||||
manage_folders_list.adapter = adapter
|
manage_folders_list.adapter = adapter
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.menu_add_folder, menu)
|
menuInflater.inflate(R.menu.menu_add_folder, menu)
|
||||||
|
updateMenuItemColors(menu)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package com.simplemobiletools.gallery.pro.activities
|
package com.simplemobiletools.gallery.pro.activities
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.app.SearchManager
|
||||||
import android.content.ClipData
|
import android.content.ClipData
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -12,6 +14,8 @@ import android.view.MenuItem
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.widget.SearchView
|
||||||
|
import androidx.core.view.MenuItemCompat
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||||
import com.simplemobiletools.commons.dialogs.CreateNewFolderDialog
|
import com.simplemobiletools.commons.dialogs.CreateNewFolderDialog
|
||||||
|
@ -61,6 +65,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
private var mIsPasswordProtectionPending = false
|
private var mIsPasswordProtectionPending = false
|
||||||
private var mWasProtectionHandled = false
|
private var mWasProtectionHandled = false
|
||||||
private var mShouldStopFetching = false
|
private var mShouldStopFetching = false
|
||||||
|
private var mIsSearchOpen = false
|
||||||
private var mLatestMediaId = 0L
|
private var mLatestMediaId = 0L
|
||||||
private var mLatestMediaDateId = 0L
|
private var mLatestMediaDateId = 0L
|
||||||
private var mCurrentPathPrefix = "" // used at "Group direct subfolders" for navigation
|
private var mCurrentPathPrefix = "" // used at "Group direct subfolders" for navigation
|
||||||
|
@ -68,6 +73,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
private var mLastMediaHandler = Handler()
|
private var mLastMediaHandler = Handler()
|
||||||
private var mTempShowHiddenHandler = Handler()
|
private var mTempShowHiddenHandler = Handler()
|
||||||
private var mZoomListener: MyRecyclerView.MyZoomListener? = null
|
private var mZoomListener: MyRecyclerView.MyZoomListener? = null
|
||||||
|
private var mSearchMenuItem: MenuItem? = null
|
||||||
private var mDirs = ArrayList<Directory>()
|
private var mDirs = ArrayList<Directory>()
|
||||||
|
|
||||||
private var mStoredAnimateGifs = true
|
private var mStoredAnimateGifs = true
|
||||||
|
@ -145,6 +151,10 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
|
|
||||||
updateWidgets()
|
updateWidgets()
|
||||||
registerFileUpdateListener()
|
registerFileUpdateListener()
|
||||||
|
|
||||||
|
directories_switch_searching.setOnClickListener {
|
||||||
|
launchSearchActivity()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
|
@ -192,6 +202,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
directories_empty_text_label.setTextColor(config.textColor)
|
directories_empty_text_label.setTextColor(config.textColor)
|
||||||
directories_empty_text.setTextColor(getAdjustedPrimaryColor())
|
directories_empty_text.setTextColor(getAdjustedPrimaryColor())
|
||||||
|
directories_switch_searching.setTextColor(getAdjustedPrimaryColor())
|
||||||
|
directories_switch_searching.underlineText()
|
||||||
|
|
||||||
if (mIsPasswordProtectionPending && !mWasProtectionHandled) {
|
if (mIsPasswordProtectionPending && !mWasProtectionHandled) {
|
||||||
handleAppPasswordProtection {
|
handleAppPasswordProtection {
|
||||||
|
@ -218,6 +230,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
super.onStop()
|
super.onStop()
|
||||||
|
mSearchMenuItem?.collapseActionView()
|
||||||
|
|
||||||
if (config.temporarilyShowHidden || config.tempSkipDeleteConfirmation) {
|
if (config.temporarilyShowHidden || config.tempSkipDeleteConfirmation) {
|
||||||
mTempShowHiddenHandler.postDelayed({
|
mTempShowHiddenHandler.postDelayed({
|
||||||
config.temporarilyShowHidden = false
|
config.temporarilyShowHidden = false
|
||||||
|
@ -268,18 +282,19 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
findItem(R.id.reduce_column_count).isVisible = config.viewTypeFolders == VIEW_TYPE_GRID && config.dirColumnCnt > 1
|
findItem(R.id.reduce_column_count).isVisible = config.viewTypeFolders == VIEW_TYPE_GRID && config.dirColumnCnt > 1
|
||||||
findItem(R.id.hide_the_recycle_bin).isVisible = useBin && config.showRecycleBinAtFolders
|
findItem(R.id.hide_the_recycle_bin).isVisible = useBin && config.showRecycleBinAtFolders
|
||||||
findItem(R.id.show_the_recycle_bin).isVisible = useBin && !config.showRecycleBinAtFolders
|
findItem(R.id.show_the_recycle_bin).isVisible = useBin && !config.showRecycleBinAtFolders
|
||||||
|
setupSearch(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.findItem(R.id.temporarily_show_hidden).isVisible = !config.shouldShowHidden
|
menu.findItem(R.id.temporarily_show_hidden).isVisible = !config.shouldShowHidden
|
||||||
menu.findItem(R.id.stop_showing_hidden).isVisible = config.temporarilyShowHidden
|
menu.findItem(R.id.stop_showing_hidden).isVisible = config.temporarilyShowHidden
|
||||||
|
|
||||||
|
updateMenuItemColors(menu)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.search -> launchSearchActivity()
|
|
||||||
R.id.sort -> showSortingDialog()
|
R.id.sort -> showSortingDialog()
|
||||||
R.id.filter -> showFilterMediaDialog()
|
R.id.filter -> showFilterMediaDialog()
|
||||||
R.id.open_camera -> launchCamera()
|
R.id.open_camera -> launchCamera()
|
||||||
|
@ -323,6 +338,45 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupSearch(menu: Menu) {
|
||||||
|
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
|
||||||
|
mSearchMenuItem = menu.findItem(R.id.search)
|
||||||
|
(mSearchMenuItem?.actionView as? SearchView)?.apply {
|
||||||
|
setSearchableInfo(searchManager.getSearchableInfo(componentName))
|
||||||
|
isSubmitButtonEnabled = false
|
||||||
|
setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||||
|
override fun onQueryTextSubmit(query: String) = false
|
||||||
|
|
||||||
|
override fun onQueryTextChange(newText: String): Boolean {
|
||||||
|
if (mIsSearchOpen) {
|
||||||
|
setupAdapter(mDirs, newText)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItemCompat.setOnActionExpandListener(mSearchMenuItem, object : MenuItemCompat.OnActionExpandListener {
|
||||||
|
override fun onMenuItemActionExpand(item: MenuItem?): Boolean {
|
||||||
|
directories_switch_searching.beVisible()
|
||||||
|
mIsSearchOpen = true
|
||||||
|
directories_refresh_layout.isEnabled = false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// this triggers on device rotation too, avoid doing anything
|
||||||
|
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
|
||||||
|
if (mIsSearchOpen) {
|
||||||
|
directories_switch_searching.beGone()
|
||||||
|
mIsSearchOpen = false
|
||||||
|
directories_refresh_layout.isEnabled = config.enablePullToRefresh
|
||||||
|
setupAdapter(mDirs, "")
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private fun startNewPhotoFetcher() {
|
private fun startNewPhotoFetcher() {
|
||||||
if (isNougatPlus()) {
|
if (isNougatPlus()) {
|
||||||
val photoFetcher = NewPhotoFetcher()
|
val photoFetcher = NewPhotoFetcher()
|
||||||
|
@ -336,7 +390,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
if (config.tempFolderPath.isNotEmpty()) {
|
if (config.tempFolderPath.isNotEmpty()) {
|
||||||
val newFolder = File(config.tempFolderPath)
|
val newFolder = File(config.tempFolderPath)
|
||||||
if (newFolder.exists() && newFolder.isDirectory) {
|
if (newFolder.exists() && newFolder.isDirectory) {
|
||||||
if (newFolder.list()?.isEmpty() == true) {
|
if (newFolder.list()?.isEmpty() == true && newFolder.getProperSize(true) == 0L && newFolder.getFileCount(true) == 0) {
|
||||||
toast(String.format(getString(R.string.deleting_folder), config.tempFolderPath), Toast.LENGTH_LONG)
|
toast(String.format(getString(R.string.deleting_folder), config.tempFolderPath), Toast.LENGTH_LONG)
|
||||||
tryDeleteFileDirItem(newFolder.toFileDirItem(), true, true)
|
tryDeleteFileDirItem(newFolder.toFileDirItem(), true, true)
|
||||||
}
|
}
|
||||||
|
@ -965,7 +1019,10 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
directories_empty_text_label.beVisibleIf(dirs.isEmpty() && mLoadedInitialPhotos)
|
directories_empty_text_label.beVisibleIf(dirs.isEmpty() && mLoadedInitialPhotos)
|
||||||
directories_empty_text.beVisibleIf(dirs.isEmpty() && mLoadedInitialPhotos)
|
directories_empty_text.beVisibleIf(dirs.isEmpty() && mLoadedInitialPhotos)
|
||||||
|
|
||||||
if (dirs.isEmpty() && config.filterMedia == TYPE_DEFAULT_FILTER) {
|
if (mIsSearchOpen) {
|
||||||
|
directories_empty_text_label.text = getString(R.string.no_items_found)
|
||||||
|
directories_empty_text.beGone()
|
||||||
|
} else if (dirs.isEmpty() && config.filterMedia == TYPE_DEFAULT_FILTER) {
|
||||||
directories_empty_text_label.text = getString(R.string.no_media_add_included)
|
directories_empty_text_label.text = getString(R.string.no_media_add_included)
|
||||||
directories_empty_text.text = getString(R.string.add_folder)
|
directories_empty_text.text = getString(R.string.add_folder)
|
||||||
|
|
||||||
|
@ -1017,10 +1074,12 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
}
|
}
|
||||||
measureRecyclerViewContent(dirsToShow)
|
measureRecyclerViewContent(dirsToShow)
|
||||||
} else {
|
} else {
|
||||||
if (textToSearch.isNotEmpty()) {
|
|
||||||
dirsToShow = dirsToShow.filter { it.name.contains(textToSearch, true) }.sortedBy { !it.name.startsWith(textToSearch, true) }.toMutableList() as ArrayList
|
|
||||||
}
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
|
if (textToSearch.isNotEmpty()) {
|
||||||
|
dirsToShow = dirsToShow.filter { it.name.contains(textToSearch, true) }.sortedBy { !it.name.startsWith(textToSearch, true) }.toMutableList() as ArrayList
|
||||||
|
}
|
||||||
|
checkPlaceholderVisibility(dirsToShow)
|
||||||
|
|
||||||
(directories_grid.adapter as? DirectoryAdapter)?.updateDirs(dirsToShow)
|
(directories_grid.adapter as? DirectoryAdapter)?.updateDirs(dirsToShow)
|
||||||
measureRecyclerViewContent(dirsToShow)
|
measureRecyclerViewContent(dirsToShow)
|
||||||
}
|
}
|
||||||
|
@ -1215,6 +1274,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
add(Release(220, R.string.release_220))
|
add(Release(220, R.string.release_220))
|
||||||
add(Release(221, R.string.release_221))
|
add(Release(221, R.string.release_221))
|
||||||
add(Release(225, R.string.release_225))
|
add(Release(225, R.string.release_225))
|
||||||
|
add(Release(258, R.string.release_258))
|
||||||
checkWhatsNew(this, BuildConfig.VERSION_CODE)
|
checkWhatsNew(this, BuildConfig.VERSION_CODE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
||||||
private var mStoredCropThumbnails = true
|
private var mStoredCropThumbnails = true
|
||||||
private var mStoredScrollHorizontally = true
|
private var mStoredScrollHorizontally = true
|
||||||
private var mStoredShowInfoBubble = true
|
private var mStoredShowInfoBubble = true
|
||||||
|
private var mStoredShowFileTypes = true
|
||||||
private var mStoredTextColor = 0
|
private var mStoredTextColor = 0
|
||||||
private var mStoredPrimaryColor = 0
|
private var mStoredPrimaryColor = 0
|
||||||
|
|
||||||
|
@ -141,6 +142,10 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
||||||
getMedia()
|
getMedia()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mStoredShowFileTypes != config.showThumbnailFileTypes) {
|
||||||
|
getMediaAdapter()?.updateShowFileTypes(config.showThumbnailFileTypes)
|
||||||
|
}
|
||||||
|
|
||||||
if (mStoredTextColor != config.textColor) {
|
if (mStoredTextColor != config.textColor) {
|
||||||
getMediaAdapter()?.updateTextColor(config.textColor)
|
getMediaAdapter()?.updateTextColor(config.textColor)
|
||||||
}
|
}
|
||||||
|
@ -207,7 +212,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.menu_media, menu)
|
menuInflater.inflate(R.menu.menu_media, menu)
|
||||||
|
|
||||||
val isFolderHidden = File(mPath).containsNoMedia()
|
val isFolderHidden = mPath.containsNoMedia()
|
||||||
menu.apply {
|
menu.apply {
|
||||||
findItem(R.id.group).isVisible = !config.scrollHorizontally
|
findItem(R.id.group).isVisible = !config.scrollHorizontally
|
||||||
|
|
||||||
|
@ -234,6 +239,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
setupSearch(menu)
|
setupSearch(menu)
|
||||||
|
updateMenuItemColors(menu)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,6 +290,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
||||||
mStoredCropThumbnails = cropThumbnails
|
mStoredCropThumbnails = cropThumbnails
|
||||||
mStoredScrollHorizontally = scrollHorizontally
|
mStoredScrollHorizontally = scrollHorizontally
|
||||||
mStoredShowInfoBubble = showInfoBubble
|
mStoredShowInfoBubble = showInfoBubble
|
||||||
|
mStoredShowFileTypes = showThumbnailFileTypes
|
||||||
mStoredTextColor = textColor
|
mStoredTextColor = textColor
|
||||||
mStoredPrimaryColor = primaryColor
|
mStoredPrimaryColor = primaryColor
|
||||||
mShowAll = showAll
|
mShowAll = showAll
|
||||||
|
@ -381,7 +388,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
||||||
val fastscroller = if (config.scrollHorizontally) media_horizontal_fastscroller else media_vertical_fastscroller
|
val fastscroller = if (config.scrollHorizontally) media_horizontal_fastscroller else media_vertical_fastscroller
|
||||||
MediaAdapter(this, mMedia.clone() as ArrayList<ThumbnailItem>, this, mIsGetImageIntent || mIsGetVideoIntent || mIsGetAnyIntent,
|
MediaAdapter(this, mMedia.clone() as ArrayList<ThumbnailItem>, this, mIsGetImageIntent || mIsGetVideoIntent || mIsGetAnyIntent,
|
||||||
mAllowPickingMultiple, mPath, media_grid, fastscroller) {
|
mAllowPickingMultiple, mPath, media_grid, fastscroller) {
|
||||||
if (it is Medium) {
|
if (it is Medium && !isFinishing) {
|
||||||
itemClicked(it.path)
|
itemClicked(it.path)
|
||||||
}
|
}
|
||||||
}.apply {
|
}.apply {
|
||||||
|
@ -632,7 +639,10 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
||||||
|
|
||||||
private fun deleteDBDirectory() {
|
private fun deleteDBDirectory() {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
mDirectoryDao.deleteDirPath(mPath)
|
try {
|
||||||
|
mDirectoryDao.deleteDirPath(mPath)
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -832,7 +842,9 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
|
||||||
} else {
|
} else {
|
||||||
val isVideo = path.isVideoFast()
|
val isVideo = path.isVideoFast()
|
||||||
if (isVideo) {
|
if (isVideo) {
|
||||||
openPath(path, false)
|
val extras = HashMap<String, Boolean>()
|
||||||
|
extras[SHOW_FAVORITES] = mPath == FAVORITES
|
||||||
|
openPath(path, false, extras)
|
||||||
} else {
|
} else {
|
||||||
Intent(this, ViewPagerActivity::class.java).apply {
|
Intent(this, ViewPagerActivity::class.java).apply {
|
||||||
putExtra(PATH, path)
|
putExtra(PATH, path)
|
||||||
|
|
|
@ -45,7 +45,7 @@ open class PanoramaPhotoActivity : SimpleActivity() {
|
||||||
explore.setOnClickListener {
|
explore.setOnClickListener {
|
||||||
isExploreEnabled = !isExploreEnabled
|
isExploreEnabled = !isExploreEnabled
|
||||||
panorama_view.setPureTouchTracking(isExploreEnabled)
|
panorama_view.setPureTouchTracking(isExploreEnabled)
|
||||||
explore.setImageResource(if (isExploreEnabled) R.drawable.ic_explore else R.drawable.ic_explore_off)
|
explore.setImageResource(if (isExploreEnabled) R.drawable.ic_explore_vector else R.drawable.ic_explore_off_vector)
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePermission(PERMISSION_WRITE_STORAGE) {
|
handlePermission(PERMISSION_WRITE_STORAGE) {
|
||||||
|
|
|
@ -259,7 +259,7 @@ open class PanoramaVideoActivity : SimpleActivity(), SeekBar.OnSeekBarChangeList
|
||||||
explore.setOnClickListener {
|
explore.setOnClickListener {
|
||||||
mIsExploreEnabled = !mIsExploreEnabled
|
mIsExploreEnabled = !mIsExploreEnabled
|
||||||
vr_video_view.setPureTouchTracking(mIsExploreEnabled)
|
vr_video_view.setPureTouchTracking(mIsExploreEnabled)
|
||||||
explore.setImageResource(if (mIsExploreEnabled) R.drawable.ic_explore else R.drawable.ic_explore_off)
|
explore.setImageResource(if (mIsExploreEnabled) R.drawable.ic_explore_vector else R.drawable.ic_explore_off_vector)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ import com.simplemobiletools.commons.extensions.*
|
||||||
import com.simplemobiletools.commons.helpers.IS_FROM_GALLERY
|
import com.simplemobiletools.commons.helpers.IS_FROM_GALLERY
|
||||||
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE
|
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE
|
||||||
import com.simplemobiletools.commons.helpers.REAL_FILE_PATH
|
import com.simplemobiletools.commons.helpers.REAL_FILE_PATH
|
||||||
import com.simplemobiletools.commons.helpers.SIDELOADING_TRUE
|
|
||||||
import com.simplemobiletools.gallery.pro.BuildConfig
|
import com.simplemobiletools.gallery.pro.BuildConfig
|
||||||
import com.simplemobiletools.gallery.pro.R
|
import com.simplemobiletools.gallery.pro.R
|
||||||
import com.simplemobiletools.gallery.pro.extensions.*
|
import com.simplemobiletools.gallery.pro.extensions.*
|
||||||
|
@ -41,8 +40,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.fragment_holder)
|
setContentView(R.layout.fragment_holder)
|
||||||
|
|
||||||
if (config.appSideloadingStatus == SIDELOADING_TRUE) {
|
if (checkAppSideloading()) {
|
||||||
showSideloadingDialog()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,6 +229,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
||||||
|
|
||||||
private fun sendViewPagerIntent(path: String) {
|
private fun sendViewPagerIntent(path: String) {
|
||||||
Intent(this, ViewPagerActivity::class.java).apply {
|
Intent(this, ViewPagerActivity::class.java).apply {
|
||||||
|
putExtra(SHOW_FAVORITES, intent.getBooleanExtra(SHOW_FAVORITES, false))
|
||||||
putExtra(IS_VIEW_INTENT, true)
|
putExtra(IS_VIEW_INTENT, true)
|
||||||
putExtra(IS_FROM_GALLERY, mIsFromGallery)
|
putExtra(IS_FROM_GALLERY, mIsFromGallery)
|
||||||
putExtra(PATH, path)
|
putExtra(PATH, path)
|
||||||
|
@ -250,6 +249,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
||||||
findItem(R.id.menu_show_on_map).isVisible = visibleBottomActions and BOTTOM_ACTION_SHOW_ON_MAP == 0
|
findItem(R.id.menu_show_on_map).isVisible = visibleBottomActions and BOTTOM_ACTION_SHOW_ON_MAP == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateMenuItemColors(menu)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,15 @@ class SearchActivity : SimpleActivity(), MediaOperationsListener {
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.menu_search, menu)
|
menuInflater.inflate(R.menu.menu_search, menu)
|
||||||
setupSearch(menu)
|
setupSearch(menu)
|
||||||
|
updateMenuItemColors(menu)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.toggle_filename -> toggleFilenameVisibility()
|
||||||
|
else -> return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +144,11 @@ class SearchActivity : SimpleActivity(), MediaOperationsListener {
|
||||||
|
|
||||||
private fun getMediaAdapter() = media_grid.adapter as? MediaAdapter
|
private fun getMediaAdapter() = media_grid.adapter as? MediaAdapter
|
||||||
|
|
||||||
|
private fun toggleFilenameVisibility() {
|
||||||
|
config.displayFileNames = !config.displayFileNames
|
||||||
|
getMediaAdapter()?.updateDisplayFilenames(config.displayFileNames)
|
||||||
|
}
|
||||||
|
|
||||||
private fun itemClicked(path: String) {
|
private fun itemClicked(path: String) {
|
||||||
val isVideo = path.isVideoFast()
|
val isVideo = path.isVideoFast()
|
||||||
if (isVideo) {
|
if (isVideo) {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||||
|
import com.simplemobiletools.commons.extensions.checkAppSideloading
|
||||||
import com.simplemobiletools.commons.extensions.toast
|
import com.simplemobiletools.commons.extensions.toast
|
||||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||||
import com.simplemobiletools.commons.helpers.isNougatPlus
|
import com.simplemobiletools.commons.helpers.isNougatPlus
|
||||||
|
@ -31,6 +32,10 @@ class SetWallpaperActivity : SimpleActivity(), CropImageView.OnCropImageComplete
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_set_wallpaper)
|
setContentView(R.layout.activity_set_wallpaper)
|
||||||
|
|
||||||
|
if (checkAppSideloading()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (intent.data == null) {
|
if (intent.data == null) {
|
||||||
val pickIntent = Intent(applicationContext, MainActivity::class.java)
|
val pickIntent = Intent(applicationContext, MainActivity::class.java)
|
||||||
pickIntent.action = Intent.ACTION_PICK
|
pickIntent.action = Intent.ACTION_PICK
|
||||||
|
@ -43,6 +48,20 @@ class SetWallpaperActivity : SimpleActivity(), CropImageView.OnCropImageComplete
|
||||||
setupBottomActions()
|
setupBottomActions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.menu_set_wallpaper, menu)
|
||||||
|
updateMenuItemColors(menu)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.save -> confirmWallpaper()
|
||||||
|
else -> return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleImage(intent: Intent) {
|
private fun handleImage(intent: Intent) {
|
||||||
uri = intent.data
|
uri = intent.data
|
||||||
if (uri.scheme != "file" && uri.scheme != "content") {
|
if (uri.scheme != "file" && uri.scheme != "content") {
|
||||||
|
@ -76,19 +95,6 @@ class SetWallpaperActivity : SimpleActivity(), CropImageView.OnCropImageComplete
|
||||||
bottom_set_wallpaper_aspect_ratio.setImageResource(if (isLandscapeRatio) R.drawable.ic_minimize else R.drawable.ic_maximize)
|
bottom_set_wallpaper_aspect_ratio.setImageResource(if (isLandscapeRatio) R.drawable.ic_minimize else R.drawable.ic_maximize)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
||||||
menuInflater.inflate(R.menu.menu_set_wallpaper, menu)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
when (item.itemId) {
|
|
||||||
R.id.save -> confirmWallpaper()
|
|
||||||
else -> return super.onOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun changeAspectRatio(isLandscape: Boolean) {
|
private fun changeAspectRatio(isLandscape: Boolean) {
|
||||||
isLandscapeRatio = isLandscape
|
isLandscapeRatio = isLandscape
|
||||||
setupAspectRatio()
|
setupAspectRatio()
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.simplemobiletools.gallery.pro.activities
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
|
import android.view.Menu
|
||||||
import com.simplemobiletools.commons.dialogs.*
|
import com.simplemobiletools.commons.dialogs.*
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
import com.simplemobiletools.commons.helpers.*
|
import com.simplemobiletools.commons.helpers.*
|
||||||
|
@ -63,6 +64,7 @@ class SettingsActivity : SimpleActivity() {
|
||||||
setupShowNotch()
|
setupShowNotch()
|
||||||
setupBottomActions()
|
setupBottomActions()
|
||||||
setupThumbnailVideoDuration()
|
setupThumbnailVideoDuration()
|
||||||
|
setupThumbnailFileTypes()
|
||||||
setupShowMediaCount()
|
setupShowMediaCount()
|
||||||
setupKeepLastModified()
|
setupKeepLastModified()
|
||||||
setupShowInfoBubble()
|
setupShowInfoBubble()
|
||||||
|
@ -84,6 +86,12 @@ class SettingsActivity : SimpleActivity() {
|
||||||
setupSectionColors()
|
setupSectionColors()
|
||||||
setupExportSettings()
|
setupExportSettings()
|
||||||
setupImportSettings()
|
setupImportSettings()
|
||||||
|
invalidateOptionsMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
|
updateMenuItemColors(menu)
|
||||||
|
return super.onCreateOptionsMenu(menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupSectionColors() {
|
private fun setupSectionColors() {
|
||||||
|
@ -240,6 +248,14 @@ class SettingsActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupThumbnailFileTypes() {
|
||||||
|
settings_show_thumbnail_file_types.isChecked = config.showThumbnailFileTypes
|
||||||
|
settings_show_thumbnail_file_types_holder.setOnClickListener {
|
||||||
|
settings_show_thumbnail_file_types.toggle()
|
||||||
|
config.showThumbnailFileTypes = settings_show_thumbnail_file_types.isChecked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupDarkBackground() {
|
private fun setupDarkBackground() {
|
||||||
settings_black_background.isChecked = config.blackBackground
|
settings_black_background.isChecked = config.blackBackground
|
||||||
settings_black_background_holder.setOnClickListener {
|
settings_black_background_holder.setOnClickListener {
|
||||||
|
@ -615,9 +631,6 @@ class SettingsActivity : SimpleActivity() {
|
||||||
put(FILE_LOADING_PRIORITY, config.fileLoadingPriority)
|
put(FILE_LOADING_PRIORITY, config.fileLoadingPriority)
|
||||||
put(AUTOPLAY_VIDEOS, config.autoplayVideos)
|
put(AUTOPLAY_VIDEOS, config.autoplayVideos)
|
||||||
put(REMEMBER_LAST_VIDEO_POSITION, config.rememberLastVideoPosition)
|
put(REMEMBER_LAST_VIDEO_POSITION, config.rememberLastVideoPosition)
|
||||||
config.getAllLastVideoPositions().forEach {
|
|
||||||
put(it.key, it.value.toString())
|
|
||||||
}
|
|
||||||
put(LOOP_VIDEOS, config.loopVideos)
|
put(LOOP_VIDEOS, config.loopVideos)
|
||||||
put(OPEN_VIDEOS_ON_SEPARATE_SCREEN, config.openVideosOnSeparateScreen)
|
put(OPEN_VIDEOS_ON_SEPARATE_SCREEN, config.openVideosOnSeparateScreen)
|
||||||
put(ALLOW_VIDEO_GESTURES, config.allowVideoGestures)
|
put(ALLOW_VIDEO_GESTURES, config.allowVideoGestures)
|
||||||
|
@ -793,17 +806,13 @@ class SettingsActivity : SimpleActivity() {
|
||||||
SLIDESHOW_MOVE_BACKWARDS -> config.slideshowMoveBackwards = value.toBoolean()
|
SLIDESHOW_MOVE_BACKWARDS -> config.slideshowMoveBackwards = value.toBoolean()
|
||||||
SLIDESHOW_LOOP -> config.loopSlideshow = value.toBoolean()
|
SLIDESHOW_LOOP -> config.loopSlideshow = value.toBoolean()
|
||||||
LAST_EDITOR_CROP_ASPECT_RATIO -> config.lastEditorCropAspectRatio = value.toInt()
|
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_X -> config.lastEditorCropOtherAspectRatioX = value.toString().toFloat()
|
||||||
LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_Y -> config.lastEditorCropOtherAspectRatioY = value.toInt()
|
LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_Y -> config.lastEditorCropOtherAspectRatioY = value.toString().toFloat()
|
||||||
LAST_EDITOR_DRAW_COLOR -> config.lastEditorDrawColor = value.toInt()
|
LAST_EDITOR_DRAW_COLOR -> config.lastEditorDrawColor = value.toInt()
|
||||||
LAST_EDITOR_BRUSH_SIZE -> config.lastEditorBrushSize = value.toInt()
|
LAST_EDITOR_BRUSH_SIZE -> config.lastEditorBrushSize = value.toInt()
|
||||||
LAST_CONFLICT_RESOLUTION -> config.lastConflictResolution = value.toInt()
|
LAST_CONFLICT_RESOLUTION -> config.lastConflictResolution = value.toInt()
|
||||||
LAST_CONFLICT_APPLY_TO_ALL -> config.lastConflictApplyToAll = value.toBoolean()
|
LAST_CONFLICT_APPLY_TO_ALL -> config.lastConflictApplyToAll = value.toBoolean()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key.startsWith(LAST_VIDEO_POSITION_PREFIX)) {
|
|
||||||
config.saveLastVideoPosition(key, value as Int)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toast(if (configValues.size > 0) R.string.settings_imported_successfully else R.string.no_entries_for_importing)
|
toast(if (configValues.size > 0) R.string.settings_imported_successfully else R.string.no_entries_for_importing)
|
||||||
|
|
|
@ -4,8 +4,6 @@ import android.content.Intent
|
||||||
import com.simplemobiletools.commons.activities.BaseSplashActivity
|
import com.simplemobiletools.commons.activities.BaseSplashActivity
|
||||||
|
|
||||||
class SplashActivity : BaseSplashActivity() {
|
class SplashActivity : BaseSplashActivity() {
|
||||||
override fun getAppPackageName() = packageName
|
|
||||||
|
|
||||||
override fun initActivity() {
|
override fun initActivity() {
|
||||||
startActivity(Intent(this, MainActivity::class.java))
|
startActivity(Intent(this, MainActivity::class.java))
|
||||||
finish()
|
finish()
|
||||||
|
|
|
@ -19,6 +19,7 @@ import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
|
import android.text.Html
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -126,6 +127,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
|
|
||||||
supportActionBar?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
supportActionBar?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||||
|
supportActionBar?.title = Html.fromHtml("<font color=#FFFFFF'>${mPath.getFilenameFromPath()}</font>")
|
||||||
window.statusBarColor = Color.TRANSPARENT
|
window.statusBarColor = Color.TRANSPARENT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,6 +191,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
||||||
if (visibleBottomActions != 0) {
|
if (visibleBottomActions != 0) {
|
||||||
updateBottomActionIcons(currentMedium)
|
updateBottomActionIcons(currentMedium)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateMenuItemColors(menu, baseColor = Color.BLACK)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,6 +576,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
||||||
|
|
||||||
val fileDirItems = arrayListOf(FileDirItem(currPath, currPath.getFilenameFromPath()))
|
val fileDirItems = arrayListOf(FileDirItem(currPath, currPath.getFilenameFromPath()))
|
||||||
tryCopyMoveFilesTo(fileDirItems, isCopyOperation) {
|
tryCopyMoveFilesTo(fileDirItems, isCopyOperation) {
|
||||||
|
fixDateTaken(arrayListOf(currPath), false)
|
||||||
config.tempFolderPath = ""
|
config.tempFolderPath = ""
|
||||||
if (!isCopyOperation) {
|
if (!isCopyOperation) {
|
||||||
refreshViewPager()
|
refreshViewPager()
|
||||||
|
@ -620,12 +625,12 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
||||||
private fun getChangeOrientationIcon(): Int {
|
private fun getChangeOrientationIcon(): Int {
|
||||||
return if (mIsOrientationLocked) {
|
return if (mIsOrientationLocked) {
|
||||||
if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
|
if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
|
||||||
R.drawable.ic_orientation_portrait
|
R.drawable.ic_orientation_portrait_vector
|
||||||
} else {
|
} else {
|
||||||
R.drawable.ic_orientation_landscape
|
R.drawable.ic_orientation_landscape_vector
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
R.drawable.ic_orientation_auto
|
R.drawable.ic_orientation_auto_vector
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,7 +698,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCurrentFragment() = (view_pager.adapter as MyPagerAdapter).getCurrentFragment(view_pager.currentItem)
|
private fun getCurrentFragment() = (view_pager.adapter as? MyPagerAdapter)?.getCurrentFragment(view_pager.currentItem)
|
||||||
|
|
||||||
private fun showProperties() {
|
private fun showProperties() {
|
||||||
if (getCurrentMedium() != null) {
|
if (getCurrentMedium() != null) {
|
||||||
|
@ -798,10 +803,10 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val favoriteIcon = if (medium.isFavorite) R.drawable.ic_star_on else R.drawable.ic_star_off
|
val favoriteIcon = if (medium.isFavorite) R.drawable.ic_star_on_vector else R.drawable.ic_star_off_vector
|
||||||
bottom_favorite.setImageResource(favoriteIcon)
|
bottom_favorite.setImageResource(favoriteIcon)
|
||||||
|
|
||||||
val hideIcon = if (medium.isHidden()) R.drawable.ic_unhide else R.drawable.ic_hide
|
val hideIcon = if (medium.isHidden()) R.drawable.ic_unhide_vector else R.drawable.ic_hide
|
||||||
bottom_toggle_file_visibility.setImageResource(hideIcon)
|
bottom_toggle_file_visibility.setImageResource(hideIcon)
|
||||||
|
|
||||||
bottom_rotate.beVisibleIf(config.visibleBottomActions and BOTTOM_ACTION_ROTATE != 0 && getCurrentMedium()?.isImage() == true)
|
bottom_rotate.beVisibleIf(config.visibleBottomActions and BOTTOM_ACTION_ROTATE != 0 && getCurrentMedium()?.isImage() == true)
|
||||||
|
|
|
@ -145,8 +145,8 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkHideBtnVisibility(menu: Menu, selectedPaths: ArrayList<String>) {
|
private fun checkHideBtnVisibility(menu: Menu, selectedPaths: ArrayList<String>) {
|
||||||
menu.findItem(R.id.cab_hide).isVisible = selectedPaths.any { !File(it).doesThisOrParentHaveNoMedia() }
|
menu.findItem(R.id.cab_hide).isVisible = selectedPaths.any { !it.doesThisOrParentHaveNoMedia() }
|
||||||
menu.findItem(R.id.cab_unhide).isVisible = selectedPaths.any { File(it).doesThisOrParentHaveNoMedia() }
|
menu.findItem(R.id.cab_unhide).isVisible = selectedPaths.any { it.doesThisOrParentHaveNoMedia() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkPinBtnVisibility(menu: Menu, selectedPaths: ArrayList<String>) {
|
private fun checkPinBtnVisibility(menu: Menu, selectedPaths: ArrayList<String>) {
|
||||||
|
@ -218,28 +218,23 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hide) {
|
||||||
|
if (config.wasHideFolderTooltipShown) {
|
||||||
|
hideFolders(selectedPaths)
|
||||||
|
} else {
|
||||||
|
config.wasHideFolderTooltipShown = true
|
||||||
|
ConfirmationDialog(activity, activity.getString(R.string.hide_folder_description)) {
|
||||||
|
hideFolders(selectedPaths)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
selectedPaths.filter { it != FAVORITES && it != RECYCLE_BIN && (selectedPaths.size == 1 || !activity.config.isFolderProtected(it)) }.forEach {
|
selectedPaths.filter { it != FAVORITES && it != RECYCLE_BIN && (selectedPaths.size == 1 || !activity.config.isFolderProtected(it)) }.forEach {
|
||||||
val path = it
|
val path = it
|
||||||
if (hide) {
|
activity.handleLockedFolderOpening(path) { success ->
|
||||||
if (config.wasHideFolderTooltipShown) {
|
if (success) {
|
||||||
activity.handleLockedFolderOpening(path) { success ->
|
if (path.containsNoMedia()) {
|
||||||
if (success) {
|
|
||||||
hideFolder(path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
config.wasHideFolderTooltipShown = true
|
|
||||||
ConfirmationDialog(activity, activity.getString(R.string.hide_folder_description)) {
|
|
||||||
activity.handleLockedFolderOpening(path) { success ->
|
|
||||||
if (success) {
|
|
||||||
hideFolder(path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
activity.handleLockedFolderOpening(path) { success ->
|
|
||||||
if (success) {
|
|
||||||
activity.removeNoMedia(path) {
|
activity.removeNoMedia(path) {
|
||||||
if (activity.config.shouldShowHidden) {
|
if (activity.config.shouldShowHidden) {
|
||||||
updateFolderNames()
|
updateFolderNames()
|
||||||
|
@ -250,12 +245,28 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
config.addIncludedFolder(path)
|
||||||
|
activity.runOnUiThread {
|
||||||
|
listener?.refreshItems()
|
||||||
|
finishActMode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun hideFolders(paths: ArrayList<String>) {
|
||||||
|
for (path in paths) {
|
||||||
|
activity.handleLockedFolderOpening(path) { success ->
|
||||||
|
if (success) {
|
||||||
|
hideFolder(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun tryEmptyRecycleBin(askConfirmation: Boolean) {
|
private fun tryEmptyRecycleBin(askConfirmation: Boolean) {
|
||||||
if (askConfirmation) {
|
if (askConfirmation) {
|
||||||
activity.showRecycleBinEmptyingDialog {
|
activity.showRecycleBinEmptyingDialog {
|
||||||
|
@ -308,7 +319,7 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
||||||
val affectedPositions = ArrayList<Int>()
|
val affectedPositions = ArrayList<Int>()
|
||||||
val includedFolders = activity.config.includedFolders
|
val includedFolders = activity.config.includedFolders
|
||||||
val newDirs = dirs.filterIndexed { index, directory ->
|
val newDirs = dirs.filterIndexed { index, directory ->
|
||||||
val removeDir = File(directory.path).doesThisOrParentHaveNoMedia() && !includedFolders.contains(directory.path)
|
val removeDir = directory.path.doesThisOrParentHaveNoMedia() && !includedFolders.contains(directory.path)
|
||||||
if (removeDir) {
|
if (removeDir) {
|
||||||
affectedPositions.add(index)
|
affectedPositions.add(index)
|
||||||
}
|
}
|
||||||
|
@ -431,6 +442,7 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
||||||
|
|
||||||
val fileDirItems = paths.map { FileDirItem(it, it.getFilenameFromPath()) } as ArrayList<FileDirItem>
|
val fileDirItems = paths.map { FileDirItem(it, it.getFilenameFromPath()) } as ArrayList<FileDirItem>
|
||||||
activity.tryCopyMoveFilesTo(fileDirItems, isCopyOperation) {
|
activity.tryCopyMoveFilesTo(fileDirItems, isCopyOperation) {
|
||||||
|
activity.fixDateTaken(paths, false)
|
||||||
config.tempFolderPath = ""
|
config.tempFolderPath = ""
|
||||||
listener?.refreshItems()
|
listener?.refreshItems()
|
||||||
finishActMode()
|
finishActMode()
|
||||||
|
@ -456,7 +468,7 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
||||||
activity.getShortcutImage(coverThumbnail, drawable) {
|
activity.getShortcutImage(coverThumbnail, drawable) {
|
||||||
val intent = Intent(activity, MediaActivity::class.java)
|
val intent = Intent(activity, MediaActivity::class.java)
|
||||||
intent.action = Intent.ACTION_VIEW
|
intent.action = Intent.ACTION_VIEW
|
||||||
intent.flags = intent.flags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NO_HISTORY
|
intent.flags = intent.flags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||||
intent.putExtra(DIRECTORY, path)
|
intent.putExtra(DIRECTORY, path)
|
||||||
|
|
||||||
val shortcut = ShortcutInfo.Builder(activity, path)
|
val shortcut = ShortcutInfo.Builder(activity, path)
|
||||||
|
@ -595,7 +607,7 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
||||||
listener?.refreshItems()
|
listener?.refreshItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSelectedItems() = dirs.filter { selectedKeys.contains(it.path.hashCode()) } as ArrayList<Directory>
|
private fun getSelectedItems() = selectedKeys.mapNotNull { getItemWithKey(it) } as ArrayList<Directory>
|
||||||
|
|
||||||
private fun getSelectedPaths() = getSelectedItems().map { it.path } as ArrayList<String>
|
private fun getSelectedPaths() = getSelectedItems().map { it.path } as ArrayList<String>
|
||||||
|
|
||||||
|
@ -669,7 +681,7 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
||||||
dir_pin.beVisibleIf(pinnedFolders.contains(directory.path))
|
dir_pin.beVisibleIf(pinnedFolders.contains(directory.path))
|
||||||
dir_location.beVisibleIf(directory.location != LOCATION_INTERNAL)
|
dir_location.beVisibleIf(directory.location != LOCATION_INTERNAL)
|
||||||
if (dir_location.isVisible()) {
|
if (dir_location.isVisible()) {
|
||||||
dir_location.setImageResource(if (directory.location == LOCATION_SD) R.drawable.ic_sd_card else R.drawable.ic_usb)
|
dir_location.setImageResource(if (directory.location == LOCATION_SD) R.drawable.ic_sd_card_vector else R.drawable.ic_usb_vector)
|
||||||
}
|
}
|
||||||
|
|
||||||
photo_cnt.beVisibleIf(showMediaCount)
|
photo_cnt.beVisibleIf(showMediaCount)
|
||||||
|
|
|
@ -10,8 +10,8 @@ import com.bumptech.glide.Glide
|
||||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||||
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
|
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
|
||||||
import com.simplemobiletools.commons.dialogs.PropertiesDialog
|
import com.simplemobiletools.commons.dialogs.PropertiesDialog
|
||||||
|
import com.simplemobiletools.commons.dialogs.RenameDialog
|
||||||
import com.simplemobiletools.commons.dialogs.RenameItemDialog
|
import com.simplemobiletools.commons.dialogs.RenameItemDialog
|
||||||
import com.simplemobiletools.commons.dialogs.RenameItemsPatternDialog
|
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||||
import com.simplemobiletools.commons.models.FileDirItem
|
import com.simplemobiletools.commons.models.FileDirItem
|
||||||
|
@ -21,6 +21,8 @@ import com.simplemobiletools.gallery.pro.R
|
||||||
import com.simplemobiletools.gallery.pro.dialogs.DeleteWithRememberDialog
|
import com.simplemobiletools.gallery.pro.dialogs.DeleteWithRememberDialog
|
||||||
import com.simplemobiletools.gallery.pro.extensions.*
|
import com.simplemobiletools.gallery.pro.extensions.*
|
||||||
import com.simplemobiletools.gallery.pro.helpers.SHOW_ALL
|
import com.simplemobiletools.gallery.pro.helpers.SHOW_ALL
|
||||||
|
import com.simplemobiletools.gallery.pro.helpers.TYPE_GIFS
|
||||||
|
import com.simplemobiletools.gallery.pro.helpers.TYPE_RAWS
|
||||||
import com.simplemobiletools.gallery.pro.helpers.VIEW_TYPE_LIST
|
import com.simplemobiletools.gallery.pro.helpers.VIEW_TYPE_LIST
|
||||||
import com.simplemobiletools.gallery.pro.interfaces.MediaOperationsListener
|
import com.simplemobiletools.gallery.pro.interfaces.MediaOperationsListener
|
||||||
import com.simplemobiletools.gallery.pro.models.Medium
|
import com.simplemobiletools.gallery.pro.models.Medium
|
||||||
|
@ -52,6 +54,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
|
||||||
private var animateGifs = config.animateGifs
|
private var animateGifs = config.animateGifs
|
||||||
private var cropThumbnails = config.cropThumbnails
|
private var cropThumbnails = config.cropThumbnails
|
||||||
private var displayFilenames = config.displayFileNames
|
private var displayFilenames = config.displayFileNames
|
||||||
|
private var showFileTypes = config.showThumbnailFileTypes
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setupDragListener(true)
|
setupDragListener(true)
|
||||||
|
@ -215,7 +218,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
RenameItemsPatternDialog(activity, getSelectedPaths()) {
|
RenameDialog(activity, getSelectedPaths()) {
|
||||||
enableInstantLoad()
|
enableInstantLoad()
|
||||||
listener?.refreshItems()
|
listener?.refreshItems()
|
||||||
finishActMode()
|
finishActMode()
|
||||||
|
@ -326,6 +329,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
|
||||||
config.tempFolderPath = ""
|
config.tempFolderPath = ""
|
||||||
activity.applicationContext.rescanFolderMedia(it)
|
activity.applicationContext.rescanFolderMedia(it)
|
||||||
activity.applicationContext.rescanFolderMedia(fileDirItems.first().getParentPath())
|
activity.applicationContext.rescanFolderMedia(fileDirItems.first().getParentPath())
|
||||||
|
activity.fixDateTaken(paths, false)
|
||||||
if (!isCopyOperation) {
|
if (!isCopyOperation) {
|
||||||
listener?.refreshItems()
|
listener?.refreshItems()
|
||||||
activity.updateFavoritePaths(fileDirItems, it)
|
activity.updateFavoritePaths(fileDirItems, it)
|
||||||
|
@ -394,7 +398,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSelectedItems() = media.filter { selectedKeys.contains((it as? Medium)?.path?.hashCode()) } as ArrayList<Medium>
|
private fun getSelectedItems() = selectedKeys.mapNotNull { getItemWithKey(it) } as ArrayList<Medium>
|
||||||
|
|
||||||
private fun getSelectedPaths() = getSelectedItems().map { it.path } as ArrayList<String>
|
private fun getSelectedPaths() = getSelectedItems().map { it.path } as ArrayList<String>
|
||||||
|
|
||||||
|
@ -431,6 +435,11 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateShowFileTypes(showFileTypes: Boolean) {
|
||||||
|
this.showFileTypes = showFileTypes
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
private fun enableInstantLoad() {
|
private fun enableInstantLoad() {
|
||||||
loadImageInstantly = true
|
loadImageInstantly = true
|
||||||
delayHandler.postDelayed({
|
delayHandler.postDelayed({
|
||||||
|
@ -444,6 +453,18 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
|
||||||
val isSelected = selectedKeys.contains(medium.path.hashCode())
|
val isSelected = selectedKeys.contains(medium.path.hashCode())
|
||||||
view.apply {
|
view.apply {
|
||||||
play_outline.beVisibleIf(medium.isVideo())
|
play_outline.beVisibleIf(medium.isVideo())
|
||||||
|
|
||||||
|
if (showFileTypes && (medium.isGIF() || medium.isRaw() || medium.isSVG())) {
|
||||||
|
file_type.setText(when (medium.type) {
|
||||||
|
TYPE_GIFS -> R.string.gif
|
||||||
|
TYPE_RAWS -> R.string.raw
|
||||||
|
else -> R.string.svg
|
||||||
|
})
|
||||||
|
file_type.beVisible()
|
||||||
|
} else {
|
||||||
|
file_type.beGone()
|
||||||
|
}
|
||||||
|
|
||||||
medium_name.beVisibleIf(displayFilenames || isListViewType)
|
medium_name.beVisibleIf(displayFilenames || isListViewType)
|
||||||
medium_name.text = medium.name
|
medium_name.text = medium.name
|
||||||
medium_name.tag = medium.path
|
medium_name.tag = medium.path
|
||||||
|
|
|
@ -9,11 +9,11 @@ import com.simplemobiletools.commons.extensions.value
|
||||||
import com.simplemobiletools.gallery.pro.R
|
import com.simplemobiletools.gallery.pro.R
|
||||||
import kotlinx.android.synthetic.main.dialog_custom_aspect_ratio.view.*
|
import kotlinx.android.synthetic.main.dialog_custom_aspect_ratio.view.*
|
||||||
|
|
||||||
class CustomAspectRatioDialog(val activity: BaseSimpleActivity, val defaultCustomAspectRatio: Pair<Int, Int>?, val callback: (aspectRatio: Pair<Int, Int>) -> Unit) {
|
class CustomAspectRatioDialog(val activity: BaseSimpleActivity, val defaultCustomAspectRatio: Pair<Float, Float>?, val callback: (aspectRatio: Pair<Float, Float>) -> Unit) {
|
||||||
init {
|
init {
|
||||||
val view = activity.layoutInflater.inflate(R.layout.dialog_custom_aspect_ratio, null).apply {
|
val view = activity.layoutInflater.inflate(R.layout.dialog_custom_aspect_ratio, null).apply {
|
||||||
aspect_ratio_width.setText(defaultCustomAspectRatio?.first?.toString() ?: "")
|
aspect_ratio_width.setText(defaultCustomAspectRatio?.first?.toInt()?.toString() ?: "")
|
||||||
aspect_ratio_height.setText(defaultCustomAspectRatio?.second?.toString() ?: "")
|
aspect_ratio_height.setText(defaultCustomAspectRatio?.second?.toInt()?.toString() ?: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
AlertDialog.Builder(activity)
|
AlertDialog.Builder(activity)
|
||||||
|
@ -32,8 +32,8 @@ class CustomAspectRatioDialog(val activity: BaseSimpleActivity, val defaultCusto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getViewValue(view: EditText): Int {
|
private fun getViewValue(view: EditText): Float {
|
||||||
val textValue = view.value
|
val textValue = view.value
|
||||||
return if (textValue.isEmpty()) 0 else textValue.toInt()
|
return if (textValue.isEmpty()) 0f else textValue.toFloat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,44 +6,44 @@ import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||||
import com.simplemobiletools.gallery.pro.R
|
import com.simplemobiletools.gallery.pro.R
|
||||||
import kotlinx.android.synthetic.main.dialog_other_aspect_ratio.view.*
|
import kotlinx.android.synthetic.main.dialog_other_aspect_ratio.view.*
|
||||||
|
|
||||||
class OtherAspectRatioDialog(val activity: BaseSimpleActivity, val lastOtherAspectRatio: Pair<Int, Int>?, val callback: (aspectRatio: Pair<Int, Int>) -> Unit) {
|
class OtherAspectRatioDialog(val activity: BaseSimpleActivity, val lastOtherAspectRatio: Pair<Float, Float>?, val callback: (aspectRatio: Pair<Float, Float>) -> Unit) {
|
||||||
private val dialog: AlertDialog
|
private val dialog: AlertDialog
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val view = activity.layoutInflater.inflate(R.layout.dialog_other_aspect_ratio, null).apply {
|
val view = activity.layoutInflater.inflate(R.layout.dialog_other_aspect_ratio, null).apply {
|
||||||
other_aspect_ratio_2_1.setOnClickListener { ratioPicked(Pair(2, 1)) }
|
other_aspect_ratio_2_1.setOnClickListener { ratioPicked(Pair(2f, 1f)) }
|
||||||
other_aspect_ratio_3_2.setOnClickListener { ratioPicked(Pair(3, 2)) }
|
other_aspect_ratio_3_2.setOnClickListener { ratioPicked(Pair(3f, 2f)) }
|
||||||
other_aspect_ratio_4_3.setOnClickListener { ratioPicked(Pair(4, 3)) }
|
other_aspect_ratio_4_3.setOnClickListener { ratioPicked(Pair(4f, 3f)) }
|
||||||
other_aspect_ratio_5_3.setOnClickListener { ratioPicked(Pair(5, 3)) }
|
other_aspect_ratio_5_3.setOnClickListener { ratioPicked(Pair(5f, 3f)) }
|
||||||
other_aspect_ratio_16_9.setOnClickListener { ratioPicked(Pair(16, 9)) }
|
other_aspect_ratio_16_9.setOnClickListener { ratioPicked(Pair(16f, 9f)) }
|
||||||
other_aspect_ratio_19_9.setOnClickListener { ratioPicked(Pair(19, 9)) }
|
other_aspect_ratio_19_9.setOnClickListener { ratioPicked(Pair(19f, 9f)) }
|
||||||
other_aspect_ratio_custom.setOnClickListener { customRatioPicked() }
|
other_aspect_ratio_custom.setOnClickListener { customRatioPicked() }
|
||||||
|
|
||||||
other_aspect_ratio_1_2.setOnClickListener { ratioPicked(Pair(1, 2)) }
|
other_aspect_ratio_1_2.setOnClickListener { ratioPicked(Pair(1f, 2f)) }
|
||||||
other_aspect_ratio_2_3.setOnClickListener { ratioPicked(Pair(2, 3)) }
|
other_aspect_ratio_2_3.setOnClickListener { ratioPicked(Pair(2f, 3f)) }
|
||||||
other_aspect_ratio_3_4.setOnClickListener { ratioPicked(Pair(3, 4)) }
|
other_aspect_ratio_3_4.setOnClickListener { ratioPicked(Pair(3f, 4f)) }
|
||||||
other_aspect_ratio_3_5.setOnClickListener { ratioPicked(Pair(3, 5)) }
|
other_aspect_ratio_3_5.setOnClickListener { ratioPicked(Pair(3f, 5f)) }
|
||||||
other_aspect_ratio_9_16.setOnClickListener { ratioPicked(Pair(9, 16)) }
|
other_aspect_ratio_9_16.setOnClickListener { ratioPicked(Pair(9f, 16f)) }
|
||||||
other_aspect_ratio_9_19.setOnClickListener { ratioPicked(Pair(9, 19)) }
|
other_aspect_ratio_9_19.setOnClickListener { ratioPicked(Pair(9f, 19f)) }
|
||||||
|
|
||||||
val radio1SelectedItemId = when (lastOtherAspectRatio) {
|
val radio1SelectedItemId = when (lastOtherAspectRatio) {
|
||||||
Pair(2, 1) -> other_aspect_ratio_2_1.id
|
Pair(2f, 1f) -> other_aspect_ratio_2_1.id
|
||||||
Pair(3, 2) -> other_aspect_ratio_3_2.id
|
Pair(3f, 2f) -> other_aspect_ratio_3_2.id
|
||||||
Pair(4, 3) -> other_aspect_ratio_4_3.id
|
Pair(4f, 3f) -> other_aspect_ratio_4_3.id
|
||||||
Pair(5, 3) -> other_aspect_ratio_5_3.id
|
Pair(5f, 3f) -> other_aspect_ratio_5_3.id
|
||||||
Pair(16, 9) -> other_aspect_ratio_16_9.id
|
Pair(16f, 9f) -> other_aspect_ratio_16_9.id
|
||||||
Pair(19, 9) -> other_aspect_ratio_19_9.id
|
Pair(19f, 9f) -> other_aspect_ratio_19_9.id
|
||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
other_aspect_ratio_dialog_radio_1.check(radio1SelectedItemId)
|
other_aspect_ratio_dialog_radio_1.check(radio1SelectedItemId)
|
||||||
|
|
||||||
val radio2SelectedItemId = when (lastOtherAspectRatio) {
|
val radio2SelectedItemId = when (lastOtherAspectRatio) {
|
||||||
Pair(1, 2) -> other_aspect_ratio_1_2.id
|
Pair(1f, 2f) -> other_aspect_ratio_1_2.id
|
||||||
Pair(2, 3) -> other_aspect_ratio_2_3.id
|
Pair(2f, 3f) -> other_aspect_ratio_2_3.id
|
||||||
Pair(3, 4) -> other_aspect_ratio_3_4.id
|
Pair(3f, 4f) -> other_aspect_ratio_3_4.id
|
||||||
Pair(3, 5) -> other_aspect_ratio_3_5.id
|
Pair(3f, 5f) -> other_aspect_ratio_3_5.id
|
||||||
Pair(9, 16) -> other_aspect_ratio_9_16.id
|
Pair(9f, 16f) -> other_aspect_ratio_9_16.id
|
||||||
Pair(9, 19) -> other_aspect_ratio_9_19.id
|
Pair(9f, 19f) -> other_aspect_ratio_9_19.id
|
||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
other_aspect_ratio_dialog_radio_2.check(radio2SelectedItemId)
|
other_aspect_ratio_dialog_radio_2.check(radio2SelectedItemId)
|
||||||
|
@ -67,7 +67,7 @@ class OtherAspectRatioDialog(val activity: BaseSimpleActivity, val lastOtherAspe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ratioPicked(pair: Pair<Int, Int>) {
|
private fun ratioPicked(pair: Pair<Float, Float>) {
|
||||||
callback(pair)
|
callback(pair)
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import com.simplemobiletools.gallery.pro.BuildConfig
|
||||||
import com.simplemobiletools.gallery.pro.R
|
import com.simplemobiletools.gallery.pro.R
|
||||||
import com.simplemobiletools.gallery.pro.activities.SimpleActivity
|
import com.simplemobiletools.gallery.pro.activities.SimpleActivity
|
||||||
import com.simplemobiletools.gallery.pro.dialogs.PickDirectoryDialog
|
import com.simplemobiletools.gallery.pro.dialogs.PickDirectoryDialog
|
||||||
import com.simplemobiletools.gallery.pro.helpers.NOMEDIA
|
|
||||||
import com.simplemobiletools.gallery.pro.helpers.RECYCLE_BIN
|
import com.simplemobiletools.gallery.pro.helpers.RECYCLE_BIN
|
||||||
import com.simplemobiletools.gallery.pro.interfaces.MediumDao
|
import com.simplemobiletools.gallery.pro.interfaces.MediumDao
|
||||||
import com.squareup.picasso.Picasso
|
import com.squareup.picasso.Picasso
|
||||||
|
@ -61,8 +60,8 @@ fun Activity.setAs(path: String) {
|
||||||
setAsIntent(path, BuildConfig.APPLICATION_ID)
|
setAsIntent(path, BuildConfig.APPLICATION_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Activity.openPath(path: String, forceChooser: Boolean) {
|
fun Activity.openPath(path: String, forceChooser: Boolean, extras: HashMap<String, Boolean> = HashMap()) {
|
||||||
openPathIntent(path, forceChooser, BuildConfig.APPLICATION_ID)
|
openPathIntent(path, forceChooser, BuildConfig.APPLICATION_ID, extras = extras)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Activity.openEditor(path: String, forceChooser: Boolean = false) {
|
fun Activity.openEditor(path: String, forceChooser: Boolean = false) {
|
||||||
|
@ -100,7 +99,8 @@ fun SimpleActivity.launchAbout() {
|
||||||
FAQItem(R.string.faq_14_title, R.string.faq_14_text),
|
FAQItem(R.string.faq_14_title, R.string.faq_14_text),
|
||||||
FAQItem(R.string.faq_15_title, R.string.faq_15_text),
|
FAQItem(R.string.faq_15_title, R.string.faq_15_text),
|
||||||
FAQItem(R.string.faq_2_title_commons, R.string.faq_2_text_commons),
|
FAQItem(R.string.faq_2_title_commons, R.string.faq_2_text_commons),
|
||||||
FAQItem(R.string.faq_6_title_commons, R.string.faq_6_text_commons))
|
FAQItem(R.string.faq_6_title_commons, R.string.faq_6_text_commons),
|
||||||
|
FAQItem(R.string.faq_7_title_commons, R.string.faq_7_text_commons))
|
||||||
|
|
||||||
startAboutActivity(R.string.app_name, licenses, BuildConfig.VERSION_NAME, faqItems, true)
|
startAboutActivity(R.string.app_name, licenses, BuildConfig.VERSION_NAME, faqItems, true)
|
||||||
}
|
}
|
||||||
|
@ -257,11 +257,15 @@ fun BaseSimpleActivity.restoreRecycleBinPath(path: String, callback: () -> Unit)
|
||||||
fun BaseSimpleActivity.restoreRecycleBinPaths(paths: ArrayList<String>, mediumDao: MediumDao = galleryDB.MediumDao(), callback: () -> Unit) {
|
fun BaseSimpleActivity.restoreRecycleBinPaths(paths: ArrayList<String>, mediumDao: MediumDao = galleryDB.MediumDao(), callback: () -> Unit) {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
val newPaths = ArrayList<String>()
|
val newPaths = ArrayList<String>()
|
||||||
paths.forEach {
|
for (source in paths) {
|
||||||
val source = it
|
val destination = source.removePrefix(recycleBinPath)
|
||||||
val destination = it.removePrefix(recycleBinPath)
|
|
||||||
val lastModified = File(source).lastModified()
|
val lastModified = File(source).lastModified()
|
||||||
|
|
||||||
|
val isShowingSAF = handleSAFDialog(destination) {}
|
||||||
|
if (isShowingSAF) {
|
||||||
|
return@ensureBackgroundThread
|
||||||
|
}
|
||||||
|
|
||||||
var inputStream: InputStream? = null
|
var inputStream: InputStream? = null
|
||||||
var out: OutputStream? = null
|
var out: OutputStream? = null
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -401,15 +401,18 @@ fun Context.rescanFolderMediaSync(path: String) {
|
||||||
val newMedia = it
|
val newMedia = it
|
||||||
val mediumDao = galleryDB.MediumDao()
|
val mediumDao = galleryDB.MediumDao()
|
||||||
val media = newMedia.filter { it is Medium } as ArrayList<Medium>
|
val media = newMedia.filter { it is Medium } as ArrayList<Medium>
|
||||||
mediumDao.insertAll(media)
|
try {
|
||||||
|
mediumDao.insertAll(media)
|
||||||
|
|
||||||
cached.forEach {
|
cached.forEach {
|
||||||
if (!newMedia.contains(it)) {
|
if (!newMedia.contains(it)) {
|
||||||
val mediumPath = (it as? Medium)?.path
|
val mediumPath = (it as? Medium)?.path
|
||||||
if (mediumPath != null) {
|
if (mediumPath != null) {
|
||||||
deleteDBPath(mediumDao, mediumPath)
|
deleteDBPath(mediumDao, mediumPath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (ignored: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.execute()
|
}.execute()
|
||||||
|
@ -424,7 +427,7 @@ fun Context.storeDirectoryItems(items: ArrayList<Directory>, directoryDao: Direc
|
||||||
|
|
||||||
fun Context.checkAppendingHidden(path: String, hidden: String, includedFolders: MutableSet<String>): String {
|
fun Context.checkAppendingHidden(path: String, hidden: String, includedFolders: MutableSet<String>): String {
|
||||||
val dirName = getFolderNameFromPath(path)
|
val dirName = getFolderNameFromPath(path)
|
||||||
return if (File(path).doesThisOrParentHaveNoMedia() && !path.isThisOrParentIncluded(includedFolders)) {
|
return if (path.doesThisOrParentHaveNoMedia() && !path.isThisOrParentIncluded(includedFolders)) {
|
||||||
"$dirName $hidden"
|
"$dirName $hidden"
|
||||||
} else {
|
} else {
|
||||||
dirName
|
dirName
|
||||||
|
@ -587,7 +590,7 @@ fun Context.getCachedDirectories(getVideosOnly: Boolean = false, getImagesOnly:
|
||||||
|
|
||||||
val hiddenString = resources.getString(R.string.hidden)
|
val hiddenString = resources.getString(R.string.hidden)
|
||||||
filteredDirectories.forEach {
|
filteredDirectories.forEach {
|
||||||
it.name = if (File(it.path).doesThisOrParentHaveNoMedia() && !it.path.isThisOrParentIncluded(includedPaths)) {
|
it.name = if (it.path.doesThisOrParentHaveNoMedia() && !it.path.isThisOrParentIncluded(includedPaths)) {
|
||||||
"${it.name.removeSuffix(hiddenString).trim()} $hiddenString"
|
"${it.name.removeSuffix(hiddenString).trim()} $hiddenString"
|
||||||
} else {
|
} else {
|
||||||
it.name
|
it.name
|
||||||
|
@ -620,7 +623,7 @@ fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImag
|
||||||
try {
|
try {
|
||||||
val currMedia = mediumDao.getMediaFromPath(it)
|
val currMedia = mediumDao.getMediaFromPath(it)
|
||||||
media.addAll(currMedia)
|
media.addAll(currMedia)
|
||||||
} catch (ignored: IllegalStateException) {
|
} catch (ignored: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
package com.simplemobiletools.gallery.pro.extensions
|
|
||||||
|
|
||||||
import com.simplemobiletools.gallery.pro.helpers.NOMEDIA
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
fun File.containsNoMedia() = isDirectory && File(this, NOMEDIA).exists()
|
|
||||||
|
|
||||||
fun File.doesThisOrParentHaveNoMedia(): Boolean {
|
|
||||||
var curFile = this
|
|
||||||
while (true) {
|
|
||||||
if (curFile.containsNoMedia()) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
curFile = curFile.parentFile ?: break
|
|
||||||
if (curFile.absolutePath == "/") {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
|
@ -1,7 +1,8 @@
|
||||||
package com.simplemobiletools.gallery.pro.extensions
|
package com.simplemobiletools.gallery.pro.extensions
|
||||||
|
|
||||||
import android.media.MediaMetadataRetriever
|
import android.media.MediaMetadataRetriever
|
||||||
import com.simplemobiletools.gallery.pro.helpers.NOMEDIA
|
import com.simplemobiletools.commons.extensions.doesThisOrParentHaveNoMedia
|
||||||
|
import com.simplemobiletools.commons.helpers.NOMEDIA
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
|
|
|
@ -251,7 +251,6 @@ class PhotoFragment : ViewPagerFragment() {
|
||||||
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
super.onConfigurationChanged(newConfig)
|
super.onConfigurationChanged(newConfig)
|
||||||
|
|
||||||
if (!mWasInit) {
|
if (!mWasInit) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -272,6 +271,7 @@ class PhotoFragment : ViewPagerFragment() {
|
||||||
loadImage()
|
loadImage()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
measureScreen()
|
||||||
initExtendedDetails()
|
initExtendedDetails()
|
||||||
updateInstantSwitchWidths()
|
updateInstantSwitchWidths()
|
||||||
}
|
}
|
||||||
|
@ -461,13 +461,14 @@ class PhotoFragment : ViewPagerFragment() {
|
||||||
mIsSubsamplingVisible = true
|
mIsSubsamplingVisible = true
|
||||||
val config = context!!.config
|
val config = context!!.config
|
||||||
val showHighestQuality = config.showHighestQuality
|
val showHighestQuality = config.showHighestQuality
|
||||||
|
val minTileDpi = if (showHighestQuality) -1 else getMinTileDpi()
|
||||||
|
|
||||||
val bitmapDecoder = object : DecoderFactory<ImageDecoder> {
|
val bitmapDecoder = object : DecoderFactory<ImageDecoder> {
|
||||||
override fun make() = PicassoDecoder(mMedium.path, Picasso.get(), rotation)
|
override fun make() = MyGlideImageDecoder(rotation)
|
||||||
}
|
}
|
||||||
|
|
||||||
val regionDecoder = object : DecoderFactory<ImageRegionDecoder> {
|
val regionDecoder = object : DecoderFactory<ImageRegionDecoder> {
|
||||||
override fun make() = PicassoRegionDecoder(showHighestQuality)
|
override fun make() = PicassoRegionDecoder(showHighestQuality, mScreenWidth, mScreenHeight, minTileDpi)
|
||||||
}
|
}
|
||||||
|
|
||||||
var newOrientation = (rotation + mCurrentRotationDegrees) % 360
|
var newOrientation = (rotation + mCurrentRotationDegrees) % 360
|
||||||
|
@ -477,7 +478,7 @@ class PhotoFragment : ViewPagerFragment() {
|
||||||
|
|
||||||
mView.subsampling_view.apply {
|
mView.subsampling_view.apply {
|
||||||
setMaxTileSize(if (showHighestQuality) Integer.MAX_VALUE else 4096)
|
setMaxTileSize(if (showHighestQuality) Integer.MAX_VALUE else 4096)
|
||||||
setMinimumTileDpi(if (showHighestQuality) -1 else getMinTileDpi())
|
setMinimumTileDpi(minTileDpi)
|
||||||
background = ColorDrawable(Color.TRANSPARENT)
|
background = ColorDrawable(Color.TRANSPARENT)
|
||||||
bitmapDecoderFactory = bitmapDecoder
|
bitmapDecoderFactory = bitmapDecoder
|
||||||
regionDecoderFactory = regionDecoder
|
regionDecoderFactory = regionDecoder
|
||||||
|
@ -487,6 +488,7 @@ class PhotoFragment : ViewPagerFragment() {
|
||||||
isOneToOneZoomEnabled = config.allowOneToOneZoom
|
isOneToOneZoomEnabled = config.allowOneToOneZoom
|
||||||
orientation = newOrientation
|
orientation = newOrientation
|
||||||
setImage(mMedium.path)
|
setImage(mMedium.path)
|
||||||
|
|
||||||
onImageEventListener = object : SubsamplingScaleImageView.OnImageEventListener {
|
onImageEventListener = object : SubsamplingScaleImageView.OnImageEventListener {
|
||||||
override fun onReady() {
|
override fun onReady() {
|
||||||
background = ColorDrawable(if (config.blackBackground) Color.BLACK else config.backgroundColor)
|
background = ColorDrawable(if (config.blackBackground) Color.BLACK else config.backgroundColor)
|
||||||
|
@ -520,10 +522,10 @@ class PhotoFragment : ViewPagerFragment() {
|
||||||
val averageDpi = (metrics.xdpi + metrics.ydpi) / 2
|
val averageDpi = (metrics.xdpi + metrics.ydpi) / 2
|
||||||
val device = "${Build.BRAND} ${Build.MODEL}".toLowerCase()
|
val device = "${Build.BRAND} ${Build.MODEL}".toLowerCase()
|
||||||
return when {
|
return when {
|
||||||
WEIRD_DEVICES.contains(device) -> 240
|
WEIRD_DEVICES.contains(device) -> WEIRD_TILE_DPI
|
||||||
averageDpi > 400 -> 280
|
averageDpi > 400 -> HIGH_TILE_DPI
|
||||||
averageDpi > 300 -> 220
|
averageDpi > 300 -> NORMAL_TILE_DPI
|
||||||
else -> 160
|
else -> LOW_TILE_DPI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,12 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
private var mWasVideoStarted = false
|
private var mWasVideoStarted = false
|
||||||
private var mWasPlayerInited = false
|
private var mWasPlayerInited = false
|
||||||
private var mWasLastPositionRestored = false
|
private var mWasLastPositionRestored = false
|
||||||
|
private var mPlayOnPrepared = false
|
||||||
|
private var mIsPlayerPrepared = false
|
||||||
private var mCurrTime = 0
|
private var mCurrTime = 0
|
||||||
private var mDuration = 0
|
private var mDuration = 0
|
||||||
private var mPositionWhenInit = 0
|
private var mPositionWhenInit = 0
|
||||||
|
private var mPositionAtPause = 0L
|
||||||
|
|
||||||
private var mExoPlayer: SimpleExoPlayer? = null
|
private var mExoPlayer: SimpleExoPlayer? = null
|
||||||
private var mVideoSize = Point(1, 1)
|
private var mVideoSize = Point(1, 1)
|
||||||
|
@ -80,11 +83,12 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
mView = inflater.inflate(R.layout.pager_video_item, container, false).apply {
|
mView = inflater.inflate(R.layout.pager_video_item, container, false).apply {
|
||||||
instant_prev_item.setOnClickListener { listener?.goToPrevItem() }
|
instant_prev_item.setOnClickListener { listener?.goToPrevItem() }
|
||||||
instant_next_item.setOnClickListener { listener?.goToNextItem() }
|
instant_next_item.setOnClickListener { listener?.goToNextItem() }
|
||||||
|
panorama_outline.setOnClickListener { openPanorama() }
|
||||||
video_curr_time.setOnClickListener { skip(false) }
|
video_curr_time.setOnClickListener { skip(false) }
|
||||||
video_duration.setOnClickListener { skip(true) }
|
video_duration.setOnClickListener { skip(true) }
|
||||||
video_holder.setOnClickListener { toggleFullscreen() }
|
video_holder.setOnClickListener { toggleFullscreen() }
|
||||||
video_preview.setOnClickListener { toggleFullscreen() }
|
video_preview.setOnClickListener { toggleFullscreen() }
|
||||||
panorama_outline.setOnClickListener { openPanorama() }
|
video_surface_frame.setOnClickListener { toggleFullscreen() }
|
||||||
video_play_outline.setOnClickListener {
|
video_play_outline.setOnClickListener {
|
||||||
if (mConfig.openVideosOnSeparateScreen) {
|
if (mConfig.openVideosOnSeparateScreen) {
|
||||||
launchVideoPlayer()
|
launchVideoPlayer()
|
||||||
|
@ -108,6 +112,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
mBrightnessSideScroll = video_brightness_controller
|
mBrightnessSideScroll = video_brightness_controller
|
||||||
mVolumeSideScroll = video_volume_controller
|
mVolumeSideScroll = video_volume_controller
|
||||||
mTextureView = video_surface
|
mTextureView = video_surface
|
||||||
|
mTextureView.surfaceTextureListener = this@VideoFragment
|
||||||
|
|
||||||
if (mConfig.allowDownGesture) {
|
if (mConfig.allowDownGesture) {
|
||||||
video_preview.setOnTouchListener { view, event ->
|
video_preview.setOnTouchListener { view, event ->
|
||||||
|
@ -158,7 +163,6 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mIsPanorama) {
|
if (!mIsPanorama) {
|
||||||
setupPlayer()
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
mCurrTime = savedInstanceState.getInt(PROGRESS)
|
mCurrTime = savedInstanceState.getInt(PROGRESS)
|
||||||
}
|
}
|
||||||
|
@ -268,23 +272,8 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupPlayer() {
|
|
||||||
if (activity == null || mConfig.openVideosOnSeparateScreen || mIsPanorama) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mView.video_surface_frame.setOnClickListener { toggleFullscreen() }
|
|
||||||
mTextureView.surfaceTextureListener = this
|
|
||||||
|
|
||||||
checkExtendedDetails()
|
|
||||||
|
|
||||||
mExoPlayer = ExoPlayerFactory.newSimpleInstance(context)
|
|
||||||
mExoPlayer!!.seekParameters = SeekParameters.CLOSEST_SYNC
|
|
||||||
initExoPlayerListeners()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun saveVideoProgress() {
|
private fun saveVideoProgress() {
|
||||||
if (!videoEnded()) {
|
if (!videoEnded() && mExoPlayer != null) {
|
||||||
mConfig.saveLastVideoPosition(mMedium.path, mExoPlayer!!.currentPosition.toInt() / 1000)
|
mConfig.saveLastVideoPosition(mMedium.path, mExoPlayer!!.currentPosition.toInt() / 1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -292,6 +281,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
private fun restoreLastVideoSavedPosition() {
|
private fun restoreLastVideoSavedPosition() {
|
||||||
val pos = mConfig.getLastVideoPosition(mMedium.path)
|
val pos = mConfig.getLastVideoPosition(mMedium.path)
|
||||||
if (pos > 0) {
|
if (pos > 0) {
|
||||||
|
mPositionAtPause = pos * 1000L
|
||||||
setPosition(pos)
|
setPosition(pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -317,6 +307,13 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initExoPlayer() {
|
private fun initExoPlayer() {
|
||||||
|
if (activity == null || mConfig.openVideosOnSeparateScreen || mIsPanorama || mExoPlayer != null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mExoPlayer = ExoPlayerFactory.newSimpleInstance(context)
|
||||||
|
mExoPlayer!!.seekParameters = SeekParameters.CLOSEST_SYNC
|
||||||
|
|
||||||
val isContentUri = mMedium.path.startsWith("content://")
|
val isContentUri = mMedium.path.startsWith("content://")
|
||||||
val uri = if (isContentUri) Uri.parse(mMedium.path) else Uri.fromFile(File(mMedium.path))
|
val uri = if (isContentUri) Uri.parse(mMedium.path) else Uri.fromFile(File(mMedium.path))
|
||||||
val dataSpec = DataSpec(uri)
|
val dataSpec = DataSpec(uri)
|
||||||
|
@ -325,15 +322,19 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
fileDataSource.open(dataSpec)
|
fileDataSource.open(dataSpec)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
activity?.showErrorToast(e)
|
activity?.showErrorToast(e)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val factory = DataSource.Factory { fileDataSource }
|
val factory = DataSource.Factory { fileDataSource }
|
||||||
val audioSource = ExtractorMediaSource(fileDataSource.uri, factory, DefaultExtractorsFactory(), null, null)
|
val audioSource = ExtractorMediaSource(fileDataSource.uri, factory, DefaultExtractorsFactory(), null, null)
|
||||||
|
mPlayOnPrepared = true
|
||||||
mExoPlayer!!.audioStreamType = C.STREAM_TYPE_MUSIC
|
mExoPlayer!!.audioStreamType = C.STREAM_TYPE_MUSIC
|
||||||
mExoPlayer!!.prepare(audioSource)
|
mExoPlayer!!.prepare(audioSource)
|
||||||
}
|
|
||||||
|
|
||||||
private fun initExoPlayerListeners() {
|
if (mTextureView.surfaceTexture != null) {
|
||||||
|
mExoPlayer!!.setVideoSurface(Surface(mTextureView.surfaceTexture))
|
||||||
|
}
|
||||||
|
|
||||||
mExoPlayer!!.addListener(object : Player.EventListener {
|
mExoPlayer!!.addListener(object : Player.EventListener {
|
||||||
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) {}
|
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) {}
|
||||||
|
|
||||||
|
@ -364,7 +365,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
mExoPlayer!!.addVideoListener(object : SimpleExoPlayer.VideoListener {
|
mExoPlayer!!.addVideoListener(object : SimpleExoPlayer.VideoListener {
|
||||||
override fun onVideoSizeChanged(width: Int, height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float) {
|
override fun onVideoSizeChanged(width: Int, height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float) {
|
||||||
mVideoSize.x = width
|
mVideoSize.x = width
|
||||||
mVideoSize.y = height
|
mVideoSize.y = (height / pixelWidthHeightRatio).toInt()
|
||||||
setVideoSize()
|
setVideoSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,10 +484,14 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun skip(forward: Boolean) {
|
private fun skip(forward: Boolean) {
|
||||||
if (mExoPlayer == null || mIsPanorama) {
|
if (mIsPanorama) {
|
||||||
|
return
|
||||||
|
} else if (mExoPlayer == null) {
|
||||||
|
playVideo()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mPositionAtPause = 0L
|
||||||
val curr = mExoPlayer!!.currentPosition
|
val curr = mExoPlayer!!.currentPosition
|
||||||
val twoPercents = Math.max((mExoPlayer!!.duration / 50).toInt(), MIN_SKIP_LENGTH)
|
val twoPercents = Math.max((mExoPlayer!!.duration / 50).toInt(), MIN_SKIP_LENGTH)
|
||||||
val newProgress = if (forward) curr + twoPercents else curr - twoPercents
|
val newProgress = if (forward) curr + twoPercents else curr - twoPercents
|
||||||
|
@ -499,17 +504,25 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||||
if (mExoPlayer != null && fromUser) {
|
if (fromUser) {
|
||||||
if (!mWasPlayerInited) {
|
if (mExoPlayer != null) {
|
||||||
mPositionWhenInit = progress
|
if (!mWasPlayerInited) {
|
||||||
|
mPositionWhenInit = progress
|
||||||
|
}
|
||||||
|
setPosition(progress)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mExoPlayer == null) {
|
||||||
|
mPositionAtPause = progress * 1000L
|
||||||
|
playVideo()
|
||||||
}
|
}
|
||||||
setPosition(progress)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartTrackingTouch(seekBar: SeekBar) {
|
override fun onStartTrackingTouch(seekBar: SeekBar) {
|
||||||
if (mExoPlayer == null)
|
if (mExoPlayer == null) {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
mExoPlayer!!.playWhenReady = false
|
mExoPlayer!!.playWhenReady = false
|
||||||
mIsDragged = true
|
mIsDragged = true
|
||||||
|
@ -527,26 +540,27 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
if (mIsPlaying) {
|
if (mIsPlaying) {
|
||||||
mExoPlayer!!.playWhenReady = true
|
mExoPlayer!!.playWhenReady = true
|
||||||
} else {
|
} else {
|
||||||
togglePlayPause()
|
playVideo()
|
||||||
}
|
}
|
||||||
|
|
||||||
mIsDragged = false
|
mIsDragged = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun togglePlayPause() {
|
private fun togglePlayPause() {
|
||||||
if (activity == null || !isAdded)
|
if (activity == null || !isAdded) {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
mIsPlaying = !mIsPlaying
|
|
||||||
if (mIsPlaying) {
|
if (mIsPlaying) {
|
||||||
playVideo()
|
|
||||||
} else {
|
|
||||||
pauseVideo()
|
pauseVideo()
|
||||||
|
} else {
|
||||||
|
playVideo()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun playVideo() {
|
fun playVideo() {
|
||||||
if (mExoPlayer == null) {
|
if (mExoPlayer == null) {
|
||||||
|
initExoPlayer()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,9 +589,11 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
}
|
}
|
||||||
|
|
||||||
mWasVideoStarted = true
|
mWasVideoStarted = true
|
||||||
mIsPlaying = true
|
if (mIsPlayerPrepared) {
|
||||||
|
mIsPlaying = true
|
||||||
|
}
|
||||||
mExoPlayer?.playWhenReady = true
|
mExoPlayer?.playWhenReady = true
|
||||||
activity!!.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun pauseVideo() {
|
private fun pauseVideo() {
|
||||||
|
@ -592,6 +608,8 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
|
|
||||||
mPlayPauseButton.setImageResource(R.drawable.ic_play_outline)
|
mPlayPauseButton.setImageResource(R.drawable.ic_play_outline)
|
||||||
activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
mPositionAtPause = mExoPlayer?.currentPosition ?: 0L
|
||||||
|
releaseExoPlayer()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun videoEnded(): Boolean {
|
private fun videoEnded(): Boolean {
|
||||||
|
@ -604,6 +622,10 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
mExoPlayer?.seekTo(seconds * 1000L)
|
mExoPlayer?.seekTo(seconds * 1000L)
|
||||||
mSeekBar.progress = seconds
|
mSeekBar.progress = seconds
|
||||||
mCurrTimeView.text = seconds.getFormattedDuration()
|
mCurrTimeView.text = seconds.getFormattedDuration()
|
||||||
|
|
||||||
|
if (!mIsPlaying) {
|
||||||
|
mPositionAtPause = mExoPlayer?.currentPosition ?: 0L
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupVideoDuration() {
|
private fun setupVideoDuration() {
|
||||||
|
@ -627,7 +649,17 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
setPosition(mPositionWhenInit)
|
setPosition(mPositionWhenInit)
|
||||||
mPositionWhenInit = 0
|
mPositionWhenInit = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mIsPlayerPrepared = true
|
||||||
|
if (mPlayOnPrepared && !mIsPlaying) {
|
||||||
|
if (mPositionAtPause != 0L) {
|
||||||
|
mExoPlayer?.seekTo(mPositionAtPause)
|
||||||
|
mPositionAtPause = 0L
|
||||||
|
}
|
||||||
|
playVideo()
|
||||||
|
}
|
||||||
mWasPlayerInited = true
|
mWasPlayerInited = true
|
||||||
|
mPlayOnPrepared = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun videoCompleted() {
|
private fun videoCompleted() {
|
||||||
|
@ -657,6 +689,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun releaseExoPlayer() {
|
private fun releaseExoPlayer() {
|
||||||
|
mIsPlayerPrepared = false
|
||||||
mExoPlayer?.stop()
|
mExoPlayer?.stop()
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
mExoPlayer?.release()
|
mExoPlayer?.release()
|
||||||
|
|
|
@ -178,6 +178,10 @@ class Config(context: Context) : BaseConfig(context) {
|
||||||
get() = prefs.getBoolean(SHOW_THUMBNAIL_VIDEO_DURATION, false)
|
get() = prefs.getBoolean(SHOW_THUMBNAIL_VIDEO_DURATION, false)
|
||||||
set(showThumbnailVideoDuration) = prefs.edit().putBoolean(SHOW_THUMBNAIL_VIDEO_DURATION, showThumbnailVideoDuration).apply()
|
set(showThumbnailVideoDuration) = prefs.edit().putBoolean(SHOW_THUMBNAIL_VIDEO_DURATION, showThumbnailVideoDuration).apply()
|
||||||
|
|
||||||
|
var showThumbnailFileTypes: Boolean
|
||||||
|
get() = prefs.getBoolean(SHOW_THUMBNAIL_FILE_TYPES, true)
|
||||||
|
set(showThumbnailFileTypes) = prefs.edit().putBoolean(SHOW_THUMBNAIL_FILE_TYPES, showThumbnailFileTypes).apply()
|
||||||
|
|
||||||
var screenRotation: Int
|
var screenRotation: Int
|
||||||
get() = prefs.getInt(SCREEN_ROTATION, ROTATE_BY_SYSTEM_SETTING)
|
get() = prefs.getInt(SCREEN_ROTATION, ROTATE_BY_SYSTEM_SETTING)
|
||||||
set(screenRotation) = prefs.edit().putInt(SCREEN_ROTATION, screenRotation).apply()
|
set(screenRotation) = prefs.edit().putInt(SCREEN_ROTATION, screenRotation).apply()
|
||||||
|
@ -447,13 +451,13 @@ class Config(context: Context) : BaseConfig(context) {
|
||||||
get() = prefs.getInt(LAST_EDITOR_CROP_ASPECT_RATIO, ASPECT_RATIO_FREE)
|
get() = prefs.getInt(LAST_EDITOR_CROP_ASPECT_RATIO, ASPECT_RATIO_FREE)
|
||||||
set(lastEditorCropAspectRatio) = prefs.edit().putInt(LAST_EDITOR_CROP_ASPECT_RATIO, lastEditorCropAspectRatio).apply()
|
set(lastEditorCropAspectRatio) = prefs.edit().putInt(LAST_EDITOR_CROP_ASPECT_RATIO, lastEditorCropAspectRatio).apply()
|
||||||
|
|
||||||
var lastEditorCropOtherAspectRatioX: Int
|
var lastEditorCropOtherAspectRatioX: Float
|
||||||
get() = prefs.getInt(LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_X, 2)
|
get() = prefs.getFloat(LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_X, 2f)
|
||||||
set(lastEditorCropOtherAspectRatioX) = prefs.edit().putInt(LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_X, lastEditorCropOtherAspectRatioX).apply()
|
set(lastEditorCropOtherAspectRatioX) = prefs.edit().putFloat(LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_X, lastEditorCropOtherAspectRatioX).apply()
|
||||||
|
|
||||||
var lastEditorCropOtherAspectRatioY: Int
|
var lastEditorCropOtherAspectRatioY: Float
|
||||||
get() = prefs.getInt(LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_Y, 1)
|
get() = prefs.getFloat(LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_Y, 1f)
|
||||||
set(lastEditorCropOtherAspectRatioY) = prefs.edit().putInt(LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_Y, lastEditorCropOtherAspectRatioY).apply()
|
set(lastEditorCropOtherAspectRatioY) = prefs.edit().putFloat(LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_Y, lastEditorCropOtherAspectRatioY).apply()
|
||||||
|
|
||||||
var groupDirectSubfolders: Boolean
|
var groupDirectSubfolders: Boolean
|
||||||
get() = prefs.getBoolean(GROUP_DIRECT_SUBFOLDERS, false)
|
get() = prefs.getBoolean(GROUP_DIRECT_SUBFOLDERS, false)
|
||||||
|
|
|
@ -67,8 +67,8 @@ const val LAST_BIN_CHECK = "last_bin_check"
|
||||||
const val SHOW_HIGHEST_QUALITY = "show_highest_quality"
|
const val SHOW_HIGHEST_QUALITY = "show_highest_quality"
|
||||||
const val ALLOW_DOWN_GESTURE = "allow_down_gesture"
|
const val ALLOW_DOWN_GESTURE = "allow_down_gesture"
|
||||||
const val LAST_EDITOR_CROP_ASPECT_RATIO = "last_editor_crop_aspect_ratio"
|
const val LAST_EDITOR_CROP_ASPECT_RATIO = "last_editor_crop_aspect_ratio"
|
||||||
const val LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_X = "last_editor_crop_other_aspect_ratio_x"
|
const val LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_X = "last_editor_crop_other_aspect_ratio_x_2"
|
||||||
const val LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_Y = "last_editor_crop_other_aspect_ratio_y"
|
const val LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_Y = "last_editor_crop_other_aspect_ratio_y_2"
|
||||||
const val GROUP_DIRECT_SUBFOLDERS = "group_direct_subfolders"
|
const val GROUP_DIRECT_SUBFOLDERS = "group_direct_subfolders"
|
||||||
const val SHOW_WIDGET_FOLDER_NAME = "show_widget_folder_name"
|
const val SHOW_WIDGET_FOLDER_NAME = "show_widget_folder_name"
|
||||||
const val ALLOW_ONE_TO_ONE_ZOOM = "allow_one_to_one_zoom"
|
const val ALLOW_ONE_TO_ONE_ZOOM = "allow_one_to_one_zoom"
|
||||||
|
@ -78,6 +78,7 @@ const val LAST_EDITOR_BRUSH_SIZE = "last_editor_brush_size"
|
||||||
const val SHOW_NOTCH = "show_notch"
|
const val SHOW_NOTCH = "show_notch"
|
||||||
const val FILE_LOADING_PRIORITY = "file_loading_priority"
|
const val FILE_LOADING_PRIORITY = "file_loading_priority"
|
||||||
const val SPAM_FOLDERS_CHECKED = "spam_folders_checked"
|
const val SPAM_FOLDERS_CHECKED = "spam_folders_checked"
|
||||||
|
const val SHOW_THUMBNAIL_FILE_TYPES = "show_thumbnail_file_types"
|
||||||
|
|
||||||
// slideshow
|
// slideshow
|
||||||
const val SLIDESHOW_INTERVAL = "slideshow_interval"
|
const val SLIDESHOW_INTERVAL = "slideshow_interval"
|
||||||
|
@ -97,7 +98,6 @@ const val SLIDESHOW_ANIMATION_NONE = 0
|
||||||
const val SLIDESHOW_ANIMATION_SLIDE = 1
|
const val SLIDESHOW_ANIMATION_SLIDE = 1
|
||||||
const val SLIDESHOW_ANIMATION_FADE = 2
|
const val SLIDESHOW_ANIMATION_FADE = 2
|
||||||
|
|
||||||
const val NOMEDIA = ".nomedia"
|
|
||||||
const val FAVORITES = "favorites"
|
const val FAVORITES = "favorites"
|
||||||
const val RECYCLE_BIN = "recycle_bin"
|
const val RECYCLE_BIN = "recycle_bin"
|
||||||
const val SHOW_FAVORITES = "show_favorites"
|
const val SHOW_FAVORITES = "show_favorites"
|
||||||
|
@ -209,3 +209,9 @@ const val MAX_VIDEO_ZOOM_SCALE = 5f
|
||||||
const val ZOOM_MODE_NONE = 0
|
const val ZOOM_MODE_NONE = 0
|
||||||
const val ZOOM_MODE_DRAG = 1
|
const val ZOOM_MODE_DRAG = 1
|
||||||
const val ZOOM_MODE_ZOOM = 2
|
const val ZOOM_MODE_ZOOM = 2
|
||||||
|
|
||||||
|
// constants related to image quality
|
||||||
|
const val LOW_TILE_DPI = 160
|
||||||
|
const val NORMAL_TILE_DPI = 220
|
||||||
|
const val WEIRD_TILE_DPI = 240
|
||||||
|
const val HIGH_TILE_DPI = 280
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.simplemobiletools.gallery.pro.helpers
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
|
import android.provider.BaseColumns
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
|
@ -37,34 +38,56 @@ class MediaFetcher(val context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFoldersToScan(): ArrayList<String> {
|
fun getFoldersToScan(): ArrayList<String> {
|
||||||
val filterMedia = context.config.filterMedia
|
|
||||||
val projection = arrayOf(MediaStore.Images.Media.DATA)
|
|
||||||
val uri = MediaStore.Files.getContentUri("external")
|
|
||||||
|
|
||||||
val selection = "${getSelectionQuery(filterMedia)} ${MediaStore.Images.ImageColumns.BUCKET_ID} IS NOT NULL) GROUP BY (${MediaStore.Images.ImageColumns.BUCKET_ID}"
|
|
||||||
val selectionArgs = getSelectionArgsQuery(filterMedia).toTypedArray()
|
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
val cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)
|
val folders = getLatestFileFolders()
|
||||||
val folders = parseCursor(cursor)
|
folders.addAll(arrayListOf(
|
||||||
|
|
||||||
val priorityFolders = arrayListOf(
|
|
||||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString(),
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString(),
|
||||||
"${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)}/Camera",
|
"${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)}/Camera",
|
||||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString()
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString()
|
||||||
).filter { File(it).exists() }
|
).filter { File(it).exists() })
|
||||||
|
|
||||||
folders.sortBy {
|
val filterMedia = context.config.filterMedia
|
||||||
val folder = it
|
val uri = MediaStore.Files.getContentUri("external")
|
||||||
!priorityFolders.any { it.equals(folder, true) }
|
val projection = arrayOf(MediaStore.Images.Media.DATA)
|
||||||
}
|
val selection = "${getSelectionQuery(filterMedia)} ${MediaStore.Images.ImageColumns.BUCKET_ID} IS NOT NULL) GROUP BY (${MediaStore.Images.ImageColumns.BUCKET_ID}"
|
||||||
|
val selectionArgs = getSelectionArgsQuery(filterMedia).toTypedArray()
|
||||||
|
val cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||||
|
folders.addAll(parseCursor(cursor))
|
||||||
|
|
||||||
folders
|
val config = context.config
|
||||||
|
val shouldShowHidden = config.shouldShowHidden
|
||||||
|
val excludedPaths = config.excludedFolders
|
||||||
|
val includedPaths = config.includedFolders
|
||||||
|
folders.filter { it.shouldFolderBeVisible(excludedPaths, includedPaths, shouldShowHidden) }.toMutableList() as ArrayList<String>
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
context.showErrorToast(e)
|
||||||
ArrayList()
|
ArrayList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getLatestFileFolders(): LinkedHashSet<String> {
|
||||||
|
val uri = MediaStore.Files.getContentUri("external")
|
||||||
|
val projection = arrayOf(MediaStore.Images.ImageColumns.DATA)
|
||||||
|
val parents = LinkedHashSet<String>()
|
||||||
|
val sorting = "${BaseColumns._ID} DESC LIMIT 50"
|
||||||
|
var cursor: Cursor? = null
|
||||||
|
try {
|
||||||
|
cursor = context.contentResolver.query(uri, projection, null, null, sorting)
|
||||||
|
if (cursor?.moveToFirst() == true) {
|
||||||
|
do {
|
||||||
|
val path = cursor.getStringValue(MediaStore.Images.ImageColumns.DATA) ?: continue
|
||||||
|
parents.add(path.getParentPath())
|
||||||
|
} while (cursor.moveToNext())
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
context.showErrorToast(e)
|
||||||
|
} finally {
|
||||||
|
cursor?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return parents
|
||||||
|
}
|
||||||
|
|
||||||
private fun getSelectionQuery(filterMedia: Int): String {
|
private fun getSelectionQuery(filterMedia: Int): String {
|
||||||
val query = StringBuilder()
|
val query = StringBuilder()
|
||||||
query.append("(")
|
query.append("(")
|
||||||
|
@ -130,7 +153,7 @@ class MediaFetcher(val context: Context) {
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseCursor(cursor: Cursor): ArrayList<String> {
|
private fun parseCursor(cursor: Cursor): LinkedHashSet<String> {
|
||||||
val foldersToIgnore = arrayListOf("/storage/emulated/legacy")
|
val foldersToIgnore = arrayListOf("/storage/emulated/legacy")
|
||||||
val config = context.config
|
val config = context.config
|
||||||
val includedFolders = config.includedFolders
|
val includedFolders = config.includedFolders
|
||||||
|
@ -155,7 +178,7 @@ class MediaFetcher(val context: Context) {
|
||||||
val showHidden = config.shouldShowHidden
|
val showHidden = config.shouldShowHidden
|
||||||
val excludedFolders = config.excludedFolders
|
val excludedFolders = config.excludedFolders
|
||||||
foldersToScan = foldersToScan.filter { it.shouldFolderBeVisible(excludedFolders, includedFolders, showHidden) } as ArrayList<String>
|
foldersToScan = foldersToScan.filter { it.shouldFolderBeVisible(excludedFolders, includedFolders, showHidden) } as ArrayList<String>
|
||||||
return foldersToScan.distinctBy { it.getDistinctPath() } as ArrayList<String>
|
return foldersToScan.distinctBy { it.getDistinctPath() }.toSet() as LinkedHashSet<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addFolder(curFolders: ArrayList<String>, folder: String) {
|
private fun addFolder(curFolders: ArrayList<String>, folder: String) {
|
||||||
|
@ -230,7 +253,7 @@ class MediaFetcher(val context: Context) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkFileExistence && !file.exists()) {
|
if (checkFileExistence && (!file.exists() || !file.isFile)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.simplemobiletools.gallery.pro.helpers
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.net.Uri
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.load.DecodeFormat
|
||||||
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
|
import com.bumptech.glide.request.RequestOptions
|
||||||
|
import com.bumptech.glide.request.target.Target
|
||||||
|
import com.davemorrissey.labs.subscaleview.ImageDecoder
|
||||||
|
|
||||||
|
class MyGlideImageDecoder(val degrees: Int) : ImageDecoder {
|
||||||
|
|
||||||
|
override fun decode(context: Context, uri: Uri): Bitmap {
|
||||||
|
val options = RequestOptions()
|
||||||
|
.format(DecodeFormat.PREFER_ARGB_8888)
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
.fitCenter()
|
||||||
|
|
||||||
|
val builder = Glide.with(context)
|
||||||
|
.asBitmap()
|
||||||
|
.load(uri)
|
||||||
|
.apply(options)
|
||||||
|
.transform(RotateTransformation(-degrees))
|
||||||
|
.into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
|
||||||
|
|
||||||
|
return builder.get()
|
||||||
|
}
|
||||||
|
}
|
|
@ -74,7 +74,11 @@ class MyWidgetProvider : AppWidgetProvider() {
|
||||||
}
|
}
|
||||||
|
|
||||||
setupAppOpenIntent(context, views, R.id.widget_holder, it)
|
setupAppOpenIntent(context, views, R.id.widget_holder, it)
|
||||||
appWidgetManager.updateAppWidget(it.widgetId, views)
|
|
||||||
|
try {
|
||||||
|
appWidgetManager.updateAppWidget(it.widgetId, views)
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
package com.simplemobiletools.gallery.pro.helpers
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.net.Uri
|
|
||||||
import com.davemorrissey.labs.subscaleview.ImageDecoder
|
|
||||||
import com.squareup.picasso.MemoryPolicy
|
|
||||||
import com.squareup.picasso.Picasso
|
|
||||||
|
|
||||||
class PicassoDecoder(val tag: String, val picasso: Picasso, val degrees: Int) : ImageDecoder {
|
|
||||||
|
|
||||||
override fun decode(context: Context, uri: Uri): Bitmap {
|
|
||||||
return picasso
|
|
||||||
.load(uri)
|
|
||||||
.tag(tag)
|
|
||||||
.config(Bitmap.Config.ARGB_8888)
|
|
||||||
.memoryPolicy(MemoryPolicy.NO_CACHE)
|
|
||||||
.rotate(-degrees.toFloat())
|
|
||||||
.get()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@ import android.graphics.*
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.davemorrissey.labs.subscaleview.ImageRegionDecoder
|
import com.davemorrissey.labs.subscaleview.ImageRegionDecoder
|
||||||
|
|
||||||
class PicassoRegionDecoder(val showHighestQuality: Boolean) : ImageRegionDecoder {
|
class PicassoRegionDecoder(val showHighestQuality: Boolean, val screenWidth: Int, val screenHeight: Int, val minTileDpi: Int) : ImageRegionDecoder {
|
||||||
private var decoder: BitmapRegionDecoder? = null
|
private var decoder: BitmapRegionDecoder? = null
|
||||||
private val decoderLock = Any()
|
private val decoderLock = Any()
|
||||||
|
|
||||||
|
@ -18,10 +18,20 @@ class PicassoRegionDecoder(val showHighestQuality: Boolean) : ImageRegionDecoder
|
||||||
|
|
||||||
override fun decodeRegion(rect: Rect, sampleSize: Int): Bitmap {
|
override fun decodeRegion(rect: Rect, sampleSize: Int): Bitmap {
|
||||||
synchronized(decoderLock) {
|
synchronized(decoderLock) {
|
||||||
|
var newSampleSize = sampleSize
|
||||||
|
if (!showHighestQuality && minTileDpi == LOW_TILE_DPI) {
|
||||||
|
if ((rect.width() > rect.height() && screenWidth > screenHeight) || (rect.height() > rect.width() && screenHeight > screenWidth)) {
|
||||||
|
if ((rect.width() / sampleSize > screenWidth || rect.height() / sampleSize > screenHeight)) {
|
||||||
|
newSampleSize *= 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val options = BitmapFactory.Options()
|
val options = BitmapFactory.Options()
|
||||||
options.inSampleSize = sampleSize
|
options.inSampleSize = newSampleSize
|
||||||
options.inPreferredConfig = if (showHighestQuality) Bitmap.Config.ARGB_8888 else Bitmap.Config.RGB_565
|
options.inPreferredConfig = if (showHighestQuality) Bitmap.Config.ARGB_8888 else Bitmap.Config.RGB_565
|
||||||
val bitmap = decoder!!.decodeRegion(rect, options)
|
val bitmap = decoder!!.decodeRegion(rect, options)
|
||||||
|
|
||||||
return bitmap ?: throw RuntimeException("Region decoder returned null bitmap - image format may not be supported")
|
return bitmap ?: throw RuntimeException("Region decoder returned null bitmap - image format may not be supported")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.simplemobiletools.gallery.pro.helpers
|
||||||
|
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.Matrix
|
||||||
|
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
||||||
|
import java.security.MessageDigest
|
||||||
|
|
||||||
|
class RotateTransformation(var degrees: Int) : BitmapTransformation() {
|
||||||
|
override fun updateDiskCacheKey(messageDigest: MessageDigest) {}
|
||||||
|
|
||||||
|
override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap {
|
||||||
|
val matrix = Matrix()
|
||||||
|
matrix.postRotate(degrees.toFloat())
|
||||||
|
return Bitmap.createBitmap(toTransform, 0, 0, toTransform.width, toTransform.height, matrix, true)
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,7 +44,11 @@ class NewPhotoFetcher : JobService() {
|
||||||
addTriggerContentUri(JobInfo.TriggerContentUri(photoUri, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS))
|
addTriggerContentUri(JobInfo.TriggerContentUri(photoUri, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS))
|
||||||
addTriggerContentUri(JobInfo.TriggerContentUri(videoUri, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS))
|
addTriggerContentUri(JobInfo.TriggerContentUri(videoUri, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS))
|
||||||
addTriggerContentUri(JobInfo.TriggerContentUri(MEDIA_URI, 0))
|
addTriggerContentUri(JobInfo.TriggerContentUri(MEDIA_URI, 0))
|
||||||
context.getSystemService(JobScheduler::class.java).schedule(build())
|
|
||||||
|
try {
|
||||||
|
context.getSystemService(JobScheduler::class.java).schedule(build())
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,46 +60,45 @@ class NewPhotoFetcher : JobService() {
|
||||||
|
|
||||||
override fun onStartJob(params: JobParameters): Boolean {
|
override fun onStartJob(params: JobParameters): Boolean {
|
||||||
mRunningParams = params
|
mRunningParams = params
|
||||||
|
|
||||||
val affectedFolderPaths = HashSet<String>()
|
|
||||||
if (params.triggeredContentAuthorities != null && params.triggeredContentUris != null) {
|
|
||||||
val ids = arrayListOf<String>()
|
|
||||||
for (uri in params.triggeredContentUris!!) {
|
|
||||||
val path = uri.pathSegments
|
|
||||||
if (path != null && (path.size == PHOTO_PATH_SEGMENTS.size + 1 || path.size == VIDEO_PATH_SEGMENTS.size + 1)) {
|
|
||||||
ids.add(path[path.size - 1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ids.isNotEmpty()) {
|
|
||||||
val selection = StringBuilder()
|
|
||||||
for (id in ids) {
|
|
||||||
if (selection.isNotEmpty()) {
|
|
||||||
selection.append(" OR ")
|
|
||||||
}
|
|
||||||
selection.append("${MediaStore.Images.ImageColumns._ID} = '$id'")
|
|
||||||
}
|
|
||||||
|
|
||||||
var cursor: Cursor? = null
|
|
||||||
try {
|
|
||||||
val projection = arrayOf(MediaStore.Images.ImageColumns.DATA)
|
|
||||||
val uris = arrayListOf(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
|
|
||||||
uris.forEach {
|
|
||||||
cursor = contentResolver.query(it, projection, selection.toString(), null, null)
|
|
||||||
while (cursor!!.moveToNext()) {
|
|
||||||
val path = cursor!!.getStringValue(MediaStore.Images.ImageColumns.DATA)
|
|
||||||
affectedFolderPaths.add(path.getParentPath())
|
|
||||||
addPathToDB(path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
} finally {
|
|
||||||
cursor?.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
|
val affectedFolderPaths = HashSet<String>()
|
||||||
|
if (params.triggeredContentAuthorities != null && params.triggeredContentUris != null) {
|
||||||
|
val ids = arrayListOf<String>()
|
||||||
|
for (uri in params.triggeredContentUris!!) {
|
||||||
|
val path = uri.pathSegments
|
||||||
|
if (path != null && (path.size == PHOTO_PATH_SEGMENTS.size + 1 || path.size == VIDEO_PATH_SEGMENTS.size + 1)) {
|
||||||
|
ids.add(path[path.size - 1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ids.isNotEmpty()) {
|
||||||
|
val selection = StringBuilder()
|
||||||
|
for (id in ids) {
|
||||||
|
if (selection.isNotEmpty()) {
|
||||||
|
selection.append(" OR ")
|
||||||
|
}
|
||||||
|
selection.append("${MediaStore.Images.ImageColumns._ID} = '$id'")
|
||||||
|
}
|
||||||
|
|
||||||
|
var cursor: Cursor? = null
|
||||||
|
try {
|
||||||
|
val projection = arrayOf(MediaStore.Images.ImageColumns.DATA)
|
||||||
|
val uris = arrayListOf(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
|
||||||
|
uris.forEach {
|
||||||
|
cursor = contentResolver.query(it, projection, selection.toString(), null, null)
|
||||||
|
while (cursor!!.moveToNext()) {
|
||||||
|
val path = cursor!!.getStringValue(MediaStore.Images.ImageColumns.DATA)
|
||||||
|
affectedFolderPaths.add(path.getParentPath())
|
||||||
|
addPathToDB(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
} finally {
|
||||||
|
cursor?.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
affectedFolderPaths.forEach {
|
affectedFolderPaths.forEach {
|
||||||
updateDirectoryPath(it)
|
updateDirectoryPath(it)
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ class MediaSideScroll(context: Context, attrs: AttributeSet) : RelativeLayout(co
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCurrentVolume() = activity!!.audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
|
private fun getCurrentVolume() = activity?.audioManager?.getStreamVolume(AudioManager.STREAM_MUSIC) ?: 0
|
||||||
|
|
||||||
private fun getCurrentBrightness(): Int {
|
private fun getCurrentBrightness(): Int {
|
||||||
return try {
|
return try {
|
||||||
|
|
Before Width: | Height: | Size: 198 B |
Before Width: | Height: | Size: 680 B |
Before Width: | Height: | Size: 464 B |
Before Width: | Height: | Size: 450 B |
Before Width: | Height: | Size: 531 B |
Before Width: | Height: | Size: 203 B |
Before Width: | Height: | Size: 344 B |
Before Width: | Height: | Size: 140 B |
Before Width: | Height: | Size: 292 B |
Before Width: | Height: | Size: 214 B |
Before Width: | Height: | Size: 647 B |
Before Width: | Height: | Size: 620 B |
Before Width: | Height: | Size: 656 B |
Before Width: | Height: | Size: 301 B |
Before Width: | Height: | Size: 221 B |
Before Width: | Height: | Size: 174 B |
Before Width: | Height: | Size: 812 B |
Before Width: | Height: | Size: 601 B |
Before Width: | Height: | Size: 569 B |
Before Width: | Height: | Size: 670 B |
Before Width: | Height: | Size: 187 B |
Before Width: | Height: | Size: 297 B |
Before Width: | Height: | Size: 92 B |
Before Width: | Height: | Size: 324 B |
Before Width: | Height: | Size: 246 B |
Before Width: | Height: | Size: 733 B |
Before Width: | Height: | Size: 688 B |
Before Width: | Height: | Size: 741 B |
Before Width: | Height: | Size: 413 B |
Before Width: | Height: | Size: 219 B |
Before Width: | Height: | Size: 221 B |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 867 B |
Before Width: | Height: | Size: 845 B |
Before Width: | Height: | Size: 979 B |
Before Width: | Height: | Size: 259 B |
Before Width: | Height: | Size: 442 B |
Before Width: | Height: | Size: 143 B |
Before Width: | Height: | Size: 473 B |
Before Width: | Height: | Size: 320 B |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 509 B |
Before Width: | Height: | Size: 308 B |
Before Width: | Height: | Size: 289 B |
Before Width: | Height: | Size: 994 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 324 B |
Before Width: | Height: | Size: 684 B |
Before Width: | Height: | Size: 110 B |
Before Width: | Height: | Size: 585 B |
Before Width: | Height: | Size: 361 B |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 670 B |
Before Width: | Height: | Size: 373 B |
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M19,12h-2v3h-3v2h5v-5zM7,9h3L10,7L5,7v5h2L7,9zM21,3L3,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM21,19.01L3,19.01L3,4.99h18v14.02z"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M7.47,21.49C4.2,19.93 1.86,16.76 1.5,13L0,13c0.51,6.16 5.66,11 11.95,11 0.23,0 0.44,-0.02 0.66,-0.03L8.8,20.15l-1.33,1.34zM12.05,0c-0.23,0 -0.44,0.02 -0.66,0.04l3.81,3.81 1.33,-1.33C19.8,4.07 22.14,7.24 22.5,11L24,11c-0.51,-6.16 -5.66,-11 -11.95,-11zM16,14h2L18,8c0,-1.11 -0.9,-2 -2,-2h-6v2h6v6zM8,16L8,4L6,4v2L4,6v2h2v8c0,1.1 0.89,2 2,2h8v2h2v-2h2v-2L8,16z"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M4.59,6.89c0.7,-0.71 1.4,-1.35 1.71,-1.22 0.5,0.2 0,1.03 -0.3,1.52 -0.25,0.42 -2.86,3.89 -2.86,6.31 0,1.28 0.48,2.34 1.34,2.98 0.75,0.56 1.74,0.73 2.64,0.46 1.07,-0.31 1.95,-1.4 3.06,-2.77 1.21,-1.49 2.83,-3.44 4.08,-3.44 1.63,0 1.65,1.01 1.76,1.79 -3.78,0.64 -5.38,3.67 -5.38,5.37 0,1.7 1.44,3.09 3.21,3.09 1.63,0 4.29,-1.33 4.69,-6.1L21,14.88v-2.5h-2.47c-0.15,-1.65 -1.09,-4.2 -4.03,-4.2 -2.25,0 -4.18,1.91 -4.94,2.84 -0.58,0.73 -2.06,2.48 -2.29,2.72 -0.25,0.3 -0.68,0.84 -1.11,0.84 -0.45,0 -0.72,-0.83 -0.36,-1.92 0.35,-1.09 1.4,-2.86 1.85,-3.52 0.78,-1.14 1.3,-1.92 1.3,-3.28C8.95,3.69 7.31,3 6.44,3 5.12,3 3.97,4 3.72,4.25c-0.36,0.36 -0.66,0.66 -0.88,0.93l1.75,1.71zM13.88,18.55c-0.31,0 -0.74,-0.26 -0.74,-0.72 0,-0.6 0.73,-2.2 2.87,-2.76 -0.3,2.69 -1.43,3.48 -2.13,3.48z"/>
|
||||||
|
</vector>
|