Skip to content

Commit

Permalink
Applied patch from @Nolence mattreid1#38. Also added quick and dirty …
Browse files Browse the repository at this point in the history
…try/catch in CacheManager.get() with Reference toMap issue.
  • Loading branch information
jessejajit committed Apr 29, 2021
1 parent ec5fc9f commit 2b5ec0a
Show file tree
Hide file tree
Showing 6 changed files with 388 additions and 56 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## [1.0.1+1] 12/03/2021
* Fixes [#37] "Operand of null-aware operation '!' has type 'String' which excludes null."
* Switches to strong-mode which includes no implicity casts and no implicit-dynamics.
* Removes several force unwraps (!) thus handling nullable values better

## [1.0.1] 12/03/2021
* Formatted code according to `dartfmt`

Expand Down
60 changes: 35 additions & 25 deletions lib/src/cache_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:firebase_image/firebase_image.dart';
import 'package:firebase_image/src/firebase_image.dart';
import 'package:firebase_image/src/image_object.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/foundation.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
Expand All @@ -26,7 +27,7 @@ class FirebaseImageCacheManager {

Future<void> open() async {
db = await openDatabase(
join((await getDatabasesPath())!, dbName),
join((await getDatabasesPath()), dbName),
onCreate: (Database db, int version) async {
await db.execute('''
CREATE TABLE $table (
Expand Down Expand Up @@ -73,7 +74,7 @@ class FirebaseImageCacheManager {
where: 'uri = ?',
whereArgs: [object.uri],
);
return maps.length > 0;
return maps.isNotEmpty;
}

Future<FirebaseImageObject?> get(String uri, FirebaseImage image) async {
Expand All @@ -88,33 +89,38 @@ class FirebaseImageCacheManager {
where: 'uri = ?',
whereArgs: [uri],
);
if (maps.length > 0) {
FirebaseImageObject returnObject =
FirebaseImageObject.fromMap(maps.first);
returnObject.reference = getImageRef(returnObject, image.firebaseApp);
if (CacheRefreshStrategy.BY_METADATA_DATE == this.cacheRefreshStrategy) {
checkForUpdate(returnObject, image); // Check for update in background
print(maps.first);
if (maps.isNotEmpty) {
try {
final returnObject = FirebaseImageObject.fromMap(maps.first);
returnObject.reference = getImageRef(returnObject, image.firebaseApp);
if (CacheRefreshStrategy.BY_METADATA_DATE == cacheRefreshStrategy) {
await checkForUpdate(
returnObject, image); // Check for update in background
}
return returnObject;
} catch (e) {
return null;
}
return returnObject;
}
return null;
}

Reference getImageRef(FirebaseImageObject object, FirebaseApp? firebaseApp) {
FirebaseStorage storage =
final storage =
FirebaseStorage.instanceFor(app: firebaseApp, bucket: object.bucket);
return storage.ref().child(object.remotePath);
}

Future<void> checkForUpdate(
FirebaseImageObject object, FirebaseImage image) async {
int remoteVersion = (await object.reference.getMetadata())
final remoteVersion = (await object.reference.getMetadata())
.updated
?.millisecondsSinceEpoch ??
-1;
if (remoteVersion != object.version) {
// If true, download new image for next load
await this.upsertRemoteFileToCache(object, image.maxSizeBytes);
await upsertRemoteFileToCache(object, image.maxSizeBytes);
}
}

Expand All @@ -134,8 +140,10 @@ class FirebaseImageCacheManager {
}

Future<Uint8List?> localFileBytes(FirebaseImageObject? object) async {
if (await _fileExists(object)) {
return File(object!.localPath!).readAsBytes();
final localPath = object?.localPath;
if (localPath == null) return null;
if (await _fileExists(localPath)) {
return File(localPath).readAsBytes();
}
return null;
}
Expand All @@ -147,33 +155,35 @@ class FirebaseImageCacheManager {

Future<Uint8List?> upsertRemoteFileToCache(
FirebaseImageObject object, int maxSizeBytes) async {
if (CacheRefreshStrategy.BY_METADATA_DATE == this.cacheRefreshStrategy) {
if (CacheRefreshStrategy.BY_METADATA_DATE == cacheRefreshStrategy) {
object.version = (await object.reference.getMetadata())
.updated
?.millisecondsSinceEpoch ??
0;
}
Uint8List? bytes = await remoteFileBytes(object, maxSizeBytes);
await putFile(object, bytes);
final bytes = await remoteFileBytes(object, maxSizeBytes);

if (bytes != null) {
debugPrint('Bytes of object ${object.remotePath} could not be fetched');
await putFile(object, bytes);
}

return bytes;
}

Future<FirebaseImageObject> putFile(
FirebaseImageObject object, final bytes) async {
String path = basePath + "/" + object.remotePath;
path = path.replaceAll("//", "/");
FirebaseImageObject object, List<int> bytes) async {
var path = basePath + '/' + object.remotePath;
path = path.replaceAll('//', '/');
//print(join(basePath, object.remotePath)); Join isn't working?
final localFile = await File(path).create(recursive: true);
await localFile.writeAsBytes(bytes);
object.localPath = localFile.path;
return await upsert(object);
}

Future<bool> _fileExists(FirebaseImageObject? object) async {
if (object?.localPath == null) {
return false;
}
return File(object!.localPath!).exists();
Future<bool> _fileExists(String localPath) async {
return File(localPath).exists();
}

Future<String> _createFilePath() async {
Expand Down
29 changes: 11 additions & 18 deletions lib/src/firebase_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,35 +65,29 @@ class FirebaseImage extends ImageProvider<FirebaseImage> {
}

static Reference _getImageRef(String location, FirebaseApp? firebaseApp) {
FirebaseStorage storage = FirebaseStorage.instanceFor(
final storage = FirebaseStorage.instanceFor(
app: firebaseApp, bucket: _getBucket(location));
return storage.ref().child(_getImagePath(location));
}

Future<Uint8List> _fetchImage() async {
Uint8List? bytes;
FirebaseImageCacheManager cacheManager = FirebaseImageCacheManager(
cacheRefreshStrategy,
);
final cacheManager = FirebaseImageCacheManager(cacheRefreshStrategy);

if (shouldCache) {
await cacheManager.open();
FirebaseImageObject? localObject =
await cacheManager.get(_imageObject.uri, this);
final localObject = await cacheManager.get(_imageObject.uri, this);

if (localObject != null) {
bytes = await cacheManager.localFileBytes(localObject);
if (bytes == null) {
bytes = await cacheManager.upsertRemoteFileToCache(
_imageObject, this.maxSizeBytes);
}
bytes ??= await cacheManager.upsertRemoteFileToCache(
_imageObject, maxSizeBytes);
} else {
bytes = await cacheManager.upsertRemoteFileToCache(
_imageObject, this.maxSizeBytes);
_imageObject, maxSizeBytes);
}
} else {
bytes =
await cacheManager.remoteFileBytes(_imageObject, this.maxSizeBytes);
bytes = await cacheManager.remoteFileBytes(_imageObject, maxSizeBytes);
}

return bytes!;
Expand All @@ -120,15 +114,14 @@ class FirebaseImage extends ImageProvider<FirebaseImage> {
@override
bool operator ==(dynamic other) {
if (other.runtimeType != runtimeType) return false;
final FirebaseImage typedOther = other;
final typedOther = other as FirebaseImage;
return _imageObject.uri == typedOther._imageObject.uri &&
this.scale == typedOther.scale;
scale == typedOther.scale;
}

@override
int get hashCode => hashValues(_imageObject.uri, this.scale);
int get hashCode => hashValues(_imageObject.uri, scale);

@override
String toString() =>
'$runtimeType("${_imageObject.uri}", scale: ${this.scale})';
String toString() => '$runtimeType("${_imageObject.uri}", scale: $scale)';
}
22 changes: 11 additions & 11 deletions lib/src/image_object.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,22 @@ class FirebaseImageObject {
}) : uri = '$bucket$remotePath';

Map<String, dynamic> toMap() {
return {
'version': this.version,
'localPath': this.localPath,
'bucket': this.bucket,
'remotePath': this.remotePath,
'uri': this.uri,
return <String, dynamic>{
'version': version,
'localPath': localPath,
'bucket': bucket,
'remotePath': remotePath,
'uri': uri,
};
}

factory FirebaseImageObject.fromMap(Map<String, dynamic> map) {
return FirebaseImageObject(
version: map["version"] ?? -1,
reference: map["reference"],
localPath: map["localPath"],
bucket: map["bucket"],
remotePath: map["remotePath"],
version: map['version'] as int? ?? -1,
reference: map['reference'] as Reference,
localPath: map['localPath'] as String?,
bucket: map['bucket'] as String,
remotePath: map['remotePath'] as String,
);
}
}
Loading

0 comments on commit 2b5ec0a

Please sign in to comment.