23
CHANGELOG.md
|
@ -1,6 +1,29 @@
|
|||
Changelog
|
||||
==========
|
||||
|
||||
Version 4.1.1 *(2018-05-26)*
|
||||
----------------------------
|
||||
|
||||
* Always set folder thumbnail based on folder content sorting
|
||||
* Make sure hidden folders have the "(hidden)" appended
|
||||
|
||||
Version 4.1.0 *(2018-05-25)*
|
||||
----------------------------
|
||||
|
||||
* Added sorting by Date Taken
|
||||
* Fixed file renaming on Android Oreo
|
||||
* Fixed some scrollbar glitches
|
||||
* Fixed broken "Use english language" in some cases
|
||||
* Make sure only the proper files are shown at "Show all folders content"
|
||||
* Many other smaller UX, stability improvements and bugfixes
|
||||
|
||||
Version 4.0.0 *(2018-05-13)*
|
||||
----------------------------
|
||||
|
||||
* Allow customizing the app launcher color
|
||||
* Remove the top spinning circle at initial launch
|
||||
* Many other bugfixes and UX/stability improvements
|
||||
|
||||
Version 3.8.2 *(2018-04-26)*
|
||||
----------------------------
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ android {
|
|||
applicationId "com.simplemobiletools.gallery"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 27
|
||||
versionCode 176
|
||||
versionName "3.8.2"
|
||||
versionCode 179
|
||||
versionName "4.1.1"
|
||||
multiDexEnabled true
|
||||
setProperty("archivesBaseName", "gallery")
|
||||
}
|
||||
|
@ -47,16 +47,16 @@ ext {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.simplemobiletools:commons:3.19.21'
|
||||
implementation 'com.simplemobiletools:commons:4.1.4'
|
||||
implementation 'com.theartofdev.edmodo:android-image-cropper:2.7.0'
|
||||
implementation 'com.android.support:multidex:1.0.3'
|
||||
implementation 'it.sephiroth.android.exif:library:1.0.1'
|
||||
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.12'
|
||||
implementation 'com.github.chrisbanes:PhotoView:2.1.3'
|
||||
|
||||
kapt "android.arch.persistence.room:compiler:1.0.0"
|
||||
implementation "android.arch.persistence.room:runtime:1.0.0"
|
||||
annotationProcessor "android.arch.persistence.room:compiler:1.0.0"
|
||||
kapt "android.arch.persistence.room:compiler:1.1.0"
|
||||
implementation "android.arch.persistence.room:runtime:1.1.0"
|
||||
annotationProcessor "android.arch.persistence.room:compiler:1.1.0"
|
||||
|
||||
//implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.9.0'
|
||||
implementation 'com.github.tibbi:subsampling-scale-image-view:v3.10.0-fork'
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
android:name=".activities.SplashActivity"
|
||||
android:theme="@style/SplashTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
@ -212,5 +210,252 @@
|
|||
<action android:name="com.simplemobiletools.REFRESH_MEDIA"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- Do not append ".Orange" to the default alias "name", it would remove the old homescreen launcher of users at upgrade -->
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity"
|
||||
android:enabled="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Red"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_red"
|
||||
android:roundIcon="@mipmap/ic_launcher_red"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Pink"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_pink"
|
||||
android:roundIcon="@mipmap/ic_launcher_pink"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Purple"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_purple"
|
||||
android:roundIcon="@mipmap/ic_launcher_purple"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Deep_purple"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_deep_purple"
|
||||
android:roundIcon="@mipmap/ic_launcher_deep_purple"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Indigo"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_indigo"
|
||||
android:roundIcon="@mipmap/ic_launcher_indigo"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Blue"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_blue"
|
||||
android:roundIcon="@mipmap/ic_launcher_blue"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Light_blue"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_light_blue"
|
||||
android:roundIcon="@mipmap/ic_launcher_light_blue"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Cyan"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_cyan"
|
||||
android:roundIcon="@mipmap/ic_launcher_cyan"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Teal"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_teal"
|
||||
android:roundIcon="@mipmap/ic_launcher_teal"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Green"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_green"
|
||||
android:roundIcon="@mipmap/ic_launcher_green"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Light_green"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_light_green"
|
||||
android:roundIcon="@mipmap/ic_launcher_light_green"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Lime"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_lime"
|
||||
android:roundIcon="@mipmap/ic_launcher_lime"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Yellow"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_yellow"
|
||||
android:roundIcon="@mipmap/ic_launcher_yellow"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Amber"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_amber"
|
||||
android:roundIcon="@mipmap/ic_launcher_amber"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Deep_orange"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_deep_orange"
|
||||
android:roundIcon="@mipmap/ic_launcher_deep_orange"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Brown"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_brown"
|
||||
android:roundIcon="@mipmap/ic_launcher_brown"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Blue_grey"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_blue_grey"
|
||||
android:roundIcon="@mipmap/ic_launcher_blue_grey"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Grey_black"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_grey_black"
|
||||
android:roundIcon="@mipmap/ic_launcher_grey_black"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
|
@ -176,6 +176,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
|||
}
|
||||
|
||||
Intent().apply {
|
||||
data = saveUri
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
setResult(RESULT_OK, this)
|
||||
}
|
||||
|
@ -260,7 +261,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
|||
}
|
||||
|
||||
private fun scanFinalPath(path: String) {
|
||||
scanPath(path) {
|
||||
scanPathRecursively(path) {
|
||||
setResult(Activity.RESULT_OK, intent)
|
||||
toast(R.string.file_saved)
|
||||
finish()
|
||||
|
|
|
@ -5,7 +5,7 @@ import android.view.Menu
|
|||
import android.view.MenuItem
|
||||
import com.simplemobiletools.commons.dialogs.FilePickerDialog
|
||||
import com.simplemobiletools.commons.extensions.beVisibleIf
|
||||
import com.simplemobiletools.commons.extensions.scanPath
|
||||
import com.simplemobiletools.commons.extensions.scanPathRecursively
|
||||
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.adapters.ManageFoldersAdapter
|
||||
|
@ -55,7 +55,7 @@ class IncludedFoldersActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
|||
config.addIncludedFolder(it)
|
||||
updateFolders()
|
||||
Thread {
|
||||
scanPath(it)
|
||||
scanPathRecursively(it)
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ import com.simplemobiletools.commons.views.MyRecyclerView
|
|||
import com.simplemobiletools.gallery.BuildConfig
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.adapters.DirectoryAdapter
|
||||
import com.simplemobiletools.gallery.databases.GalleryDataBase
|
||||
import com.simplemobiletools.gallery.databases.GalleryDatabase
|
||||
import com.simplemobiletools.gallery.dialogs.ChangeSortingDialog
|
||||
import com.simplemobiletools.gallery.dialogs.FilterMediaDialog
|
||||
import com.simplemobiletools.gallery.extensions.*
|
||||
|
@ -72,7 +72,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
appLaunched()
|
||||
appLaunched(BuildConfig.APPLICATION_ID)
|
||||
|
||||
mIsPickImageIntent = isPickImageIntent(intent)
|
||||
mIsPickVideoIntent = isPickVideoIntent(intent)
|
||||
|
@ -188,10 +188,11 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
config.temporarilyShowHidden = false
|
||||
config.tempSkipDeleteConfirmation = false
|
||||
mTempShowHiddenHandler.removeCallbacksAndMessages(null)
|
||||
removeTempFolder()
|
||||
if (!isChangingConfigurations) {
|
||||
GalleryDataBase.destroyInstance()
|
||||
GalleryDatabase.destroyInstance()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,11 +295,6 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
val getVideosOnly = mIsPickVideoIntent || mIsGetVideoContentIntent
|
||||
|
||||
getCachedDirectories(getVideosOnly, getImagesOnly) {
|
||||
if (!mLoadedInitialPhotos) {
|
||||
runOnUiThread {
|
||||
directories_refresh_layout.isRefreshing = true
|
||||
}
|
||||
}
|
||||
gotDirectories(addTempFolderIfNeeded(it))
|
||||
}
|
||||
}
|
||||
|
@ -542,7 +538,8 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
}
|
||||
|
||||
private fun fillIntentPath(resultData: Intent, resultIntent: Intent) {
|
||||
val path = resultData.data.path
|
||||
val data = resultData.data
|
||||
val path = if (data.toString().startsWith("/")) data.toString() else data.path
|
||||
val uri = getFilePublicUri(File(path), BuildConfig.APPLICATION_ID)
|
||||
val type = path.getMimeType()
|
||||
resultIntent.setDataAndTypeAndNormalize(uri, type)
|
||||
|
@ -595,9 +592,10 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
val isSortingAscending = config.directorySorting and SORT_DESCENDING == 0
|
||||
val mediumDao = galleryDB.MediumDao()
|
||||
val directoryDao = galleryDB.DirectoryDao()
|
||||
val getProperDateTaken = config.directorySorting and SORT_BY_DATE_TAKEN != 0
|
||||
|
||||
for (directory in dirs) {
|
||||
val curMedia = mediaFetcher.getFilesFrom(directory.path, getImagesOnly, getVideosOnly)
|
||||
val curMedia = mediaFetcher.getFilesFrom(directory.path, getImagesOnly, getVideosOnly, getProperDateTaken)
|
||||
val newDir = if (curMedia.isEmpty()) {
|
||||
directory
|
||||
} else {
|
||||
|
@ -611,6 +609,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
|
||||
directory.apply {
|
||||
tmb = newDir.tmb
|
||||
name = newDir.name
|
||||
mediaCnt = newDir.mediaCnt
|
||||
modified = newDir.modified
|
||||
taken = newDir.taken
|
||||
|
@ -632,13 +631,14 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
}
|
||||
}
|
||||
|
||||
val foldersToScan = mediaFetcher.getFoldersToScan("")
|
||||
val foldersToScan = mediaFetcher.getFoldersToScan()
|
||||
dirs.forEach {
|
||||
foldersToScan.remove(it.path)
|
||||
}
|
||||
|
||||
// check the remaining folders which were not cached at all yet
|
||||
for (folder in foldersToScan) {
|
||||
val newMedia = mediaFetcher.getFilesFrom(folder, getImagesOnly, getVideosOnly)
|
||||
val newMedia = mediaFetcher.getFilesFrom(folder, getImagesOnly, getVideosOnly, getProperDateTaken)
|
||||
if (newMedia.isEmpty()) {
|
||||
continue
|
||||
}
|
||||
|
@ -779,7 +779,7 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
|
||||
private fun getCurrentlyDisplayedDirs() = getRecyclerAdapter()?.dirs ?: ArrayList()
|
||||
|
||||
private fun getBubbleTextItem(index: Int) = getRecyclerAdapter()?.dirs?.getOrNull(index)?.getBubbleText() ?: ""
|
||||
private fun getBubbleTextItem(index: Int) = getRecyclerAdapter()?.dirs?.getOrNull(index)?.getBubbleText(config.directorySorting) ?: ""
|
||||
|
||||
private fun setupLatestMediaId() {
|
||||
Thread {
|
||||
|
@ -873,6 +873,8 @@ class MainActivity : SimpleActivity(), DirectoryAdapter.DirOperationsListener {
|
|||
add(Release(158, R.string.release_158))
|
||||
add(Release(159, R.string.release_159))
|
||||
add(Release(163, R.string.release_163))
|
||||
add(Release(177, R.string.release_177))
|
||||
add(Release(178, R.string.release_178))
|
||||
checkWhatsNew(this, BuildConfig.VERSION_CODE)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,6 +175,7 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
super.onDestroy()
|
||||
if (config.showAll) {
|
||||
config.temporarilyShowHidden = false
|
||||
config.tempSkipDeleteConfirmation = false
|
||||
}
|
||||
|
||||
mTempShowHiddenHandler.removeCallbacksAndMessages(null)
|
||||
|
@ -333,20 +334,22 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
media_horizontal_fastscroller.isHorizontal = true
|
||||
media_horizontal_fastscroller.beVisibleIf(allowHorizontalScroll)
|
||||
|
||||
val sorting = config.getFileSorting(mPath)
|
||||
|
||||
if (allowHorizontalScroll) {
|
||||
media_horizontal_fastscroller.allowBubbleDisplay = config.showInfoBubble
|
||||
media_horizontal_fastscroller.setViews(media_grid, media_refresh_layout) {
|
||||
media_horizontal_fastscroller.updateBubbleText(getBubbleTextItem(it))
|
||||
media_horizontal_fastscroller.updateBubbleText(getBubbleTextItem(it, sorting))
|
||||
}
|
||||
} else {
|
||||
media_vertical_fastscroller.allowBubbleDisplay = config.showInfoBubble
|
||||
media_vertical_fastscroller.setViews(media_grid, media_refresh_layout) {
|
||||
media_vertical_fastscroller.updateBubbleText(getBubbleTextItem(it))
|
||||
media_vertical_fastscroller.updateBubbleText(getBubbleTextItem(it, sorting))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBubbleTextItem(index: Int) = getMediaAdapter()?.media?.getOrNull(index)?.getBubbleText() ?: ""
|
||||
private fun getBubbleTextItem(index: Int, sorting: Int) = getMediaAdapter()?.media?.getOrNull(index)?.getBubbleText(sorting) ?: ""
|
||||
|
||||
private fun checkLastMediaChanged() {
|
||||
if (isActivityDestroyed())
|
||||
|
@ -479,6 +482,7 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
mCurrAsyncTask = GetMediaAsynctask(applicationContext, mPath, mIsGetImageIntent, mIsGetVideoIntent, mShowAll) {
|
||||
gotMedia(it)
|
||||
}
|
||||
|
||||
mCurrAsyncTask!!.execute()
|
||||
}
|
||||
|
||||
|
|
|
@ -67,14 +67,14 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
|||
|
||||
mIsFromGallery = intent.getBooleanExtra(IS_FROM_GALLERY, false)
|
||||
if (mUri!!.scheme == "file") {
|
||||
scanPath(mUri!!.path)
|
||||
scanPathRecursively(mUri!!.path)
|
||||
sendViewPagerIntent(mUri!!.path)
|
||||
finish()
|
||||
return
|
||||
} else {
|
||||
val path = applicationContext.getRealPathFromURI(mUri!!) ?: ""
|
||||
if (path != mUri.toString() && path.isNotEmpty() && mUri!!.authority != "mms") {
|
||||
scanPath(mUri!!.path)
|
||||
scanPathRecursively(mUri!!.path)
|
||||
sendViewPagerIntent(path)
|
||||
finish()
|
||||
return
|
||||
|
|
|
@ -1,5 +1,30 @@
|
|||
package com.simplemobiletools.gallery.activities
|
||||
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.gallery.R
|
||||
|
||||
open class SimpleActivity : BaseSimpleActivity()
|
||||
open class SimpleActivity : BaseSimpleActivity() {
|
||||
override fun getAppIconIDs() = arrayListOf(
|
||||
R.mipmap.ic_launcher_red,
|
||||
R.mipmap.ic_launcher_pink,
|
||||
R.mipmap.ic_launcher_purple,
|
||||
R.mipmap.ic_launcher_deep_purple,
|
||||
R.mipmap.ic_launcher_indigo,
|
||||
R.mipmap.ic_launcher_blue,
|
||||
R.mipmap.ic_launcher_light_blue,
|
||||
R.mipmap.ic_launcher_cyan,
|
||||
R.mipmap.ic_launcher_teal,
|
||||
R.mipmap.ic_launcher_green,
|
||||
R.mipmap.ic_launcher_light_green,
|
||||
R.mipmap.ic_launcher_lime,
|
||||
R.mipmap.ic_launcher_yellow,
|
||||
R.mipmap.ic_launcher_amber,
|
||||
R.mipmap.ic_launcher,
|
||||
R.mipmap.ic_launcher_deep_orange,
|
||||
R.mipmap.ic_launcher_brown,
|
||||
R.mipmap.ic_launcher_blue_grey,
|
||||
R.mipmap.ic_launcher_grey_black
|
||||
)
|
||||
|
||||
override fun getAppLauncherName() = getString(R.string.app_launcher_name)
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
private var mPos = -1
|
||||
private var mShowAll = false
|
||||
private var mIsSlideshowActive = false
|
||||
private var mSkipConfirmationDialog = false
|
||||
private var mRotationDegrees = 0
|
||||
private var mPrevHashcode = 0
|
||||
|
||||
|
@ -182,7 +181,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
|
||||
if (!getDoesFilePathExist(mPath)) {
|
||||
Thread {
|
||||
scanPath(mPath)
|
||||
scanPathRecursively(mPath)
|
||||
}.start()
|
||||
finish()
|
||||
return
|
||||
|
@ -554,7 +553,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}
|
||||
|
||||
copyFile(tmpPath, newPath)
|
||||
scanPath(newPath)
|
||||
scanPathRecursively(newPath)
|
||||
toast(R.string.file_saved)
|
||||
|
||||
if (config.keepLastModified) {
|
||||
|
@ -728,7 +727,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}
|
||||
|
||||
private fun checkDeleteConfirmation() {
|
||||
if (mSkipConfirmationDialog || config.skipDeleteConfirmation) {
|
||||
if (config.tempSkipDeleteConfirmation || config.skipDeleteConfirmation) {
|
||||
deleteConfirmed()
|
||||
} else {
|
||||
askConfirmDelete()
|
||||
|
@ -737,7 +736,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
|
||||
private fun askConfirmDelete() {
|
||||
DeleteWithRememberDialog(this, getString(R.string.proceed_with_deletion)) {
|
||||
mSkipConfirmationDialog = it
|
||||
config.tempSkipDeleteConfirmation = it
|
||||
deleteConfirmed()
|
||||
}
|
||||
}
|
||||
|
@ -833,7 +832,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
tryDeleteFileDirItem(fileDirItem, true)
|
||||
}
|
||||
|
||||
scanPath(mDirectory)
|
||||
scanPathRecursively(mDirectory)
|
||||
}
|
||||
|
||||
private fun checkOrientation() {
|
||||
|
|
|
@ -61,8 +61,8 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
}
|
||||
|
||||
override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) {
|
||||
val dir = dirs[position]
|
||||
val view = holder.bindView(dir, !isPickIntent) { itemView, layoutPosition ->
|
||||
val dir = dirs.getOrNull(position) ?: return
|
||||
val view = holder.bindView(dir, !isPickIntent) { itemView, adapterPosition ->
|
||||
setupView(itemView, dir)
|
||||
}
|
||||
bindViewHolder(holder, position, view)
|
||||
|
@ -169,7 +169,10 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
tmb = File(it, tmb.getFilenameFromPath()).absolutePath
|
||||
}
|
||||
updateDirs(dirs)
|
||||
listener?.updateDirectories(dirs.toList() as ArrayList)
|
||||
Thread {
|
||||
activity.galleryDB.DirectoryDao().updateDirectoryAfterRename(firstDir.tmb, firstDir.name, firstDir.path, sourcePath)
|
||||
listener?.refreshItems()
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -400,6 +403,7 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList<Directo
|
|||
dirs = newDirs.clone() as ArrayList<Directory>
|
||||
notifyDataSetChanged()
|
||||
finishActMode()
|
||||
fastScroller?.measureRecyclerView()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ class ManageFoldersAdapter(activity: BaseSimpleActivity, var folders: ArrayList<
|
|||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val folder = folders[position]
|
||||
val view = holder.bindView(folder) { itemView, layoutPosition ->
|
||||
val view = holder.bindView(folder) { itemView, adapterPosition ->
|
||||
setupView(itemView, folder)
|
||||
}
|
||||
bindViewHolder(holder, position, view)
|
||||
|
|
|
@ -45,7 +45,7 @@ class ManageHiddenFoldersAdapter(activity: BaseSimpleActivity, var folders: Arra
|
|||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val folder = folders[position]
|
||||
val view = holder.bindView(folder) { itemView, layoutPosition ->
|
||||
val view = holder.bindView(folder) { itemView, adapterPosition ->
|
||||
setupView(itemView, folder)
|
||||
}
|
||||
bindViewHolder(holder, position, view)
|
||||
|
|
|
@ -31,7 +31,6 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
|
||||
private val config = activity.config
|
||||
private val isListViewType = config.viewTypeFiles == VIEW_TYPE_LIST
|
||||
private var skipConfirmationDialog = false
|
||||
private var visibleItemPaths = ArrayList<String>()
|
||||
private var loadImageInstantly = false
|
||||
private var delayHandler = Handler(Looper.getMainLooper())
|
||||
|
@ -64,9 +63,9 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
}
|
||||
|
||||
override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) {
|
||||
val medium = media[position]
|
||||
val medium = media.getOrNull(position) ?: return
|
||||
visibleItemPaths.add(medium.path)
|
||||
val view = holder.bindView(medium, !allowMultiplePicks) { itemView, layoutPosition ->
|
||||
val view = holder.bindView(medium, !allowMultiplePicks) { itemView, adapterPosition ->
|
||||
setupView(itemView, medium)
|
||||
}
|
||||
bindViewHolder(holder, position, view)
|
||||
|
@ -152,12 +151,13 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
RenameItemDialog(activity, oldPath) {
|
||||
Thread {
|
||||
activity.updateDBMediaPath(oldPath, it)
|
||||
}.start()
|
||||
|
||||
activity.runOnUiThread {
|
||||
listener?.refreshItems()
|
||||
finishActMode()
|
||||
}
|
||||
activity.runOnUiThread {
|
||||
enableInstantLoad()
|
||||
listener?.refreshItems()
|
||||
finishActMode()
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
}
|
||||
|
||||
private fun checkDeleteConfirmation() {
|
||||
if (skipConfirmationDialog || config.skipDeleteConfirmation) {
|
||||
if (config.tempSkipDeleteConfirmation || config.skipDeleteConfirmation) {
|
||||
deleteFiles()
|
||||
} else {
|
||||
askConfirmDelete()
|
||||
|
@ -212,7 +212,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
val items = resources.getQuantityString(R.plurals.delete_items, selectedPositions.size, selectedPositions.size)
|
||||
val question = String.format(resources.getString(R.string.deletion_confirmation), items)
|
||||
DeleteWithRememberDialog(activity, question) {
|
||||
skipConfirmationDialog = it
|
||||
config.tempSkipDeleteConfirmation = it
|
||||
deleteFiles()
|
||||
}
|
||||
}
|
||||
|
@ -260,6 +260,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
enableInstantLoad()
|
||||
notifyDataSetChanged()
|
||||
finishActMode()
|
||||
fastScroller?.measureRecyclerView()
|
||||
}, 100L)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ class MyPagerAdapter(val activity: ViewPagerActivity, fm: FragmentManager, val m
|
|||
// try fixing TransactionTooLargeException crash on Android Nougat, tip from https://stackoverflow.com/a/43193425/1967672
|
||||
override fun saveState(): Parcelable? {
|
||||
val bundle = super.saveState() as Bundle?
|
||||
bundle!!.putParcelableArray("states", null)
|
||||
bundle?.putParcelableArray("states", null)
|
||||
return bundle
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.simplemobiletools.gallery.asynctasks
|
|||
|
||||
import android.content.Context
|
||||
import android.os.AsyncTask
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_DATE_TAKEN
|
||||
import com.simplemobiletools.commons.models.FileDirItem.Companion.sorting
|
||||
import com.simplemobiletools.gallery.extensions.config
|
||||
import com.simplemobiletools.gallery.helpers.MediaFetcher
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
|
@ -13,19 +15,19 @@ class GetMediaAsynctask(val context: Context, val mPath: String, val isPickImage
|
|||
private val mediaFetcher = MediaFetcher(context)
|
||||
|
||||
override fun doInBackground(vararg params: Void): ArrayList<Medium> {
|
||||
val getProperDateTaken = sorting and SORT_BY_DATE_TAKEN != 0
|
||||
return if (showAll) {
|
||||
val foldersToScan = mediaFetcher.getFoldersToScan("")
|
||||
val foldersToScan = mediaFetcher.getFoldersToScan()
|
||||
val media = ArrayList<Medium>()
|
||||
for (folder in foldersToScan) {
|
||||
val newMedia = mediaFetcher.getFilesFrom(folder, isPickImage, isPickVideo)
|
||||
foldersToScan.forEach {
|
||||
val newMedia = mediaFetcher.getFilesFrom(it, isPickImage, isPickVideo, getProperDateTaken)
|
||||
media.addAll(newMedia)
|
||||
}
|
||||
|
||||
Medium.sorting = context.config.getFileSorting("")
|
||||
media.sort()
|
||||
MediaFetcher(context).sortMedia(media, context.config.getFileSorting(""))
|
||||
media
|
||||
} else {
|
||||
mediaFetcher.getFilesFrom(mPath, isPickImage, isPickVideo)
|
||||
mediaFetcher.getFilesFrom(mPath, isPickImage, isPickVideo, getProperDateTaken)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,28 +10,30 @@ import com.simplemobiletools.gallery.models.Directory
|
|||
import com.simplemobiletools.gallery.models.Medium
|
||||
|
||||
@Database(entities = [(Directory::class), (Medium::class)], version = 2)
|
||||
abstract class GalleryDataBase : RoomDatabase() {
|
||||
abstract class GalleryDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun DirectoryDao(): DirectoryDao
|
||||
|
||||
abstract fun MediumDao(): MediumDao
|
||||
|
||||
companion object {
|
||||
private var INSTANCE: GalleryDataBase? = null
|
||||
private var db: GalleryDatabase? = null
|
||||
|
||||
fun getInstance(context: Context): GalleryDataBase {
|
||||
if (INSTANCE == null) {
|
||||
synchronized(GalleryDataBase::class) {
|
||||
INSTANCE = Room.databaseBuilder(context.applicationContext, GalleryDataBase::class.java, "gallery.db")
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
fun getInstance(context: Context): GalleryDatabase {
|
||||
if (db == null) {
|
||||
synchronized(GalleryDatabase::class) {
|
||||
if (db == null) {
|
||||
db = Room.databaseBuilder(context.applicationContext, GalleryDatabase::class.java, "gallery.db")
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
return INSTANCE!!
|
||||
return db!!
|
||||
}
|
||||
|
||||
fun destroyInstance() {
|
||||
INSTANCE = null
|
||||
db = null
|
||||
}
|
||||
}
|
||||
}
|
|
@ -44,6 +44,7 @@ class ChangeSortingDialog(val activity: BaseSimpleActivity, val isDirectorySorti
|
|||
currSorting and SORT_BY_PATH != 0 -> sortingRadio.sorting_dialog_radio_path
|
||||
currSorting and SORT_BY_SIZE != 0 -> sortingRadio.sorting_dialog_radio_size
|
||||
currSorting and SORT_BY_DATE_MODIFIED != 0 -> sortingRadio.sorting_dialog_radio_last_modified
|
||||
currSorting and SORT_BY_DATE_TAKEN != 0 -> sortingRadio.sorting_dialog_radio_date_taken
|
||||
else -> sortingRadio.sorting_dialog_radio_name
|
||||
}
|
||||
sortBtn.isChecked = true
|
||||
|
@ -65,7 +66,8 @@ class ChangeSortingDialog(val activity: BaseSimpleActivity, val isDirectorySorti
|
|||
R.id.sorting_dialog_radio_name -> SORT_BY_NAME
|
||||
R.id.sorting_dialog_radio_path -> SORT_BY_PATH
|
||||
R.id.sorting_dialog_radio_size -> SORT_BY_SIZE
|
||||
else -> SORT_BY_DATE_MODIFIED
|
||||
R.id.sorting_dialog_radio_last_modified -> SORT_BY_DATE_MODIFIED
|
||||
else -> SORT_BY_DATE_TAKEN
|
||||
}
|
||||
|
||||
if (view.sorting_dialog_radio_order.checkedRadioButtonId == R.id.sorting_dialog_radio_descending) {
|
||||
|
|
|
@ -72,6 +72,7 @@ class PickDirectoryDialog(val activity: BaseSimpleActivity, val sourcePath: Stri
|
|||
}
|
||||
|
||||
val scrollHorizontally = activity.config.scrollHorizontally && isGridViewType
|
||||
val sorting = activity.config.directorySorting
|
||||
view.apply {
|
||||
directories_grid.adapter = adapter
|
||||
|
||||
|
@ -84,12 +85,12 @@ class PickDirectoryDialog(val activity: BaseSimpleActivity, val sourcePath: Stri
|
|||
if (scrollHorizontally) {
|
||||
directories_horizontal_fastscroller.allowBubbleDisplay = activity.config.showInfoBubble
|
||||
directories_horizontal_fastscroller.setViews(directories_grid) {
|
||||
directories_horizontal_fastscroller.updateBubbleText(dirs[it].getBubbleText())
|
||||
directories_horizontal_fastscroller.updateBubbleText(dirs[it].getBubbleText(sorting))
|
||||
}
|
||||
} else {
|
||||
directories_vertical_fastscroller.allowBubbleDisplay = activity.config.showInfoBubble
|
||||
directories_vertical_fastscroller.setViews(directories_grid) {
|
||||
directories_vertical_fastscroller.updateBubbleText(dirs[it].getBubbleText())
|
||||
directories_vertical_fastscroller.updateBubbleText(dirs[it].getBubbleText(sorting))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ class PickMediumDialog(val activity: BaseSimpleActivity, val path: String, val c
|
|||
}
|
||||
|
||||
val scrollHorizontally = activity.config.scrollHorizontally && isGridViewType
|
||||
val sorting = activity.config.getFileSorting(path)
|
||||
view.apply {
|
||||
media_grid.adapter = adapter
|
||||
|
||||
|
@ -80,12 +81,12 @@ class PickMediumDialog(val activity: BaseSimpleActivity, val path: String, val c
|
|||
if (scrollHorizontally) {
|
||||
media_horizontal_fastscroller.allowBubbleDisplay = activity.config.showInfoBubble
|
||||
media_horizontal_fastscroller.setViews(media_grid) {
|
||||
media_horizontal_fastscroller.updateBubbleText(media[it].getBubbleText())
|
||||
media_horizontal_fastscroller.updateBubbleText(media[it].getBubbleText(sorting))
|
||||
}
|
||||
} else {
|
||||
media_vertical_fastscroller.allowBubbleDisplay = activity.config.showInfoBubble
|
||||
media_vertical_fastscroller.setViews(media_grid) {
|
||||
media_vertical_fastscroller.updateBubbleText(media[it].getBubbleText())
|
||||
media_vertical_fastscroller.updateBubbleText(media[it].getBubbleText(sorting))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ fun BaseSimpleActivity.addNoMedia(path: String, callback: () -> Unit) {
|
|||
val fileDocument = getDocumentFile(path)
|
||||
if (fileDocument?.exists() == true && fileDocument.isDirectory) {
|
||||
fileDocument.createFile("", NOMEDIA)
|
||||
applicationContext.scanFile(file) {
|
||||
applicationContext.scanFileRecursively(file) {
|
||||
callback()
|
||||
}
|
||||
} else {
|
||||
|
@ -117,7 +117,7 @@ fun BaseSimpleActivity.addNoMedia(path: String, callback: () -> Unit) {
|
|||
} else {
|
||||
try {
|
||||
file.createNewFile()
|
||||
applicationContext.scanFile(file) {
|
||||
applicationContext.scanFileRecursively(file) {
|
||||
callback()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
|
|
|
@ -16,11 +16,11 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
|
|||
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.OTG_PATH
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.activities.SettingsActivity
|
||||
import com.simplemobiletools.gallery.asynctasks.GetMediaAsynctask
|
||||
import com.simplemobiletools.gallery.databases.GalleryDataBase
|
||||
import com.simplemobiletools.gallery.databases.GalleryDatabase
|
||||
import com.simplemobiletools.gallery.helpers.*
|
||||
import com.simplemobiletools.gallery.interfaces.DirectoryDao
|
||||
import com.simplemobiletools.gallery.models.Directory
|
||||
|
@ -70,7 +70,7 @@ fun Context.launchSettings() {
|
|||
|
||||
val Context.config: Config get() = Config.newInstance(applicationContext)
|
||||
|
||||
val Context.galleryDB: GalleryDataBase get() = GalleryDataBase.getInstance(applicationContext)
|
||||
val Context.galleryDB: GalleryDatabase get() = GalleryDatabase.getInstance(applicationContext)
|
||||
|
||||
fun Context.movePinnedDirectoriesToFront(dirs: ArrayList<Directory>): ArrayList<Directory> {
|
||||
val foundFolders = ArrayList<Directory>()
|
||||
|
@ -96,9 +96,26 @@ fun Context.movePinnedDirectoriesToFront(dirs: ArrayList<Directory>): ArrayList<
|
|||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun Context.getSortedDirectories(source: ArrayList<Directory>): ArrayList<Directory> {
|
||||
Directory.sorting = config.directorySorting
|
||||
val sorting = config.directorySorting
|
||||
val dirs = source.clone() as ArrayList<Directory>
|
||||
dirs.sort()
|
||||
|
||||
dirs.sortWith(Comparator { o1, o2 ->
|
||||
o1 as Directory
|
||||
o2 as Directory
|
||||
var result = when {
|
||||
sorting and SORT_BY_NAME != 0 -> AlphanumericComparator().compare(o1.name.toLowerCase(), o2.name.toLowerCase())
|
||||
sorting and SORT_BY_PATH != 0 -> AlphanumericComparator().compare(o1.path.toLowerCase(), o2.path.toLowerCase())
|
||||
sorting and SORT_BY_SIZE != 0 -> o1.size.compareTo(o2.size)
|
||||
sorting and SORT_BY_DATE_MODIFIED != 0 -> o1.modified.compareTo(o2.modified)
|
||||
else -> o1.taken.compareTo(o2.taken)
|
||||
}
|
||||
|
||||
if (sorting and SORT_DESCENDING != 0) {
|
||||
result *= -1
|
||||
}
|
||||
result
|
||||
})
|
||||
|
||||
return movePinnedDirectoriesToFront(dirs)
|
||||
}
|
||||
|
||||
|
@ -276,34 +293,51 @@ fun Context.getCachedDirectories(getVideosOnly: Boolean = false, getImagesOnly:
|
|||
}
|
||||
}) as ArrayList<Directory>
|
||||
|
||||
callback(filteredDirectories.distinctBy { it.path.getDistinctPath() } as ArrayList<Directory>)
|
||||
val hiddenString = resources.getString(R.string.hidden)
|
||||
filteredDirectories.forEach {
|
||||
it.name = if (File(it.path).doesThisOrParentHaveNoMedia() && !it.path.isThisOrParentIncluded(includedPaths)) {
|
||||
"${it.name.removeSuffix(hiddenString).trim()} $hiddenString"
|
||||
} else {
|
||||
it.name
|
||||
}
|
||||
}
|
||||
|
||||
removeInvalidDBDirectories(directories, directoryDao)
|
||||
val clone = filteredDirectories.clone() as ArrayList<Directory>
|
||||
callback(clone.distinctBy { it.path.getDistinctPath() } as ArrayList<Directory>)
|
||||
|
||||
removeInvalidDBDirectories(filteredDirectories, directoryDao)
|
||||
}.start()
|
||||
}
|
||||
|
||||
fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImagesOnly: Boolean = false, callback: (ArrayList<Medium>) -> Unit) {
|
||||
Thread {
|
||||
val mediumDao = galleryDB.MediumDao()
|
||||
val media = (if (path == "/") mediumDao.getAll() else mediumDao.getMediaFromPath(path)) as ArrayList<Medium>
|
||||
val foldersToScan = if (path == "/") MediaFetcher(this).getFoldersToScan() else arrayListOf(path)
|
||||
var media = ArrayList<Medium>()
|
||||
val shouldShowHidden = config.shouldShowHidden
|
||||
var filteredMedia = media
|
||||
foldersToScan.forEach {
|
||||
val currMedia = mediumDao.getMediaFromPath(it)
|
||||
media.addAll(currMedia)
|
||||
}
|
||||
|
||||
if (!shouldShowHidden) {
|
||||
filteredMedia = media.filter { !it.name.startsWith('.') } as ArrayList<Medium>
|
||||
media = media.filter { !it.path.contains("/.") } as ArrayList<Medium>
|
||||
}
|
||||
|
||||
val filterMedia = config.filterMedia
|
||||
filteredMedia = (when {
|
||||
getVideosOnly -> filteredMedia.filter { it.type == TYPE_VIDEOS }
|
||||
getImagesOnly -> filteredMedia.filter { it.type == TYPE_IMAGES }
|
||||
else -> filteredMedia.filter {
|
||||
media = (when {
|
||||
getVideosOnly -> media.filter { it.type == TYPE_VIDEOS }
|
||||
getImagesOnly -> media.filter { it.type == TYPE_IMAGES }
|
||||
else -> media.filter {
|
||||
(filterMedia and TYPE_IMAGES != 0 && it.type == TYPE_IMAGES) ||
|
||||
(filterMedia and TYPE_VIDEOS != 0 && it.type == TYPE_VIDEOS) ||
|
||||
(filterMedia and TYPE_GIFS != 0 && it.type == TYPE_GIFS)
|
||||
}
|
||||
}) as ArrayList<Medium>
|
||||
|
||||
callback(filteredMedia)
|
||||
MediaFetcher(this).sortMedia(media, config.getFileSorting(path))
|
||||
callback(media.clone() as ArrayList<Medium>)
|
||||
|
||||
media.filter { !getDoesFilePathExist(it.path) }.forEach {
|
||||
mediumDao.deleteMediumPath(it.path)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import com.google.gson.Gson
|
|||
import com.google.gson.reflect.TypeToken
|
||||
import com.simplemobiletools.commons.helpers.BaseConfig
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_DATE_MODIFIED
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_DATE_TAKEN
|
||||
import com.simplemobiletools.commons.helpers.SORT_DESCENDING
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.models.AlbumCover
|
||||
|
@ -18,13 +17,7 @@ class Config(context: Context) : BaseConfig(context) {
|
|||
}
|
||||
|
||||
var directorySorting: Int
|
||||
get(): Int {
|
||||
var sort = prefs.getInt(DIRECTORY_SORT_ORDER, SORT_BY_DATE_MODIFIED or SORT_DESCENDING)
|
||||
if (sort and SORT_BY_DATE_TAKEN != 0) {
|
||||
sort = sort - SORT_BY_DATE_TAKEN + SORT_BY_DATE_MODIFIED
|
||||
}
|
||||
return sort
|
||||
}
|
||||
get(): Int = prefs.getInt(DIRECTORY_SORT_ORDER, SORT_BY_DATE_MODIFIED or SORT_DESCENDING)
|
||||
set(order) = prefs.edit().putInt(DIRECTORY_SORT_ORDER, order).apply()
|
||||
|
||||
fun saveFileSorting(path: String, value: Int) {
|
||||
|
@ -35,13 +28,7 @@ class Config(context: Context) : BaseConfig(context) {
|
|||
}
|
||||
}
|
||||
|
||||
fun getFileSorting(path: String): Int {
|
||||
var sort = prefs.getInt(SORT_FOLDER_PREFIX + path.toLowerCase(), sorting)
|
||||
if (sort and SORT_BY_DATE_TAKEN != 0) {
|
||||
sort = sort - SORT_BY_DATE_TAKEN + SORT_BY_DATE_MODIFIED
|
||||
}
|
||||
return sort
|
||||
}
|
||||
fun getFileSorting(path: String) = prefs.getInt(SORT_FOLDER_PREFIX + path.toLowerCase(), sorting)
|
||||
|
||||
fun removeFileSorting(path: String) {
|
||||
prefs.edit().remove(SORT_FOLDER_PREFIX + path.toLowerCase()).apply()
|
||||
|
@ -331,4 +318,8 @@ class Config(context: Context) : BaseConfig(context) {
|
|||
var wasOTGHandled: Boolean
|
||||
get() = prefs.getBoolean(WAS_OTG_HANDLED, false)
|
||||
set(wasOTGHandled) = prefs.edit().putBoolean(WAS_OTG_HANDLED, wasOTGHandled).apply()
|
||||
|
||||
var tempSkipDeleteConfirmation: Boolean
|
||||
get() = prefs.getBoolean(TEMP_SKIP_DELETE_CONFIRMATION, false)
|
||||
set(tempSkipDeleteConfirmation) = prefs.edit().putBoolean(TEMP_SKIP_DELETE_CONFIRMATION, tempSkipDeleteConfirmation).apply()
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ const val DO_EXTRA_CHECK = "do_extra_check"
|
|||
const val WAS_NEW_APP_SHOWN = "was_new_app_shown_clock"
|
||||
const val LAST_FILEPICKER_PATH = "last_filepicker_path"
|
||||
const val WAS_OTG_HANDLED = "was_otg_handled"
|
||||
const val TEMP_SKIP_DELETE_CONFIRMATION = "temp_skip_delete_confirmation"
|
||||
|
||||
// slideshow
|
||||
const val SLIDESHOW_INTERVAL = "slideshow_interval"
|
||||
|
|
|
@ -5,9 +5,7 @@ import android.database.Cursor
|
|||
import android.net.Uri
|
||||
import android.provider.MediaStore
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.OTG_PATH
|
||||
import com.simplemobiletools.commons.helpers.photoExtensions
|
||||
import com.simplemobiletools.commons.helpers.videoExtensions
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.gallery.extensions.config
|
||||
import com.simplemobiletools.gallery.extensions.getDistinctPath
|
||||
import com.simplemobiletools.gallery.extensions.getOTGFolderChildren
|
||||
|
@ -18,7 +16,7 @@ import java.io.File
|
|||
class MediaFetcher(val context: Context) {
|
||||
var shouldStop = false
|
||||
|
||||
fun getFilesFrom(curPath: String, isPickImage: Boolean, isPickVideo: Boolean): ArrayList<Medium> {
|
||||
fun getFilesFrom(curPath: String, isPickImage: Boolean, isPickVideo: Boolean, getProperDateTaken: Boolean): ArrayList<Medium> {
|
||||
val filterMedia = context.config.filterMedia
|
||||
if (filterMedia == 0) {
|
||||
return ArrayList()
|
||||
|
@ -29,37 +27,32 @@ class MediaFetcher(val context: Context) {
|
|||
val newMedia = getMediaOnOTG(curPath, isPickImage, isPickVideo, filterMedia)
|
||||
curMedia.addAll(newMedia)
|
||||
} else {
|
||||
val newMedia = fetchFolderContent(curPath, isPickImage, isPickVideo, filterMedia)
|
||||
val newMedia = getMediaInFolder(curPath, isPickImage, isPickVideo, filterMedia, getProperDateTaken)
|
||||
curMedia.addAll(newMedia)
|
||||
}
|
||||
|
||||
Medium.sorting = context.config.getFileSorting(curPath)
|
||||
curMedia.sort()
|
||||
sortMedia(curMedia, context.config.getFileSorting(curPath))
|
||||
return curMedia
|
||||
}
|
||||
|
||||
fun getFoldersToScan(path: String): 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(path, filterMedia)} ${MediaStore.Images.ImageColumns.BUCKET_ID} IS NOT NULL) GROUP BY (${MediaStore.Images.ImageColumns.BUCKET_ID}"
|
||||
val selectionArgs = getSelectionArgsQuery(path, filterMedia).toTypedArray()
|
||||
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 {
|
||||
val cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
parseCursor(cursor, path)
|
||||
parseCursor(cursor)
|
||||
} catch (e: Exception) {
|
||||
ArrayList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSelectionQuery(path: String, filterMedia: Int): String {
|
||||
private fun getSelectionQuery(filterMedia: Int): String {
|
||||
val query = StringBuilder()
|
||||
if (path.isNotEmpty()) {
|
||||
query.append("${MediaStore.Images.Media.DATA} LIKE ? AND ${MediaStore.Images.Media.DATA} NOT LIKE ? AND ")
|
||||
}
|
||||
|
||||
query.append("(")
|
||||
if (filterMedia and TYPE_IMAGES != 0) {
|
||||
photoExtensions.forEach {
|
||||
|
@ -82,13 +75,8 @@ class MediaFetcher(val context: Context) {
|
|||
return selectionQuery
|
||||
}
|
||||
|
||||
private fun getSelectionArgsQuery(path: String, filterMedia: Int): ArrayList<String> {
|
||||
private fun getSelectionArgsQuery(filterMedia: Int): ArrayList<String> {
|
||||
val args = ArrayList<String>()
|
||||
if (path.isNotEmpty()) {
|
||||
args.add("$path/%")
|
||||
args.add("$path/%/%")
|
||||
}
|
||||
|
||||
if (filterMedia and TYPE_IMAGES != 0) {
|
||||
photoExtensions.forEach {
|
||||
args.add("%$it")
|
||||
|
@ -108,7 +96,7 @@ class MediaFetcher(val context: Context) {
|
|||
return args
|
||||
}
|
||||
|
||||
private fun parseCursor(cursor: Cursor, curPath: String): ArrayList<String> {
|
||||
private fun parseCursor(cursor: Cursor): ArrayList<String> {
|
||||
val config = context.config
|
||||
val includedFolders = config.includedFolders
|
||||
var foldersToScan = ArrayList<String>()
|
||||
|
@ -126,20 +114,12 @@ class MediaFetcher(val context: Context) {
|
|||
}
|
||||
|
||||
includedFolders.forEach {
|
||||
if (curPath.isEmpty()) {
|
||||
addFolder(foldersToScan, it)
|
||||
} else if (curPath == it) {
|
||||
foldersToScan.add(it)
|
||||
}
|
||||
addFolder(foldersToScan, it)
|
||||
}
|
||||
|
||||
val showHidden = config.shouldShowHidden
|
||||
val excludedFolders = config.excludedFolders
|
||||
foldersToScan = foldersToScan.filter { it.shouldFolderBeVisible(excludedFolders, includedFolders, showHidden) } as ArrayList<String>
|
||||
if (config.isThirdPartyIntent && curPath.isNotEmpty()) {
|
||||
foldersToScan.add(curPath)
|
||||
}
|
||||
|
||||
return foldersToScan.distinctBy { it.getDistinctPath() } as ArrayList<String>
|
||||
}
|
||||
|
||||
|
@ -163,19 +143,12 @@ class MediaFetcher(val context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
private fun fetchFolderContent(path: String, isPickImage: Boolean, isPickVideo: Boolean, filterMedia: Int): ArrayList<Medium> {
|
||||
return if (path.startsWith(OTG_PATH)) {
|
||||
getMediaOnOTG(path, isPickImage, isPickVideo, filterMedia)
|
||||
} else {
|
||||
getMediaInFolder(path, isPickImage, isPickVideo, filterMedia)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMediaInFolder(folder: String, isPickImage: Boolean, isPickVideo: Boolean, filterMedia: Int): ArrayList<Medium> {
|
||||
private fun getMediaInFolder(folder: String, isPickImage: Boolean, isPickVideo: Boolean, filterMedia: Int, getProperDateTaken: Boolean): ArrayList<Medium> {
|
||||
val media = ArrayList<Medium>()
|
||||
val files = File(folder).listFiles() ?: return media
|
||||
val doExtraCheck = context.config.doExtraCheck
|
||||
val showHidden = context.config.shouldShowHidden
|
||||
val dateTakens = if (getProperDateTaken) getFolderDateTakens(folder) else HashMap()
|
||||
|
||||
for (file in files) {
|
||||
if (shouldStop) {
|
||||
|
@ -206,8 +179,12 @@ class MediaFetcher(val context: Context) {
|
|||
if (size <= 0L || (doExtraCheck && !file.exists()))
|
||||
continue
|
||||
|
||||
val dateTaken = file.lastModified()
|
||||
val dateModified = file.lastModified()
|
||||
val lastModified = file.lastModified()
|
||||
var dateTaken = lastModified
|
||||
|
||||
if (getProperDateTaken) {
|
||||
dateTaken = dateTakens.remove(filename) ?: lastModified
|
||||
}
|
||||
|
||||
val type = when {
|
||||
isImage -> TYPE_IMAGES
|
||||
|
@ -215,7 +192,7 @@ class MediaFetcher(val context: Context) {
|
|||
else -> TYPE_GIFS
|
||||
}
|
||||
|
||||
val medium = Medium(null, filename, file.absolutePath, folder, dateModified, dateTaken, size, type)
|
||||
val medium = Medium(null, filename, file.absolutePath, folder, lastModified, dateTaken, size, type)
|
||||
media.add(medium)
|
||||
}
|
||||
return media
|
||||
|
@ -272,4 +249,51 @@ class MediaFetcher(val context: Context) {
|
|||
|
||||
return media
|
||||
}
|
||||
|
||||
private fun getFolderDateTakens(folder: String): HashMap<String, Long> {
|
||||
val projection = arrayOf(
|
||||
MediaStore.Images.Media.DISPLAY_NAME,
|
||||
MediaStore.Images.Media.DATE_TAKEN
|
||||
)
|
||||
|
||||
val uri = MediaStore.Files.getContentUri("external")
|
||||
val selection = "${MediaStore.Images.Media.DATA} LIKE ? AND ${MediaStore.Images.Media.DATA} NOT LIKE ?"
|
||||
val selectionArgs = arrayOf("$folder/%", "$folder/%/%")
|
||||
|
||||
val dateTakens = HashMap<String, Long>()
|
||||
val cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
cursor.use {
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
try {
|
||||
val path = cursor.getStringValue(MediaStore.Images.Media.DISPLAY_NAME)
|
||||
val dateTaken = cursor.getLongValue(MediaStore.Images.Media.DATE_TAKEN)
|
||||
dateTakens[path] = dateTaken
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
}
|
||||
|
||||
return dateTakens
|
||||
}
|
||||
|
||||
fun sortMedia(media: ArrayList<Medium>, sorting: Int) {
|
||||
media.sortWith(Comparator { o1, o2 ->
|
||||
o1 as Medium
|
||||
o2 as Medium
|
||||
var result = when {
|
||||
sorting and SORT_BY_NAME != 0 -> AlphanumericComparator().compare(o1.name.toLowerCase(), o2.name.toLowerCase())
|
||||
sorting and SORT_BY_PATH != 0 -> AlphanumericComparator().compare(o1.path.toLowerCase(), o2.path.toLowerCase())
|
||||
sorting and SORT_BY_SIZE != 0 -> o1.size.compareTo(o2.size)
|
||||
sorting and SORT_BY_DATE_MODIFIED != 0 -> o1.modified.compareTo(o2.modified)
|
||||
else -> o1.taken.compareTo(o2.taken)
|
||||
}
|
||||
|
||||
if (sorting and SORT_DESCENDING != 0) {
|
||||
result *= -1
|
||||
}
|
||||
result
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,9 @@ interface DirectoryDao {
|
|||
@Query("DELETE FROM directories WHERE path = :path")
|
||||
fun deleteDirPath(path: String)
|
||||
|
||||
@Query("UPDATE OR REPLACE directories SET thumbnail = :thumbnail, media_count = :mediaCnt, last_modified = :lastModified, date_taken = :dateTaken, size = :size, media_types = :mediaTypes WHERE path = :path")
|
||||
@Query("UPDATE OR REPLACE directories SET thumbnail = :thumbnail, media_count = :mediaCnt, last_modified = :lastModified, date_taken = :dateTaken, size = :size, media_types = :mediaTypes WHERE path = :path")
|
||||
fun updateDirectory(path: String, thumbnail: String, mediaCnt: Int, lastModified: Long, dateTaken: Long, size: Long, mediaTypes: Int)
|
||||
|
||||
@Query("UPDATE directories SET thumbnail = :thumbnail, filename = :name, path = :newPath WHERE path = :oldPath")
|
||||
fun updateDirectoryAfterRename(thumbnail: String, name: String, newPath: String, oldPath: String)
|
||||
}
|
||||
|
|
|
@ -8,9 +8,6 @@ import com.simplemobiletools.gallery.models.Medium
|
|||
|
||||
@Dao
|
||||
interface MediumDao {
|
||||
@Query("SELECT * FROM media")
|
||||
fun getAll(): List<Medium>
|
||||
|
||||
@Query("SELECT filename, full_path, parent_path, last_modified, date_taken, size, type FROM media WHERE parent_path = :path")
|
||||
fun getMediaFromPath(path: String): List<Medium>
|
||||
|
||||
|
|
|
@ -6,7 +6,10 @@ import android.arch.persistence.room.Index
|
|||
import android.arch.persistence.room.PrimaryKey
|
||||
import com.simplemobiletools.commons.extensions.formatDate
|
||||
import com.simplemobiletools.commons.extensions.formatSize
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_DATE_MODIFIED
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_NAME
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_PATH
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_SIZE
|
||||
import java.io.Serializable
|
||||
|
||||
@Entity(tableName = "directories", indices = [Index(value = "path", unique = true)])
|
||||
|
@ -20,42 +23,13 @@ data class Directory(
|
|||
@ColumnInfo(name = "date_taken") var taken: Long,
|
||||
@ColumnInfo(name = "size") var size: Long,
|
||||
@ColumnInfo(name = "location") val location: Int,
|
||||
@ColumnInfo(name = "media_types") var types: Int) : Serializable, Comparable<Directory> {
|
||||
@ColumnInfo(name = "media_types") var types: Int) : Serializable {
|
||||
|
||||
companion object {
|
||||
private const val serialVersionUID = -6553345863555455L
|
||||
var sorting: Int = 0
|
||||
}
|
||||
|
||||
override fun compareTo(other: Directory): Int {
|
||||
var result: Int
|
||||
when {
|
||||
sorting and SORT_BY_NAME != 0 -> result = AlphanumericComparator().compare(name.toLowerCase(), other.name.toLowerCase())
|
||||
sorting and SORT_BY_PATH != 0 -> result = AlphanumericComparator().compare(path.toLowerCase(), other.path.toLowerCase())
|
||||
sorting and SORT_BY_SIZE != 0 -> result = when {
|
||||
size == other.size -> 0
|
||||
size > other.size -> 1
|
||||
else -> -1
|
||||
}
|
||||
sorting and SORT_BY_DATE_MODIFIED != 0 -> result = when {
|
||||
modified == other.modified -> 0
|
||||
modified > other.modified -> 1
|
||||
else -> -1
|
||||
}
|
||||
else -> result = when {
|
||||
taken == other.taken -> 0
|
||||
taken > other.taken -> 1
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
|
||||
if (sorting and SORT_DESCENDING != 0) {
|
||||
result *= -1
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun getBubbleText() = when {
|
||||
fun getBubbleText(sorting: Int) = when {
|
||||
sorting and SORT_BY_NAME != 0 -> name
|
||||
sorting and SORT_BY_PATH != 0 -> path
|
||||
sorting and SORT_BY_SIZE != 0 -> size.formatSize()
|
||||
|
|
|
@ -7,7 +7,10 @@ import android.arch.persistence.room.PrimaryKey
|
|||
import com.simplemobiletools.commons.extensions.formatDate
|
||||
import com.simplemobiletools.commons.extensions.formatSize
|
||||
import com.simplemobiletools.commons.extensions.isDng
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_DATE_MODIFIED
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_NAME
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_PATH
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_SIZE
|
||||
import com.simplemobiletools.gallery.helpers.TYPE_GIFS
|
||||
import com.simplemobiletools.gallery.helpers.TYPE_IMAGES
|
||||
import com.simplemobiletools.gallery.helpers.TYPE_VIDEOS
|
||||
|
@ -20,13 +23,12 @@ data class Medium(
|
|||
@ColumnInfo(name = "full_path") var path: String,
|
||||
@ColumnInfo(name = "parent_path") var parentPath: String,
|
||||
@ColumnInfo(name = "last_modified") val modified: Long,
|
||||
@ColumnInfo(name = "date_taken") val taken: Long,
|
||||
@ColumnInfo(name = "date_taken") var taken: Long,
|
||||
@ColumnInfo(name = "size") val size: Long,
|
||||
@ColumnInfo(name = "type") val type: Int) : Serializable, Comparable<Medium> {
|
||||
@ColumnInfo(name = "type") val type: Int) : Serializable {
|
||||
|
||||
companion object {
|
||||
private const val serialVersionUID = -6553149366975455L
|
||||
var sorting: Int = 0
|
||||
}
|
||||
|
||||
fun isGif() = type == TYPE_GIFS
|
||||
|
@ -37,35 +39,7 @@ data class Medium(
|
|||
|
||||
fun isDng() = path.isDng()
|
||||
|
||||
override fun compareTo(other: Medium): Int {
|
||||
var result: Int
|
||||
when {
|
||||
sorting and SORT_BY_NAME != 0 -> result = AlphanumericComparator().compare(name.toLowerCase(), other.name.toLowerCase())
|
||||
sorting and SORT_BY_PATH != 0 -> result = AlphanumericComparator().compare(path.toLowerCase(), other.path.toLowerCase())
|
||||
sorting and SORT_BY_SIZE != 0 -> result = when {
|
||||
size == other.size -> 0
|
||||
size > other.size -> 1
|
||||
else -> -1
|
||||
}
|
||||
sorting and SORT_BY_DATE_MODIFIED != 0 -> result = when {
|
||||
modified == other.modified -> 0
|
||||
modified > other.modified -> 1
|
||||
else -> -1
|
||||
}
|
||||
else -> result = when {
|
||||
taken == other.taken -> 0
|
||||
taken > other.taken -> 1
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
|
||||
if (sorting and SORT_DESCENDING != 0) {
|
||||
result *= -1
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun getBubbleText() = when {
|
||||
fun getBubbleText(sorting: Int) = when {
|
||||
sorting and SORT_BY_NAME != 0 -> name
|
||||
sorting and SORT_BY_PATH != 0 -> path
|
||||
sorting and SORT_BY_SIZE != 0 -> size.formatSize()
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M63.58,40.16m-5.73,0a5.73,5.73 0,1 1,11.47 0a5.73,5.73 0,1 1,-11.47 0"/>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M47.37,46.64l-17.45,25.43l45.46,0l-9.89,-16.21l-5.9,8.39z"/>
|
||||
</vector>
|
|
@ -52,6 +52,14 @@
|
|||
android:paddingTop="@dimen/medium_margin"
|
||||
android:text="@string/last_modified"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyCompatRadioButton
|
||||
android:id="@+id/sorting_dialog_radio_date_taken"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/medium_margin"
|
||||
android:paddingTop="@dimen/medium_margin"
|
||||
android:text="@string/date_taken"/>
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
<include
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/color_primary"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<background android:drawable="@color/md_orange_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
|
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_amber.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_amber_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_blue.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_blue_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_blue_grey_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_brown.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_brown_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_cyan.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_cyan_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_deep_orange_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_deep_purple_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_green.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_green_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_grey_black"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_indigo_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_light_blue_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_light_green_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_lime.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_lime_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_pink.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_pink_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_purple_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_red.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_red_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_teal.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_teal_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_yellow_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 4.2 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_amber.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_blue.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_blue_grey.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_brown.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_cyan.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_deep_orange.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_deep_purple.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_green.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_grey_black.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_indigo.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_light_blue.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_light_green.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_lime.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_pink.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_purple.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_red.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_teal.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_yellow.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_amber.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_blue.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_blue_grey.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_brown.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_cyan.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_deep_orange.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_deep_purple.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_green.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_grey_black.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_indigo.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_light_blue.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_light_green.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_lime.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_pink.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_purple.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_red.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_teal.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_yellow.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 6.1 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_amber.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_blue.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_blue_grey.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_brown.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_cyan.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_deep_orange.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_deep_purple.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_green.png
Normal file
After Width: | Height: | Size: 5.8 KiB |