diff --git a/modules/ensemble/lib/framework/theme/theme_loader.dart b/modules/ensemble/lib/framework/theme/theme_loader.dart index 67ed7708b..4362a76d7 100644 --- a/modules/ensemble/lib/framework/theme/theme_loader.dart +++ b/modules/ensemble/lib/framework/theme/theme_loader.dart @@ -3,6 +3,7 @@ import 'package:ensemble/framework/theme/default_theme.dart'; import 'package:ensemble/framework/theme/theme_manager.dart'; import 'package:ensemble/model/text_scale.dart'; import 'package:ensemble/util/utils.dart'; +import 'package:ensemble/widget/image.dart'; import 'package:flutter/material.dart'; import 'package:yaml/yaml.dart'; @@ -158,6 +159,9 @@ mixin ThemeLoader { maxFactor: Utils.optionalDouble( getProp(appOverrides, ['textScale', 'maxFactor']), min: 0))); + + // Configure image cache settings from App.imageCache + _configureImageCache(appOverrides); // extends ThemeData return customTheme.copyWith(extensions: [ @@ -507,6 +511,32 @@ mixin ThemeLoader { BorderRadius.all(Radius.circular(variant == InputVariant.box ? 8 : 0)); } + /// Configures image cache settings from App.imageCache in theme.yaml. + /// + /// Example YAML: + /// ```yaml + /// App: + /// imageCache: + /// stalePeriodMinutes: 10080 # 7 days (default: 15 minutes) + /// maxObjects: 500 # (default: 50) + /// ``` + void _configureImageCache(YamlMap? appOverrides) { + final imageCache = appOverrides?['imageCache']; + if (imageCache == null) { + return; + } + + final stalePeriodMinutes = Utils.optionalInt(imageCache['stalePeriodMinutes'], min: 1); + final maxObjects = Utils.optionalInt(imageCache['maxObjects'], min: 1); + + if (stalePeriodMinutes != null || maxObjects != null) { + ImageCacheConfig().configure( + stalePeriodMinutes: stalePeriodMinutes, + maxObjects: maxObjects, + ); + } + } + // add more data to checkbox theme extension CheckboxThemeDataExtension on CheckboxThemeData { static int? _size; diff --git a/modules/ensemble/lib/widget/image.dart b/modules/ensemble/lib/widget/image.dart index 2cb7a0acb..ba173d49d 100644 --- a/modules/ensemble/lib/widget/image.dart +++ b/modules/ensemble/lib/widget/image.dart @@ -381,15 +381,86 @@ class ImageState extends EWidgetState { } return fallbackWidget; } + +} + +/// Configuration for image caching behavior. +/// Can be set at app level via theme.yaml: +/// ```yaml +/// App: +/// imageCache: +/// stalePeriodMinutes: 10080 # 7 days +/// maxObjects: 500 +/// ``` +class ImageCacheConfig { + static final ImageCacheConfig _instance = ImageCacheConfig._internal(); + + factory ImageCacheConfig() => _instance; + + ImageCacheConfig._internal(); + + // Default values - 15 minutes stale period, 50 objects max + static const int defaultStalePeriodMinutes = 15; + static const int defaultMaxObjects = 50; + + int _stalePeriodMinutes = defaultStalePeriodMinutes; + int _maxObjects = defaultMaxObjects; + bool _initialized = false; + + /// Gets the configured stale period in minutes + int get stalePeriodMinutes => _stalePeriodMinutes; + + /// Gets the configured max number of cached objects + int get maxObjects => _maxObjects; + + /// Whether the cache config has been explicitly initialized + bool get isInitialized => _initialized; + + /// Configure the image cache settings. + /// Called from theme loader when parsing App.imageCache settings. + void configure({int? stalePeriodMinutes, int? maxObjects}) { + if (stalePeriodMinutes != null && stalePeriodMinutes > 0) { + _stalePeriodMinutes = stalePeriodMinutes; + } + if (maxObjects != null && maxObjects > 0) { + _maxObjects = maxObjects; + } + _initialized = true; + + // Reinitialize the cache manager with new settings + EnsembleImageCacheManager._reinitialize(); + } + + /// Reset to default values (useful for testing) + void reset() { + _stalePeriodMinutes = defaultStalePeriodMinutes; + _maxObjects = defaultMaxObjects; + _initialized = false; + EnsembleImageCacheManager._reinitialize(); + } } class EnsembleImageCacheManager { static const key = 'ensembleImageCacheKey'; - static CacheManager instance = CacheManager(Config( - key, - stalePeriod: const Duration(minutes: 15), - maxNrOfCacheObjects: 50, - )); + + static CacheManager _instance = _createCacheManager(); + + static CacheManager get instance => _instance; + + static CacheManager _createCacheManager() { + final config = ImageCacheConfig(); + return CacheManager(Config( + key, + stalePeriod: Duration(minutes: config.stalePeriodMinutes), + maxNrOfCacheObjects: config.maxObjects, + )); + } + + /// Reinitialize the cache manager with current config settings. + /// Called when ImageCacheConfig.configure() is called. + static void _reinitialize() { + _instance = _createCacheManager(); + } } class PinchToZoom extends StatefulWidget {