Skip to content

Commit

Permalink
Add setting to change image cache settings on Android (#1105)
Browse files Browse the repository at this point in the history
* Improve image caching

* Add highlightKey to image caching mode setting

* Restrict image caching mode setting to Android
  • Loading branch information
micahmo authored Feb 12, 2024
1 parent ccd0707 commit f8d76f4
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 9 deletions.
4 changes: 4 additions & 0 deletions lib/core/enums/image_caching_mode.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
enum ImageCachingMode {
aggressive,
relaxed;
}
2 changes: 2 additions & 0 deletions lib/core/enums/local_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ enum LocalSettings {
// Advanced Settings
userFormat(name: 'user_format', key: 'userFormat', category: LocalSettingsCategories.general, subCategory: LocalSettingsSubCategories.advanced),
communityFormat(name: 'community_format', key: 'communityFormat', category: LocalSettingsCategories.general, subCategory: LocalSettingsSubCategories.advanced),
imageCachingMode(name: 'setting_advanced_image_caching_mode', key: 'imageCachingMode', category: LocalSettingsCategories.general, subCategory: LocalSettingsSubCategories.advanced),

/// -------------------------- Post Page Related Settings --------------------------
// Comment Related Settings
Expand Down Expand Up @@ -295,6 +296,7 @@ extension LocalizationExt on AppLocalizations {
'cardPostCardMetadataItems': cardPostCardMetadataItems,
'userFormat': userFormat,
'communityFormat': communityFormat,
'imageCachingMode': imageCachingMode,
'defaultCommentSortType': defaultCommentSortType,
'collapseParentCommentBodyOnGesture': collapseParentCommentBodyOnGesture,
'showCommentActionButtons': showCommentActionButtons,
Expand Down
20 changes: 20 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,26 @@
"@hot": {},
"image": "Image",
"@image": {},
"imageCachingMode": "Image Caching Mode",
"@imageCachingMode": {
"description": "Title for setting related to image caching mode"
},
"imageCachingModeAggressive": "Aggressively cache images (uses more memory)",
"@imageCachingModeAggressive": {
"description": "Long description for aggressive image caching mode"
},
"imageCachingModeAggressiveShort": "Aggressive",
"@imageCachingModeAggressiveShort": {
"description": "Short description for aggressive image caching mode"
},
"imageCachingModeRelaxed": "Let image caches expire (uses less memory but causes images to reload more often)",
"@imageCachingModeRelaxed": {
"description": "Long description for relaxed image caching mode"
},
"imageCachingModeRelaxedShort": "Relaxed",
"@imageCachingModeRelaxedShort": {
"description": "Short description for relaxed image caching mode"
},
"importExportSettings": "Import/Export Settings",
"@importExportSettings": {
"description": "Category for settings related to import and export."
Expand Down
33 changes: 33 additions & 0 deletions lib/settings/pages/general_settings_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:thunder/core/enums/browser_mode.dart';
import 'package:smooth_highlight/smooth_highlight.dart';
import 'package:thunder/core/enums/full_name_separator.dart';
import 'package:thunder/core/enums/image_caching_mode.dart';

import 'package:thunder/core/enums/local_settings.dart';
import 'package:thunder/core/singletons/lemmy_client.dart';
Expand Down Expand Up @@ -106,6 +107,9 @@ class _GeneralSettingsPageState extends State<GeneralSettingsPage> with SingleTi
/// Defines the separator used to denote full commuity names
FullNameSeparator communitySeparator = FullNameSeparator.dot;

/// Defines the image caching mode
ImageCachingMode imageCachingMode = ImageCachingMode.relaxed;

SortType defaultSortType = DEFAULT_SORT_TYPE;

GlobalKey settingToHighlightKey = GlobalKey();
Expand Down Expand Up @@ -201,6 +205,10 @@ class _GeneralSettingsPageState extends State<GeneralSettingsPage> with SingleTi
await prefs.setString(LocalSettings.communityFormat.name, value);
setState(() => communitySeparator = FullNameSeparator.values.byName(value ?? FullNameSeparator.dot));
break;
case LocalSettings.imageCachingMode:
await prefs.setString(LocalSettings.imageCachingMode.name, value);
setState(() => imageCachingMode = ImageCachingMode.values.byName(value ?? ImageCachingMode.relaxed));
break;
}

if (context.mounted) {
Expand Down Expand Up @@ -243,6 +251,7 @@ class _GeneralSettingsPageState extends State<GeneralSettingsPage> with SingleTi

userSeparator = FullNameSeparator.values.byName(prefs.getString(LocalSettings.userFormat.name) ?? FullNameSeparator.at.name);
communitySeparator = FullNameSeparator.values.byName(prefs.getString(LocalSettings.communityFormat.name) ?? FullNameSeparator.dot.name);
imageCachingMode = ImageCachingMode.values.byName(prefs.getString(LocalSettings.imageCachingMode.name) ?? ImageCachingMode.relaxed.name);

showInAppUpdateNotification = prefs.getBool(LocalSettings.showInAppUpdateNotification.name) ?? false;
enableInboxNotifications = prefs.getBool(LocalSettings.enableInboxNotifications.name) ?? false;
Expand Down Expand Up @@ -631,6 +640,30 @@ class _GeneralSettingsPageState extends State<GeneralSettingsPage> with SingleTi
highlightKey: settingToHighlight == LocalSettings.communityFormat ? settingToHighlightKey : null,
),
),
if (!kIsWeb && Platform.isAndroid)
SliverToBoxAdapter(
child: ListOption(
description: l10n.imageCachingMode,
value: ListPickerItem(
label: switch (imageCachingMode) {
ImageCachingMode.aggressive => l10n.imageCachingModeAggressiveShort,
ImageCachingMode.relaxed => l10n.imageCachingModeRelaxedShort,
},
payload: imageCachingMode,
capitalizeLabel: false,
),
options: [
ListPickerItem(icon: Icons.broken_image, label: l10n.imageCachingModeAggressive, payload: ImageCachingMode.aggressive, capitalizeLabel: false),
ListPickerItem(icon: Icons.broken_image_outlined, label: l10n.imageCachingModeRelaxed, payload: ImageCachingMode.relaxed, capitalizeLabel: false),
],
icon: switch (imageCachingMode) {
ImageCachingMode.aggressive => Icons.broken_image,
ImageCachingMode.relaxed => Icons.broken_image_outlined,
},
onChanged: (value) => setPreferences(LocalSettings.imageCachingMode, value.payload.name),
highlightKey: settingToHighlight == LocalSettings.imageCachingMode ? settingToHighlightKey : null,
),
),

const SliverToBoxAdapter(child: SizedBox(height: 16.0)),
SliverToBoxAdapter(
Expand Down
9 changes: 6 additions & 3 deletions lib/shared/image_preview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import 'dart:typed_data';
import 'package:flutter/material.dart';

import 'package:extended_image/extended_image.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:thunder/core/enums/image_caching_mode.dart';
import 'package:thunder/thunder/bloc/thunder_bloc.dart';

import 'package:thunder/utils/image.dart';

Expand Down Expand Up @@ -82,6 +85,7 @@ class _ImagePreviewState extends State<ImagePreview> {
Widget imagePreview(BuildContext context) {
final ThemeData theme = Theme.of(context);
final AppLocalizations l10n = AppLocalizations.of(context)!;
final ThunderState thunderState = context.read<ThunderBloc>().state;

return Container(
clipBehavior: Clip.hardEdge,
Expand All @@ -108,8 +112,7 @@ class _ImagePreviewState extends State<ImagePreview> {
width: widget.width,
fit: BoxFit.cover,
cache: true,
clearMemoryCacheWhenDispose: false,
cacheMaxAge: const Duration(minutes: 1),
clearMemoryCacheWhenDispose: thunderState.imageCachingMode == ImageCachingMode.relaxed,
cacheWidth: ((MediaQuery.of(context).size.width - 24) * View.of(context).devicePixelRatio.ceil()).toInt(),
loadStateChanged: (state) {
if (state.extendedImageLoadState == LoadState.loading) {
Expand Down Expand Up @@ -141,7 +144,7 @@ class _ImagePreviewState extends State<ImagePreview> {
height: widget.height,
width: widget.width,
fit: BoxFit.cover,
clearMemoryCacheWhenDispose: true,
clearMemoryCacheWhenDispose: thunderState.imageCachingMode == ImageCachingMode.relaxed,
cacheWidth: ((MediaQuery.of(context).size.width - 24) * View.of(context).devicePixelRatio.ceil()).toInt(),
loadStateChanged: (state) {
if (state.extendedImageLoadState == LoadState.loading) {
Expand Down
8 changes: 6 additions & 2 deletions lib/shared/image_viewer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@ import 'package:flutter/material.dart';

import 'package:extended_image/extended_image.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:gal/gal.dart';
import 'package:share_plus/share_plus.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:thunder/core/enums/image_caching_mode.dart';
import 'package:thunder/shared/dialogs.dart';

import 'package:thunder/shared/snackbar.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:thunder/thunder/bloc/thunder_bloc.dart';
import 'package:thunder/utils/image.dart';

class ImageViewer extends StatefulWidget {
Expand Down Expand Up @@ -133,6 +136,8 @@ class _ImageViewerState extends State<ImageViewer> with TickerProviderStateMixin

@override
Widget build(BuildContext context) {
final ThunderState thunderState = context.read<ThunderBloc>().state;

AnimationController animationController = AnimationController(duration: const Duration(milliseconds: 140), vsync: this);
Function() animationListener = () {};
Animation? animation;
Expand Down Expand Up @@ -251,8 +256,7 @@ class _ImageViewerState extends State<ImageViewer> with TickerProviderStateMixin
mode: ExtendedImageMode.gesture,
extendedImageGestureKey: gestureKey,
cache: true,
clearMemoryCacheWhenDispose: false,
cacheMaxAge: const Duration(minutes: 1),
clearMemoryCacheWhenDispose: thunderState.imageCachingMode == ImageCachingMode.relaxed,
initGestureConfigHandler: (ExtendedImageState state) {
return GestureConfig(
minScale: 0.8,
Expand Down
6 changes: 4 additions & 2 deletions lib/shared/media_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import 'package:flex_color_scheme/flex_color_scheme.dart';
import 'package:extended_image/extended_image.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lemmy_api_client/v3.dart';
import 'package:thunder/core/enums/image_caching_mode.dart';

import 'package:thunder/feed/bloc/feed_bloc.dart';
import 'package:thunder/post/enums/post_action.dart';
import 'package:thunder/thunder/bloc/thunder_bloc.dart';
import 'package:thunder/utils/links.dart';
import 'package:thunder/user/bloc/user_bloc.dart';
import 'package:thunder/core/enums/media_type.dart';
Expand Down Expand Up @@ -212,6 +214,7 @@ class _MediaViewState extends State<MediaView> with SingleTickerProviderStateMix

Widget previewImage(BuildContext context) {
final theme = Theme.of(context);
final ThunderState thunderState = context.read<ThunderBloc>().state;

double? height = widget.viewMode == ViewMode.compact ? 75 : (widget.showFullHeightImages ? widget.postView!.media.first.height : 150);
double width = widget.viewMode == ViewMode.compact ? 75 : MediaQuery.of(context).size.width - (widget.edgeToEdgeImages ? 0 : 24);
Expand All @@ -224,8 +227,7 @@ class _MediaViewState extends State<MediaView> with SingleTickerProviderStateMix
width: width,
fit: widget.viewMode == ViewMode.compact ? BoxFit.cover : BoxFit.fitWidth,
cache: true,
clearMemoryCacheWhenDispose: false,
cacheMaxAge: const Duration(minutes: 1),
clearMemoryCacheWhenDispose: thunderState.imageCachingMode == ImageCachingMode.relaxed,
cacheWidth: widget.viewMode == ViewMode.compact
? (75 * View.of(context).devicePixelRatio.ceil())
: ((MediaQuery.of(context).size.width - (widget.edgeToEdgeImages ? 0 : 24)) * View.of(context).devicePixelRatio.ceil()).toInt(),
Expand Down
4 changes: 2 additions & 2 deletions lib/shared/preview_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';

import 'package:extended_image/extended_image.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:thunder/core/enums/image_caching_mode.dart';

import 'package:thunder/core/enums/view_mode.dart';
import 'package:thunder/thunder/bloc/thunder_bloc.dart';
Expand Down Expand Up @@ -55,8 +56,7 @@ class _PreviewImageState extends State<PreviewImage> with SingleTickerProviderSt
width: width,
fit: widget.viewMode == ViewMode.compact ? BoxFit.cover : BoxFit.fitWidth,
cache: true,
clearMemoryCacheWhenDispose: false,
cacheMaxAge: const Duration(minutes: 1),
clearMemoryCacheWhenDispose: state.imageCachingMode == ImageCachingMode.relaxed,
cacheWidth: widget.viewMode == ViewMode.compact ? (75 * View.of(context).devicePixelRatio.ceil()) : ((MediaQuery.of(context).size.width - 24) * View.of(context).devicePixelRatio.ceil()).toInt(),
loadStateChanged: (ExtendedImageState state) {
switch (state.extendedImageLoadState) {
Expand Down
3 changes: 3 additions & 0 deletions lib/thunder/bloc/thunder_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'package:thunder/core/enums/custom_theme_type.dart';
import 'package:thunder/core/enums/fab_action.dart';
import 'package:thunder/core/enums/font_scale.dart';
import 'package:thunder/core/enums/full_name_separator.dart';
import 'package:thunder/core/enums/image_caching_mode.dart';
import 'package:thunder/core/enums/local_settings.dart';
import 'package:thunder/core/enums/nested_comment_indicator.dart';
import 'package:thunder/core/enums/post_body_view_type.dart';
Expand Down Expand Up @@ -116,6 +117,7 @@ class ThunderBloc extends Bloc<ThunderEvent, ThunderState> {
String? appLanguageCode = prefs.getString(LocalSettings.appLanguageCode.name) ?? 'en';
FullNameSeparator userSeparator = FullNameSeparator.values.byName(prefs.getString(LocalSettings.userFormat.name) ?? FullNameSeparator.at.name);
FullNameSeparator communitySeparator = FullNameSeparator.values.byName(prefs.getString(LocalSettings.communityFormat.name) ?? FullNameSeparator.dot.name);
ImageCachingMode imageCachingMode = ImageCachingMode.values.byName(prefs.getString(LocalSettings.imageCachingMode.name) ?? ImageCachingMode.relaxed.name);
bool hideTopBarOnScroll = prefs.getBool(LocalSettings.hideTopBarOnScroll.name) ?? false;

BrowserMode browserMode = BrowserMode.values.byName(prefs.getString(LocalSettings.browserMode.name) ?? BrowserMode.customTabs.name);
Expand Down Expand Up @@ -253,6 +255,7 @@ class ThunderBloc extends Bloc<ThunderEvent, ThunderState> {
appLanguageCode: appLanguageCode,
userSeparator: userSeparator,
communitySeparator: communitySeparator,
imageCachingMode: imageCachingMode,
hideTopBarOnScroll: hideTopBarOnScroll,

/// -------------------------- Feed Post Related Settings --------------------------
Expand Down
5 changes: 5 additions & 0 deletions lib/thunder/bloc/thunder_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class ThunderState extends Equatable {
this.scoreCounters = false,
this.userSeparator = FullNameSeparator.at,
this.communitySeparator = FullNameSeparator.dot,
this.imageCachingMode = ImageCachingMode.relaxed,
this.hideTopBarOnScroll = false,

/// -------------------------- Feed Post Related Settings --------------------------
Expand Down Expand Up @@ -165,6 +166,7 @@ class ThunderState extends Equatable {
final String? appLanguageCode;
final FullNameSeparator userSeparator;
final FullNameSeparator communitySeparator;
final ImageCachingMode imageCachingMode;
final bool hideTopBarOnScroll;

/// -------------------------- Feed Post Related Settings --------------------------
Expand Down Expand Up @@ -304,6 +306,7 @@ class ThunderState extends Equatable {
bool? scoreCounters,
FullNameSeparator? userSeparator,
FullNameSeparator? communitySeparator,
ImageCachingMode? imageCachingMode,
bool? hideTopBarOnScroll,

/// -------------------------- Feed Post Related Settings --------------------------
Expand Down Expand Up @@ -436,6 +439,7 @@ class ThunderState extends Equatable {
appLanguageCode: appLanguageCode ?? this.appLanguageCode,
userSeparator: userSeparator ?? this.userSeparator,
communitySeparator: communitySeparator ?? this.communitySeparator,
imageCachingMode: imageCachingMode ?? this.imageCachingMode,
hideTopBarOnScroll: hideTopBarOnScroll ?? this.hideTopBarOnScroll,

/// -------------------------- Feed Post Related Settings --------------------------
Expand Down Expand Up @@ -573,6 +577,7 @@ class ThunderState extends Equatable {
enableInboxNotifications,
userSeparator,
communitySeparator,
imageCachingMode,

/// -------------------------- Feed Post Related Settings --------------------------
/// Compact Related Settings
Expand Down

0 comments on commit f8d76f4

Please sign in to comment.