From 7a1022b5150d9f61c433bb1b80c6be57e24b53e2 Mon Sep 17 00:00:00 2001 From: Rick van Dijk Date: Mon, 20 Jul 2026 13:36:02 -0600 Subject: [PATCH 1/7] chore: raise Dart SDK to 3.8.0 and update flutter_cache_manager dependencies Bump runtime and dev dependency constraints to current compatible releases and regenerate Mockito mocks. Co-authored-by: Cursor --- flutter_cache_manager/pubspec.yaml | 26 +- flutter_cache_manager/test/mock.mocks.dart | 610 ++++++++++----------- 2 files changed, 289 insertions(+), 347 deletions(-) diff --git a/flutter_cache_manager/pubspec.yaml b/flutter_cache_manager/pubspec.yaml index 4e49f688..e7b30b94 100644 --- a/flutter_cache_manager/pubspec.yaml +++ b/flutter_cache_manager/pubspec.yaml @@ -6,27 +6,27 @@ topics: - cache - cache-manager environment: - sdk: '>=3.0.0 <4.0.0' + sdk: '>=3.8.0 <4.0.0' dependencies: - clock: ^1.1.1 - collection: ^1.18.0 - file: ^7.0.0 + clock: ^1.1.2 + collection: ^1.19.1 + file: ^7.0.1 flutter: sdk: flutter - http: ^1.2.2 - path: ^1.9.0 - path_provider: ^2.1.4 - rxdart: '>=0.27.7 <0.29.0' - sqflite: ^2.3.3+1 - uuid: ^4.4.2 + http: ^1.6.0 + path: ^1.9.1 + path_provider: ^2.1.5 + rxdart: ^0.28.0 + sqflite: ^2.4.2 + uuid: ^4.6.0 dev_dependencies: - build_runner: ^2.4.12 - flutter_lints: ^4.0.0 + build_runner: ^2.14.0 + flutter_lints: ^6.0.0 flutter_test: sdk: flutter - mockito: ^5.4.4 + mockito: ^5.7.0 platforms: android: diff --git a/flutter_cache_manager/test/mock.mocks.dart b/flutter_cache_manager/test/mock.mocks.dart index 708ee9dd..a1496764 100644 --- a/flutter_cache_manager/test/mock.mocks.dart +++ b/flutter_cache_manager/test/mock.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.4 from annotations +// Mocks generated by Mockito 5.4.6 from annotations // in flutter_cache_manager/test/mock.dart. // Do not manually edit this file. @@ -20,70 +20,42 @@ import 'package:mockito/src/dummies.dart' as _i6; // ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable // ignore_for_file: prefer_const_constructors // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member class _FakeCacheObject_0 extends _i1.SmartFake implements _i2.CacheObject { - _FakeCacheObject_0( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeCacheObject_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeDuration_1 extends _i1.SmartFake implements Duration { - _FakeDuration_1( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeDuration_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeFileSystem_2 extends _i1.SmartFake implements _i3.FileSystem { - _FakeFileSystem_2( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeFileSystem_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeDateTime_3 extends _i1.SmartFake implements DateTime { - _FakeDateTime_3( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeDateTime_3(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeFileServiceResponse_4 extends _i1.SmartFake implements _i3.FileServiceResponse { - _FakeFileServiceResponse_4( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeFileServiceResponse_4(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeFileService_5 extends _i1.SmartFake implements _i3.FileService { - _FakeFileService_5( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeFileService_5(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } /// A class which mocks [CacheInfoRepository]. @@ -96,32 +68,28 @@ class MockCacheInfoRepositoryBase extends _i1.Mock } @override - _i4.Future exists() => (super.noSuchMethod( - Invocation.method( - #exists, - [], - ), - returnValue: _i4.Future.value(false), - ) as _i4.Future); + _i4.Future exists() => + (super.noSuchMethod( + Invocation.method(#exists, []), + returnValue: _i4.Future.value(false), + ) + as _i4.Future); @override - _i4.Future open() => (super.noSuchMethod( - Invocation.method( - #open, - [], - ), - returnValue: _i4.Future.value(false), - ) as _i4.Future); + _i4.Future open() => + (super.noSuchMethod( + Invocation.method(#open, []), + returnValue: _i4.Future.value(false), + ) + as _i4.Future); @override _i4.Future updateOrInsert(_i2.CacheObject? cacheObject) => (super.noSuchMethod( - Invocation.method( - #updateOrInsert, - [cacheObject], - ), - returnValue: _i4.Future.value(), - ) as _i4.Future); + Invocation.method(#updateOrInsert, [cacheObject]), + returnValue: _i4.Future.value(), + ) + as _i4.Future); @override _i4.Future<_i2.CacheObject> insert( @@ -129,47 +97,47 @@ class MockCacheInfoRepositoryBase extends _i1.Mock bool? setTouchedToNow = true, }) => (super.noSuchMethod( - Invocation.method( - #insert, - [cacheObject], - {#setTouchedToNow: setTouchedToNow}, - ), - returnValue: _i4.Future<_i2.CacheObject>.value(_FakeCacheObject_0( - this, - Invocation.method( - #insert, - [cacheObject], - {#setTouchedToNow: setTouchedToNow}, - ), - )), - ) as _i4.Future<_i2.CacheObject>); - - @override - _i4.Future<_i2.CacheObject?> get(String? key) => (super.noSuchMethod( - Invocation.method( - #get, - [key], - ), - returnValue: _i4.Future<_i2.CacheObject?>.value(), - ) as _i4.Future<_i2.CacheObject?>); - - @override - _i4.Future delete(int? id) => (super.noSuchMethod( - Invocation.method( - #delete, - [id], - ), - returnValue: _i4.Future.value(0), - ) as _i4.Future); - - @override - _i4.Future deleteAll(Iterable? ids) => (super.noSuchMethod( - Invocation.method( - #deleteAll, - [ids], - ), - returnValue: _i4.Future.value(0), - ) as _i4.Future); + Invocation.method( + #insert, + [cacheObject], + {#setTouchedToNow: setTouchedToNow}, + ), + returnValue: _i4.Future<_i2.CacheObject>.value( + _FakeCacheObject_0( + this, + Invocation.method( + #insert, + [cacheObject], + {#setTouchedToNow: setTouchedToNow}, + ), + ), + ), + ) + as _i4.Future<_i2.CacheObject>); + + @override + _i4.Future<_i2.CacheObject?> get(String? key) => + (super.noSuchMethod( + Invocation.method(#get, [key]), + returnValue: _i4.Future<_i2.CacheObject?>.value(), + ) + as _i4.Future<_i2.CacheObject?>); + + @override + _i4.Future delete(int? id) => + (super.noSuchMethod( + Invocation.method(#delete, [id]), + returnValue: _i4.Future.value(0), + ) + as _i4.Future); + + @override + _i4.Future deleteAll(Iterable? ids) => + (super.noSuchMethod( + Invocation.method(#deleteAll, [ids]), + returnValue: _i4.Future.value(0), + ) + as _i4.Future); @override _i4.Future update( @@ -177,64 +145,61 @@ class MockCacheInfoRepositoryBase extends _i1.Mock bool? setTouchedToNow = true, }) => (super.noSuchMethod( - Invocation.method( - #update, - [cacheObject], - {#setTouchedToNow: setTouchedToNow}, - ), - returnValue: _i4.Future.value(0), - ) as _i4.Future); + Invocation.method( + #update, + [cacheObject], + {#setTouchedToNow: setTouchedToNow}, + ), + returnValue: _i4.Future.value(0), + ) + as _i4.Future); @override - _i4.Future> getAllObjects() => (super.noSuchMethod( - Invocation.method( - #getAllObjects, - [], - ), - returnValue: - _i4.Future>.value(<_i2.CacheObject>[]), - ) as _i4.Future>); + _i4.Future> getAllObjects() => + (super.noSuchMethod( + Invocation.method(#getAllObjects, []), + returnValue: _i4.Future>.value( + <_i2.CacheObject>[], + ), + ) + as _i4.Future>); @override _i4.Future> getObjectsOverCapacity(int? capacity) => (super.noSuchMethod( - Invocation.method( - #getObjectsOverCapacity, - [capacity], - ), - returnValue: - _i4.Future>.value(<_i2.CacheObject>[]), - ) as _i4.Future>); + Invocation.method(#getObjectsOverCapacity, [capacity]), + returnValue: _i4.Future>.value( + <_i2.CacheObject>[], + ), + ) + as _i4.Future>); @override _i4.Future> getOldObjects(Duration? maxAge) => (super.noSuchMethod( - Invocation.method( - #getOldObjects, - [maxAge], - ), - returnValue: - _i4.Future>.value(<_i2.CacheObject>[]), - ) as _i4.Future>); - - @override - _i4.Future close() => (super.noSuchMethod( - Invocation.method( - #close, - [], - ), - returnValue: _i4.Future.value(false), - ) as _i4.Future); - - @override - _i4.Future deleteDataFile() => (super.noSuchMethod( - Invocation.method( - #deleteDataFile, - [], - ), - returnValue: _i4.Future.value(), - returnValueForMissingStub: _i4.Future.value(), - ) as _i4.Future); + Invocation.method(#getOldObjects, [maxAge]), + returnValue: _i4.Future>.value( + <_i2.CacheObject>[], + ), + ) + as _i4.Future>); + + @override + _i4.Future close() => + (super.noSuchMethod( + Invocation.method(#close, []), + returnValue: _i4.Future.value(false), + ) + as _i4.Future); + + @override + _i4.Future deleteDataFile() => + (super.noSuchMethod( + Invocation.method(#deleteDataFile, []), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) + as _i4.Future); } /// A class which mocks [CacheStore]. @@ -246,68 +211,66 @@ class MockCacheStoreBase extends _i1.Mock implements _i5.CacheStore { } @override - Duration get cleanupRunMinInterval => (super.noSuchMethod( - Invocation.getter(#cleanupRunMinInterval), - returnValue: _FakeDuration_1( - this, - Invocation.getter(#cleanupRunMinInterval), - ), - ) as Duration); + Duration get cleanupRunMinInterval => + (super.noSuchMethod( + Invocation.getter(#cleanupRunMinInterval), + returnValue: _FakeDuration_1( + this, + Invocation.getter(#cleanupRunMinInterval), + ), + ) + as Duration); @override - set cleanupRunMinInterval(Duration? _cleanupRunMinInterval) => - super.noSuchMethod( - Invocation.setter( - #cleanupRunMinInterval, - _cleanupRunMinInterval, - ), - returnValueForMissingStub: null, - ); + _i3.FileSystem get fileSystem => + (super.noSuchMethod( + Invocation.getter(#fileSystem), + returnValue: _FakeFileSystem_2( + this, + Invocation.getter(#fileSystem), + ), + ) + as _i3.FileSystem); @override - _i3.FileSystem get fileSystem => (super.noSuchMethod( - Invocation.getter(#fileSystem), - returnValue: _FakeFileSystem_2( - this, - Invocation.getter(#fileSystem), - ), - ) as _i3.FileSystem); + String get storeKey => + (super.noSuchMethod( + Invocation.getter(#storeKey), + returnValue: _i6.dummyValue( + this, + Invocation.getter(#storeKey), + ), + ) + as String); @override - set fileSystem(_i3.FileSystem? _fileSystem) => super.noSuchMethod( - Invocation.setter( - #fileSystem, - _fileSystem, - ), - returnValueForMissingStub: null, - ); + DateTime get lastCleanupRun => + (super.noSuchMethod( + Invocation.getter(#lastCleanupRun), + returnValue: _FakeDateTime_3( + this, + Invocation.getter(#lastCleanupRun), + ), + ) + as DateTime); @override - DateTime get lastCleanupRun => (super.noSuchMethod( - Invocation.getter(#lastCleanupRun), - returnValue: _FakeDateTime_3( - this, - Invocation.getter(#lastCleanupRun), - ), - ) as DateTime); + set cleanupRunMinInterval(Duration? value) => super.noSuchMethod( + Invocation.setter(#cleanupRunMinInterval, value), + returnValueForMissingStub: null, + ); @override - set lastCleanupRun(DateTime? _lastCleanupRun) => super.noSuchMethod( - Invocation.setter( - #lastCleanupRun, - _lastCleanupRun, - ), - returnValueForMissingStub: null, - ); + set fileSystem(_i3.FileSystem? value) => super.noSuchMethod( + Invocation.setter(#fileSystem, value), + returnValueForMissingStub: null, + ); @override - String get storeKey => (super.noSuchMethod( - Invocation.getter(#storeKey), - returnValue: _i6.dummyValue( - this, - Invocation.getter(#storeKey), - ), - ) as String); + set lastCleanupRun(DateTime? value) => super.noSuchMethod( + Invocation.setter(#lastCleanupRun, value), + returnValueForMissingStub: null, + ); @override _i4.Future<_i3.FileInfo?> getFile( @@ -315,23 +278,23 @@ class MockCacheStoreBase extends _i1.Mock implements _i5.CacheStore { bool? ignoreMemCache = false, }) => (super.noSuchMethod( - Invocation.method( - #getFile, - [key], - {#ignoreMemCache: ignoreMemCache}, - ), - returnValue: _i4.Future<_i3.FileInfo?>.value(), - ) as _i4.Future<_i3.FileInfo?>); + Invocation.method( + #getFile, + [key], + {#ignoreMemCache: ignoreMemCache}, + ), + returnValue: _i4.Future<_i3.FileInfo?>.value(), + ) + as _i4.Future<_i3.FileInfo?>); @override - _i4.Future putFile(_i2.CacheObject? cacheObject) => (super.noSuchMethod( - Invocation.method( - #putFile, - [cacheObject], - ), - returnValue: _i4.Future.value(), - returnValueForMissingStub: _i4.Future.value(), - ) as _i4.Future); + _i4.Future putFile(_i2.CacheObject? cacheObject) => + (super.noSuchMethod( + Invocation.method(#putFile, [cacheObject]), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) + as _i4.Future); @override _i4.Future<_i2.CacheObject?> retrieveCacheData( @@ -339,81 +302,71 @@ class MockCacheStoreBase extends _i1.Mock implements _i5.CacheStore { bool? ignoreMemCache = false, }) => (super.noSuchMethod( - Invocation.method( - #retrieveCacheData, - [key], - {#ignoreMemCache: ignoreMemCache}, - ), - returnValue: _i4.Future<_i2.CacheObject?>.value(), - ) as _i4.Future<_i2.CacheObject?>); + Invocation.method( + #retrieveCacheData, + [key], + {#ignoreMemCache: ignoreMemCache}, + ), + returnValue: _i4.Future<_i2.CacheObject?>.value(), + ) + as _i4.Future<_i2.CacheObject?>); @override _i4.Future<_i3.FileInfo?> getFileFromMemory(String? key) => (super.noSuchMethod( - Invocation.method( - #getFileFromMemory, - [key], - ), - returnValue: _i4.Future<_i3.FileInfo?>.value(), - ) as _i4.Future<_i3.FileInfo?>); + Invocation.method(#getFileFromMemory, [key]), + returnValue: _i4.Future<_i3.FileInfo?>.value(), + ) + as _i4.Future<_i3.FileInfo?>); @override - _i4.Future emptyCache() => (super.noSuchMethod( - Invocation.method( - #emptyCache, - [], - ), - returnValue: _i4.Future.value(), - returnValueForMissingStub: _i4.Future.value(), - ) as _i4.Future); + _i4.Future emptyCache() => + (super.noSuchMethod( + Invocation.method(#emptyCache, []), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) + as _i4.Future); @override void emptyMemoryCache() => super.noSuchMethod( - Invocation.method( - #emptyMemoryCache, - [], - ), - returnValueForMissingStub: null, - ); + Invocation.method(#emptyMemoryCache, []), + returnValueForMissingStub: null, + ); @override _i4.Future removeCachedFile(_i2.CacheObject? cacheObject) => (super.noSuchMethod( - Invocation.method( - #removeCachedFile, - [cacheObject], - ), - returnValue: _i4.Future.value(), - returnValueForMissingStub: _i4.Future.value(), - ) as _i4.Future); - - @override - bool memoryCacheContainsKey(String? key) => (super.noSuchMethod( - Invocation.method( - #memoryCacheContainsKey, - [key], - ), - returnValue: false, - ) as bool); - - @override - _i4.Future dispose() => (super.noSuchMethod( - Invocation.method( - #dispose, - [], - ), - returnValue: _i4.Future.value(), - returnValueForMissingStub: _i4.Future.value(), - ) as _i4.Future); - - @override - _i4.Future getCacheSize() => (super.noSuchMethod( - Invocation.method( - #getCacheSize, - [], - ), - returnValue: _i4.Future.value(0), - ) as _i4.Future); + Invocation.method(#removeCachedFile, [cacheObject]), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) + as _i4.Future); + + @override + bool memoryCacheContainsKey(String? key) => + (super.noSuchMethod( + Invocation.method(#memoryCacheContainsKey, [key]), + returnValue: false, + ) + as bool); + + @override + _i4.Future dispose() => + (super.noSuchMethod( + Invocation.method(#dispose, []), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) + as _i4.Future); + + @override + _i4.Future getCacheSize() => + (super.noSuchMethod( + Invocation.method(#getCacheSize, []), + returnValue: _i4.Future.value(0), + ) + as _i4.Future); } /// A class which mocks [FileService]. @@ -425,19 +378,15 @@ class MockFileServiceBase extends _i1.Mock implements _i3.FileService { } @override - int get concurrentFetches => (super.noSuchMethod( - Invocation.getter(#concurrentFetches), - returnValue: 0, - ) as int); + int get concurrentFetches => + (super.noSuchMethod(Invocation.getter(#concurrentFetches), returnValue: 0) + as int); @override - set concurrentFetches(int? _concurrentFetches) => super.noSuchMethod( - Invocation.setter( - #concurrentFetches, - _concurrentFetches, - ), - returnValueForMissingStub: null, - ); + set concurrentFetches(int? value) => super.noSuchMethod( + Invocation.setter(#concurrentFetches, value), + returnValueForMissingStub: null, + ); @override _i4.Future<_i3.FileServiceResponse> get( @@ -445,21 +394,15 @@ class MockFileServiceBase extends _i1.Mock implements _i3.FileService { Map? headers, }) => (super.noSuchMethod( - Invocation.method( - #get, - [url], - {#headers: headers}, - ), - returnValue: _i4.Future<_i3.FileServiceResponse>.value( - _FakeFileServiceResponse_4( - this, - Invocation.method( - #get, - [url], - {#headers: headers}, - ), - )), - ) as _i4.Future<_i3.FileServiceResponse>); + Invocation.method(#get, [url], {#headers: headers}), + returnValue: _i4.Future<_i3.FileServiceResponse>.value( + _FakeFileServiceResponse_4( + this, + Invocation.method(#get, [url], {#headers: headers}), + ), + ), + ) + as _i4.Future<_i3.FileServiceResponse>); } /// A class which mocks [WebHelper]. @@ -471,28 +414,26 @@ class MockWebHelper extends _i1.Mock implements _i7.WebHelper { } @override - _i3.FileService get fileFetcher => (super.noSuchMethod( - Invocation.getter(#fileFetcher), - returnValue: _FakeFileService_5( - this, - Invocation.getter(#fileFetcher), - ), - ) as _i3.FileService); + _i3.FileService get fileFetcher => + (super.noSuchMethod( + Invocation.getter(#fileFetcher), + returnValue: _FakeFileService_5( + this, + Invocation.getter(#fileFetcher), + ), + ) + as _i3.FileService); @override - int get concurrentCalls => (super.noSuchMethod( - Invocation.getter(#concurrentCalls), - returnValue: 0, - ) as int); + int get concurrentCalls => + (super.noSuchMethod(Invocation.getter(#concurrentCalls), returnValue: 0) + as int); @override - set concurrentCalls(int? _concurrentCalls) => super.noSuchMethod( - Invocation.setter( - #concurrentCalls, - _concurrentCalls, - ), - returnValueForMissingStub: null, - ); + set concurrentCalls(int? value) => super.noSuchMethod( + Invocation.setter(#concurrentCalls, value), + returnValueForMissingStub: null, + ); @override _i4.Stream<_i3.FileResponse> downloadFile( @@ -502,15 +443,16 @@ class MockWebHelper extends _i1.Mock implements _i7.WebHelper { bool? ignoreMemCache = false, }) => (super.noSuchMethod( - Invocation.method( - #downloadFile, - [url], - { - #key: key, - #authHeaders: authHeaders, - #ignoreMemCache: ignoreMemCache, - }, - ), - returnValue: _i4.Stream<_i3.FileResponse>.empty(), - ) as _i4.Stream<_i3.FileResponse>); + Invocation.method( + #downloadFile, + [url], + { + #key: key, + #authHeaders: authHeaders, + #ignoreMemCache: ignoreMemCache, + }, + ), + returnValue: _i4.Stream<_i3.FileResponse>.empty(), + ) + as _i4.Stream<_i3.FileResponse>); } From 2c296fe20b4151722692eb5e5bf4ef0fc5983062 Mon Sep 17 00:00:00 2001 From: Rick van Dijk Date: Mon, 20 Jul 2026 13:36:02 -0600 Subject: [PATCH 2/7] fix: use unnamed library directive for flutter_lints 6 Remove the named library to satisfy the unnecessary_library_name lint. Co-authored-by: Cursor --- flutter_cache_manager/lib/flutter_cache_manager.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter_cache_manager/lib/flutter_cache_manager.dart b/flutter_cache_manager/lib/flutter_cache_manager.dart index 943d910a..05064282 100644 --- a/flutter_cache_manager/lib/flutter_cache_manager.dart +++ b/flutter_cache_manager/lib/flutter_cache_manager.dart @@ -1,6 +1,6 @@ /// Generic cache manager for flutter. /// Saves web files on the storages of the device and saves the cache info using sqflite -library flutter_cache_manager; +library; export 'src/cache_manager.dart'; export 'src/cache_managers/cache_managers.dart'; From d22f8fc9369c61affe038af1fbf048394b3cdba0 Mon Sep 17 00:00:00 2001 From: Rick van Dijk Date: Mon, 20 Jul 2026 13:36:03 -0600 Subject: [PATCH 3/7] chore: update example app dependencies Align the example with Dart 3.8 and refresh generated desktop plugin registrants. Co-authored-by: Cursor --- .../example/linux/flutter/generated_plugins.cmake | 1 + .../example/macos/Flutter/GeneratedPluginRegistrant.swift | 4 +--- flutter_cache_manager/example/pubspec.yaml | 8 ++++---- .../example/windows/flutter/generated_plugins.cmake | 1 + 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/flutter_cache_manager/example/linux/flutter/generated_plugins.cmake b/flutter_cache_manager/example/linux/flutter/generated_plugins.cmake index f16b4c34..df8d2f72 100644 --- a/flutter_cache_manager/example/linux/flutter/generated_plugins.cmake +++ b/flutter_cache_manager/example/linux/flutter/generated_plugins.cmake @@ -7,6 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/flutter_cache_manager/example/macos/Flutter/GeneratedPluginRegistrant.swift b/flutter_cache_manager/example/macos/Flutter/GeneratedPluginRegistrant.swift index d24127f3..645e27da 100644 --- a/flutter_cache_manager/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/flutter_cache_manager/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,12 +5,10 @@ import FlutterMacOS import Foundation -import path_provider_foundation -import sqflite +import sqflite_darwin import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) } diff --git a/flutter_cache_manager/example/pubspec.yaml b/flutter_cache_manager/example/pubspec.yaml index 5f5bcc98..bc83f26c 100644 --- a/flutter_cache_manager/example/pubspec.yaml +++ b/flutter_cache_manager/example/pubspec.yaml @@ -3,21 +3,21 @@ description: A project that showcases usage of flutter_cache_manager publish_to: none version: 1.0.0+1 environment: - sdk: '>=3.0.0 <4.0.0' + sdk: '>=3.8.0 <4.0.0' dependencies: - baseflow_plugin_template: ^2.2.0 + baseflow_plugin_template: ^2.2.1 cupertino_icons: ^1.0.8 flutter: sdk: flutter flutter_cache_manager: path: ../ - url_launcher: ^6.3.0 + url_launcher: ^6.3.2 dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^4.0.0 + flutter_lints: ^6.0.0 flutter: uses-material-design: true diff --git a/flutter_cache_manager/example/windows/flutter/generated_plugins.cmake b/flutter_cache_manager/example/windows/flutter/generated_plugins.cmake index 88b22e5c..a962892f 100644 --- a/flutter_cache_manager/example/windows/flutter/generated_plugins.cmake +++ b/flutter_cache_manager/example/windows/flutter/generated_plugins.cmake @@ -7,6 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES) From 85096ddcba57783852067807e48f46d6cf9e1cfe Mon Sep 17 00:00:00 2001 From: Rick van Dijk Date: Mon, 20 Jul 2026 13:36:03 -0600 Subject: [PATCH 4/7] docs: note SDK and dependency updates in CHANGELOG Co-authored-by: Cursor --- flutter_cache_manager/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/flutter_cache_manager/CHANGELOG.md b/flutter_cache_manager/CHANGELOG.md index ae33d3f2..90b5238e 100644 --- a/flutter_cache_manager/CHANGELOG.md +++ b/flutter_cache_manager/CHANGELOG.md @@ -1,5 +1,6 @@ ## [Unreleased] +* Raise minimum Dart SDK to 3.8.0 and update dependencies * Update example Android project for Flutter 3.44 (Gradle 9.1 / AGP 9.0.1 / Kotlin 2.3.20, Java 17) * Migrate example Android app to built-in Kotlin * Migrate example iOS app from CocoaPods to Swift Package Manager From 6308ff9d92d432fd737ae4a0c53aa1424e9373d2 Mon Sep 17 00:00:00 2001 From: Rick van Dijk Date: Mon, 20 Jul 2026 13:36:03 -0600 Subject: [PATCH 5/7] chore: ignore FVM local Flutter SDK files Co-authored-by: Cursor --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index b22a5648..f894cace 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ .history .svn/ devtools_options.yaml +.fvmrc +.fvm/ # Environment files ios/Flutter/Dart-Defines.xcconfig From cce9a65b970a4fb5e028d3a70e9f1af6b36ae395 Mon Sep 17 00:00:00 2001 From: Rick van Dijk Date: Mon, 20 Jul 2026 13:41:59 -0600 Subject: [PATCH 6/7] formatted files --- flutter_cache_manager/example/lib/main.dart | 25 +- .../lib/plugin_example/download_page.dart | 5 +- .../floating_action_button.dart | 5 +- .../lib/src/cache_manager.dart | 70 ++-- .../cache_managers/base_cache_manager.dart | 23 +- .../cache_managers/image_cache_manager.dart | 59 ++-- .../lib/src/cache_store.dart | 32 +- .../lib/src/compat/file_fetcher.dart | 7 +- .../lib/src/compat/file_service_compat.dart | 6 +- .../lib/src/config/_config_io.dart | 10 +- .../lib/src/config/_config_web.dart | 10 +- .../lib/src/config/config.dart | 3 +- flutter_cache_manager/lib/src/logger.dart | 7 +- .../lib/src/result/file_info.dart | 10 +- .../cache_info_repository.dart | 12 +- .../cache_object_provider.dart | 127 +++++--- .../json_cache_info_repository.dart | 24 +- .../non_storing_object_provider.dart | 5 +- .../lib/src/storage/cache_object.dart | 22 +- .../lib/src/web/file_service.dart | 8 +- .../lib/src/web/mime_converter.dart | 2 +- .../lib/src/web/web_helper.dart | 70 ++-- .../test/cache_manager_test.dart | 288 ++++++++++------- .../test/cache_object_test.dart | 4 +- .../test/cache_store_test.dart | 305 ++++++++++-------- .../test/helpers/config_extensions.dart | 21 +- .../test/helpers/json_repo_helpers.dart | 10 +- .../helpers/mock_cache_info_repository.dart | 29 +- .../test/helpers/mock_cache_store.dart | 6 +- .../helpers/mock_file_fetcher_response.dart | 20 +- .../test/helpers/mock_file_service.dart | 5 +- .../test/helpers/test_configuration.dart | 5 +- .../test/http_file_fetcher_test.dart | 48 ++- .../test/image_cache_manager_test.dart | 86 ++--- .../json_file_repository_test.dart | 50 +-- .../test/repositories/migration_test.dart | 9 +- .../test/web_helper_test.dart | 169 ++++++---- 37 files changed, 947 insertions(+), 650 deletions(-) diff --git a/flutter_cache_manager/example/lib/main.dart b/flutter_cache_manager/example/lib/main.dart index 081c9973..ee34ca00 100644 --- a/flutter_cache_manager/example/lib/main.dart +++ b/flutter_cache_manager/example/lib/main.dart @@ -47,9 +47,7 @@ class CacheManagerPageState extends State { body: const ListTile( title: Text('Tap the floating action button to download.'), ), - floatingActionButton: Fab( - downloadFile: _downloadFile, - ), + floatingActionButton: Fab(downloadFile: _downloadFile), ); } return DownloadPage( @@ -68,15 +66,18 @@ class CacheManagerPageState extends State { } void _removeFile() { - DefaultCacheManager().removeFile(url).then((value) { - if (kDebugMode) { - print('File removed'); - } - }).onError((error, stackTrace) { - if (kDebugMode) { - print(error); - } - }); + DefaultCacheManager() + .removeFile(url) + .then((value) { + if (kDebugMode) { + print('File removed'); + } + }) + .onError((error, stackTrace) { + if (kDebugMode) { + print(error); + } + }); setState(() { fileStream = null; }); diff --git a/flutter_cache_manager/example/lib/plugin_example/download_page.dart b/flutter_cache_manager/example/lib/plugin_example/download_page.dart index 16645e3a..534e4cd3 100644 --- a/flutter_cache_manager/example/lib/plugin_example/download_page.dart +++ b/flutter_cache_manager/example/lib/plugin_example/download_page.dart @@ -47,8 +47,9 @@ class DownloadPage extends StatelessWidget { return Scaffold( body: body, - floatingActionButton: - !loading ? Fab(downloadFile: downloadFile) : null, + floatingActionButton: !loading + ? Fab(downloadFile: downloadFile) + : null, ); }, ); diff --git a/flutter_cache_manager/example/lib/plugin_example/floating_action_button.dart b/flutter_cache_manager/example/lib/plugin_example/floating_action_button.dart index 33ca5346..fc6f3746 100644 --- a/flutter_cache_manager/example/lib/plugin_example/floating_action_button.dart +++ b/flutter_cache_manager/example/lib/plugin_example/floating_action_button.dart @@ -4,10 +4,7 @@ import 'package:flutter/material.dart'; class Fab extends StatelessWidget { final VoidCallback downloadFile; - const Fab({ - required this.downloadFile, - super.key, - }); + const Fab({required this.downloadFile, super.key}); @override Widget build(BuildContext context) { diff --git a/flutter_cache_manager/lib/src/cache_manager.dart b/flutter_cache_manager/lib/src/cache_manager.dart index 82ac52a9..c04b9e7a 100644 --- a/flutter_cache_manager/lib/src/cache_manager.dart +++ b/flutter_cache_manager/lib/src/cache_manager.dart @@ -29,9 +29,7 @@ class CacheManager implements BaseCacheManager { /// The [fileService] can be used to customize how files are downloaded. For example /// to edit the urls, add headers or use a proxy. You can also choose to supply /// a CacheStore or WebHelper directly if you want more customization. - CacheManager(Config config) - : _config = config, - _store = CacheStore(config) { + CacheManager(Config config) : _config = config, _store = CacheStore(config) { _webHelper = WebHelper(_store, config.fileService); } @@ -40,8 +38,8 @@ class CacheManager implements BaseCacheManager { Config config, { CacheStore? cacheStore, WebHelper? webHelper, - }) : _config = config, - _store = cacheStore ?? CacheStore(config) { + }) : _config = config, + _store = cacheStore ?? CacheStore(config) { _webHelper = webHelper ?? WebHelper(_store, config.fileService); } @@ -87,8 +85,11 @@ class CacheManager implements BaseCacheManager { /// cached file is too old the newly downloaded file is returned afterwards. @override @Deprecated('Prefer to use the new getFileStream method') - Stream getFile(String url, - {String? key, Map? headers}) { + Stream getFile( + String url, { + String? key, + Map? headers, + }) { return getFileStream( url, key: key, @@ -108,8 +109,12 @@ class CacheManager implements BaseCacheManager { /// returned from the cache there will be no progress given, although the file /// might be outdated and a new file is being downloaded in the background. @override - Stream getFileStream(String url, - {String? key, Map? headers, bool withProgress = false}) { + Stream getFileStream( + String url, { + String? key, + Map? headers, + bool withProgress = false, + }) { key ??= url; final streamController = StreamController(); _pushFileToStream(streamController, url, key, headers, withProgress); @@ -133,13 +138,17 @@ class CacheManager implements BaseCacheManager { } } on Object catch (e) { cacheLogger.log( - 'CacheManager: Failed to load cached file for $url with error:\n$e', - CacheManagerLogLevel.debug); + 'CacheManager: Failed to load cached file for $url with error:\n$e', + CacheManagerLogLevel.debug, + ); } if (cacheFile == null || cacheFile.validTill.isBefore(DateTime.now())) { try { - await for (final response - in _webHelper.downloadFile(url, key: key, authHeaders: headers)) { + await for (final response in _webHelper.downloadFile( + url, + key: key, + authHeaders: headers, + )) { if (response is DownloadProgress && withProgress) { streamController.add(response); } @@ -149,8 +158,9 @@ class CacheManager implements BaseCacheManager { } } on Object catch (e) { cacheLogger.log( - 'CacheManager: Failed to download file from $url with error:\n$e', - CacheManagerLogLevel.debug); + 'CacheManager: Failed to download file from $url with error:\n$e', + CacheManagerLogLevel.debug, + ); if (cacheFile == null && streamController.hasListener) { streamController.addError(e); } @@ -170,10 +180,12 @@ class CacheManager implements BaseCacheManager { ///Download the file and add to cache @override - Future downloadFile(String url, - {String? key, - Map? authHeaders, - bool force = false}) async { + Future downloadFile( + String url, { + String? key, + Map? authHeaders, + bool force = false, + }) async { key ??= url; final fileResponse = await _webHelper .downloadFile( @@ -189,9 +201,10 @@ class CacheManager implements BaseCacheManager { /// Get the file from the cache. /// Specify [ignoreMemCache] to force a re-read from the database @override - Future getFileFromCache(String key, - {bool ignoreMemCache = false}) => - _store.getFile(key, ignoreMemCache: ignoreMemCache); + Future getFileFromCache( + String key, { + bool ignoreMemCache = false, + }) => _store.getFile(key, ignoreMemCache: ignoreMemCache); ///Returns the file from memory if it has already been fetched @override @@ -251,11 +264,14 @@ class CacheManager implements BaseCacheManager { }) async { key ??= url; var cacheObject = await _store.retrieveCacheData(key); - cacheObject ??= CacheObject(url, - key: key, - relativePath: '${const Uuid().v1()}' - '.$fileExtension', - validTill: DateTime.now().add(maxAge)); + cacheObject ??= CacheObject( + url, + key: key, + relativePath: + '${const Uuid().v1()}' + '.$fileExtension', + validTill: DateTime.now().add(maxAge), + ); cacheObject = cacheObject.copyWith( validTill: DateTime.now().add(maxAge), diff --git a/flutter_cache_manager/lib/src/cache_managers/base_cache_manager.dart b/flutter_cache_manager/lib/src/cache_managers/base_cache_manager.dart index 7449a1bc..c6f3a59d 100644 --- a/flutter_cache_manager/lib/src/cache_managers/base_cache_manager.dart +++ b/flutter_cache_manager/lib/src/cache_managers/base_cache_manager.dart @@ -23,8 +23,11 @@ abstract class BaseCacheManager { /// The files are returned as stream. First the cached file if available, when the /// cached file is too old the newly downloaded file is returned afterwards. @Deprecated('Prefer to use the new getFileStream method') - Stream getFile(String url, - {String key, Map headers}); + Stream getFile( + String url, { + String key, + Map headers, + }); /// Get the file from the cache and/or online, depending on availability and age. /// Downloaded form [url], [headers] can be used for example for authentication. @@ -37,12 +40,20 @@ abstract class BaseCacheManager { /// set on true and the file is not available in the cache. When the file is /// returned from the cache there will be no progress given, although the file /// might be outdated and a new file is being downloaded in the background. - Stream getFileStream(String url, - {String? key, Map? headers, bool withProgress}); + Stream getFileStream( + String url, { + String? key, + Map? headers, + bool withProgress, + }); ///Download the file and add to cache - Future downloadFile(String url, - {String? key, Map? authHeaders, bool force = false}); + Future downloadFile( + String url, { + String? key, + Map? authHeaders, + bool force = false, + }); /// Get the file from the cache. /// Specify [ignoreMemCache] to force a re-read from the database diff --git a/flutter_cache_manager/lib/src/cache_managers/image_cache_manager.dart b/flutter_cache_manager/lib/src/cache_managers/image_cache_manager.dart index 614d7d9d..e27b07c1 100644 --- a/flutter_cache_manager/lib/src/cache_managers/image_cache_manager.dart +++ b/flutter_cache_manager/lib/src/cache_managers/image_cache_manager.dart @@ -26,8 +26,12 @@ mixin ImageCacheManager on BaseCacheManager { int? maxWidth, }) async* { if (maxHeight == null && maxWidth == null) { - yield* getFileStream(url, - key: key, headers: headers, withProgress: withProgress); + yield* getFileStream( + url, + key: key, + headers: headers, + withProgress: withProgress, + ); return; } key ??= url; @@ -80,8 +84,8 @@ mixin ImageCacheManager on BaseCacheManager { final shouldResize = maxWidth != null ? image.width > maxWidth : false || maxHeight != null - ? image.height > maxHeight - : false; + ? image.height > maxHeight + : false; if (!shouldResize) return originalFile; if (maxWidth != null && maxHeight != null) { final resizeFactorWidth = image.width / maxWidth; @@ -92,12 +96,14 @@ mixin ImageCacheManager on BaseCacheManager { maxHeight = (image.height / resizeFactor).round(); } - final resized = await _decodeImage(originalFile.file, - width: maxWidth, height: maxHeight); - final resizedFile = - (await resized.toByteData(format: ui.ImageByteFormat.png))! - .buffer - .asUint8List(); + final resized = await _decodeImage( + originalFile.file, + width: maxWidth, + height: maxHeight, + ); + final resizedFile = (await resized.toByteData( + format: ui.ImageByteFormat.png, + ))!.buffer.asUint8List(); final maxAge = originalFile.validTill.difference(DateTime.now()); final file = await putFile( @@ -135,31 +141,36 @@ mixin ImageCacheManager on BaseCacheManager { yield response; } if (response is FileInfo) { - yield await _resizeImageFile( - response, - resizedKey, - maxWidth, - maxHeight, - ); + yield await _resizeImageFile(response, resizedKey, maxWidth, maxHeight); } } } } -Future _decodeImage(File file, - {int? width, int? height, bool allowUpscaling = false}) { +Future _decodeImage( + File file, { + int? width, + int? height, + bool allowUpscaling = false, +}) { final shouldResize = width != null || height != null; final fileImage = FileImage(file); final image = shouldResize - ? ResizeImage(fileImage, - width: width, height: height, allowUpscaling: allowUpscaling) + ? ResizeImage( + fileImage, + width: width, + height: height, + allowUpscaling: allowUpscaling, + ) : fileImage as ImageProvider; final completer = Completer(); image .resolve(ImageConfiguration.empty) - .addListener(ImageStreamListener((info, _) { - completer.complete(info.image); - image.evict(); - })); + .addListener( + ImageStreamListener((info, _) { + completer.complete(info.image); + image.evict(); + }), + ); return completer.future; } diff --git a/flutter_cache_manager/lib/src/cache_store.dart b/flutter_cache_manager/lib/src/cache_store.dart index ca6e9188..44ffbfeb 100644 --- a/flutter_cache_manager/lib/src/cache_store.dart +++ b/flutter_cache_manager/lib/src/cache_store.dart @@ -28,19 +28,23 @@ class CacheStore { Timer? _scheduledCleanup; CacheStore(Config config) - : _config = config, - fileSystem = config.fileSystem, - _cacheInfoRepository = config.repo.open().then((value) => config.repo); + : _config = config, + fileSystem = config.fileSystem, + _cacheInfoRepository = config.repo.open().then((value) => config.repo); Future getFile(String key, {bool ignoreMemCache = false}) async { - final cacheObject = - await retrieveCacheData(key, ignoreMemCache: ignoreMemCache); + final cacheObject = await retrieveCacheData( + key, + ignoreMemCache: ignoreMemCache, + ); if (cacheObject == null) { return null; } final file = await fileSystem.createFile(cacheObject.relativePath); cacheLogger.log( - 'CacheManager: Loaded $key from cache', CacheManagerLogLevel.verbose); + 'CacheManager: Loaded $key from cache', + CacheManagerLogLevel.verbose, + ); return FileInfo( file, @@ -60,8 +64,10 @@ class CacheStore { } } - Future retrieveCacheData(String key, - {bool ignoreMemCache = false}) async { + Future retrieveCacheData( + String key, { + bool ignoreMemCache = false, + }) async { if (!ignoreMemCache && _memCache.containsKey(key)) { if (await _fileExists(_memCache[key])) { return _memCache[key]; @@ -96,7 +102,11 @@ class CacheStore { } final file = await fileSystem.createFile(cacheObject.relativePath); return FileInfo( - file, FileSource.Cache, cacheObject.validTill, cacheObject.url); + file, + FileSource.Cache, + cacheObject.validTill, + cacheObject.url, + ); } Future _fileExists(CacheObject? cacheObject) async { @@ -173,7 +183,9 @@ class CacheStore { } Future _removeCachedFile( - CacheObject cacheObject, List toRemove) async { + CacheObject cacheObject, + List toRemove, + ) async { if (toRemove.contains(cacheObject.id)) return; toRemove.add(cacheObject.id!); diff --git a/flutter_cache_manager/lib/src/compat/file_fetcher.dart b/flutter_cache_manager/lib/src/compat/file_fetcher.dart index ce3ec589..3988fc58 100644 --- a/flutter_cache_manager/lib/src/compat/file_fetcher.dart +++ b/flutter_cache_manager/lib/src/compat/file_fetcher.dart @@ -8,8 +8,11 @@ import 'package:http/http.dart' as http; ///Released under MIT License. /// Deprecated FileFetcher function -typedef FileFetcher = Future Function(String url, - {Map? headers}); +typedef FileFetcher = + Future Function( + String url, { + Map? headers, + }); abstract class FileFetcherResponse { Object get statusCode; diff --git a/flutter_cache_manager/lib/src/compat/file_service_compat.dart b/flutter_cache_manager/lib/src/compat/file_service_compat.dart index 0df201e1..7d6fdbc6 100644 --- a/flutter_cache_manager/lib/src/compat/file_service_compat.dart +++ b/flutter_cache_manager/lib/src/compat/file_service_compat.dart @@ -10,8 +10,10 @@ class FileServiceCompat extends FileService { FileServiceCompat(this.fileFetcher); @override - Future get(String url, - {Map? headers}) async { + Future get( + String url, { + Map? headers, + }) async { final legacyResponse = await fileFetcher(url, headers: headers); return CompatFileServiceGetResponse(legacyResponse); } diff --git a/flutter_cache_manager/lib/src/config/_config_io.dart b/flutter_cache_manager/lib/src/config/_config_io.dart index 67eb8cb3..8df79baf 100644 --- a/flutter_cache_manager/lib/src/config/_config_io.dart +++ b/flutter_cache_manager/lib/src/config/_config_io.dart @@ -11,11 +11,11 @@ class Config implements def.Config { CacheInfoRepository? repo, FileSystem? fileSystem, FileService? fileService, - }) : stalePeriod = stalePeriod ?? const Duration(days: 30), - maxNrOfCacheObjects = maxNrOfCacheObjects ?? 200, - repo = repo ?? _createRepo(cacheKey), - fileSystem = fileSystem ?? IOFileSystem(cacheKey), - fileService = fileService ?? HttpFileService(); + }) : stalePeriod = stalePeriod ?? const Duration(days: 30), + maxNrOfCacheObjects = maxNrOfCacheObjects ?? 200, + repo = repo ?? _createRepo(cacheKey), + fileSystem = fileSystem ?? IOFileSystem(cacheKey), + fileService = fileService ?? HttpFileService(); @override final CacheInfoRepository repo; diff --git a/flutter_cache_manager/lib/src/config/_config_web.dart b/flutter_cache_manager/lib/src/config/_config_web.dart index 99e4f3b8..9a019781 100644 --- a/flutter_cache_manager/lib/src/config/_config_web.dart +++ b/flutter_cache_manager/lib/src/config/_config_web.dart @@ -12,11 +12,11 @@ class Config implements def.Config { CacheInfoRepository? repo, FileSystem? fileSystem, FileService? fileService, - }) : stalePeriod = stalePeriod ?? const Duration(days: 30), - maxNrOfCacheObjects = maxNrOfCacheObjects ?? 200, - repo = repo ?? NonStoringObjectProvider(), - fileSystem = fileSystem ?? MemoryCacheSystem(), - fileService = fileService ?? HttpFileService(); + }) : stalePeriod = stalePeriod ?? const Duration(days: 30), + maxNrOfCacheObjects = maxNrOfCacheObjects ?? 200, + repo = repo ?? NonStoringObjectProvider(), + fileSystem = fileSystem ?? MemoryCacheSystem(), + fileService = fileService ?? HttpFileService(); @override final CacheInfoRepository repo; diff --git a/flutter_cache_manager/lib/src/config/config.dart b/flutter_cache_manager/lib/src/config/config.dart index 1af4730f..88dabb37 100644 --- a/flutter_cache_manager/lib/src/config/config.dart +++ b/flutter_cache_manager/lib/src/config/config.dart @@ -1,7 +1,8 @@ import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:flutter_cache_manager/src/config/_config_unsupported.dart' if (dart.library.js_interop) '_config_web.dart' - if (dart.library.io) '_config_io.dart' as impl; + if (dart.library.io) '_config_io.dart' + as impl; abstract class Config { /// Config file for the CacheManager. diff --git a/flutter_cache_manager/lib/src/logger.dart b/flutter_cache_manager/lib/src/logger.dart index 75d08bec..d056d0fd 100644 --- a/flutter_cache_manager/lib/src/logger.dart +++ b/flutter_cache_manager/lib/src/logger.dart @@ -5,12 +5,7 @@ CacheLogger cacheLogger = CacheLogger(); /// Log levels of the cache manager. Debug shows failed downloads and verbose /// also shows successful downloads and cache retrievals. -enum CacheManagerLogLevel { - none, - warning, - debug, - verbose, -} +enum CacheManagerLogLevel { none, warning, debug, verbose } /// [CacheLogger] which is used by the cache manager to log useful information class CacheLogger { diff --git a/flutter_cache_manager/lib/src/result/file_info.dart b/flutter_cache_manager/lib/src/result/file_info.dart index ae874830..21fd5c84 100644 --- a/flutter_cache_manager/lib/src/result/file_info.dart +++ b/flutter_cache_manager/lib/src/result/file_info.dart @@ -12,9 +12,13 @@ enum FileSource { NA, Cache, Online } /// FileInfo contains the fetch File next to some info on the validity and /// the origin of the file. class FileInfo extends FileResponse { - const FileInfo(this.file, this.source, this.validTill, String originalUrl, - {this.statusCode = 200}) - : super(originalUrl); + const FileInfo( + this.file, + this.source, + this.validTill, + String originalUrl, { + this.statusCode = 200, + }) : super(originalUrl); /// Fetched file final File file; diff --git a/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_info_repository.dart b/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_info_repository.dart index 5a282b24..da204275 100644 --- a/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_info_repository.dart +++ b/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_info_repository.dart @@ -15,8 +15,10 @@ abstract class CacheInfoRepository { Future updateOrInsert(CacheObject cacheObject); /// Inserts [cacheObject] into the repository - Future insert(CacheObject cacheObject, - {bool setTouchedToNow = true}); + Future insert( + CacheObject cacheObject, { + bool setTouchedToNow = true, + }); /// Gets a [CacheObject] by [key] Future get(String key); @@ -60,8 +62,10 @@ extension MigrationExtension on CacheInfoRepository { await _putAll(cacheObjects); final isClosed = await previousRepository.close(); if (!isClosed) { - cacheLogger.log('Deleting an open repository while migrating.', - CacheManagerLogLevel.warning); + cacheLogger.log( + 'Deleting an open repository while migrating.', + CacheManagerLogLevel.warning, + ); } await previousRepository.deleteDataFile(); } diff --git a/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_object_provider.dart b/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_object_provider.dart index 16bf5656..b386ea58 100644 --- a/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_object_provider.dart +++ b/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_object_provider.dart @@ -27,9 +27,11 @@ class CacheObjectProvider extends CacheInfoRepository } final path = await _getPath(); await File(path).parent.create(recursive: true); - db = await openDatabase(path, version: 3, - onCreate: (Database db, int version) async { - await db.execute(''' + db = await openDatabase( + path, + version: 3, + onCreate: (Database db, int version) async { + await db.execute(''' create table $_tableCacheObject ( ${CacheObject.columnId} integer primary key, ${CacheObject.columnUrl} text, @@ -43,46 +45,48 @@ class CacheObjectProvider extends CacheInfoRepository create unique index $_tableCacheObject${CacheObject.columnKey} ON $_tableCacheObject (${CacheObject.columnKey}); '''); - }, onUpgrade: (Database db, int oldVersion, int newVersion) async { - // Migration for adding the optional key, does the following: - // Adds the new column - // Creates a unique index for the column - // Migrates over any existing URLs to keys - if (oldVersion <= 1) { - var alreadyHasKeyColumn = false; - try { - await db.execute(''' + }, + onUpgrade: (Database db, int oldVersion, int newVersion) async { + // Migration for adding the optional key, does the following: + // Adds the new column + // Creates a unique index for the column + // Migrates over any existing URLs to keys + if (oldVersion <= 1) { + var alreadyHasKeyColumn = false; + try { + await db.execute(''' alter table $_tableCacheObject add ${CacheObject.columnKey} text; '''); - } on DatabaseException catch (e) { - if (!e.isDuplicateColumnError(CacheObject.columnKey)) rethrow; - alreadyHasKeyColumn = true; - } - await db.execute(''' + } on DatabaseException catch (e) { + if (!e.isDuplicateColumnError(CacheObject.columnKey)) rethrow; + alreadyHasKeyColumn = true; + } + await db.execute(''' update $_tableCacheObject set ${CacheObject.columnKey} = ${CacheObject.columnUrl} where ${CacheObject.columnKey} is null; '''); - if (!alreadyHasKeyColumn) { - await db.execute(''' + if (!alreadyHasKeyColumn) { + await db.execute(''' create index $_tableCacheObject${CacheObject.columnKey} on $_tableCacheObject (${CacheObject.columnKey}); '''); + } } - } - if (oldVersion <= 2) { - try { - await db.execute(''' + if (oldVersion <= 2) { + try { + await db.execute(''' alter table $_tableCacheObject add ${CacheObject.columnLength} integer; '''); - } on DatabaseException catch (e) { - if (!e.isDuplicateColumnError(CacheObject.columnLength)) rethrow; + } on DatabaseException catch (e) { + if (!e.isDuplicateColumnError(CacheObject.columnLength)) rethrow; + } } - } - }); + }, + ); return opened(); } @@ -96,8 +100,10 @@ class CacheObjectProvider extends CacheInfoRepository } @override - Future insert(CacheObject cacheObject, - {bool setTouchedToNow = true}) async { + Future insert( + CacheObject cacheObject, { + bool setTouchedToNow = true, + }) async { final id = await db!.insert( _tableCacheObject, cacheObject.toMap(setTouchedToNow: setTouchedToNow), @@ -107,8 +113,12 @@ class CacheObjectProvider extends CacheInfoRepository @override Future get(String key) async { - final List> maps = await db!.query(_tableCacheObject, - columns: null, where: '${CacheObject.columnKey} = ?', whereArgs: [key]); + final List> maps = await db!.query( + _tableCacheObject, + columns: null, + where: '${CacheObject.columnKey} = ?', + whereArgs: [key], + ); if (maps.isNotEmpty) { return CacheObject.fromMap(maps.first.cast()); } @@ -117,14 +127,19 @@ class CacheObjectProvider extends CacheInfoRepository @override Future delete(int id) { - return db!.delete(_tableCacheObject, - where: '${CacheObject.columnId} = ?', whereArgs: [id]); + return db!.delete( + _tableCacheObject, + where: '${CacheObject.columnId} = ?', + whereArgs: [id], + ); } @override Future deleteAll(Iterable ids) { - return db!.delete(_tableCacheObject, - where: '${CacheObject.columnId} IN (${ids.join(',')})'); + return db!.delete( + _tableCacheObject, + where: '${CacheObject.columnId} IN (${ids.join(',')})', + ); } @override @@ -146,28 +161,34 @@ class CacheObjectProvider extends CacheInfoRepository @override Future> getObjectsOverCapacity(int capacity) async { - return CacheObject.fromMapList(await db!.query( - _tableCacheObject, - columns: null, - orderBy: '${CacheObject.columnTouched} DESC', - where: '${CacheObject.columnTouched} < ?', - whereArgs: [ - DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch - ], - limit: 100, - offset: capacity, - )); + return CacheObject.fromMapList( + await db!.query( + _tableCacheObject, + columns: null, + orderBy: '${CacheObject.columnTouched} DESC', + where: '${CacheObject.columnTouched} < ?', + whereArgs: [ + DateTime.now() + .subtract(const Duration(days: 1)) + .millisecondsSinceEpoch, + ], + limit: 100, + offset: capacity, + ), + ); } @override Future> getOldObjects(Duration maxAge) async { - return CacheObject.fromMapList(await db!.query( - _tableCacheObject, - where: '${CacheObject.columnTouched} < ?', - columns: null, - whereArgs: [DateTime.now().subtract(maxAge).millisecondsSinceEpoch], - limit: 100, - )); + return CacheObject.fromMapList( + await db!.query( + _tableCacheObject, + where: '${CacheObject.columnTouched} < ?', + columns: null, + whereArgs: [DateTime.now().subtract(maxAge).millisecondsSinceEpoch], + limit: 100, + ), + ); } @override diff --git a/flutter_cache_manager/lib/src/storage/cache_info_repositories/json_cache_info_repository.dart b/flutter_cache_manager/lib/src/storage/cache_info_repositories/json_cache_info_repository.dart index 800f4ba1..e8ee293f 100644 --- a/flutter_cache_manager/lib/src/storage/cache_info_repositories/json_cache_info_repository.dart +++ b/flutter_cache_manager/lib/src/storage/cache_info_repositories/json_cache_info_repository.dart @@ -21,7 +21,7 @@ class JsonCacheInfoRepository extends CacheInfoRepository /// If the path is provider it should end with '{databaseName}.json', /// for example: /data/user/0/com.example.example/databases/imageCache.json JsonCacheInfoRepository({this.path, this.databaseName}) - : assert(path == null || databaseName == null); + : assert(path == null || databaseName == null); /// The directory and the databaseName should both the provided. The database /// is stored as {databaseName}.json in the directory, @@ -98,9 +98,7 @@ class JsonCacheInfoRepository extends CacheInfoRepository Future> getOldObjects(Duration maxAge) async { final oldestTimestamp = DateTime.now().subtract(maxAge); return _cacheObjects.values - .where( - (element) => element.touched!.isBefore(oldestTimestamp), - ) + .where((element) => element.touched!.isBefore(oldestTimestamp)) .toList(); } @@ -149,15 +147,17 @@ class JsonCacheInfoRepository extends CacheInfoRepository _cacheObjects[cacheObject.key] = cacheObject; } } on Object catch (e, stacktrace) { - FlutterError.reportError(FlutterErrorDetails( - exception: e, - stack: stacktrace, - library: 'flutter cache manager', - context: ErrorDescription( - 'Thrown when reading the file containing cache info. ' - 'The cached files cannot be used by the cache manager anymore.', + FlutterError.reportError( + FlutterErrorDetails( + exception: e, + stack: stacktrace, + library: 'flutter cache manager', + context: ErrorDescription( + 'Thrown when reading the file containing cache info. ' + 'The cached files cannot be used by the cache manager anymore.', + ), ), - )); + ); } } } diff --git a/flutter_cache_manager/lib/src/storage/cache_info_repositories/non_storing_object_provider.dart b/flutter_cache_manager/lib/src/storage/cache_info_repositories/non_storing_object_provider.dart index 92ea41c2..01dd6c3f 100644 --- a/flutter_cache_manager/lib/src/storage/cache_info_repositories/non_storing_object_provider.dart +++ b/flutter_cache_manager/lib/src/storage/cache_info_repositories/non_storing_object_provider.dart @@ -51,10 +51,7 @@ class NonStoringObjectProvider implements CacheInfoRepository { } @override - Future update( - CacheObject cacheObject, { - bool setTouchedToNow = true, - }) { + Future update(CacheObject cacheObject, {bool setTouchedToNow = true}) { return Future.value(0); } diff --git a/flutter_cache_manager/lib/src/storage/cache_object.dart b/flutter_cache_manager/lib/src/storage/cache_object.dart index 23fc406f..a471d521 100644 --- a/flutter_cache_manager/lib/src/storage/cache_object.dart +++ b/flutter_cache_manager/lib/src/storage/cache_object.dart @@ -27,16 +27,16 @@ class CacheObject { }) : key = key ?? url; CacheObject.fromMap(Map map) - : id = map[columnId] as int, - url = map[columnUrl] as String, - key = map[columnKey] as String? ?? map[columnUrl] as String, - relativePath = map[columnPath] as String, - validTill = - DateTime.fromMillisecondsSinceEpoch(map[columnValidTill] as int), - eTag = map[columnETag] as String?, - length = map[columnLength] as int?, - touched = - DateTime.fromMillisecondsSinceEpoch(map[columnTouched] as int); + : id = map[columnId] as int, + url = map[columnUrl] as String, + key = map[columnKey] as String? ?? map[columnUrl] as String, + relativePath = map[columnPath] as String, + validTill = DateTime.fromMillisecondsSinceEpoch( + map[columnValidTill] as int, + ), + eTag = map[columnETag] as String?, + length = map[columnLength] as int?, + touched = DateTime.fromMillisecondsSinceEpoch(map[columnTouched] as int); /// Internal ID used to represent this cache object final int? id; @@ -73,7 +73,7 @@ class CacheObject { columnValidTill: validTill.millisecondsSinceEpoch, columnTouched: (setTouchedToNow ? clock.now() : touched)?.millisecondsSinceEpoch ?? - 0, + 0, columnLength: length, if (id != null) columnId: id, }; diff --git a/flutter_cache_manager/lib/src/web/file_service.dart b/flutter_cache_manager/lib/src/web/file_service.dart index 2dcd01d6..376d672e 100644 --- a/flutter_cache_manager/lib/src/web/file_service.dart +++ b/flutter_cache_manager/lib/src/web/file_service.dart @@ -25,11 +25,13 @@ class HttpFileService extends FileService { final http.Client _httpClient; HttpFileService({http.Client? httpClient}) - : _httpClient = httpClient ?? http.Client(); + : _httpClient = httpClient ?? http.Client(); @override - Future get(String url, - {Map? headers}) async { + Future get( + String url, { + Map? headers, + }) async { final req = http.Request('GET', Uri.parse(url)); if (headers != null) { req.headers.addAll(headers); diff --git a/flutter_cache_manager/lib/src/web/mime_converter.dart b/flutter_cache_manager/lib/src/web/mime_converter.dart index bae4911f..d73e772f 100644 --- a/flutter_cache_manager/lib/src/web/mime_converter.dart +++ b/flutter_cache_manager/lib/src/web/mime_converter.dart @@ -89,5 +89,5 @@ const mimeTypes = { 'video/ogg': '.ogv', 'video/webm': '.webm', 'video/x-msvideo': '.avi', - 'video/quicktime': '.mov' + 'video/quicktime': '.mov', }; diff --git a/flutter_cache_manager/lib/src/web/web_helper.dart b/flutter_cache_manager/lib/src/web/web_helper.dart index 20685484..126a2c8f 100644 --- a/flutter_cache_manager/lib/src/web/web_helper.dart +++ b/flutter_cache_manager/lib/src/web/web_helper.dart @@ -19,8 +19,8 @@ const statusCodesFileNotChanged = [HttpStatus.notModified]; class WebHelper { WebHelper(this._store, FileService? fileFetcher) - : _memCache = {}, - fileFetcher = fileFetcher ?? HttpFileService(); + : _memCache = {}, + fileFetcher = fileFetcher ?? HttpFileService(); final CacheStore _store; @visibleForTesting @@ -29,10 +29,12 @@ class WebHelper { final Queue _queue = Queue(); ///Download the file from the url - Stream downloadFile(String url, - {String? key, - Map? authHeaders, - bool ignoreMemCache = false}) { + Stream downloadFile( + String url, { + String? key, + Map? authHeaders, + bool ignoreMemCache = false, + }) { key ??= url; var subject = _memCache[key]; if (subject == null || ignoreMemCache) { @@ -56,13 +58,18 @@ class WebHelper { return; } cacheLogger.log( - 'CacheManager: Downloading $url', CacheManagerLogLevel.verbose); + 'CacheManager: Downloading $url', + CacheManagerLogLevel.verbose, + ); concurrentCalls++; final subject = _memCache[key]!; try { - await for (final result - in _updateFile(url, key, authHeaders: authHeaders)) { + await for (final result in _updateFile( + url, + key, + authHeaders: authHeaders, + )) { subject.add(result); } } on Object catch (e, stackTrace) { @@ -82,8 +89,11 @@ class WebHelper { } ///Download the file from the url - Stream _updateFile(String url, String key, - {Map? authHeaders}) async* { + Stream _updateFile( + String url, + String key, { + Map? authHeaders, + }) async* { var cacheObject = await _store.retrieveCacheData(key); cacheObject = cacheObject == null ? CacheObject( @@ -98,7 +108,9 @@ class WebHelper { } Future _download( - CacheObject cacheObject, Map? authHeaders) { + CacheObject cacheObject, + Map? authHeaders, + ) { final headers = {}; final etag = cacheObject.eTag; @@ -116,7 +128,9 @@ class WebHelper { } Stream _manageResponse( - CacheObject cacheObject, FileServiceResponse response) async* { + CacheObject cacheObject, + FileServiceResponse response, + ) async* { final hasNewFile = statusCodesNewFile.contains(response.statusCode); final keepOldFile = statusCodesFileNotChanged.contains(response.statusCode); if (!hasNewFile && !keepOldFile) { @@ -134,7 +148,10 @@ class WebHelper { await for (final progress in _saveFile(newCacheObject, response)) { savedBytes = progress; yield DownloadProgress( - cacheObject.url, response.contentLength, progress); + cacheObject.url, + response.contentLength, + progress, + ); } newCacheObject = newCacheObject.copyWith(length: savedBytes); } @@ -158,7 +175,9 @@ class WebHelper { } CacheObject _setDataFromHeaders( - CacheObject cacheObject, FileServiceResponse response) { + CacheObject cacheObject, + FileServiceResponse response, + ) { final fileExtension = response.fileExtension; var filePath = cacheObject.relativePath; @@ -188,19 +207,22 @@ class WebHelper { } Future _saveFileAndPostUpdates( - StreamController receivedBytesResultController, - CacheObject cacheObject, - FileServiceResponse response) async { + StreamController receivedBytesResultController, + CacheObject cacheObject, + FileServiceResponse response, + ) async { final file = await _store.fileSystem.createFile(cacheObject.relativePath); try { var receivedBytes = 0; final sink = file.openWrite(); - await response.content.map((s) { - receivedBytes += s.length; - receivedBytesResultController.add(receivedBytes); - return s; - }).pipe(sink); + await response.content + .map((s) { + receivedBytes += s.length; + receivedBytesResultController.add(receivedBytes); + return s; + }) + .pipe(sink); } on Object catch (e, stacktrace) { receivedBytesResultController.addError(e, stacktrace); } @@ -218,7 +240,7 @@ class WebHelper { class HttpExceptionWithStatus extends HttpException { const HttpExceptionWithStatus(this.statusCode, String message, {Uri? uri}) - : super(message, uri: uri); + : super(message, uri: uri); final int statusCode; } diff --git a/flutter_cache_manager/test/cache_manager_test.dart b/flutter_cache_manager/test/cache_manager_test.dart index c4be9381..95242aa0 100644 --- a/flutter_cache_manager/test/cache_manager_test.dart +++ b/flutter_cache_manager/test/cache_manager_test.dart @@ -150,13 +150,21 @@ void main() { when(store.getFile(fileUrl)).thenAnswer((_) => Future.value(cachedInfo)); var webHelper = MockWebHelper(); - var downloadedInfo = FileInfo(file, FileSource.Online, - DateTime.now().add(const Duration(days: 1)), fileUrl); - when(webHelper.downloadFile(fileUrl, key: anyNamed('key'))) - .thenAnswer((_) => Stream.value(downloadedInfo)); + var downloadedInfo = FileInfo( + file, + FileSource.Online, + DateTime.now().add(const Duration(days: 1)), + fileUrl, + ); + when( + webHelper.downloadFile(fileUrl, key: anyNamed('key')), + ).thenAnswer((_) => Stream.value(downloadedInfo)); - var cacheManager = TestCacheManager(createTestConfig(), - store: store, webHelper: webHelper); + var cacheManager = TestCacheManager( + createTestConfig(), + store: store, + webHelper: webHelper, + ); // ignore: deprecated_member_use_from_same_package var fileStream = cacheManager.getFile(fileUrl); @@ -177,8 +185,9 @@ void main() { when(store.getFile(fileUrl)).thenAnswer((_) => Future.value(null)); var webHelper = MockWebHelper(); - when(webHelper.downloadFile(fileUrl, key: anyNamed('key'))) - .thenAnswer((_) => Stream.value(fileInfo)); + when( + webHelper.downloadFile(fileUrl, key: anyNamed('key')), + ).thenAnswer((_) => Stream.value(fileInfo)); var cacheManager = TestCacheManager( createTestConfig(), @@ -199,10 +208,14 @@ void main() { when(store.getFile(fileUrl)).thenAnswer((_) => Future.value(null)); var webHelper = MockWebHelper(); - var error = HttpExceptionWithStatus(404, 'Invalid statusCode: 404', - uri: Uri.parse(fileUrl)); - when(webHelper.downloadFile(fileUrl, key: anyNamed('key'))) - .thenThrow(error); + var error = HttpExceptionWithStatus( + 404, + 'Invalid statusCode: 404', + uri: Uri.parse(fileUrl), + ); + when( + webHelper.downloadFile(fileUrl, key: anyNamed('key')), + ).thenThrow(error); var cacheManager = TestCacheManager( createTestConfig(), @@ -217,40 +230,54 @@ void main() { }); test( - 'Outdated cacheFile should call to web, where 404 response should add Error to Stream and evict cache', - () async { - var fileName = 'test.jpg'; - var fileUrl = 'baseflow.com/test'; - var validTill = DateTime.now().subtract(const Duration(days: 1)); - - var store = MockCacheStore(); - var file = await createTestConfig().fileSystem.createFile(fileName); - var cachedInfo = FileInfo(file, FileSource.Cache, validTill, fileUrl); - var cacheObject = CacheObject(fileUrl, - relativePath: file.path, validTill: validTill, id: 123); - when(store.getFile(fileUrl)).thenAnswer((_) => Future.value(cachedInfo)); - when(store.retrieveCacheData(fileUrl)) - .thenAnswer((_) => Future.value(cacheObject)); - - var webHelper = MockWebHelper(); - var error = HttpExceptionWithStatus(404, 'Invalid statusCode: 404', - uri: Uri.parse(fileUrl)); - when(webHelper.downloadFile(fileUrl, key: anyNamed('key'))) - .thenThrow(error); - - var cacheManager = TestCacheManager( - createTestConfig(), - store: store, - webHelper: webHelper, - ); - - // ignore: deprecated_member_use_from_same_package - var fileStream = cacheManager.getFile(fileUrl); - await expectLater( - fileStream, emitsInOrder([cachedInfo, emitsError(error)])); - verify(webHelper.downloadFile(any, key: anyNamed('key'))).called(1); - verify(store.removeCachedFile(cacheObject)).called(1); - }); + 'Outdated cacheFile should call to web, where 404 response should add Error to Stream and evict cache', + () async { + var fileName = 'test.jpg'; + var fileUrl = 'baseflow.com/test'; + var validTill = DateTime.now().subtract(const Duration(days: 1)); + + var store = MockCacheStore(); + var file = await createTestConfig().fileSystem.createFile(fileName); + var cachedInfo = FileInfo(file, FileSource.Cache, validTill, fileUrl); + var cacheObject = CacheObject( + fileUrl, + relativePath: file.path, + validTill: validTill, + id: 123, + ); + when( + store.getFile(fileUrl), + ).thenAnswer((_) => Future.value(cachedInfo)); + when( + store.retrieveCacheData(fileUrl), + ).thenAnswer((_) => Future.value(cacheObject)); + + var webHelper = MockWebHelper(); + var error = HttpExceptionWithStatus( + 404, + 'Invalid statusCode: 404', + uri: Uri.parse(fileUrl), + ); + when( + webHelper.downloadFile(fileUrl, key: anyNamed('key')), + ).thenThrow(error); + + var cacheManager = TestCacheManager( + createTestConfig(), + store: store, + webHelper: webHelper, + ); + + // ignore: deprecated_member_use_from_same_package + var fileStream = cacheManager.getFile(fileUrl); + await expectLater( + fileStream, + emitsInOrder([cachedInfo, emitsError(error)]), + ); + verify(webHelper.downloadFile(any, key: anyNamed('key'))).called(1); + verify(store.removeCachedFile(cacheObject)).called(1); + }, + ); }); group('explicit key', () { test('Valid cacheFile should not call to web', () async { @@ -314,8 +341,11 @@ void main() { var store = MockCacheStore(); var cacheManager = TestCacheManager(createTestConfig(), store: store); - var file = await cacheManager.putFile(fileUrl, fileBytes, - fileExtension: extension); + var file = await cacheManager.putFile( + fileUrl, + fileBytes, + fileExtension: extension, + ); expect(await file.exists(), true); expect(await file.readAsBytes(), fileBytes); verify(store.putFile(any)).called(1); @@ -330,8 +360,12 @@ void main() { var store = MockCacheStore(); var cacheManager = TestCacheManager(createTestConfig(), store: store); - var file = await cacheManager.putFile(fileUrl, fileBytes, - key: fileKey, fileExtension: extension); + var file = await cacheManager.putFile( + fileUrl, + fileBytes, + key: fileKey, + fileExtension: extension, + ); expect(await file.exists(), true); expect(await file.readAsBytes(), fileBytes); final arg = @@ -343,8 +377,8 @@ void main() { test('Check if file is written and info is stored', () async { var fileUrl = 'baseflow.com/test'; var extension = 'jpg'; - var memorySystem = - await MemoryFileSystem().systemTempDirectory.createTemp('origin'); + var memorySystem = await MemoryFileSystem().systemTempDirectory + .createTemp('origin'); var existingFile = memorySystem.childFile('testfile.jpg'); var fileBytes = Uint8List(16); @@ -354,8 +388,10 @@ void main() { var cacheManager = TestCacheManager(createTestConfig(), store: store); var file = await cacheManager.putFileStream( - fileUrl, existingFile.openRead(), - fileExtension: extension); + fileUrl, + existingFile.openRead(), + fileExtension: extension, + ); expect(await file.exists(), true); expect(await file.readAsBytes(), fileBytes); verify(store.putFile(any)).called(1); @@ -365,8 +401,8 @@ void main() { var fileUrl = 'baseflow.com/test'; var fileKey = 'test1234'; var extension = 'jpg'; - var memorySystem = - await MemoryFileSystem().systemTempDirectory.createTemp('origin'); + var memorySystem = await MemoryFileSystem().systemTempDirectory + .createTemp('origin'); var existingFile = memorySystem.childFile('testfile.jpg'); var fileBytes = Uint8List(16); @@ -376,8 +412,11 @@ void main() { var cacheManager = TestCacheManager(createTestConfig(), store: store); var file = await cacheManager.putFileStream( - fileUrl, existingFile.openRead(), - key: fileKey, fileExtension: extension); + fileUrl, + existingFile.openRead(), + key: fileKey, + fileExtension: extension, + ); expect(await file.exists(), true); expect(await file.readAsBytes(), fileBytes); final arg = @@ -392,13 +431,16 @@ void main() { var fileUrl = 'baseflow.com/test'; var store = MockCacheStore(); - when(store.retrieveCacheData(fileUrl)) - .thenAnswer((_) => Future.value(CacheObject( - fileUrl, - relativePath: 'test.png', - validTill: clock.now(), - id: 123, - ))); + when(store.retrieveCacheData(fileUrl)).thenAnswer( + (_) => Future.value( + CacheObject( + fileUrl, + relativePath: 'test.png', + validTill: clock.now(), + id: 123, + ), + ), + ); var cacheManager = TestCacheManager(createTestConfig(), store: store); @@ -410,8 +452,9 @@ void main() { var fileUrl = 'baseflow.com/test'; var store = MockCacheStore(); - when(store.retrieveCacheData(fileUrl)) - .thenAnswer((_) => Future.value(null)); + when( + store.retrieveCacheData(fileUrl), + ).thenAnswer((_) => Future.value(null)); var cacheManager = TestCacheManager(createTestConfig(), store: store); @@ -423,13 +466,16 @@ void main() { var fileUrl = 'baseflow.com/test'; var store = MockCacheStore(); - when(store.retrieveCacheData(fileUrl)) - .thenAnswer((_) => Future.value(CacheObject( - fileUrl, - relativePath: 'test.png', - validTill: clock.now(), - id: null, - ))); + when(store.retrieveCacheData(fileUrl)).thenAnswer( + (_) => Future.value( + CacheObject( + fileUrl, + relativePath: 'test.png', + validTill: clock.now(), + id: null, + ), + ), + ); var cacheManager = TestCacheManager(createTestConfig(), store: store); @@ -441,12 +487,17 @@ void main() { test('Download file just downloads file', () async { var fileUrl = 'baseflow.com/test'; - var fileInfo = FileInfo(MemoryFileSystem.test().file('f'), FileSource.Cache, - DateTime.now(), fileUrl); + var fileInfo = FileInfo( + MemoryFileSystem.test().file('f'), + FileSource.Cache, + DateTime.now(), + fileUrl, + ); var store = MockCacheStore(); var webHelper = MockWebHelper(); - when(webHelper.downloadFile(fileUrl, key: anyNamed('key'))) - .thenAnswer((_) => Stream.value(fileInfo)); + when( + webHelper.downloadFile(fileUrl, key: anyNamed('key')), + ).thenAnswer((_) => Stream.value(fileInfo)); var cacheManager = TestCacheManager( createTestConfig(), webHelper: webHelper, @@ -457,15 +508,23 @@ void main() { test('test file from memory', () async { var fileUrl = 'baseflow.com/test'; - var fileInfo = FileInfo(MemoryFileSystem.test().file('f'), FileSource.Cache, - DateTime.now(), fileUrl); + var fileInfo = FileInfo( + MemoryFileSystem.test().file('f'), + FileSource.Cache, + DateTime.now(), + fileUrl, + ); var store = MockCacheStore(); - when(store.getFileFromMemory(fileUrl)) - .thenAnswer((realInvocation) async => fileInfo); + when( + store.getFileFromMemory(fileUrl), + ).thenAnswer((realInvocation) async => fileInfo); var webHelper = MockWebHelper(); - var cacheManager = TestCacheManager(createTestConfig(), - store: store, webHelper: webHelper); + var cacheManager = TestCacheManager( + createTestConfig(), + store: store, + webHelper: webHelper, + ); var result = await cacheManager.getFileFromMemory(fileUrl); expect(result, fileInfo); }); @@ -484,15 +543,19 @@ void main() { var config = createTestConfig(); var fileService = config.fileService; var downloadStreamController = StreamController>(); - when(fileService.get(fileUrl, headers: anyNamed('headers'))) - .thenAnswer((_) { - return Future.value(MockFileFetcherResponse( + when(fileService.get(fileUrl, headers: anyNamed('headers'))).thenAnswer(( + _, + ) { + return Future.value( + MockFileFetcherResponse( downloadStreamController.stream, 6, 'testv1', '.jpg', 200, - DateTime.now())); + DateTime.now(), + ), + ); }); var cacheManager = TestCacheManager(config); @@ -505,15 +568,16 @@ void main() { downloadStreamController.add([5]); await downloadStreamController.close(); expect( - fileStream, - emitsInOrder([ - isA().having((p) => p.progress, '1/6', 1 / 6), - isA().having((p) => p.progress, '2/6', 2 / 6), - isA().having((p) => p.progress, '4/6', 4 / 6), - isA().having((p) => p.progress, '5/6', 5 / 6), - isA().having((p) => p.progress, '6/6', 1), - isA(), - ])); + fileStream, + emitsInOrder([ + isA().having((p) => p.progress, '1/6', 1 / 6), + isA().having((p) => p.progress, '2/6', 2 / 6), + isA().having((p) => p.progress, '4/6', 4 / 6), + isA().having((p) => p.progress, '5/6', 5 / 6), + isA().having((p) => p.progress, '6/6', 1), + isA(), + ]), + ); }); test("Don't get progress when not asked", () async { @@ -527,15 +591,19 @@ void main() { when(store.getFile(fileUrl)).thenAnswer((_) => Future.value(null)); var downloadStreamController = StreamController>(); - when(config.fileService.get(fileUrl, headers: anyNamed('headers'))) - .thenAnswer((_) { - return Future.value(MockFileFetcherResponse( + when( + config.fileService.get(fileUrl, headers: anyNamed('headers')), + ).thenAnswer((_) { + return Future.value( + MockFileFetcherResponse( downloadStreamController.stream, 6, 'testv1', '.jpg', 200, - DateTime.now())); + DateTime.now(), + ), + ); }); var cacheManager = TestCacheManager(config); @@ -549,20 +617,16 @@ void main() { await downloadStreamController.close(); // Only expect a FileInfo Result and no DownloadProgress status objects. - expect( - fileStream, - emitsInOrder([ - isA(), - ])); + expect(fileStream, emitsInOrder([isA()])); }); }); } class TestCacheManager extends CacheManager with ImageCacheManager { - TestCacheManager( - Config? config, { - CacheStore? store, - WebHelper? webHelper, - }) : super.custom(config ?? createTestConfig(), - cacheStore: store, webHelper: webHelper); + TestCacheManager(Config? config, {CacheStore? store, WebHelper? webHelper}) + : super.custom( + config ?? createTestConfig(), + cacheStore: store, + webHelper: webHelper, + ); } diff --git a/flutter_cache_manager/test/cache_object_test.dart b/flutter_cache_manager/test/cache_object_test.dart index d6d51c3c..7a96a6a1 100644 --- a/flutter_cache_manager/test/cache_object_test.dart +++ b/flutter_cache_manager/test/cache_object_test.dart @@ -54,7 +54,7 @@ void main() { columnPath: 'test.png', columnETag: 'test1', columnValidTill: validMillis, - columnTouched: now.millisecondsSinceEpoch + columnTouched: now.millisecondsSinceEpoch, }; var object = CacheObject.fromMap(map); expect(object.id, 3); @@ -73,7 +73,7 @@ void main() { columnPath: 'test.png', columnETag: 'test1', columnValidTill: validMillis, - columnTouched: now.millisecondsSinceEpoch + columnTouched: now.millisecondsSinceEpoch, }; var object = CacheObject.fromMap(map); expect(object.id, 3); diff --git a/flutter_cache_manager/test/cache_store_test.dart b/flutter_cache_manager/test/cache_store_test.dart index ddc693a9..412a35f1 100644 --- a/flutter_cache_manager/test/cache_store_test.dart +++ b/flutter_cache_manager/test/cache_store_test.dart @@ -57,8 +57,13 @@ void main() { test('Store should return null if file is not cached', () async { var config = createTestConfig(); await config.returnsFile(fileName); - config.returnsCacheObject(fileUrl, fileName, validTill, - id: fileId, key: fileUrl); + config.returnsCacheObject( + fileUrl, + fileName, + validTill, + id: fileId, + key: fileUrl, + ); var tempDir = createDir(); await (await tempDir).childFile('testimage.png').create(); @@ -70,21 +75,21 @@ void main() { store.removeCachedFile(cacheObject), ]); - expect( - () => results, - returnsNormally, - ); + expect(() => results, returnsNormally); }); test('Store should return null when file is no longer cached', () async { var repo = MockCacheInfoRepository(); - when(repo.get('baseflow.com/test.png')) - .thenAnswer((_) => Future.value(CacheObject( - 'baseflow.com/test.png', - relativePath: 'testimage.png', - validTill: clock.now().add(const Duration(days: 7)), - ))); + when(repo.get('baseflow.com/test.png')).thenAnswer( + (_) => Future.value( + CacheObject( + 'baseflow.com/test.png', + relativePath: 'testimage.png', + validTill: clock.now().add(const Duration(days: 7)), + ), + ), + ); var store = CacheStore(createTestConfig()); expect(await store.getFile('baseflow.com/test.png'), null); @@ -109,57 +114,61 @@ void main() { expect(cacheObject!.id, isNotNull); }); - test('Store should return CacheInfo from memory when asked twice', - () async { - var validTill = DateTime.now(); - var config = createTestConfig(); + test( + 'Store should return CacheInfo from memory when asked twice', + () async { + var validTill = DateTime.now(); + var config = createTestConfig(); - await config.returnsFile(fileName); - config.returnsCacheObject(fileUrl, fileName, validTill, id: 1); - var store = CacheStore(config); + await config.returnsFile(fileName); + config.returnsCacheObject(fileUrl, fileName, validTill, id: 1); + var store = CacheStore(config); - var result = await store.retrieveCacheData(fileUrl); - expect(result, isNotNull); - expect(result!.id, isNotNull); + var result = await store.retrieveCacheData(fileUrl); + expect(result, isNotNull); + expect(result!.id, isNotNull); - var otherResult = await store.retrieveCacheData(fileUrl); - expect(otherResult!.id, isNotNull); + var otherResult = await store.retrieveCacheData(fileUrl); + expect(otherResult!.id, isNotNull); - verify(config.mockRepo.get(any)).called(1); - }); + verify(config.mockRepo.get(any)).called(1); + }, + ); test( - 'Store should return File from memcache only when file is retrieved before', - () async { - var validTill = DateTime.now(); - var config = createTestConfig(); + 'Store should return File from memcache only when file is retrieved before', + () async { + var validTill = DateTime.now(); + var config = createTestConfig(); - await config.returnsFile(fileName); - config.returnsCacheObject(fileUrl, fileName, validTill); + await config.returnsFile(fileName); + config.returnsCacheObject(fileUrl, fileName, validTill); - var store = CacheStore(config); + var store = CacheStore(config); - expect(await store.getFileFromMemory(fileUrl), null); - await store.getFile(fileUrl); - expect(await store.getFileFromMemory(fileUrl), isNotNull); - }); + expect(await store.getFileFromMemory(fileUrl), null); + await store.getFile(fileUrl); + expect(await store.getFileFromMemory(fileUrl), isNotNull); + }, + ); test( - 'Store.memoryCacheContainsKey should return true if the key is present in the memory cache', - () async { - var config = createTestConfig(); - var store = CacheStore(config); - - var cacheObject = CacheObject( - 'baseflow.com/test.png', - relativePath: 'testimage.png', - validTill: clock.now().add(const Duration(days: 7)), - ); - await store.putFile(cacheObject); - - expect(store.memoryCacheContainsKey('baseflow.com/test.png'), true); - expect(store.memoryCacheContainsKey('unseen-file'), false); - }); + 'Store.memoryCacheContainsKey should return true if the key is present in the memory cache', + () async { + var config = createTestConfig(); + var store = CacheStore(config); + + var cacheObject = CacheObject( + 'baseflow.com/test.png', + relativePath: 'testimage.png', + validTill: clock.now().add(const Duration(days: 7)), + ); + await store.putFile(cacheObject); + + expect(store.memoryCacheContainsKey('baseflow.com/test.png'), true); + expect(store.memoryCacheContainsKey('unseen-file'), false); + }, + ); }); group('Storing files in store', () { @@ -178,29 +187,30 @@ void main() { }); test( - 'Store should store fileinfo in repo and id should be available afterwards', - () async { - var config = createTestConfig(); + 'Store should store fileinfo in repo and id should be available afterwards', + () async { + var config = createTestConfig(); - var cacheObject = CacheObject( - 'baseflow.com/test.png', - relativePath: 'testimage.png', - validTill: clock.now().add(const Duration(days: 7)), - ); + var cacheObject = CacheObject( + 'baseflow.com/test.png', + relativePath: 'testimage.png', + validTill: clock.now().add(const Duration(days: 7)), + ); - await config.returnsFile(cacheObject.relativePath); - when(config.mockRepo.updateOrInsert(cacheObject)).thenAnswer( - (realInvocation) async => cacheObject.copyWith(id: 1), - ); + await config.returnsFile(cacheObject.relativePath); + when( + config.mockRepo.updateOrInsert(cacheObject), + ).thenAnswer((realInvocation) async => cacheObject.copyWith(id: 1)); - var store = CacheStore(config); - await store.putFile(cacheObject); + var store = CacheStore(config); + await store.putFile(cacheObject); - verify(config.repo.updateOrInsert(cacheObject)).called(1); + verify(config.repo.updateOrInsert(cacheObject)).called(1); - final result = await store.retrieveCacheData(cacheObject.key); - expect(result!.id, isNotNull); - }); + final result = await store.retrieveCacheData(cacheObject.key); + expect(result!.id, isNotNull); + }, + ); }); group('Removing files in store', () { @@ -222,8 +232,9 @@ void main() { ); await store.removeCachedFile(cacheObject); - verify(config.mockRepo.deleteAll(argThat(contains(cacheObject.id)))) - .called(1); + verify( + config.mockRepo.deleteAll(argThat(contains(cacheObject.id))), + ).called(1); }); test('Store should remove file over capacity', () async { @@ -239,20 +250,24 @@ void main() { ); await config.returnsFile('testimage.png'); - when(config.mockRepo.getObjectsOverCapacity(any)) - .thenAnswer((_) => Future.value([cacheObject])); - when(config.mockRepo.getOldObjects(any)) - .thenAnswer((_) => Future.value([])); - when(config.mockRepo.get('baseflow.com/test.png')) - .thenAnswer((_) => Future.value(cacheObject)); + when( + config.mockRepo.getObjectsOverCapacity(any), + ).thenAnswer((_) => Future.value([cacheObject])); + when( + config.mockRepo.getOldObjects(any), + ).thenAnswer((_) => Future.value([])); + when( + config.mockRepo.get('baseflow.com/test.png'), + ).thenAnswer((_) => Future.value(cacheObject)); expect(await store.getFile('baseflow.com/test.png'), isNotNull); await untilCalled(config.mockRepo.deleteAll(any)); verify(config.mockRepo.getObjectsOverCapacity(any)).called(1); - verify(config.mockRepo.deleteAll(argThat(contains(cacheObject.id)))) - .called(1); + verify( + config.mockRepo.deleteAll(argThat(contains(cacheObject.id))), + ).called(1); }); test('Store should remove file over that are too old', () async { @@ -268,20 +283,24 @@ void main() { validTill: clock.now().add(const Duration(days: 7)), ); - when(config.mockRepo.getObjectsOverCapacity(any)) - .thenAnswer((_) => Future.value([])); - when(config.mockRepo.getOldObjects(any)) - .thenAnswer((_) => Future.value([cacheObject])); - when(config.mockRepo.get('baseflow.com/test.png')) - .thenAnswer((_) => Future.value(cacheObject)); + when( + config.mockRepo.getObjectsOverCapacity(any), + ).thenAnswer((_) => Future.value([])); + when( + config.mockRepo.getOldObjects(any), + ).thenAnswer((_) => Future.value([cacheObject])); + when( + config.mockRepo.get('baseflow.com/test.png'), + ).thenAnswer((_) => Future.value(cacheObject)); expect(await store.getFile('baseflow.com/test.png'), isNotNull); await untilCalled(config.mockRepo.deleteAll(any)); verify(config.mockRepo.getOldObjects(any)).called(1); - verify(config.mockRepo.deleteAll(argThat(contains(cacheObject.id)))) - .called(1); + verify( + config.mockRepo.deleteAll(argThat(contains(cacheObject.id))), + ).called(1); }); test('Store should remove file old and over capacity', () async { @@ -297,12 +316,15 @@ void main() { validTill: clock.now().add(const Duration(days: 7)), ); - when(config.mockRepo.getObjectsOverCapacity(any)) - .thenAnswer((_) => Future.value([cacheObject])); - when(config.mockRepo.getOldObjects(any)) - .thenAnswer((_) => Future.value([cacheObject])); - when(config.mockRepo.get('baseflow.com/test.png')) - .thenAnswer((_) => Future.value(cacheObject)); + when( + config.mockRepo.getObjectsOverCapacity(any), + ).thenAnswer((_) => Future.value([cacheObject])); + when( + config.mockRepo.getOldObjects(any), + ).thenAnswer((_) => Future.value([cacheObject])); + when( + config.mockRepo.get('baseflow.com/test.png'), + ).thenAnswer((_) => Future.value(cacheObject)); expect(await store.getFile('baseflow.com/test.png'), isNotNull); @@ -311,8 +333,9 @@ void main() { verify(config.mockRepo.getObjectsOverCapacity(any)).called(1); verify(config.mockRepo.getOldObjects(any)).called(1); - verify(config.mockRepo.deleteAll(argThat(contains(cacheObject.id)))) - .called(1); + verify( + config.mockRepo.deleteAll(argThat(contains(cacheObject.id))), + ).called(1); }); test('Store should recheck cache info when file is removed', () async { @@ -328,46 +351,56 @@ void main() { validTill: clock.now().add(const Duration(days: 7)), ); - when(config.mockRepo.getObjectsOverCapacity(any)) - .thenAnswer((_) => Future.value([])); - when(config.mockRepo.getOldObjects(any)) - .thenAnswer((_) => Future.value([])); - when(config.mockRepo.get('baseflow.com/test.png')) - .thenAnswer((_) => Future.value(cacheObject)); + when( + config.mockRepo.getObjectsOverCapacity(any), + ).thenAnswer((_) => Future.value([])); + when( + config.mockRepo.getOldObjects(any), + ).thenAnswer((_) => Future.value([])); + when( + config.mockRepo.get('baseflow.com/test.png'), + ).thenAnswer((_) => Future.value(cacheObject)); expect(await store.getFile('baseflow.com/test.png'), isNotNull); await file.delete(); expect(await store.getFile('baseflow.com/test.png'), isNull); }); - test('Store should not remove files that are not old or over capacity', - () async { - var config = createTestConfig(); - var store = CacheStore(config); - store.cleanupRunMinInterval = const Duration(milliseconds: 1); - await config.returnsFile('testimage.png'); - - var cacheObject = CacheObject( - 'baseflow.com/test.png', - relativePath: 'testimage.png', - id: 1, - validTill: clock.now().add(const Duration(days: 7)), - ); - - when(config.mockRepo.getObjectsOverCapacity(any)) - .thenAnswer((_) => Future.value([])); - when(config.mockRepo.getOldObjects(any)) - .thenAnswer((_) => Future.value([])); - when(config.mockRepo.get('baseflow.com/test.png')) - .thenAnswer((_) => Future.value(cacheObject)); - - expect(await store.getFile('baseflow.com/test.png'), isNotNull); - - await untilCalled(config.mockRepo.deleteAll(any)); - - verify(config.mockRepo.getOldObjects(any)).called(1); - verifyNever(config.mockRepo.deleteAll(argThat(contains(cacheObject.id)))); - }); + test( + 'Store should not remove files that are not old or over capacity', + () async { + var config = createTestConfig(); + var store = CacheStore(config); + store.cleanupRunMinInterval = const Duration(milliseconds: 1); + await config.returnsFile('testimage.png'); + + var cacheObject = CacheObject( + 'baseflow.com/test.png', + relativePath: 'testimage.png', + id: 1, + validTill: clock.now().add(const Duration(days: 7)), + ); + + when( + config.mockRepo.getObjectsOverCapacity(any), + ).thenAnswer((_) => Future.value([])); + when( + config.mockRepo.getOldObjects(any), + ).thenAnswer((_) => Future.value([])); + when( + config.mockRepo.get('baseflow.com/test.png'), + ).thenAnswer((_) => Future.value(cacheObject)); + + expect(await store.getFile('baseflow.com/test.png'), isNotNull); + + await untilCalled(config.mockRepo.deleteAll(any)); + + verify(config.mockRepo.getOldObjects(any)).called(1); + verifyNever( + config.mockRepo.deleteAll(argThat(contains(cacheObject.id))), + ); + }, + ); test('Store should remove all files when emptying cache', () async { var config = createTestConfig(); @@ -394,13 +427,17 @@ void main() { validTill: clock.now().add(const Duration(days: 7)), ); - when(config.mockRepo.getAllObjects()) - .thenAnswer((_) => Future.value([co1, co2, co3])); + when( + config.mockRepo.getAllObjects(), + ).thenAnswer((_) => Future.value([co1, co2, co3])); await store.emptyCache(); - verify(config.mockRepo - .deleteAll(argThat(containsAll([co1.id, co2.id, co3.id])))).called(1); + verify( + config.mockRepo.deleteAll( + argThat(containsAll([co1.id, co2.id, co3.id])), + ), + ).called(1); }); test('Store should delete file when remove cached file', () async { diff --git a/flutter_cache_manager/test/helpers/config_extensions.dart b/flutter_cache_manager/test/helpers/config_extensions.dart index e3d128dd..98f7bb5a 100644 --- a/flutter_cache_manager/test/helpers/config_extensions.dart +++ b/flutter_cache_manager/test/helpers/config_extensions.dart @@ -24,14 +24,15 @@ extension ConfigExtensions on Config { String? key, int? id, }) { - when(repo.get(key ?? fileUrl)) - .thenAnswer((realInvocation) async => CacheObject( - fileUrl, - relativePath: fileName, - validTill: validTill, - key: key ?? fileUrl, - id: id, - )); + when(repo.get(key ?? fileUrl)).thenAnswer( + (realInvocation) async => CacheObject( + fileUrl, + relativePath: fileName, + validTill: validTill, + key: key ?? fileUrl, + id: id, + ), + ); } void returnsNoCacheObject(String fileUrl) { @@ -40,9 +41,7 @@ extension ConfigExtensions on Config { void verifyNoDownloadCall() { verifyNoMoreInteractions(fileService); - verifyNever( - mockFileService.get(any, headers: anyNamed('headers')), - ); + verifyNever(mockFileService.get(any, headers: anyNamed('headers'))); verifyNever(mockFileService.get(any)); } diff --git a/flutter_cache_manager/test/helpers/json_repo_helpers.dart b/flutter_cache_manager/test/helpers/json_repo_helpers.dart index c275c0e9..d31ef552 100644 --- a/flutter_cache_manager/test/helpers/json_repo_helpers.dart +++ b/flutter_cache_manager/test/helpers/json_repo_helpers.dart @@ -15,8 +15,9 @@ const String testurl3 = 'www.baseflow.com/test3.png'; const String testurl4 = 'www.baseflow.com/test4.png'; class JsonRepoHelpers { - static Future createRepository( - {bool open = true}) async { + static Future createRepository({ + bool open = true, + }) async { var directory = await _createDirectory(); var file = await _createFile(directory); var repository = JsonCacheInfoRepository.withFile(file); @@ -25,8 +26,9 @@ class JsonRepoHelpers { } static Future _createDirectory() async { - var testDir = - await MemoryFileSystem().systemTempDirectory.createTemp('testFolder'); + var testDir = await MemoryFileSystem().systemTempDirectory.createTemp( + 'testFolder', + ); await testDir.create(recursive: true); return testDir; } diff --git a/flutter_cache_manager/test/helpers/mock_cache_info_repository.dart b/flutter_cache_manager/test/helpers/mock_cache_info_repository.dart index 1033de72..045205a5 100644 --- a/flutter_cache_manager/test/helpers/mock_cache_info_repository.dart +++ b/flutter_cache_manager/test/helpers/mock_cache_info_repository.dart @@ -11,20 +11,27 @@ class MockCacheInfoRepository extends MockCacheInfoRepositoryBase { when(provider.delete(any)).thenAnswer((_) => Future.value(0)); when(provider.deleteAll(any)).thenAnswer((_) => Future.value(0)); when(provider.get(any)).thenAnswer((_) => Future.value(null)); - when(provider.insert(any, setTouchedToNow: anyNamed('setTouchedToNow'))) - .thenAnswer((realInvocation) { + when( + provider.insert(any, setTouchedToNow: anyNamed('setTouchedToNow')), + ).thenAnswer((realInvocation) { return Future.value( - realInvocation.positionalArguments.first as CacheObject); + realInvocation.positionalArguments.first as CacheObject, + ); }); when(provider.open()).thenAnswer((_) => Future.value(true)); - when(provider.update(any, setTouchedToNow: anyNamed('setTouchedToNow'))) - .thenAnswer((realInvocation) => Future.value(0)); - when(provider.updateOrInsert(any)).thenAnswer((realInvocation) async => - Future.value(realInvocation.positionalArguments.first)); - when(provider.getObjectsOverCapacity(any)) - .thenAnswer((realInvocation) async => Future.value([])); - when(provider.getOldObjects(any)) - .thenAnswer((realInvocation) async => Future.value([])); + when( + provider.update(any, setTouchedToNow: anyNamed('setTouchedToNow')), + ).thenAnswer((realInvocation) => Future.value(0)); + when(provider.updateOrInsert(any)).thenAnswer( + (realInvocation) async => + Future.value(realInvocation.positionalArguments.first), + ); + when( + provider.getObjectsOverCapacity(any), + ).thenAnswer((realInvocation) async => Future.value([])); + when( + provider.getOldObjects(any), + ).thenAnswer((realInvocation) async => Future.value([])); return provider; } } diff --git a/flutter_cache_manager/test/helpers/mock_cache_store.dart b/flutter_cache_manager/test/helpers/mock_cache_store.dart index 5641c45d..0ea927f8 100644 --- a/flutter_cache_manager/test/helpers/mock_cache_store.dart +++ b/flutter_cache_manager/test/helpers/mock_cache_store.dart @@ -7,9 +7,9 @@ class MockCacheStore extends MockCacheStoreBase { factory MockCacheStore() { final store = MockCacheStore._(); - when(store.retrieveCacheData(any, - ignoreMemCache: anyNamed('ignoreMemCache'))) - .thenAnswer((_) => Future.value(null)); + when( + store.retrieveCacheData(any, ignoreMemCache: anyNamed('ignoreMemCache')), + ).thenAnswer((_) => Future.value(null)); return store; } } diff --git a/flutter_cache_manager/test/helpers/mock_file_fetcher_response.dart b/flutter_cache_manager/test/helpers/mock_file_fetcher_response.dart index 97e370fd..d2cb57e5 100644 --- a/flutter_cache_manager/test/helpers/mock_file_fetcher_response.dart +++ b/flutter_cache_manager/test/helpers/mock_file_fetcher_response.dart @@ -9,12 +9,24 @@ class MockFileFetcherResponse implements FileServiceResponse { final DateTime _validTill; factory MockFileFetcherResponse.basic() { - return MockFileFetcherResponse(Stream.value([0, 1, 2, 3, 4, 5]), 6, - 'testv1', '.jpg', 200, DateTime.now()); + return MockFileFetcherResponse( + Stream.value([0, 1, 2, 3, 4, 5]), + 6, + 'testv1', + '.jpg', + 200, + DateTime.now(), + ); } - MockFileFetcherResponse(this._content, this._contentLength, this._eTag, - this._fileExtension, this._statusCode, this._validTill); + MockFileFetcherResponse( + this._content, + this._contentLength, + this._eTag, + this._fileExtension, + this._statusCode, + this._validTill, + ); @override Stream> get content => _content; diff --git a/flutter_cache_manager/test/helpers/mock_file_service.dart b/flutter_cache_manager/test/helpers/mock_file_service.dart index 39ee0bf2..9c191dbf 100644 --- a/flutter_cache_manager/test/helpers/mock_file_service.dart +++ b/flutter_cache_manager/test/helpers/mock_file_service.dart @@ -13,8 +13,9 @@ class MockFileService extends MockFileServiceBase { var fileService = MockFileService._(); if (includeStandardResponse) { when(fileService.concurrentFetches).thenReturn(2); - when(fileService.get(any, headers: anyNamed('headers'))) - .thenAnswer((realInvocation) async { + when(fileService.get(any, headers: anyNamed('headers'))).thenAnswer(( + realInvocation, + ) async { return TestResponse(); }); } diff --git a/flutter_cache_manager/test/helpers/test_configuration.dart b/flutter_cache_manager/test/helpers/test_configuration.dart index 151fbd2a..64379633 100644 --- a/flutter_cache_manager/test/helpers/test_configuration.dart +++ b/flutter_cache_manager/test/helpers/test_configuration.dart @@ -16,8 +16,9 @@ Config createTestConfig() { } class TestFileSystem extends FileSystem { - final directoryFuture = - MemoryFileSystem().systemTempDirectory.createTemp('test'); + final directoryFuture = MemoryFileSystem().systemTempDirectory.createTemp( + 'test', + ); @override Future createFile(String name) async { diff --git a/flutter_cache_manager/test/http_file_fetcher_test.dart b/flutter_cache_manager/test/http_file_fetcher_test.dart index 4cdc6d27..34f81d0b 100644 --- a/flutter_cache_manager/test/http_file_fetcher_test.dart +++ b/flutter_cache_manager/test/http_file_fetcher_test.dart @@ -17,11 +17,15 @@ void main() { var maxAge = const Duration(hours: 2); var client = MockClient((request) async { - return Response.bytes(Uint8List(contentLength), 200, headers: { - 'etag': 'test', - 'content-type': contentType, - 'cache-control': 'max-age=${maxAge.inSeconds}' - }); + return Response.bytes( + Uint8List(contentLength), + 200, + headers: { + 'etag': 'test', + 'content-type': contentType, + 'cache-control': 'max-age=${maxAge.inSeconds}', + }, + ); }); await withClock(Clock.fixed(DateTime.now()), () async { @@ -42,8 +46,11 @@ void main() { var contentType = 'unknown/$fileExtension'; var client = MockClient((request) async { - return Response.bytes(Uint8List(16), 200, - headers: {'content-type': contentType}); + return Response.bytes( + Uint8List(16), + 200, + headers: {'content-type': contentType}, + ); }); var httpFileFetcher = HttpFileService(httpClient: client); @@ -57,8 +64,11 @@ void main() { var contentType = 'audio/mpeg;chartset=UTF-8'; var client = MockClient((request) async { - return Response.bytes(Uint8List(16), 200, - headers: {'content-type': contentType}); + return Response.bytes( + Uint8List(16), + 200, + headers: {'content-type': contentType}, + ); }); var httpFileFetcher = HttpFileService(httpClient: client); @@ -75,15 +85,21 @@ void main() { var maxAge = const Duration(hours: 2); var client = MockClient((request) async { - return Response.bytes(Uint8List(contentLength), 200, headers: { - 'etag': 'test', - 'content-type': contentType, - 'cache-control': 'max-age=${maxAge.inSeconds}' - }); + return Response.bytes( + Uint8List(contentLength), + 200, + headers: { + 'etag': 'test', + 'content-type': contentType, + 'cache-control': 'max-age=${maxAge.inSeconds}', + }, + ); }); - Future defaultHttpGetter(String url, - {Map? headers}) async { + Future defaultHttpGetter( + String url, { + Map? headers, + }) async { var httpResponse = await client.get(Uri.parse(url), headers: headers); return HttpFileFetcherResponse(httpResponse); } diff --git a/flutter_cache_manager/test/image_cache_manager_test.dart b/flutter_cache_manager/test/image_cache_manager_test.dart index f3701d5d..ce8ec599 100644 --- a/flutter_cache_manager/test/image_cache_manager_test.dart +++ b/flutter_cache_manager/test/image_cache_manager_test.dart @@ -28,55 +28,57 @@ void main() { await verifySize(bytes, 120, 120); }); - test('File should not be modified when no height or width is given', - () async { - var cacheManager = await setupCacheManager(); - var result = await cacheManager.getImageFile(fileUrl).last as FileInfo; - var image = await result.file.readAsBytes(); - await verifySize(image, 120, 120); - }); + test( + 'File should not be modified when no height or width is given', + () async { + var cacheManager = await setupCacheManager(); + var result = await cacheManager.getImageFile(fileUrl).last as FileInfo; + var image = await result.file.readAsBytes(); + await verifySize(image, 120, 120); + }, + ); test('File should not be modified when height is given', () async { var cacheManager = await setupCacheManager(); - var result = await cacheManager - .getImageFile( - fileUrl, - maxHeight: 100, - ) - .last as FileInfo; + var result = + await cacheManager.getImageFile(fileUrl, maxHeight: 100).last + as FileInfo; var image = await result.file.readAsBytes(); await verifySize(image, 100, 100); }); test('File should not be modified when width is given', () async { var cacheManager = await setupCacheManager(); - var result = await cacheManager - .getImageFile( - fileUrl, - maxWidth: 100, - ) - .last as FileInfo; + var result = + await cacheManager.getImageFile(fileUrl, maxWidth: 100).last + as FileInfo; var image = await result.file.readAsBytes(); await verifySize(image, 100, 100); }); - test('File should keep aspect ratio when both height and width are given', - () async { - var cacheManager = await setupCacheManager(); - var result = await cacheManager - .getImageFile(fileUrl, maxWidth: 100, maxHeight: 80) - .last as FileInfo; - var image = await result.file.readAsBytes(); - await verifySize(image, 80, 80); - }); + test( + 'File should keep aspect ratio when both height and width are given', + () async { + var cacheManager = await setupCacheManager(); + var result = + await cacheManager + .getImageFile(fileUrl, maxWidth: 100, maxHeight: 80) + .last + as FileInfo; + var image = await result.file.readAsBytes(); + await verifySize(image, 80, 80); + }, + ); }); group('Test resized image caching', () { test('Resized image should be fetched from cache', () async { var config = await setupConfig(cacheKey: 'resized_w100_h80_$fileUrl'); var cacheManager = TestCacheManager(config); - var result = await cacheManager - .getImageFile(fileUrl, maxWidth: 100, maxHeight: 80) - .last as FileInfo; + var result = + await cacheManager + .getImageFile(fileUrl, maxWidth: 100, maxHeight: 80) + .last + as FileInfo; expect(result, isNotNull); config.verifyNoDownloadCall(); @@ -84,15 +86,13 @@ void main() { test('Unsized image should be fetched from cache', () async { var config = await setupConfig(); - config.returnsCacheObject( - fileUrl, - fileName, - validTill, - ); + config.returnsCacheObject(fileUrl, fileName, validTill); var cacheManager = TestCacheManager(config); - var result = await cacheManager - .getImageFile(fileUrl, maxWidth: 100, maxHeight: 80) - .last as FileInfo; + var result = + await cacheManager + .getImageFile(fileUrl, maxWidth: 100, maxHeight: 80) + .last + as FileInfo; expect(result, isNotNull); config.verifyNoDownloadCall(); @@ -101,9 +101,11 @@ void main() { test('Wrongly sized image should not be fetched from cache', () async { var config = await setupConfig(cacheKey: 'resized_w100_h150_$fileUrl'); var cacheManager = TestCacheManager(config); - var result = await cacheManager - .getImageFile(fileUrl, maxWidth: 100, maxHeight: 80) - .last as FileInfo; + var result = + await cacheManager + .getImageFile(fileUrl, maxWidth: 100, maxHeight: 80) + .last + as FileInfo; expect(result, isNotNull); config.verifyDownloadCall(); diff --git a/flutter_cache_manager/test/repositories/json_file_repository_test.dart b/flutter_cache_manager/test/repositories/json_file_repository_test.dart index 0e6e1dba..941738f5 100644 --- a/flutter_cache_manager/test/repositories/json_file_repository_test.dart +++ b/flutter_cache_manager/test/repositories/json_file_repository_test.dart @@ -19,15 +19,15 @@ void main() { expect(repository, isNotNull); }); - test('Create repository with path and databaseName throws assertion error', - () { - expect( - () => JsonCacheInfoRepository( - path: path, - databaseName: databaseName, - ), - throwsAssertionError); - }); + test( + 'Create repository with path and databaseName throws assertion error', + () { + expect( + () => JsonCacheInfoRepository(path: path, databaseName: databaseName), + throwsAssertionError, + ); + }, + ); test('Create repository with directory is successful', () { var repository = JsonCacheInfoRepository.withFile(File(path)); @@ -122,8 +122,9 @@ void main() { expect(insertedObject.touched, isNotNull); var allObjects = await repo.getAllObjects(); - var newObject = - allObjects.where((element) => element.id == insertedObject.id); + var newObject = allObjects.where( + (element) => element.id == insertedObject.id, + ); expect(newObject, isNotNull); }); @@ -162,15 +163,17 @@ void main() { test('updateOrInsert inserts new item', () async { var repo = await JsonRepoHelpers.createRepository(); var objectToInsert = JsonRepoHelpers.extraCacheObject; - var insertedObject = - await repo.updateOrInsert(JsonRepoHelpers.extraCacheObject); + var insertedObject = await repo.updateOrInsert( + JsonRepoHelpers.extraCacheObject, + ); expect(insertedObject.id, JsonRepoHelpers.startCacheObjects.length + 1); expect(insertedObject.url, objectToInsert.url); expect(insertedObject.touched, isNotNull); var allObjects = await repo.getAllObjects(); - var newObject = - allObjects.where((element) => element.id == insertedObject.id); + var newObject = allObjects.where( + (element) => element.id == insertedObject.id, + ); expect(newObject, isNotNull); }); }); @@ -193,11 +196,14 @@ void main() { var deleted = await repo.deleteAll(removedIds); expect(deleted, 2); var objects = await repo.getAllObjects(); - var removedObject = - objects.where((element) => removedIds.contains(element.id)); + var removedObject = objects.where( + (element) => removedIds.contains(element.id), + ); expect(removedObject.length, 0); - expect(objects.length, - JsonRepoHelpers.startCacheObjects.length - removedIds.length); + expect( + objects.length, + JsonRepoHelpers.startCacheObjects.length - removedIds.length, + ); }); test('delete does not remove non-existing items', () async { @@ -219,8 +225,10 @@ void main() { await repo.open(); var allObjectsAfterOpen = await repo.getAllObjects(); - expect(allObjectsAfterOpen.length, - JsonRepoHelpers.startCacheObjects.length + 1); + expect( + allObjectsAfterOpen.length, + JsonRepoHelpers.startCacheObjects.length + 1, + ); }); }); } diff --git a/flutter_cache_manager/test/repositories/migration_test.dart b/flutter_cache_manager/test/repositories/migration_test.dart index a4330775..3c7ed7bb 100644 --- a/flutter_cache_manager/test/repositories/migration_test.dart +++ b/flutter_cache_manager/test/repositories/migration_test.dart @@ -56,8 +56,10 @@ MockCacheInfoRepository setupMockRepo(bool returnObjects) { ); return Future.value(cacheObject); }); - when(mockRepo.insert(any)).thenAnswer((realInvocation) => - Future.value(realInvocation.positionalArguments.first as CacheObject)); + when(mockRepo.insert(any)).thenAnswer( + (realInvocation) => + Future.value(realInvocation.positionalArguments.first as CacheObject), + ); return mockRepo; } @@ -77,7 +79,8 @@ class CacheObjectMatcher extends Matcher { bool matches(item, Map matchState) { var isMatch = false; if (item is CacheObject) { - isMatch = item.key == value.key && + isMatch = + item.key == value.key && item.url == value.url && item.relativePath == value.relativePath && item.length == value.length && diff --git a/flutter_cache_manager/test/web_helper_test.dart b/flutter_cache_manager/test/web_helper_test.dart index 661ac5ea..07075600 100644 --- a/flutter_cache_manager/test/web_helper_test.dart +++ b/flutter_cache_manager/test/web_helper_test.dart @@ -22,15 +22,19 @@ void main() { var store = CacheStore(config); final fileService = MockFileService(); - when(fileService.get(imageUrl, headers: anyNamed('headers'))) - .thenAnswer((_) { - return Future.value(MockFileFetcherResponse( + when(fileService.get(imageUrl, headers: anyNamed('headers'))).thenAnswer(( + _, + ) { + return Future.value( + MockFileFetcherResponse( Stream.value([0, 1, 2, 3, 4, 5]), 0, 'testv1', '.jpg', 200, - DateTime.now())); + DateTime.now(), + ), + ); }); var webHelper = WebHelper(store, fileService); @@ -47,18 +51,29 @@ void main() { var store = CacheStore(config); final fileService = MockFileService(); - when(fileService.get(imageUrl, headers: anyNamed('headers'))) - .thenAnswer((_) { - return Future.value(MockFileFetcherResponse( - Stream.value([]), 0, null, '', 404, DateTime.now())); + when(fileService.get(imageUrl, headers: anyNamed('headers'))).thenAnswer(( + _, + ) { + return Future.value( + MockFileFetcherResponse( + Stream.value([]), + 0, + null, + '', + 404, + DateTime.now(), + ), + ); }); var webHelper = WebHelper(store, fileService); expect( - () async => webHelper.downloadFile(imageUrl).toList(), - throwsA(predicate( - (e) => e is HttpExceptionWithStatus && e.statusCode == 404))); + () async => webHelper.downloadFile(imageUrl).toList(), + throwsA( + predicate((e) => e is HttpExceptionWithStatus && e.statusCode == 404), + ), + ); }); test('304 ignores content', () async { @@ -68,10 +83,19 @@ void main() { var store = CacheStore(config); final fileService = MockFileService(); - when(fileService.get(imageUrl, headers: anyNamed('headers'))) - .thenAnswer((_) { - return Future.value(MockFileFetcherResponse( - Stream.value([]), 0, 'testv1', '.jpg', 304, DateTime.now())); + when(fileService.get(imageUrl, headers: anyNamed('headers'))).thenAnswer(( + _, + ) { + return Future.value( + MockFileFetcherResponse( + Stream.value([]), + 0, + 'testv1', + '.jpg', + 304, + DateTime.now(), + ), + ); }); var webHelper = WebHelper(store, fileService); @@ -90,15 +114,19 @@ void main() { var store = _createStore(config); final fileService = MockFileService(); - when(fileService.get(imageUrl, headers: anyNamed('headers'))) - .thenAnswer((_) { - return Future.value(MockFileFetcherResponse( + when(fileService.get(imageUrl, headers: anyNamed('headers'))).thenAnswer(( + _, + ) { + return Future.value( + MockFileFetcherResponse( Stream.value([0, 1, 2, 3, 4, 5]), 6, 'testv1', '.jpg', 200, - DateTime.now())); + DateTime.now(), + ), + ); }); var webHelper = WebHelper(store, fileService); @@ -110,33 +138,40 @@ void main() { verify(store.retrieveCacheData(any)).called(1); }); - test('Calling webhelper twice excecutes twice when memcache ignored', - () async { - const imageUrl = 'baseflow.com/testimage'; - - var config = createTestConfig(); - var store = _createStore(config); - - final fileService = MockFileService(); - when(fileService.get(imageUrl, headers: anyNamed('headers'))) - .thenAnswer((_) { - return Future.value(MockFileFetcherResponse( - Stream.value([0, 1, 2, 3, 4, 5]), - 6, - 'testv1', - '.jpg', - 200, - DateTime.now())); - }); - - var webHelper = WebHelper(store, fileService); - var call1 = webHelper.downloadFile(imageUrl).toList(); - var call2 = - webHelper.downloadFile(imageUrl, ignoreMemCache: true).toList(); - await Future.wait([call1, call2]); - - verify(store.retrieveCacheData(any)).called(2); - }); + test( + 'Calling webhelper twice excecutes twice when memcache ignored', + () async { + const imageUrl = 'baseflow.com/testimage'; + + var config = createTestConfig(); + var store = _createStore(config); + + final fileService = MockFileService(); + when( + fileService.get(imageUrl, headers: anyNamed('headers')), + ).thenAnswer((_) { + return Future.value( + MockFileFetcherResponse( + Stream.value([0, 1, 2, 3, 4, 5]), + 6, + 'testv1', + '.jpg', + 200, + DateTime.now(), + ), + ); + }); + + var webHelper = WebHelper(store, fileService); + var call1 = webHelper.downloadFile(imageUrl).toList(); + var call2 = webHelper + .downloadFile(imageUrl, ignoreMemCache: true) + .toList(); + await Future.wait([call1, call2]); + + verify(store.retrieveCacheData(any)).called(2); + }, + ); test('No more concurrent calls than defined in fileService', () async { const url1 = 'baseflow.com/testimage1'; @@ -151,12 +186,15 @@ void main() { var completer2 = Completer(); var completer3 = Completer(); - when(fileService.get(url1, headers: anyNamed('headers'))) - .thenAnswer((realInvocation) => completer1.future); - when(fileService.get(url2, headers: anyNamed('headers'))) - .thenAnswer((realInvocation) => completer2.future); - when(fileService.get(url3, headers: anyNamed('headers'))) - .thenAnswer((realInvocation) => completer3.future); + when( + fileService.get(url1, headers: anyNamed('headers')), + ).thenAnswer((realInvocation) => completer1.future); + when( + fileService.get(url2, headers: anyNamed('headers')), + ).thenAnswer((realInvocation) => completer2.future); + when( + fileService.get(url3, headers: anyNamed('headers')), + ).thenAnswer((realInvocation) => completer3.future); var webHelper = WebHelper(store, fileService); webHelper.downloadFile(url1); @@ -187,15 +225,19 @@ void main() { config.returnsCacheObject(imageUrl, fileName, validTill); final fileService = MockFileService(); - when(fileService.get(imageUrl, headers: anyNamed('headers'))) - .thenAnswer((_) { - return Future.value(MockFileFetcherResponse( + when(fileService.get(imageUrl, headers: anyNamed('headers'))).thenAnswer(( + _, + ) { + return Future.value( + MockFileFetcherResponse( Stream.value([0, 1, 2, 3, 4, 5]), 6, 'testv1', '.jpg', 200, - DateTime.now())); + DateTime.now(), + ), + ); }); var webHelper = WebHelper(store, fileService); @@ -230,12 +272,15 @@ void main() { MockCacheStore _createStore(Config config) { final store = MockCacheStore(); when(store.putFile(argThat(anything))).thenAnswer((_) => Future.value()); - when(store.retrieveCacheData(argThat(anything))) - .thenAnswer((invocation) => Future.value(CacheObject( - invocation.positionalArguments.first as String, - relativePath: 'test.png', - validTill: clock.now().add(const Duration(days: 7)), - ))); + when(store.retrieveCacheData(argThat(anything))).thenAnswer( + (invocation) => Future.value( + CacheObject( + invocation.positionalArguments.first as String, + relativePath: 'test.png', + validTill: clock.now().add(const Duration(days: 7)), + ), + ), + ); when(store.fileSystem).thenReturn(config.fileSystem); return store; } From 3aa1dec5d00f60cede31c7fa056e71f560c16954 Mon Sep 17 00:00:00 2001 From: Rick van Dijk Date: Mon, 20 Jul 2026 14:24:01 -0600 Subject: [PATCH 7/7] Added links to PR's --- flutter_cache_manager/CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flutter_cache_manager/CHANGELOG.md b/flutter_cache_manager/CHANGELOG.md index 90b5238e..5e1dbcec 100644 --- a/flutter_cache_manager/CHANGELOG.md +++ b/flutter_cache_manager/CHANGELOG.md @@ -1,9 +1,9 @@ ## [Unreleased] -* Raise minimum Dart SDK to 3.8.0 and update dependencies -* Update example Android project for Flutter 3.44 (Gradle 9.1 / AGP 9.0.1 / Kotlin 2.3.20, Java 17) -* Migrate example Android app to built-in Kotlin -* Migrate example iOS app from CocoaPods to Swift Package Manager +* Raise minimum Dart SDK to 3.8.0 and update dependencies ([#512](https://github.com/Baseflow/flutter_cache_manager/pull/512)) +* Update example Android project for Flutter 3.44 (Gradle 9.1 / AGP 9.0.1 / Kotlin 2.3.20, Java 17) ([#510](https://github.com/Baseflow/flutter_cache_manager/pull/510)) +* Migrate example Android app to built-in Kotlin ([#510](https://github.com/Baseflow/flutter_cache_manager/pull/510)) +* Migrate example iOS app from CocoaPods to Swift Package Manager ([#511](https://github.com/Baseflow/flutter_cache_manager/pull/511)) ## [3.4.1] - 2024-08-13