This commit is contained in:
vishnukvmd 2022-11-28 13:30:37 +05:30
parent 1417ceac5a
commit 4d09bff81e
8 changed files with 160 additions and 101 deletions

View file

@ -321,7 +321,7 @@ SPEC CHECKSUMS:
FirebaseInstallations: 0a115432c4e223c5ab20b0dbbe4cbefa793a0e8e
FirebaseMessaging: 732623518591384f61c287e3d8f65294beb7ffb3
fk_user_agent: 1f47ec39291e8372b1d692b50084b0d54103c545
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_email_sender: 02d7443217d8c41483223627972bfdc09f74276b
flutter_image_compress: 5a5e9aee05b6553048b8df1c3bc456d0afaac433
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721

View file

@ -5,7 +5,7 @@ import 'package:photos/core/constants.dart';
import 'package:photos/models/ente_file.dart';
class ThumbnailLruCache {
static final LRUMap<String, Uint8List?> _map = LRUMap(1000);
static final LRUMap<String, Uint8List?> _map = LRUMap(250);
static Uint8List? get(EnteFile enteFile, [int? size]) {
return _map.get(

View file

@ -5,8 +5,8 @@ import 'dart:math';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:local_hero/local_hero.dart';
import 'package:logging/logging.dart';
import 'package:photos/core/constants.dart';
import 'package:photos/core/event_bus.dart';
@ -33,6 +33,7 @@ class LazyLoadingGallery extends StatefulWidget {
final String tag;
final String logTag;
final Stream<int> currentIndexStream;
final int imagesPerRow;
LazyLoadingGallery(
this.files,
@ -44,6 +45,7 @@ class LazyLoadingGallery extends StatefulWidget {
this.tag,
this.currentIndexStream, {
this.logTag = "",
this.imagesPerRow,
Key key,
}) : super(key: key ?? UniqueKey());
@ -251,6 +253,7 @@ class _LazyLoadingGalleryState extends State<LazyLoadingGallery> {
_files.length > kRecycleLimit,
_toggleSelectAllFromDay,
_areAllFromDaySelected,
widget.imagesPerRow,
),
);
}
@ -278,6 +281,7 @@ class LazyLoadingGridView extends StatefulWidget {
final bool shouldRecycle;
final ValueNotifier toggleSelectAllFromDay;
final ValueNotifier areAllFilesSelected;
final int imagesPerRow;
LazyLoadingGridView(
this.tag,
@ -287,7 +291,8 @@ class LazyLoadingGridView extends StatefulWidget {
this.shouldRender,
this.shouldRecycle,
this.toggleSelectAllFromDay,
this.areAllFilesSelected, {
this.areAllFilesSelected,
this.imagesPerRow, {
Key key,
}) : super(key: key ?? UniqueKey());
@ -383,10 +388,10 @@ class _LazyLoadingGridViewState extends State<LazyLoadingGridView> {
return _buildFile(context, widget.filesInDay[index]);
},
itemCount: widget.filesInDay.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisSpacing: 2,
mainAxisSpacing: 2,
crossAxisCount: 4,
crossAxisCount: widget.imagesPerRow ?? 4,
),
padding: const EdgeInsets.all(0),
);
@ -405,8 +410,8 @@ class _LazyLoadingGridViewState extends State<LazyLoadingGridView> {
HapticFeedback.lightImpact();
_selectFile(file);
},
child: ClipRRect(
borderRadius: BorderRadius.circular(1),
child: LocalHero(
tag: widget.tag + file.tag,
child: Stack(
children: [
Hero(

View file

@ -179,7 +179,6 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
_loadNetworkImage();
} else {
if (await doesLocalFileExist(widget.file) == false) {
_logger.info("Deleting file " + widget.file.tag);
FilesDB.instance.deleteLocalFile(widget.file);
Bus.instance.fire(
LocalPhotosUpdatedEvent(
@ -197,7 +196,6 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
final imageProvider = Image.memory(thumbData).image;
_cacheAndRender(imageProvider);
}
ThumbnailLruCache.put(widget.file, thumbData, thumbnailSmallSize);
}).catchError((e) {
_logger.warning("Could not load image: ", e);
_errorLoadingLocalThumbnail = true;

View file

@ -3,7 +3,9 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:local_hero/local_hero.dart';
import 'package:logging/logging.dart';
import 'package:photos/core/constants.dart';
import 'package:photos/core/event_bus.dart';
@ -203,76 +205,118 @@ class _GalleryState extends State<Gallery> {
return _getListView();
}
int _imagesPerRow = 4;
ScaleUpdateDetails _lastScaleUpdateDetails;
Widget _getListView() {
return HugeListView<List<File>>(
key: _hugeListViewKey,
controller: _itemScroller,
startIndex: 0,
totalCount: _collatedFiles.length,
isDraggableScrollbarEnabled: _collatedFiles.length > 10,
waitBuilder: (_) {
return const EnteLoadingWidget();
},
emptyResultBuilder: (_) {
final List<Widget> children = [];
if (widget.header != null) {
children.add(widget.header);
}
children.add(
Expanded(
child: widget.emptyState,
),
);
if (widget.footer != null) {
children.add(widget.footer);
}
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: children,
);
},
itemBuilder: (context, index) {
Widget gallery;
gallery = LazyLoadingGallery(
_collatedFiles[index],
index,
widget.reloadEvent,
widget.removalEventTypes,
widget.asyncLoader,
widget.selectedFiles,
widget.tagPrefix,
Bus.instance
.on<GalleryIndexUpdatedEvent>()
.where((event) => event.tag == widget.tagPrefix)
.map((event) => event.index),
logTag: _logTag,
);
if (widget.header != null && index == 0) {
gallery = Column(children: [widget.header, gallery]);
}
if (widget.footer != null && index == _collatedFiles.length - 1) {
gallery = Column(children: [gallery, widget.footer]);
}
return gallery;
},
labelTextBuilder: (int index) {
return getMonthAndYear(
DateTime.fromMicrosecondsSinceEpoch(
_collatedFiles[index][0].creationTime,
),
);
},
thumbBackgroundColor:
Theme.of(context).colorScheme.galleryThumbBackgroundColor,
thumbDrawColor: Theme.of(context).colorScheme.galleryThumbDrawColor,
thumbPadding: widget.header != null
? const EdgeInsets.only(top: 60)
: const EdgeInsets.all(0),
bottomSafeArea: widget.scrollBottomSafeArea,
firstShown: (int firstIndex) {
Bus.instance
.fire(GalleryIndexUpdatedEvent(widget.tagPrefix, firstIndex));
},
return LocalHeroScope(
duration: const Duration(milliseconds: 100),
child:
RawGestureDetector(
gestures: {
AllowMultipleGestureRecognizer: GestureRecognizerFactoryWithHandlers<
AllowMultipleGestureRecognizer>(
() => AllowMultipleGestureRecognizer(), //constructor
(AllowMultipleGestureRecognizer instance) {
instance.onUpdate = (details) {
if (details.pointerCount == 2) {
_lastScaleUpdateDetails = details;
}
};
instance.onEnd = (details) {
if (_lastScaleUpdateDetails != null) {
if (_lastScaleUpdateDetails.verticalScale > 1 &&
_lastScaleUpdateDetails.horizontalScale > 1) {
_logger.info("zoomed in");
if (_imagesPerRow > 2) {
_imagesPerRow--;
}
} else if (_lastScaleUpdateDetails.verticalScale < 1 &&
_lastScaleUpdateDetails.horizontalScale < 1) {
_logger.info("zoomed out");
if (_imagesPerRow < 4) {
_imagesPerRow++;
}
}
_lastScaleUpdateDetails = null;
setState(() {});
}
};
},
)
},
child: HugeListView<List<File>>(
key: _hugeListViewKey,
controller: _itemScroller,
startIndex: 0,
totalCount: _collatedFiles.length,
isDraggableScrollbarEnabled: _collatedFiles.length > 10,
waitBuilder: (_) {
return const EnteLoadingWidget();
},
emptyResultBuilder: (_) {
final List<Widget> children = [];
if (widget.header != null) {
children.add(widget.header);
}
children.add(
Expanded(
child: widget.emptyState,
),
);
if (widget.footer != null) {
children.add(widget.footer);
}
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: children,
);
},
itemBuilder: (context, index) {
Widget gallery;
gallery = LazyLoadingGallery(
_collatedFiles[index],
index,
widget.reloadEvent,
widget.removalEventTypes,
widget.asyncLoader,
widget.selectedFiles,
widget.tagPrefix,
Bus.instance
.on<GalleryIndexUpdatedEvent>()
.where((event) => event.tag == widget.tagPrefix)
.map((event) => event.index),
logTag: _logTag,
imagesPerRow: _imagesPerRow,
);
if (widget.header != null && index == 0) {
gallery = Column(children: [widget.header, gallery]);
}
if (widget.footer != null && index == _collatedFiles.length - 1) {
gallery = Column(children: [gallery, widget.footer]);
}
return gallery;
},
labelTextBuilder: (int index) {
return getMonthAndYear(
DateTime.fromMicrosecondsSinceEpoch(
_collatedFiles[index][0].creationTime,
),
);
},
thumbBackgroundColor:
Theme.of(context).colorScheme.galleryThumbBackgroundColor,
thumbDrawColor: Theme.of(context).colorScheme.galleryThumbDrawColor,
thumbPadding: widget.header != null
? const EdgeInsets.only(top: 60)
: const EdgeInsets.all(0),
bottomSafeArea: widget.scrollBottomSafeArea,
firstShown: (int firstIndex) {
Bus.instance
.fire(GalleryIndexUpdatedEvent(widget.tagPrefix, firstIndex));
},
),
),
);
}
@ -315,3 +359,14 @@ class GalleryIndexUpdatedEvent {
GalleryIndexUpdatedEvent(this.tag, this.index);
}
// Custom Gesture Recognizer.
// rejectGesture() is overridden. When a gesture is rejected, this is the function that is called. By default, it disposes of the
// Recognizer and runs clean up. However we modified it so that instead the Recognizer is disposed of, it is actually manually added.
// The result is instead you have one Recognizer winning the Arena, you have two. It is a win-win.
class AllowMultipleGestureRecognizer extends ScaleGestureRecognizer {
@override
void rejectGesture(int pointer) {
acceptGesture(pointer);
}
}

View file

@ -62,7 +62,7 @@ Future<Uint8List> getThumbnailFromServer(File file) async {
Future<Uint8List> getThumbnailFromLocal(
File file, {
int size = thumbnailSmallSize,
int size = thumbnailLargeSize,
int quality = thumbnailQuality,
}) async {
final lruCachedThumbnail = ThumbnailLruCache.get(file, size);

View file

@ -49,7 +49,7 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.2"
version: "2.9.0"
background_fetch:
dependency: "direct main"
description:
@ -98,14 +98,7 @@ packages:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
version: "1.2.1"
chewie:
dependency: "direct main"
description:
@ -119,7 +112,7 @@ packages:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
collection:
dependency: "direct main"
description:
@ -308,7 +301,7 @@ packages:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
version: "1.3.1"
fast_base58:
dependency: "direct main"
description:
@ -742,6 +735,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.11"
local_hero:
dependency: "direct main"
description:
name: local_hero
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
logging:
dependency: "direct main"
description:
@ -762,14 +762,14 @@ packages:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.11"
version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.4"
version: "0.1.5"
media_extension:
dependency: "direct main"
description:
@ -785,7 +785,7 @@ packages:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
version: "1.8.0"
mime:
dependency: transitive
description:
@ -913,7 +913,7 @@ packages:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.1"
version: "1.8.2"
path_drawing:
dependency: transitive
description:
@ -1254,7 +1254,7 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.2"
version: "1.9.0"
sprintf:
dependency: transitive
description:
@ -1310,7 +1310,7 @@ packages:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
syncfusion_flutter_core:
dependency: "direct main"
description:
@ -1338,28 +1338,28 @@ packages:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.2.1"
test:
dependency: "direct dev"
description:
name: test
url: "https://pub.dartlang.org"
source: hosted
version: "1.21.1"
version: "1.21.4"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.9"
version: "0.4.12"
test_core:
dependency: transitive
description:
name: test_core
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.13"
version: "0.4.16"
timezone:
dependency: transitive
description:

View file

@ -75,6 +75,7 @@ dependencies:
like_button: ^2.0.2
loading_animations: ^2.1.0
local_auth: ^1.1.5
local_hero: ^0.2.0
logging: ^1.0.1
lottie: ^1.2.2
media_extension: