Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions app/src/main/kotlin/org/fossify/gallery/MyAppGlideModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.fossify.gallery

import android.content.Context
import android.graphics.drawable.PictureDrawable
import com.bumptech.glide.Glide
import com.bumptech.glide.GlideBuilder
import com.bumptech.glide.Registry
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool
import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory
import com.bumptech.glide.load.engine.cache.LruResourceCache
import com.bumptech.glide.load.engine.cache.MemorySizeCalculator
import com.bumptech.glide.module.AppGlideModule
import com.bumptech.glide.request.RequestOptions
import com.caverock.androidsvg.SVG
import org.fossify.gallery.extensions.config
import org.fossify.gallery.svg.SvgDecoder
import org.fossify.gallery.svg.SvgDrawableTranscoder
import java.io.InputStream

// This class is automatically discovered by Glide thanks to the @GlideModule annotation.
// Merged functionality from original SvgModule and cache configuration.
@GlideModule
class MyAppGlideModule : AppGlideModule() {

override fun applyOptions(context: Context, builder: GlideBuilder) {
// Set disk cache size based on user preference
val diskCacheSizeBytes = context.config.getThumbnailCacheSizeBytes()
builder.setDiskCache(InternalCacheDiskCacheFactory(context, GLIDE_CACHE_DIR, diskCacheSizeBytes))

// Apply Fossify's preferred format
builder.setDefaultRequestOptions(RequestOptions().format(DecodeFormat.PREFER_ARGB_8888))

// Configure memory cache and bitmap pool sizes
val calculator = MemorySizeCalculator.Builder(context)
.setMemoryCacheScreens(2f)
.setBitmapPoolScreens(3f)
.build()

builder.setMemoryCache(LruResourceCache(calculator.memoryCacheSize.toLong()))
builder.setBitmapPool(LruBitmapPool(calculator.bitmapPoolSize.toLong()))
}

// Added from original SvgModule
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
registry.register(SVG::class.java, PictureDrawable::class.java, SvgDrawableTranscoder())
.append(InputStream::class.java, SVG::class.java, SvgDecoder())
}

// Disable manifest parsing to avoid potential conflicts
override fun isManifestParsingEnabled(): Boolean {
return false
}

