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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion flutter_cache_manager/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ void main() {
CacheManager.logLevel = CacheManagerLogLevel.verbose;
}

const url = 'https://picsum.photos/200/300';
const url = 'https://i.imgur.com/7j7W5eq.jpeg';

/// Example [Widget] showing the functionalities of flutter_cache_manager
class CacheManagerPage extends StatefulWidget {
Expand Down
228 changes: 228 additions & 0 deletions flutter_cache_manager/example/lib/test_indexeddb.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import 'package:flutter/material.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';

/// Simple test app to verify IndexedDB caching works on Flutter web
/// Run with: flutter run -d chrome lib/test_indexeddb.dart
void main() {
// Enable verbose logging to see caching in action
CacheManager.logLevel = CacheManagerLogLevel.verbose;
runApp(const IndexedDBTestApp());
}

class IndexedDBTestApp extends MaterialApp {
const IndexedDBTestApp({super.key})
: super(
home: const IndexedDBTestPage(),
title: 'IndexedDB Cache Test',
);
}

class IndexedDBTestPage extends StatefulWidget {
const IndexedDBTestPage({super.key});

@override
State<IndexedDBTestPage> createState() => _IndexedDBTestPageState();
}

class _IndexedDBTestPageState extends State<IndexedDBTestPage> {
// Using a reliable CDN image that supports CORS
final String testUrl = 'https://i.imgur.com/7j7W5eq.jpeg';
String status = 'Ready';
FileInfo? cachedFile;
bool isLoading = false;

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('IndexedDB Cache Test'),
backgroundColor: Colors.blue,
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Text(
'Flutter Cache Manager - IndexedDB Test',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
const SizedBox(height: 32),
if (cachedFile != null) ...[
Container(
width: 400,
height: 300,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
),
child: Image.network(
testUrl,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return const Center(
child: Text('Failed to load image'),
);
},
),
),
const SizedBox(height: 16),
Text(
'Source: ${cachedFile!.source.name}',
style: TextStyle(
color: cachedFile!.source == FileSource.Cache
? Colors.green
: Colors.orange,
fontWeight: FontWeight.bold,
),
),
Text('Valid until: ${cachedFile!.validTill}'),
],
const SizedBox(height: 32),
Text(
status,
style: const TextStyle(fontSize: 16),
textAlign: TextAlign.center,
),
const SizedBox(height: 32),
if (isLoading) const CircularProgressIndicator(),
if (!isLoading) ...[
ElevatedButton.icon(
onPressed: _downloadFile,
icon: const Icon(Icons.download),
label: const Text('Download & Cache Image'),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 16,
),
),
),
const SizedBox(height: 16),
ElevatedButton.icon(
onPressed: _loadFromCache,
icon: const Icon(Icons.cached),
label: const Text('Load from Cache'),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 16,
),
),
),
const SizedBox(height: 16),
ElevatedButton.icon(
onPressed: _clearCache,
icon: const Icon(Icons.delete),
label: const Text('Clear Cache'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 16,
),
),
),
],
const SizedBox(height: 32),
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.blue.shade50,
borderRadius: BorderRadius.circular(8),
),
child: const Text(
'💡 Test Instructions:\n'
'1. Click "Download & Cache Image" - should show source: Online\n'
'2. Refresh the page (F5)\n'
'3. Click "Load from Cache" - should show source: Cache\n'
'4. Open DevTools → Application → IndexedDB to see stored data',
style: TextStyle(fontSize: 14),
),
),
],
),
),
),
);
}

Future<void> _downloadFile() async {
setState(() {
isLoading = true;
status = 'Downloading image...';
});

try {
final info = await DefaultCacheManager().getFileFromCache(testUrl);

setState(() {
cachedFile = info;
isLoading = false;
status =
'Image downloaded and cached! Source: ${info?.source.name ?? "Unknown"}';
});
} catch (e) {
setState(() {
isLoading = false;
status = 'Error: $e';
});
}
}

Future<void> _loadFromCache() async {
setState(() {
isLoading = true;
status = 'Loading from cache...';
});

try {
final info = await DefaultCacheManager().getFileFromCache(testUrl);

if (info == null) {
setState(() {
isLoading = false;
status = 'No cached file found. Download first!';
cachedFile = null;
});
return;
}

setState(() {
cachedFile = info;
isLoading = false;
status = 'Loaded from cache! Source: ${info.source.name}';
});
} catch (e) {
setState(() {
isLoading = false;
status = 'Error loading from cache: $e';
});
}
}

