diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml
new file mode 100644
index 00000000..6466f798
--- /dev/null
+++ b/.github/workflows/android-build.yml
@@ -0,0 +1,45 @@
+name: Android Build CI
+
+on:
+ push:
+ branches:
+ - '*'
+ - '!master'
+ - '!release/*'
+concurrency:
+ group: build-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ check_spotless:
+ name: Check spotless
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v3
+ - name: Set up JDK 11
+ uses: actions/setup-java@v3
+ with:
+ distribution: "temurin"
+ java-version: 11
+ - name: Check formatting using spotless
+ uses: gradle/gradle-build-action@v2.4.2
+ with:
+ arguments: spotlessCheck
+ build:
+ name: Build debug
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - name: Set up JDK 11
+ uses: actions/setup-java@v3
+ with:
+ distribution: "temurin"
+ java-version: 11
+ - name: Build with Gradle
+ uses: gradle/gradle-build-action@v2.4.2
+ with:
+ arguments: assembledebug --stacktrace
+ env:
+ TZ: UTC
\ No newline at end of file
diff --git a/.github/workflows/android-main.yml b/.github/workflows/android-main.yml
index b46834d8..83e81f71 100644
--- a/.github/workflows/android-main.yml
+++ b/.github/workflows/android-main.yml
@@ -40,7 +40,7 @@ jobs:
- name: Build with Gradle
uses: gradle/gradle-build-action@v2.4.2
with:
- arguments: assembledebug
+ arguments: assembledebug --stacktrace
env:
TZ: UTC
- name: Publish on Telegram
diff --git a/app/build.gradle b/app/build.gradle
index dd9558b9..b39235b5 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -2,7 +2,7 @@ buildscript {
ext {
jacocoVersion = "0.8.7"
androidXLifecycleVersion = "2.3.1"
- glideVersion = '4.11.0'
+ glideVersion = '4.16.0'
fragment_version = "1.3.6"
roomVersion = "2.5.2"
billing_version = "6.0.1"
@@ -293,7 +293,7 @@ dependencies {
api "com.caverock:androidsvg:1.4"
implementation 'com.burhanrashid52:photoeditor:2.0.0'
implementation 'com.github.CanHub:Android-Image-Cropper:4.3.1'
- api 'com.github.TeamAmaze:mupdf-android-viewer:1.0.26'
+ api 'com.github.TeamAmaze:mupdf-android-viewer:1.0.27'
implementation "androidx.documentfile:documentfile:1.0.1"
implementation 'id.zelory:compressor:3.0.1'
implementation('com.github.AbedElazizShe:LightCompressor:1.3.1') {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c43662cd..278da6d2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -57,7 +57,6 @@
android:theme="@style/Theme.AmazeFileUtilities"
android:screenOrientation="portrait"
tools:ignore="LockedOrientationActivity"
- android:launchMode="singleInstance"
>
@@ -96,7 +95,6 @@
android:name=".image_viewer.ImageViewerActivity"
android:label="@string/image_viewer"
android:theme="@style/Theme.AmazeFileUtilities.FullScreen.Dark"
- android:launchMode="singleInstance"
android:exported="true"
>
@@ -198,7 +194,7 @@
android:exported="true"
android:label="@string/docx_viewer"
android:theme="@style/Theme.AmazeFileUtilities"
- android:launchMode="singleInstance">
+ >
@@ -214,7 +210,7 @@
android:name=".home_page.ui.options.AboutActivity"
android:exported="true"
android:theme="@style/Custom.Dialog.Dark"
- android:launchMode="singleInstance">
+ >
?,
+ target: Target,
isFirstResource: Boolean
): Boolean {
// do nothing
@@ -274,15 +274,15 @@ interface IAudioPlayerInterfaceHandler : OnPlaybackInfoUpdate, LifecycleOwner {
}
override fun onResourceReady(
- resource: Drawable?,
- model: Any?,
+ resource: Drawable,
+ model: Any,
target: Target?,
- dataSource: DataSource?,
+ dataSource: DataSource,
isFirstResource: Boolean
): Boolean {
getContextWeakRef().get()?.let {
context ->
- resource?.let {
+ resource.let {
getAudioPlayerHandlerViewModel().getPaletteColor(
it,
context.getColor(R.color.navy_blue_alt_3)
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/analyse/AnalyseFragment.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/analyse/AnalyseFragment.kt
index 6c914d66..923e8bbb 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/analyse/AnalyseFragment.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/analyse/AnalyseFragment.kt
@@ -22,6 +22,7 @@ package com.amaze.fileutilities.home_page.ui.analyse
import android.content.Intent
import android.content.SharedPreferences
+import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
@@ -483,6 +484,7 @@ class AnalyseFragment : AbstractMediaFileInfoOperationsFragment() {
if (!isUsageStatsPermissionGranted()) {
unusedAppsPreview.loadRequireElevatedPermission({
val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)
+ intent.data = Uri.parse("package:${requireActivity().packageName}")
startActivity(intent)
}, ::usageStatsPermissionReload)
} else {
@@ -507,10 +509,12 @@ class AnalyseFragment : AbstractMediaFileInfoOperationsFragment() {
if (!isUsageStatsPermissionGranted()) {
mostUsedAppsPreview.loadRequireElevatedPermission({
val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)
+ intent.data = Uri.parse("package:${requireActivity().packageName}")
startActivity(intent)
}, ::usageStatsPermissionReload)
leastUsedAppsPreview.loadRequireElevatedPermission({
val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)
+ intent.data = Uri.parse("package:${requireActivity().packageName}")
startActivity(intent)
}, ::usageStatsPermissionReload)
} else {
@@ -551,6 +555,7 @@ class AnalyseFragment : AbstractMediaFileInfoOperationsFragment() {
) {
networkIntensiveAppsPreview.loadRequireElevatedPermission({
val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)
+ intent.data = Uri.parse("package:${requireActivity().packageName}")
startActivity(intent)
}, ::usageStatsPermissionReload)
} else {
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/analyse/ReviewAnalysisAdapter.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/analyse/ReviewAnalysisAdapter.kt
index b2e8de4e..d2de8515 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/analyse/ReviewAnalysisAdapter.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/analyse/ReviewAnalysisAdapter.kt
@@ -35,7 +35,7 @@ import java.lang.ref.WeakReference
class ReviewAnalysisAdapter(
val context: Context,
val analysisType: Int?,
- private val preloader: MediaAdapterPreloader,
+ private val preloader: MediaAdapterPreloader,
private val mediaFileInfoList: MutableList,
toggleCheckCallback: (
checkedSize: Int,
@@ -55,10 +55,10 @@ class ReviewAnalysisAdapter(
value.clear()
for (i in mediaFileInfoList.indices) {
value.add(ListItem(mediaFileInfo = mediaFileInfoList[i]))
- preloader.addItem(mediaFileInfoList[i].path)
+ preloader.addItem(mediaFileInfoList[i])
}
if (mediaFileInfoList.size != 0) {
- preloader.addItem("")
+ preloader.addItem(null)
value.add(ListItem(EMPTY_LAST_ITEM))
}
field = value
@@ -123,12 +123,14 @@ class ReviewAnalysisAdapter(
}
}
+ /** Returns the number of items. There might be dummy items, that are also counted here */
override fun getItemCount(): Int {
return mediaFileListItems.size
}
+ /** Returns the number of actual items. Dummy items are not counted. */
override fun getOnlyItemsCount(): Int {
- return mediaFileListItems.size
+ return mediaFileListItems.size - 1
}
override fun getItemViewType(position: Int): Int {
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/analyse/ReviewImagesFragment.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/analyse/ReviewImagesFragment.kt
index d00e6820..00685324 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/analyse/ReviewImagesFragment.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/analyse/ReviewImagesFragment.kt
@@ -68,8 +68,8 @@ class ReviewImagesFragment : ItemsActionBarFragment() {
private lateinit var viewModel: AnalyseViewModel
private var gridLayoutManager: GridLayoutManager? = GridLayoutManager(context, 3)
private var mediaFileAdapter: ReviewAnalysisAdapter? = null
- private var preloader: MediaAdapterPreloader? = null
- private var recyclerViewPreloader: RecyclerViewPreloader? = null
+ private var preloader: MediaAdapterPreloader? = null
+ private var recyclerViewPreloader: RecyclerViewPreloader? = null
private val MAX_PRELOAD = 50
private var analysisType: Int? = null
@@ -147,9 +147,10 @@ class ReviewImagesFragment : ItemsActionBarFragment() {
// set list adapter
preloader = MediaAdapterPreloader(
requireContext(),
- R.drawable.ic_outline_insert_drive_file_32
+ R.drawable.ic_outline_insert_drive_file_32,
+ true
)
- val sizeProvider = ViewPreloadSizeProvider()
+ val sizeProvider = ViewPreloadSizeProvider()
recyclerViewPreloader = RecyclerViewPreloader(
Glide.with(requireActivity()),
preloader!!,
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/AbstractMediaInfoListFragment.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/AbstractMediaInfoListFragment.kt
index e64faba2..e53d8a12 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/AbstractMediaInfoListFragment.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/AbstractMediaInfoListFragment.kt
@@ -53,9 +53,10 @@ abstract class AbstractMediaInfoListFragment :
private var gridLayoutManager: GridLayoutManager? = null
private val MAX_PRELOAD = 100
private var log: Logger = LoggerFactory.getLogger(AbstractMediaInfoListFragment::class.java)
+ private var mediaPreloader: MediaAdapterPreloader? = null
override fun onDestroyView() {
- getMediaAdapterPreloader().clear()
+ mediaPreloader?.clear()
super.onDestroyView()
}
@@ -83,7 +84,7 @@ abstract class AbstractMediaInfoListFragment :
abstract fun getFileStorageSummaryAndMediaFileInfoPair():
Pair?>?
- abstract fun getMediaAdapterPreloader(): MediaAdapterPreloader
+ abstract fun getMediaAdapterPreloader(isGrid: Boolean): MediaAdapterPreloader
abstract fun getRecyclerView(): RecyclerView
@@ -116,21 +117,22 @@ abstract class AbstractMediaInfoListFragment :
storageSummary.totalUsedSpace!!
)
// set list adapter
- val sizeProvider = ViewPreloadSizeProvider()
- val recyclerViewPreloader = RecyclerViewPreloader(
- Glide.with(requireActivity()),
- getMediaAdapterPreloader(),
- sizeProvider,
- MAX_PRELOAD
- )
+ val sizeProvider = ViewPreloadSizeProvider()
val isList = requireContext()
.getAppCommonSharedPreferences().getBoolean(
"${getMediaListType()}_${PreferencesConstants.KEY_MEDIA_LIST_TYPE}",
PreferencesConstants.DEFAULT_MEDIA_LIST_TYPE
)
+ mediaPreloader = getMediaAdapterPreloader(!isList)
+ val recyclerViewPreloader = RecyclerViewPreloader(
+ Glide.with(requireActivity()),
+ mediaPreloader!!,
+ sizeProvider,
+ MAX_PRELOAD
+ )
mediaFileAdapter = MediaFileAdapter(
requireActivity(),
- getMediaAdapterPreloader(),
+ mediaPreloader!!,
this@AbstractMediaInfoListFragment, !isList,
MediaFileListSorter.SortingPreference.newInstance(
requireContext()
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/AudiosListFragment.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/AudiosListFragment.kt
index 44eb8e3b..94951a5a 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/AudiosListFragment.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/AudiosListFragment.kt
@@ -72,8 +72,8 @@ class AudiosListFragment : AbstractMediaInfoListFragment(), IAudioPlayerInterfac
Pair?>? = null
private lateinit var audioPlaybackServiceConnection: AudioPlaybackServiceConnection
- private var filesPreloader: MediaAdapterPreloader? = null
- private var playlistsPreloader: MediaAdapterPreloader? = null
+ private var filesPreloader: MediaAdapterPreloader? = null
+ private var playlistsPreloader: MediaAdapterPreloader? = null
private var isWaveformProcessing = false
private var lastPaletteColor: Int = 0
private var lastLyrics: String? = null
@@ -368,7 +368,7 @@ class AudiosListFragment : AbstractMediaInfoListFragment(), IAudioPlayerInterfac
}
}
- override fun getMediaAdapterPreloader(): MediaAdapterPreloader {
+ override fun getMediaAdapterPreloader(isGrid: Boolean): MediaAdapterPreloader {
val sharedPrefs = requireContext().getAppCommonSharedPreferences()
val groupByPref = sharedPrefs.getInt(
MediaFileListSorter.SortingPreference.getGroupByKey(MediaFileAdapter.MEDIA_TYPE_AUDIO),
@@ -378,7 +378,8 @@ class AudiosListFragment : AbstractMediaInfoListFragment(), IAudioPlayerInterfac
if (filesPreloader == null) {
filesPreloader = MediaAdapterPreloader(
requireContext(),
- R.drawable.ic_outline_audio_file_32
+ R.drawable.ic_outline_audio_file_32,
+ isGrid
)
}
return filesPreloader!!
@@ -386,7 +387,8 @@ class AudiosListFragment : AbstractMediaInfoListFragment(), IAudioPlayerInterfac
if (playlistsPreloader == null) {
playlistsPreloader = MediaAdapterPreloader(
requireContext(),
- R.drawable.ic_outline_audio_file_32
+ R.drawable.ic_outline_audio_file_32,
+ isGrid
)
}
return playlistsPreloader!!
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/DocumentsListFragment.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/DocumentsListFragment.kt
index db2ea5c2..23082284 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/DocumentsListFragment.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/DocumentsListFragment.kt
@@ -47,7 +47,7 @@ class DocumentsListFragment : AbstractMediaInfoListFragment() {
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
- private var preloader: MediaAdapterPreloader? = null
+ private var preloader: MediaAdapterPreloader? = null
override fun onCreateView(
inflater: LayoutInflater,
@@ -79,11 +79,12 @@ class DocumentsListFragment : AbstractMediaInfoListFragment() {
fileStorageSummaryAndMediaFileInfo else null
}
- override fun getMediaAdapterPreloader(): MediaAdapterPreloader {
+ override fun getMediaAdapterPreloader(isGrid: Boolean): MediaAdapterPreloader {
if (preloader == null) {
preloader = MediaAdapterPreloader(
requireContext(),
- R.drawable.ic_outline_insert_drive_file_32
+ R.drawable.ic_outline_insert_drive_file_32,
+ isGrid
)
}
return preloader!!
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/FilesFragment.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/FilesFragment.kt
index d2d6ec5f..7410d8fc 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/FilesFragment.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/FilesFragment.kt
@@ -25,8 +25,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.view.animation.Animation
-import android.view.animation.AnimationUtils
import androidx.core.graphics.ColorUtils
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
@@ -52,8 +50,8 @@ class FilesFragment : ItemsActionBarFragment() {
private val filesViewModel: FilesViewModel by activityViewModels()
private var _binding: FragmentFilesBinding? = null
private var mediaFileAdapter: RecentMediaFilesAdapter? = null
- private var preloader: MediaAdapterPreloader? = null
- private var recyclerViewPreloader: RecyclerViewPreloader? = null
+ private var preloader: MediaAdapterPreloader? = null
+ private var recyclerViewPreloader: RecyclerViewPreloader? = null
private var linearLayoutManager: LinearLayoutManager? = null
private val MAX_PRELOAD = 100
@@ -297,9 +295,10 @@ class FilesFragment : ItemsActionBarFragment() {
}
preloader = MediaAdapterPreloader(
applicationContext,
- R.drawable.ic_outline_insert_drive_file_32
+ R.drawable.ic_outline_insert_drive_file_32,
+ false
)
- val sizeProvider = ViewPreloadSizeProvider()
+ val sizeProvider = ViewPreloadSizeProvider()
recyclerViewPreloader = RecyclerViewPreloader(
Glide.with(applicationContext),
preloader!!,
@@ -370,10 +369,6 @@ class FilesFragment : ItemsActionBarFragment() {
}
binding.storagePercent.setAdaptiveColorProvider(colorProvider)
- val slideUpAnimation: Animation =
- AnimationUtils.loadAnimation(requireContext(), R.anim.slide_up_fade_in)
- binding.listFragmentParent.startAnimation(slideUpAnimation)
- binding.listFragmentParent.visibility = View.VISIBLE
return root
}
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/FilesViewModel.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/FilesViewModel.kt
index 4bc71902..02999f3e 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/FilesViewModel.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/FilesViewModel.kt
@@ -659,6 +659,22 @@ class FilesViewModel(val applicationContext: Application) :
}
}
+ /**
+ * We find histogram for a given image, divide it in 256/8 windows.
+ * For each window of this histogram, we find the red, green and blue channel peaks individually, along with it's position for a given window.
+ * All these data points are then saved in database table for all images.
+ * This process starts as soon as app starts and keeps running in background (ofcourse there are multiple optimisations done so as to not fill up RAM, for all the background running analysis in the app).
+ * Then once we have all the histograms data (all analysis resumes from last point in case user closes the app, or users take new images till the time we have processed all the images), so however multiple runs the app takes, once we have all the histogram data, it's time to figure out the similar images.
+ * To figure out the similar images, we compare the peaks of the rgb channel of each window, once we have x number of windows that matches, say 6 out of 8 windows, we can say that image may be similar (the number was decided based on multiple tests in real life).
+ * In order to make results more realistic, we also compare the position of peak along with the peak rgb channel for a given window. Ofcourse, you can't have the exact same pixel position for a peak, so a normalization was also done.
+ * Finally, when we have a matching image that satisfies above criteria, we take a checksum of all the rgb channel windows along with it's parent path (this is done so that we only match similar images in the same directory, as chances are, similar images will be in the same directory and helps to minimize false positives), and then save checksum value of all the images in the table.
+ * This second part of the analysis is also done in the background.
+ * So till here we have figured out the similar images and can uniquely identify them from their checksum, so that we don't have to repeat the second step at the runtime.
+ * Finally when a user opens the analysis section of the app, all we have to do is to group images by same checksum and list them to the user.
+ * Ofcourse there may be some false positives in this (or any other) analysis algorithm in the app, so we already have a feature where all user have to do is select the analysis result, and press the thumbs down button at top of the screen, and then that analysis will be marked false positive in the database and will not be shown to user again.
+ * Phew, this was something, I had to write this down so that I don't forget in future again instead of going through the code.
+ * I know there are multiple algorithms online, too complicated for me to understand and write from scratch in java (they're native functions in python). So I had to resort to write on my own.
+ */
fun analyseSimilarImages(
mediaFileInfoList: List,
pathPreferencesList: List
@@ -1945,7 +1961,7 @@ class FilesViewModel(val applicationContext: Application) :
recentlyUpdatedAppsLiveData?.postValue(ArrayList(result.reversed()))
}
}
-
+
fun getLargeSizeDiffApps(): LiveData?> {
if (largeSizeDiffAppsLiveData == null) {
largeSizeDiffAppsLiveData = MutableLiveData()
@@ -2010,6 +2026,12 @@ class FilesViewModel(val applicationContext: Application) :
}
}
+ /**
+ * installedAppsDao contains all the apps installed at a given instance, the list gets updated each time we fetch all apps.
+ * We fetch list of installed apps right now here again, and compare with the installedAppsDao list
+ * apps installed right now will be a subset of installedAppsDao
+ * We find the difference first, then for apps that aren't installed now, we check to see if there is any data directory present or not.
+ */
fun getJunkFilesLiveData(): LiveData, String>?> {
if (junkFilesLiveData == null) {
junkFilesLiveData = MutableLiveData()
@@ -2023,38 +2045,39 @@ class FilesViewModel(val applicationContext: Application) :
viewModelScope.launch(Dispatchers.IO) {
loadAllInstalledApps(packageManager)
val dao = AppDatabase.getInstance(applicationContext).installedAppsDao()
- val savedInstalledApps = dao.findAll().filter {
- savedAppData ->
- allApps.get()?.any {
- !it.first.packageName.equals(savedAppData.packageName)
- } == false
- }
- log.info("found following apps not installed {}", savedInstalledApps)
- val result = ArrayList()
- savedInstalledApps.forEach {
- savedApp ->
- savedApp.dataDirs.forEach {
- result.add(
- MediaFileInfo.fromFile(
- File(it),
- MediaFileInfo.ExtraInfo(
- MediaFileInfo.MEDIA_TYPE_UNKNOWN,
- null, null, null
+ val savedInstalledApps = dao.findAll()
+ allApps.get()?.map { it.first.packageName }?.toSet()?.let {
+ installedAppsPackageNames ->
+ val difference = savedInstalledApps.filter {
+ it.packageName !in installedAppsPackageNames
+ }
+ log.info("found following apps not installed {}", difference)
+ val result = ArrayList()
+ difference.forEach {
+ savedApp ->
+ savedApp.dataDirs.forEach {
+ result.add(
+ MediaFileInfo.fromFile(
+ File(it),
+ MediaFileInfo.ExtraInfo(
+ MediaFileInfo.MEDIA_TYPE_UNKNOWN,
+ null, null, null
+ )
)
)
- )
+ }
}
- }
- var size = 0L
- result.forEach {
- size += it.longSize
- }
- junkFilesLiveData?.postValue(
- Pair(
- result,
- Formatter.formatFileSize(applicationContext, size)
+ var size = 0L
+ result.forEach {
+ size += it.longSize
+ }
+ junkFilesLiveData?.postValue(
+ Pair(
+ result,
+ Formatter.formatFileSize(applicationContext, size)
+ )
)
- )
+ }
}
}
@@ -2450,7 +2473,13 @@ class FilesViewModel(val applicationContext: Application) :
allApps.get()?.let {
infoListPair ->
val installedApps = infoListPair.map {
- InstalledApps(it.first.packageName, listOf(it.first.sourceDir, it.first.dataDir))
+ InstalledApps(
+ it.first.packageName,
+ listOf(
+ it.first.sourceDir,
+ it.first.dataDir, it.first.publicSourceDir
+ )
+ )
}
val dao = AppDatabase.getInstance(applicationContext).installedAppsDao()
dao.updateOrInsert(installedApps)
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/ImagesListFragment.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/ImagesListFragment.kt
index c425ab22..9798da8b 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/ImagesListFragment.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/ImagesListFragment.kt
@@ -47,7 +47,7 @@ class ImagesListFragment : AbstractMediaInfoListFragment() {
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
- private var preloader: MediaAdapterPreloader? = null
+ private var preloader: MediaAdapterPreloader? = null
override fun onCreateView(
inflater: LayoutInflater,
@@ -79,11 +79,12 @@ class ImagesListFragment : AbstractMediaInfoListFragment() {
fileStorageSummaryAndMediaFileInfo else null
}
- override fun getMediaAdapterPreloader(): MediaAdapterPreloader {
+ override fun getMediaAdapterPreloader(isGrid: Boolean): MediaAdapterPreloader {
if (preloader == null) {
preloader = MediaAdapterPreloader(
requireContext(),
- R.drawable.ic_outline_image_32
+ R.drawable.ic_outline_image_32,
+ isGrid
)
}
return preloader!!
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaAdapterPreloader.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaAdapterPreloader.kt
index f4169228..a1de5cb1 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaAdapterPreloader.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaAdapterPreloader.kt
@@ -30,6 +30,7 @@ import com.bumptech.glide.Glide
import com.bumptech.glide.ListPreloader.PreloadModelProvider
import com.bumptech.glide.RequestBuilder
import com.bumptech.glide.load.DataSource
+import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.GranularRoundedCorners
@@ -37,48 +38,44 @@ import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
-class MediaAdapterPreloader(private val context: Context, private val loadingDrawable: Int) :
- PreloadModelProvider {
- private var request: RequestBuilder = Glide.with(context).asDrawable().fitCenter()
- private var items: MutableList? = null
+class MediaAdapterPreloader(
+ private val context: Context,
+ private val loadingDrawable: Int,
+ private val isGrid: Boolean
+) :
+ PreloadModelProvider {
+ private var request: RequestBuilder = initRequestBuilder()
+ private var items: MutableList? = null
- fun addItem(item: String) {
+ fun addItem(item: T?) {
if (items == null) {
items = arrayListOf()
}
items!!.add(item)
}
+ // be sure to call clear once you're done with this, to avoid memory leaks
fun clear() {
items?.clear()
}
- override fun getPreloadItems(position: Int): List {
- if (items == null) return emptyList()
+ override fun getPreloadItems(position: Int): List {
+ if (items == null || items!![position] == null) return emptyList()
return listOf(items!![position])
}
- override fun getPreloadRequestBuilder(item: String): RequestBuilder<*> {
- return request.clone().fallback(R.drawable.ic_outline_broken_image_24)
- .placeholder(loadingDrawable).load(item)
+ override fun getPreloadRequestBuilder(item: T): RequestBuilder<*> {
+// return request.clone().fallback(R.drawable.ic_outline_broken_image_24)
+// .placeholder(loadingDrawable).load(item)
+// return request.load(item)
+ return getReadyRequestBuilder(item)
}
- fun loadImage(item: MediaFileInfo, view: ImageView, isGrid: Boolean) {
- val toLoadPath: String = item.path
- val toLoadBitmap: Bitmap? = item.extraInfo?.audioMetaData?.albumArt
- val toLoadDrawable = item.extraInfo?.apkMetaData?.drawable
- var transformedRequest = request.fallback(R.drawable.ic_outline_broken_image_24)
- .placeholder(loadingDrawable).load(toLoadDrawable ?: toLoadBitmap ?: toLoadPath)
- if (toLoadBitmap == null) {
- // apply size constraint when we don't have bitmap, as bitmap already is resized see CursorUtils
- transformedRequest = transformedRequest
- .apply(
- RequestOptions().override(
- if (isGrid) 500 else 100,
- if (isGrid) 500 else 100
- )
- )
- }
+ private fun initRequestBuilder(): RequestBuilder {
+ var transformedRequest = Glide.with(context).asDrawable()
+ .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
+ .fallback(R.drawable.ic_outline_broken_image_24)
+ .placeholder(loadingDrawable).fitCenter()
transformedRequest = if (isGrid) {
transformedRequest.centerCrop()
.transform(CenterCrop(), GranularRoundedCorners(24.px, 24.px, 0f, 0f))
@@ -91,25 +88,54 @@ class MediaAdapterPreloader(private val context: Context, private val loadingDra
override fun onLoadFailed(
e: GlideException?,
model: Any?,
- target: Target?,
+ target: Target,
isFirstResource: Boolean
): Boolean {
if (isGrid) {
- view.setPadding(16.px.toInt(), 16.px.toInt(), 16.px.toInt(), 16.px.toInt())
+ // fallback drawable in case image fails to load.
+ // we add padding because svg placeholder is too big and looks ugly.
+// view.setPadding(16.px.toInt(), 16.px.toInt(), 16.px.toInt(), 16.px.toInt())
}
return false
}
override fun onResourceReady(
- resource: Drawable?,
- model: Any?,
+ resource: Drawable,
+ model: Any,
target: Target?,
- dataSource: DataSource?,
+ dataSource: DataSource,
isFirstResource: Boolean
): Boolean {
// do nothing
return false
}
- }).into(view)
+ })
+ return transformedRequest
+ }
+
+ private fun getReadyRequestBuilder(item: MediaFileInfo): RequestBuilder {
+ var transformedRequest = request.load(getLoadingModel(item))
+ if (item.extraInfo?.audioMetaData?.albumArt == null) {
+ // apply size constraint when we don't have bitmap, as bitmap already is resized see CursorUtils
+ transformedRequest = transformedRequest
+ .apply(
+ RequestOptions().override(
+ if (isGrid) 250 else 100,
+ if (isGrid) 250 else 100
+ ).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
+ )
+ }
+ return transformedRequest
+ }
+
+ private fun getLoadingModel(mediaFileInfo: MediaFileInfo): Any {
+ val toLoadPath: String = mediaFileInfo.path
+ val toLoadBitmap: Bitmap? = mediaFileInfo.extraInfo?.audioMetaData?.albumArt
+ val toLoadDrawable = mediaFileInfo.extraInfo?.apkMetaData?.drawable
+ return toLoadDrawable ?: toLoadBitmap ?: toLoadPath
+ }
+
+ fun loadImage(item: MediaFileInfo, view: ImageView) {
+ getReadyRequestBuilder(item).into(view)
}
}
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaFileAdapter.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaFileAdapter.kt
index bc71f986..c0dba8da 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaFileAdapter.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaFileAdapter.kt
@@ -44,7 +44,7 @@ import com.amaze.fileutilities.utilis.getAppCommonSharedPreferences
class MediaFileAdapter(
val context: Context,
- private val preloader: MediaAdapterPreloader,
+ private val preloader: MediaAdapterPreloader,
private val optionsMenuSelected: OptionsMenuSelected,
isGrid: Boolean,
private var sortingPreference: MediaFileListSorter.SortingPreference,
@@ -86,11 +86,11 @@ class MediaFileAdapter(
headerListItems.clear()
var lastHeader: String? = null
value.add(ListItem(TYPE_BANNER))
- preloader.addItem("")
+ preloader.addItem(null)
for (i in 0 until mediaFileInfoList.size) {
if (lastHeader == null || mediaFileInfoList[i].listHeader != lastHeader) {
value.add(ListItem(TYPE_HEADER, mediaFileInfoList[i].listHeader))
- preloader.addItem("")
+ preloader.addItem(null)
headerListItems.add(
ListItem(
TYPE_HEADER, mediaFileInfoList[i].listHeader.trim()
@@ -105,10 +105,10 @@ class MediaFileAdapter(
header = mediaFileInfoList[i].listHeader
)
)
- preloader.addItem(mediaFileInfoList[i].path)
+ preloader.addItem(mediaFileInfoList[i])
onlyItemsCounts++
}
- preloader.addItem("")
+ preloader.addItem(null)
value.add(ListItem(EMPTY_LAST_ITEM))
field = value
}
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaInfoRecyclerViewHolder.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaInfoRecyclerViewHolder.kt
index 057682d7..5f58c43d 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaInfoRecyclerViewHolder.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/MediaInfoRecyclerViewHolder.kt
@@ -37,6 +37,9 @@ class MediaInfoRecyclerViewHolder(view: View) : RecyclerView.ViewHolder(view) {
@JvmField
val infoSummary: TextView = view.findViewById(R.id.info_summary)
+ @JvmField
+ val infoSubSummary: TextView = view.findViewById(R.id.info_sub_summary)
+
@JvmField
val extraInfo: TextView = view.findViewById(R.id.extra_info)
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/RecentMediaFilesAdapter.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/RecentMediaFilesAdapter.kt
index c9e1ee4e..64e6bdbd 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/RecentMediaFilesAdapter.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/RecentMediaFilesAdapter.kt
@@ -28,7 +28,7 @@ import com.amaze.fileutilities.utilis.AbstractMediaFilesAdapter
class RecentMediaFilesAdapter(
val context: Context,
- val preloader: MediaAdapterPreloader,
+ val preloader: MediaAdapterPreloader,
private val mediaFileInfoList: MutableList,
toggleCheckCallback: (Int, Int, String) -> Unit,
) :
@@ -42,10 +42,10 @@ class RecentMediaFilesAdapter(
value.clear()
mediaFileInfoList.forEach {
value.add(ListItem(mediaFileInfo = it))
- preloader.addItem(it.path)
+ preloader.addItem(it)
}
if (mediaFileInfoList.size != 0) {
- preloader.addItem("")
+ preloader.addItem(null)
value.add(ListItem(EMPTY_LAST_ITEM))
}
field = value
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/SearchListFragment.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/SearchListFragment.kt
index 08415995..28733be0 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/SearchListFragment.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/SearchListFragment.kt
@@ -55,8 +55,8 @@ class SearchListFragment :
private var searchEditText: AutoCompleteTextView? = null
private var mediaFileAdapter: RecentMediaFilesAdapter? = null
- private var preloader: MediaAdapterPreloader? = null
- private var recyclerViewPreloader: RecyclerViewPreloader? = null
+ private var preloader: MediaAdapterPreloader? = null
+ private var recyclerViewPreloader: RecyclerViewPreloader? = null
private var linearLayoutManager: LinearLayoutManager? = null
private val searchQueryInput: SearchQueryInput =
SearchQueryInput(AggregatedMediaFileInfoObserver.AggregatedMediaFiles(), SearchFilter())
@@ -117,9 +117,10 @@ class SearchListFragment :
searchEditText?.requestFocus()
preloader = MediaAdapterPreloader(
requireContext(),
- R.drawable.ic_outline_insert_drive_file_32
+ R.drawable.ic_outline_insert_drive_file_32,
+ false
)
- val sizeProvider = ViewPreloadSizeProvider()
+ val sizeProvider = ViewPreloadSizeProvider()
recyclerViewPreloader = RecyclerViewPreloader(
Glide.with(requireContext()),
preloader!!,
diff --git a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/VideosListFragment.kt b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/VideosListFragment.kt
index 75999234..b5efe3fb 100644
--- a/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/VideosListFragment.kt
+++ b/app/src/main/java/com/amaze/fileutilities/home_page/ui/files/VideosListFragment.kt
@@ -47,7 +47,7 @@ class VideosListFragment : AbstractMediaInfoListFragment() {
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
- private var preloader: MediaAdapterPreloader? = null
+ private var preloader: MediaAdapterPreloader? = null
override fun onCreateView(
inflater: LayoutInflater,
@@ -79,11 +79,12 @@ class VideosListFragment : AbstractMediaInfoListFragment() {
fileStorageSummaryAndMediaFileInfo else null
}
- override fun getMediaAdapterPreloader(): MediaAdapterPreloader {
+ override fun getMediaAdapterPreloader(isGrid: Boolean): MediaAdapterPreloader {
if (preloader == null) {
preloader = MediaAdapterPreloader(
requireContext(),
- R.drawable.ic_outline_video_library_32
+ R.drawable.ic_outline_video_library_32,
+ isGrid
)
}
return preloader!!
diff --git a/app/src/main/java/com/amaze/fileutilities/image_viewer/ImageViewerFragment.kt b/app/src/main/java/com/amaze/fileutilities/image_viewer/ImageViewerFragment.kt
index 312acfdc..fd2e9dee 100644
--- a/app/src/main/java/com/amaze/fileutilities/image_viewer/ImageViewerFragment.kt
+++ b/app/src/main/java/com/amaze/fileutilities/image_viewer/ImageViewerFragment.kt
@@ -678,7 +678,7 @@ class ImageViewerFragment : AbstractMediaFragment() {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
- target: Target?,
+ target: Target,
isFirstResource: Boolean
): Boolean {
// do nothing
@@ -714,13 +714,13 @@ class ImageViewerFragment : AbstractMediaFragment() {
}
override fun onResourceReady(
- resource: Drawable?,
- model: Any?,
+ resource: Drawable,
+ model: Any,
target: Target?,
- dataSource: DataSource?,
+ dataSource: DataSource,
isFirstResource: Boolean
): Boolean {
- resource?.let {
+ resource.let {
filesViewModel.getPaletteColors(it)
.observe(this@ImageViewerFragment) {
colorPair ->
diff --git a/app/src/main/java/com/amaze/fileutilities/image_viewer/editor/EditImageActivity.kt b/app/src/main/java/com/amaze/fileutilities/image_viewer/editor/EditImageActivity.kt
index 91a6347c..0b5b9f5d 100644
--- a/app/src/main/java/com/amaze/fileutilities/image_viewer/editor/EditImageActivity.kt
+++ b/app/src/main/java/com/amaze/fileutilities/image_viewer/editor/EditImageActivity.kt
@@ -202,7 +202,7 @@ class EditImageActivity :
override fun onLoadFailed(
e: GlideException?,
model: Any?,
- target: Target?,
+ target: Target,
isFirstResource: Boolean
): Boolean {
// do nothing
@@ -211,13 +211,13 @@ class EditImageActivity :
}
override fun onResourceReady(
- resource: Drawable?,
- model: Any?,
+ resource: Drawable,
+ model: Any,
target: Target?,
- dataSource: DataSource?,
+ dataSource: DataSource,
isFirstResource: Boolean
): Boolean {
- loadedBitmap = resource?.toBitmap()
+ loadedBitmap = resource.toBitmap()
addFilterViews()
return false
}
@@ -242,7 +242,7 @@ class EditImageActivity :
override fun onLoadFailed(
e: GlideException?,
model: Any?,
- target: Target?,
+ target: Target,
isFirstResource: Boolean
): Boolean {
// do nothing
@@ -251,13 +251,13 @@ class EditImageActivity :
}
override fun onResourceReady(
- resource: Drawable?,
- model: Any?,
+ resource: Drawable,
+ model: Any,
target: Target?,
- dataSource: DataSource?,
+ dataSource: DataSource,
isFirstResource: Boolean
): Boolean {
- loadedBitmap = resource?.toBitmap()
+ loadedBitmap = resource.toBitmap()
addFilterViews()
return false
}
diff --git a/app/src/main/java/com/amaze/fileutilities/utilis/AbstractMediaFilesAdapter.kt b/app/src/main/java/com/amaze/fileutilities/utilis/AbstractMediaFilesAdapter.kt
index 5fc79a90..1b41e649 100644
--- a/app/src/main/java/com/amaze/fileutilities/utilis/AbstractMediaFilesAdapter.kt
+++ b/app/src/main/java/com/amaze/fileutilities/utilis/AbstractMediaFilesAdapter.kt
@@ -40,7 +40,7 @@ import java.util.Collections
abstract class AbstractMediaFilesAdapter(
private val superContext: Context,
- private val superPreloader: MediaAdapterPreloader,
+ private val superPreloader: MediaAdapterPreloader,
private val isGrid: Boolean,
private val listItemPressedCallback: ((mediaFileInfo: MediaFileInfo) -> Unit)?,
private val toggleCheckCallback: (
@@ -214,8 +214,9 @@ abstract class AbstractMediaFilesAdapter(
holder.infoTitle.text = mediaFileInfo.title
Utils.marqueeAfterDelay(3000, holder.infoTitle)
Utils.marqueeAfterDelay(3000, holder.infoSummary)
+ Utils.marqueeAfterDelay(3000, holder.infoSubSummary)
Glide.with(superContext).clear(holder.iconView)
- superPreloader.loadImage(mediaFileInfo, holder.iconView, isGrid)
+ superPreloader.loadImage(mediaFileInfo, holder.iconView)
if (isChecked) {
if (isGrid) {
holder.checkIconGrid.visibility = View.VISIBLE
@@ -233,6 +234,9 @@ abstract class AbstractMediaFilesAdapter(
superContext.resources.getDrawable(R.drawable.ripple)
}
}
+ if (!isGrid) {
+ holder.infoSubSummary.text = mediaFileInfo.path
+ }
holder.root.setOnLongClickListener {
toggleChecked(this, position)
invalidateCheckedTitle(getOnlyItemsCount())
@@ -305,13 +309,14 @@ abstract class AbstractMediaFilesAdapter(
formattedDate: String,
formattedSize: String
) {
- holder.infoSummary.text = if (mediaFileInfo.extraInfo?.imageMetaData?.width != null) {
- "${mediaFileInfo.extraInfo!!.imageMetaData?.width}" +
+ if (mediaFileInfo.extraInfo?.imageMetaData?.width != null) {
+ holder.infoSummary.visibility = View.GONE
+ holder.extraInfo.text = "${mediaFileInfo.extraInfo!!.imageMetaData?.width}" +
"x${mediaFileInfo.extraInfo!!.imageMetaData?.height}"
} else {
- "$formattedDate | $formattedSize"
+ holder.infoSummary.text = "$formattedDate | $formattedSize"
+ holder.extraInfo.visibility = View.GONE
}
- holder.extraInfo.text = ""
}
private fun processAudioMediaInfo(
@@ -320,7 +325,7 @@ abstract class AbstractMediaFilesAdapter(
formattedDate: String,
formattedSize: String
) {
- if (mediaFileInfo.extraInfo?.audioMetaData?.duration != null) {
+ if (mediaFileInfo.extraInfo?.audioMetaData != null) {
holder.infoSummary.text = "${mediaFileInfo.extraInfo!!.audioMetaData?.albumName} " +
"| ${mediaFileInfo.extraInfo!!.audioMetaData?.artistName}"
mediaFileInfo.extraInfo!!.audioMetaData?.duration?.let {
@@ -328,7 +333,7 @@ abstract class AbstractMediaFilesAdapter(
}
} else {
holder.infoSummary.text = "$formattedDate | $formattedSize"
- holder.extraInfo.text = ""
+ holder.extraInfo.visibility = View.GONE
}
}
@@ -338,7 +343,7 @@ abstract class AbstractMediaFilesAdapter(
formattedDate: String,
formattedSize: String
) {
- if (mediaFileInfo.extraInfo?.videoMetaData?.duration != null) {
+ if (mediaFileInfo.extraInfo?.videoMetaData != null) {
holder.infoSummary.text =
"${mediaFileInfo.extraInfo!!.videoMetaData?.width}" +
"x${mediaFileInfo.extraInfo!!.videoMetaData?.height}"
@@ -347,7 +352,7 @@ abstract class AbstractMediaFilesAdapter(
}
} else {
holder.infoSummary.text = "$formattedDate | $formattedSize"
- holder.extraInfo.text = ""
+ holder.extraInfo.visibility = View.GONE
}
}
diff --git a/app/src/main/java/com/amaze/fileutilities/utilis/Extensions.kt b/app/src/main/java/com/amaze/fileutilities/utilis/Extensions.kt
index e4b792d3..0680aa0a 100644
--- a/app/src/main/java/com/amaze/fileutilities/utilis/Extensions.kt
+++ b/app/src/main/java/com/amaze/fileutilities/utilis/Extensions.kt
@@ -33,6 +33,7 @@ import android.os.Environment
import android.os.ParcelFileDescriptor
import android.os.TransactionTooLargeException
import android.provider.MediaStore
+import android.provider.Settings
import android.util.DisplayMetrics
import android.view.Gravity
import android.view.View
@@ -686,3 +687,15 @@ fun View.fadInAnimation(duration: Long = 300, completion: (() -> Unit)? = null)
}
}
}
+
+fun Context.getScreenBrightness(): Float {
+ var brightness = 0
+ try {
+ val contentResolver = this.contentResolver
+ brightness = Settings.System.getInt(contentResolver, Settings.System.SCREEN_BRIGHTNESS)
+ } catch (e: Exception) {
+ log.warn("failed to get system brightness", e)
+ return -1f
+ }
+ return (brightness / 255).toFloat()
+}
diff --git a/app/src/main/java/com/amaze/fileutilities/video_player/BaseVideoPlayerActivity.kt b/app/src/main/java/com/amaze/fileutilities/video_player/BaseVideoPlayerActivity.kt
index 4ad39931..717b868e 100644
--- a/app/src/main/java/com/amaze/fileutilities/video_player/BaseVideoPlayerActivity.kt
+++ b/app/src/main/java/com/amaze/fileutilities/video_player/BaseVideoPlayerActivity.kt
@@ -78,6 +78,7 @@ import com.amaze.fileutilities.utilis.dialog_picker.FileFilter
import com.amaze.fileutilities.utilis.getAppCommonSharedPreferences
import com.amaze.fileutilities.utilis.getExternalStorageDirectory
import com.amaze.fileutilities.utilis.getFileFromUri
+import com.amaze.fileutilities.utilis.getScreenBrightness
import com.amaze.fileutilities.utilis.hideFade
import com.amaze.fileutilities.utilis.isNetworkAvailable
import com.amaze.fileutilities.utilis.removeExtension
@@ -990,7 +991,16 @@ abstract class BaseVideoPlayerActivity :
private fun invalidateBrightness() {
val layout = window.attributes
- layout.screenBrightness = videoPlayerViewModel?.brightnessLevel ?: 0.3f
+ val systemBrightness = this.getScreenBrightness()
+ layout.screenBrightness = if (videoPlayerViewModel != null &&
+ videoPlayerViewModel?.brightnessLevel != 0.3f
+ ) {
+ videoPlayerViewModel!!.brightnessLevel
+ } else if (systemBrightness != -1f) {
+ systemBrightness
+ } else {
+ 0.3f
+ }
window.attributes = layout
}
diff --git a/app/src/main/java/com/amaze/fileutilities/video_player/VideoPlayerActivity.kt b/app/src/main/java/com/amaze/fileutilities/video_player/VideoPlayerActivity.kt
index 98cfcfff..3a516278 100644
--- a/app/src/main/java/com/amaze/fileutilities/video_player/VideoPlayerActivity.kt
+++ b/app/src/main/java/com/amaze/fileutilities/video_player/VideoPlayerActivity.kt
@@ -20,7 +20,13 @@
package com.amaze.fileutilities.video_player
+import android.content.res.Configuration
+import android.os.Build
import android.os.Bundle
+import android.view.View
+import android.view.WindowInsets
+import android.view.WindowInsetsController
+import android.view.WindowManager
class VideoPlayerActivity : BaseVideoPlayerActivity() {
@@ -36,5 +42,30 @@ class VideoPlayerActivity : BaseVideoPlayerActivity() {
initLocalVideoModel(intent)
super.onCreate(savedInstanceState)
handleVideoPlayerActivityResources()
+ val orientation = resources.configuration.orientation
+ if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ // allow to go in notch area in landscape mode
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ // Set the system UI visibility flags
+ window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+
+ // Get the WindowInsetsController
+ val controller = window.insetsController
+
+ // Hide the system bars (navigation bar, status bar)
+ controller?.hide(WindowInsets.Type.systemBars())
+
+ // Enable the extended layout to be displayed in the notch area
+ controller?.systemBarsBehavior =
+ WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+ } else {
+ window.setFlags(
+ WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN
+ )
+ }
+ }
}
}
diff --git a/app/src/main/res/drawable/background_curved_dark_2.xml b/app/src/main/res/drawable/background_curved_dark_2.xml
deleted file mode 100644
index 81ca2bcd..00000000
--- a/app/src/main/res/drawable/background_curved_dark_2.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/button_curved_selected.xml b/app/src/main/res/drawable/button_curved_selected.xml
index 68dd6ac3..32b6338a 100644
--- a/app/src/main/res/drawable/button_curved_selected.xml
+++ b/app/src/main/res/drawable/button_curved_selected.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/app/src/main/res/drawable/circle_shape.xml b/app/src/main/res/drawable/circle_shape.xml
index 44637831..be481c48 100644
--- a/app/src/main/res/drawable/circle_shape.xml
+++ b/app/src/main/res/drawable/circle_shape.xml
@@ -3,6 +3,6 @@
android:shape="oval">
+ android:width="@dimen/minimal_icon_size"
+ android:height="@dimen/minimal_icon_size"/>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/popup_item_background.xml b/app/src/main/res/drawable/popup_item_background.xml
new file mode 100644
index 00000000..8f50be99
--- /dev/null
+++ b/app/src/main/res/drawable/popup_item_background.xml
@@ -0,0 +1,16 @@
+
+
+-
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ripple_curved_16_trans_70.xml b/app/src/main/res/drawable/ripple_curved_16_trans_70.xml
new file mode 100644
index 00000000..a2aee21d
--- /dev/null
+++ b/app/src/main/res/drawable/ripple_curved_16_trans_70.xml
@@ -0,0 +1,17 @@
+
+ -
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/media_info_grid_layout.xml b/app/src/main/res/layout/media_info_grid_layout.xml
index ccae6c79..c6a5f6ec 100644
--- a/app/src/main/res/layout/media_info_grid_layout.xml
+++ b/app/src/main/res/layout/media_info_grid_layout.xml
@@ -107,6 +107,17 @@
android:marqueeRepeatLimit="marquee_forever"
android:ellipsize="marquee"
/>
+
+
+
+
-
\ No newline at end of file
diff --git a/app/src/main/res/values-v27/themes.xml b/app/src/main/res/values-v27/themes.xml
index 7e2a1cff..0ec0e6b3 100644
--- a/app/src/main/res/values-v27/themes.xml
+++ b/app/src/main/res/values-v27/themes.xml
@@ -1,8 +1,9 @@
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 73bdd710..bdc0c588 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -63,6 +63,7 @@