companion object {
// Using Glide's default internal directory name allows calculating its size easily later
const val GLIDE_CACHE_DIR = "image_manager_disk_cache"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import com.bumptech.glide.Glide
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import org.fossify.commons.dialogs.*
import org.fossify.commons.extensions.*
import org.fossify.commons.helpers.*
import org.fossify.commons.models.RadioItem
import org.fossify.gallery.MyAppGlideModule
import org.fossify.gallery.R
import org.fossify.gallery.databinding.ActivitySettingsBinding
import org.fossify.gallery.dialogs.*
Expand Down Expand Up @@ -49,6 +52,81 @@ class SettingsActivity : SimpleActivity() {
setupSettingItems()
}

private fun getGlideCacheDirSize(): Long {
val cacheDir = File(cacheDir, MyAppGlideModule.GLIDE_CACHE_DIR)
// Use the getProperSize function from the Commons library
return cacheDir.getProperSize(true)
}

private fun updateCurrentCacheUsageDisplay() {
ensureBackgroundThread {
val currentSize = getGlideCacheDirSize()
val limitBytes = config.getThumbnailCacheSizeBytes()
val limitString = limitBytes.formatSize()
val displayString = "${currentSize.formatSize()} / $limitString Limit"

runOnUiThread {
// Check if binding is still valid before accessing views
if (!isDestroyed && !isFinishing) {
binding.settingsClearThumbnailCacheSize.text = displayString
}
}
}
}

private fun clearThumbnailCache() {
toast(R.string.clearing_cache)
ensureBackgroundThread {
Glide.get(applicationContext).clearDiskCache()
runOnUiThread {
if (!isDestroyed && !isFinishing) {
toast(R.string.cache_cleared)
updateCurrentCacheUsageDisplay()
}
}
}
}

private fun setupThumbnailCacheSettings() {
val currentLimitBytes = config.getThumbnailCacheSizeBytes()
binding.settingsThumbnailCacheSizeValue.text = currentLimitBytes.formatSize()

binding.settingsThumbnailCacheSizeHolder.setOnClickListener {
val items = arrayListOf(
RadioItem(CACHE_SIZE_AUTO, "${config.getSizeBytesFromPreference(CACHE_SIZE_AUTO).formatSize()} (${getString(R.string.default_text)})"),
RadioItem(CACHE_SIZE_500, config.getSizeBytesFromPreference(CACHE_SIZE_500).formatSize()),
RadioItem(CACHE_SIZE_1000, config.getSizeBytesFromPreference(CACHE_SIZE_1000).formatSize()),
RadioItem(CACHE_SIZE_2000, config.getSizeBytesFromPreference(CACHE_SIZE_2000).formatSize()),
RadioItem(CACHE_SIZE_5000, config.getSizeBytesFromPreference(CACHE_SIZE_5000).formatSize())
)

RadioGroupDialog(this, items, config.thumbnailCacheSizePreference) {
val newPreference = it as Int
if (newPreference == config.thumbnailCacheSizePreference) return@RadioGroupDialog // No change

val oldPreference = config.thumbnailCacheSizePreference
config.thumbnailCacheSizePreference = newPreference

val newLimitBytes = config.getThumbnailCacheSizeBytes()
binding.settingsThumbnailCacheSizeValue.text = newLimitBytes.formatSize()
updateCurrentCacheUsageDisplay()

val oldSizeBytes = config.getSizeBytesFromPreference(oldPreference)

// Clear cache only if the new limit is smaller *and* the old limit wasn't the largest size
if (newLimitBytes < oldSizeBytes && oldPreference != CACHE_SIZE_5000) {
clearThumbnailCache()
toast(R.string.cache_limit_needs_restart)
} else if (newLimitBytes > oldSizeBytes || (newPreference == CACHE_SIZE_5000 && oldPreference != CACHE_SIZE_5000)) {
// Show restart hint only when increasing the limit or switching to the largest size
toast(R.string.cache_limit_needs_restart)
}
}
}

updateCurrentCacheUsageDisplay()
}

private fun setupSettingItems() {
setupCustomizeColors()
setupUseEnglish()
Expand Down Expand Up @@ -100,7 +178,8 @@ class SettingsActivity : SimpleActivity() {
setupShowRecycleBinLast()
setupEmptyRecycleBin()
updateTextColors(binding.settingsHolder)
setupClearCache()
setupClearThumbnailCacheItem()
setupThumbnailCacheSettings()
setupExportFavorites()
setupImportFavorites()
setupExportSettings()
Expand Down Expand Up @@ -723,21 +802,9 @@ class SettingsActivity : SimpleActivity() {
}
}

private fun setupClearCache() {
ensureBackgroundThread {
val size = cacheDir.getProperSize(true).formatSize()
runOnUiThread {
binding.settingsClearCacheSize.text = size
}
}

binding.settingsClearCacheHolder.setOnClickListener {
ensureBackgroundThread {
cacheDir.deleteRecursively()
runOnUiThread {
binding.settingsClearCacheSize.text = cacheDir.getProperSize(true).formatSize()
}
}
private fun setupClearThumbnailCacheItem() {
binding.settingsClearThumbnailCacheHolder.setOnClickListener {
clearThumbnailCache()
}
}

Expand Down
25 changes: 25 additions & 0 deletions app/src/main/kotlin/org/fossify/gallery/helpers/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.res.Configuration
import android.os.Environment
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import org.fossify.commons.extensions.formatSize
import org.fossify.commons.helpers.*
import org.fossify.gallery.R
import org.fossify.gallery.models.AlbumCover
Expand Down Expand Up @@ -583,4 +584,28 @@ class Config(context: Context) : BaseConfig(context) {
var showPermissionRationale: Boolean
get() = prefs.getBoolean(SHOW_PERMISSION_RATIONALE, false)
set(showPermissionRationale) = prefs.edit().putBoolean(SHOW_PERMISSION_RATIONALE, showPermissionRationale).apply()

var thumbnailCacheSizePreference: Int
get() = prefs.getInt(THUMBNAIL_CACHE_SIZE, CACHE_SIZE_AUTO)
set(size) = prefs.edit().putInt(THUMBNAIL_CACHE_SIZE, size).apply()

fun getThumbnailCacheSizeBytes(): Long {
return when (thumbnailCacheSizePreference) {
CACHE_SIZE_500 -> 500 * 1024 * 1024L
CACHE_SIZE_1000 -> 1024 * 1024 * 1024L
CACHE_SIZE_2000 -> 2 * 1024 * 1024 * 1024L
CACHE_SIZE_5000 -> 5 * 1024 * 1024 * 1024L
else -> 250 * 1024 * 1024L // Default Auto/250MB if something unexpected is stored
}
}

// Helper function to get size in bytes directly from preference ID for comparison
fun getSizeBytesFromPreference(preference: Int): Long {
// Use a temporary preference value to reuse existing calculation logic
val originalPreference = thumbnailCacheSizePreference
thumbnailCacheSizePreference = preference
val result = getThumbnailCacheSizeBytes()
thumbnailCacheSizePreference = originalPreference
return result
}
}
8 changes: 8 additions & 0 deletions app/src/main/kotlin/org/fossify/gallery/helpers/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ const val SEARCH_ALL_FILES_BY_DEFAULT = "search_all_files_by_default"
const val LAST_EXPORTED_FAVORITES_FOLDER = "last_exported_favorites_folder"
const val SHOW_PERMISSION_RATIONALE = "show_permission_rationale"

// thumbnail cache size
const val THUMBNAIL_CACHE_SIZE = "thumbnail_cache_size_pref"
const val CACHE_SIZE_AUTO = 0 // Glide's default disk cache size is 250MB. This value is used to match that default.
const val CACHE_SIZE_500 = 500
const val CACHE_SIZE_1000 = 1000
const val CACHE_SIZE_2000 = 2000
const val CACHE_SIZE_5000 = 5000

// slideshow
const val SLIDESHOW_INTERVAL = "slideshow_interval"
const val SLIDESHOW_INCLUDE_VIDEOS = "slideshow_include_videos"
Expand Down
21 changes: 0 additions & 21 deletions app/src/main/kotlin/org/fossify/gallery/svg/SvgModule.kt

This file was deleted.

85 changes: 62 additions & 23 deletions app/src/main/res/layout/activity_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,68 @@
android:id="@+id/settings_bottom_actions_divider"
layout="@layout/divider" />

<include
android:id="@+id/settings_cache_top_divider"
layout="@layout/divider" />

<TextView
android:id="@+id/settings_cache_label"
style="@style/SettingsSectionLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/cache" />

<RelativeLayout
android:id="@+id/settings_thumbnail_cache_size_holder"
style="@style/SettingsHolderTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<org.fossify.commons.views.MyTextView
android:id="@+id/settings_thumbnail_cache_size_label"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/thumbnail_cache_size" />

<org.fossify.commons.views.MyTextView
android:id="@+id/settings_thumbnail_cache_size_value"
style="@style/SettingsTextValueStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/settings_thumbnail_cache_size_label"
tools:text="250 MB" />

</RelativeLayout>

<RelativeLayout
android:id="@+id/settings_clear_thumbnail_cache_holder"
style="@style/SettingsHolderTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground">

<org.fossify.commons.views.MyTextView
android:id="@+id/settings_clear_thumbnail_cache_label"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/clear_cache" />

<org.fossify.commons.views.MyTextView
android:id="@+id/settings_clear_thumbnail_cache_size"
style="@style/SettingsTextValueStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/settings_clear_thumbnail_cache_label"
tools:text="180 MB / 5 GB Limit" />

</RelativeLayout>

<include
android:id="@+id/settings_cache_divider"
layout="@layout/divider" />

<TextView
android:id="@+id/settings_recycle_bin_label"
style="@style/SettingsSectionLabelStyle"
Expand Down Expand Up @@ -944,29 +1006,6 @@
android:layout_height="wrap_content"
android:text="@string/migrating" />

<RelativeLayout
android:id="@+id/settings_clear_cache_holder"
style="@style/SettingsHolderTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<org.fossify.commons.views.MyTextView
android:id="@+id/settings_clear_cache_label"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/clear_cache" />

<org.fossify.commons.views.MyTextView
android:id="@+id/settings_clear_cache_size"
style="@style/SettingsTextValueStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/settings_clear_cache_label"
tools:text="0 B" />

</RelativeLayout>

<RelativeLayout
android:id="@+id/settings_export_favorites_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,13 @@
<string name="faq_17_text">That stopped working due to the system changes that came with Android 11 too, the app cannot browse real folders anymore, it relies on the so called MediaStore at fetching data.</string>
<string name="faq_18_title">Why do I see ads during video playback?</string>
<string name="faq_18_text">Our apps have no ads whatsoever. If you see them during video playback, you must be using some other apps video player. Try finding your default video player in the device settings, then do a \"Clear defaults\" on it. The next time you invoke some video intent you will see an app picker prompt, where you can select what app you want to use.</string>
<string name="cache">Cache</string>
<string name="thumbnail_cache_size">Thumbnail cache size limit</string>
<string name="current_thumbnail_cache_usage">Current thumbnail cache usage</string>
<string name="clearing_cache">Clearing cache…</string>
<string name="cache_cleared">Cache cleared</string>
<string name="cache_limit_needs_restart">New cache limit might require an app restart to take full effect</string>
<string name="default_text">Default</string>
<!--
Haven't found some strings? There's more at
https://github.com/FossifyOrg/Commons/tree/master/commons/src/main/res
Expand Down