Future<void> _clearCache() async {
setState(() {
isLoading = true;
status = 'Clearing cache...';
});

try {
await DefaultCacheManager().emptyCache();

setState(() {
cachedFile = null;
isLoading = false;
status = 'Cache cleared!';
});
} catch (e) {
setState(() {
isLoading = false;
status = 'Error clearing cache: $e';
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import FlutterMacOS
import Foundation

import path_provider_foundation
import sqflite
import sqflite_darwin
import url_launcher_macos

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
Expand Down
4 changes: 2 additions & 2 deletions flutter_cache_manager/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ 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.6.0 <4.0.0"

dependencies:
baseflow_plugin_template: ^2.2.0
Expand All @@ -17,7 +17,7 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^4.0.0
flutter_lints: ^6.0.0

flutter:
uses-material-design: true
3 changes: 1 addition & 2 deletions flutter_cache_manager/lib/flutter_cache_manager.dart
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -10,6 +10,5 @@ export 'src/logger.dart';
export 'src/result/result.dart';
export 'src/storage/cache_info_repositories/cache_info_repositories.dart';
export 'src/storage/cache_object.dart';
export 'src/storage/file_system/file_system.dart';
export 'src/web/file_service.dart';
export 'src/web/web_helper.dart' show HttpExceptionWithStatus;
5 changes: 4 additions & 1 deletion flutter_cache_manager/lib/src/cache_store.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import 'dart:async';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';

import 'storage/file_system/file_system.dart';

///Flutter Cache Manager
///Copyright (c) 2019 Rene Floor
///Released under MIT License.
Expand Down Expand Up @@ -185,7 +188,7 @@ class CacheStore {
}
final file = await fileSystem.createFile(cacheObject.relativePath);

if (file.existsSync()) {
if (kIsWeb ? await file.exists() : file.existsSync()) {
try {
await file.delete();
// ignore: unused_catch_clause
Expand Down
2 changes: 2 additions & 0 deletions flutter_cache_manager/lib/src/config/_config_io.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import 'dart:io';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:flutter_cache_manager/src/config/config.dart' as def;

import '../storage/file_system/file_system.dart';

class Config implements def.Config {
Config(
this.cacheKey, {
Expand Down
13 changes: 8 additions & 5 deletions flutter_cache_manager/lib/src/config/_config_web.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:flutter_cache_manager/src/config/config.dart' as def;
import 'package:flutter_cache_manager/src/storage/cache_info_repositories/cache_info_repository.dart';
import 'package:flutter_cache_manager/src/storage/cache_info_repositories/non_storing_object_provider.dart';
import 'package:flutter_cache_manager/src/storage/cache_info_repositories/indexed_db_cache_info_repository.dart';
import 'package:flutter_cache_manager/src/storage/file_system/file_system.dart';
import 'package:flutter_cache_manager/src/web/file_service.dart';
import 'package:flutter_cache_manager/src/storage/file_system/indexed_db_file_system.dart';

class Config implements def.Config {
Config(
Expand All @@ -14,8 +14,11 @@ class Config implements def.Config {
FileService? fileService,
}) : stalePeriod = stalePeriod ?? const Duration(days: 30),
maxNrOfCacheObjects = maxNrOfCacheObjects ?? 200,
repo = repo ?? NonStoringObjectProvider(),
fileSystem = fileSystem ?? MemoryCacheSystem(),
repo = repo ??
IndexedDbCacheInfoRepository(
databaseName: 'flutter_cache_manager_$cacheKey'),
fileSystem = fileSystem ??
IndexedDbFileSystem('flutter_cache_manager_$cacheKey'),
fileService = fileService ?? HttpFileService();

@override
Expand Down
2 changes: 2 additions & 0 deletions flutter_cache_manager/lib/src/config/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ 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;

import '../storage/file_system/file_system.dart';

abstract class Config {
/// Config file for the CacheManager.
/// [cacheKey] is used for the folder to store files and for the database
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@ export 'cache_info_repository.dart';
export 'cache_object_provider.dart';
export 'json_cache_info_repository.dart';
export 'non_storing_object_provider.dart';

// Note: indexed_db_cache_info_repository.dart is web-only and not exported here
// to avoid dart:js_interop import errors on non-web platforms.
// Web code should import it directly when needed.
Loading
Loading