Merge f5093ddf63
into bcf3084d97
This commit is contained in:
commit
283315b683
5 changed files with 113 additions and 10 deletions
|
@ -5,9 +5,11 @@ import 'package:flutter/material.dart';
|
|||
import 'package:photos/ente_theme_data.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import "package:photos/models/api/collection/user.dart";
|
||||
import "package:photos/models/file/file.dart";
|
||||
import 'package:photos/models/file/trash_file.dart';
|
||||
import 'package:photos/theme/colors.dart';
|
||||
import 'package:photos/ui/sharing/user_avator_widget.dart';
|
||||
import "package:photos/utils/data_util.dart";
|
||||
|
||||
class ThumbnailPlaceHolder extends StatelessWidget {
|
||||
const ThumbnailPlaceHolder({Key? key}) : super(key: key);
|
||||
|
@ -143,15 +145,38 @@ class OwnerAvatarOverlayIcon extends StatelessWidget {
|
|||
|
||||
class TrashedFileOverlayText extends StatelessWidget {
|
||||
final TrashFile file;
|
||||
|
||||
const TrashedFileOverlayText(this.file, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final int daysLeft =
|
||||
((file.deleteBy - DateTime.now().microsecondsSinceEpoch) /
|
||||
Duration.microsecondsPerDay)
|
||||
.ceil();
|
||||
final text = S.of(context).trashDaysLeft(daysLeft);
|
||||
return FileOverlayText(text);
|
||||
}
|
||||
}
|
||||
|
||||
class FileSizeOverlayText extends StatelessWidget {
|
||||
final EnteFile file;
|
||||
const FileSizeOverlayText(this.file, {Key? key}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (file.fileSize == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
final text = convertBytesToReadableFormat(file.fileSize!);
|
||||
return FileOverlayText(text);
|
||||
}
|
||||
}
|
||||
|
||||
class FileOverlayText extends StatelessWidget {
|
||||
final String text;
|
||||
|
||||
const FileOverlayText(this.text, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
|
@ -163,7 +188,7 @@ class TrashedFileOverlayText extends StatelessWidget {
|
|||
alignment: Alignment.bottomCenter,
|
||||
padding: const EdgeInsets.only(bottom: 5),
|
||||
child: Text(
|
||||
S.of(context).trashDaysLeft(daysLeft),
|
||||
text,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleSmall!
|
||||
|
|
|
@ -18,6 +18,8 @@ import 'package:photos/models/file/trash_file.dart';
|
|||
import 'package:photos/services/collections_service.dart';
|
||||
import 'package:photos/services/favorites_service.dart';
|
||||
import 'package:photos/ui/viewer/file/file_icons_widget.dart';
|
||||
import "package:photos/ui/viewer/gallery/component/group/type.dart";
|
||||
import "package:photos/ui/viewer/gallery/state/gallery_context_state.dart";
|
||||
import 'package:photos/utils/file_util.dart';
|
||||
import 'package:photos/utils/thumbnail_util.dart';
|
||||
|
||||
|
@ -178,6 +180,8 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
|
|||
|
||||
if (widget.file.isTrash) {
|
||||
viewChildren.add(TrashedFileOverlayText(widget.file as TrashFile));
|
||||
} else if (GalleryContextState.of(context)?.type == GroupType.size) {
|
||||
viewChildren.add(FileSizeOverlayText(widget.file));
|
||||
}
|
||||
// todo: Move this icon overlay to the collection widget.
|
||||
if (widget.shouldShowArchiveStatus) {
|
||||
|
|
|
@ -5,7 +5,14 @@ import "package:photos/generated/l10n.dart";
|
|||
import "package:photos/models/file/file.dart";
|
||||
import "package:photos/utils/date_time_util.dart";
|
||||
|
||||
enum GroupType { day, week, month, size, year }
|
||||
enum GroupType {
|
||||
day,
|
||||
week,
|
||||
month,
|
||||
size,
|
||||
year,
|
||||
none,
|
||||
}
|
||||
|
||||
extension GroupTypeExtension on GroupType {
|
||||
String get name {
|
||||
|
@ -20,9 +27,25 @@ extension GroupTypeExtension on GroupType {
|
|||
return "size";
|
||||
case GroupType.year:
|
||||
return "year";
|
||||
case GroupType.none:
|
||||
return "none";
|
||||
}
|
||||
}
|
||||
|
||||
bool timeGrouping() {
|
||||
return this == GroupType.day ||
|
||||
this == GroupType.week ||
|
||||
this == GroupType.month ||
|
||||
this == GroupType.year;
|
||||
}
|
||||
|
||||
bool showGroupHeader() {
|
||||
if (this == GroupType.size || this == GroupType.none) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
String getTitle(BuildContext context, EnteFile file, {EnteFile? lastFile}) {
|
||||
if (this == GroupType.day) {
|
||||
return _getDayTitle(context, file.creationTime!);
|
||||
|
@ -41,7 +64,7 @@ extension GroupTypeExtension on GroupType {
|
|||
return DateFormat.yMMM(Localizations.localeOf(context).languageCode)
|
||||
.format(date);
|
||||
} else {
|
||||
throw UnimplementedError("not implemented for $this");
|
||||
throw UnimplementedError("getTitle not implemented for $this");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,10 @@ import "package:photos/models/selected_files.dart";
|
|||
import "package:photos/ui/common/loading_widget.dart";
|
||||
import "package:photos/ui/huge_listview/huge_listview.dart";
|
||||
import 'package:photos/ui/viewer/gallery/component/group/lazy_group_gallery.dart';
|
||||
import "package:photos/ui/viewer/gallery/component/group/type.dart";
|
||||
import "package:photos/ui/viewer/gallery/gallery.dart";
|
||||
import "package:photos/ui/viewer/gallery/state/gallery_context_state.dart";
|
||||
import "package:photos/utils/data_util.dart";
|
||||
import "package:photos/utils/local_settings.dart";
|
||||
import "package:scrollable_positioned_list/scrollable_positioned_list.dart";
|
||||
|
||||
|
@ -65,6 +68,7 @@ class MultipleGroupsGalleryView extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final gType = GalleryContextState.of(context)!.type;
|
||||
return HugeListView<List<EnteFile>>(
|
||||
controller: itemScroller,
|
||||
startIndex: 0,
|
||||
|
@ -123,10 +127,17 @@ class MultipleGroupsGalleryView extends StatelessWidget {
|
|||
},
|
||||
labelTextBuilder: (int index) {
|
||||
try {
|
||||
final EnteFile file = groupedFiles[index][0];
|
||||
if (gType == GroupType.size) {
|
||||
return file.fileSize != null
|
||||
? convertBytesToReadableFormat(file.fileSize!)
|
||||
: "";
|
||||
}
|
||||
|
||||
return DateFormat.yMMM(Localizations.localeOf(context).languageCode)
|
||||
.format(
|
||||
DateTime.fromMicrosecondsSinceEpoch(
|
||||
groupedFiles[index][0].creationTime!,
|
||||
file.creationTime!,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
|
|
|
@ -214,7 +214,9 @@ class GalleryState extends State<Gallery> {
|
|||
// gallery reload
|
||||
bool _onFilesLoaded(List<EnteFile> files) {
|
||||
final updatedGroupedFiles =
|
||||
widget.enableFileGrouping ? _groupFiles(files) : [files];
|
||||
widget.enableFileGrouping && widget.groupType.timeGrouping()
|
||||
? _groupBasedOnTime(files)
|
||||
: _genericGroupForPerf(files);
|
||||
if (currentGroupedFiles.length != updatedGroupedFiles.length ||
|
||||
currentGroupedFiles.isEmpty) {
|
||||
if (mounted) {
|
||||
|
@ -261,20 +263,58 @@ class GalleryState extends State<Gallery> {
|
|||
tagPrefix: widget.tagPrefix,
|
||||
scrollBottomSafeArea: widget.scrollBottomSafeArea,
|
||||
limitSelectionToOne: widget.limitSelectionToOne,
|
||||
enableFileGrouping: widget.enableFileGrouping,
|
||||
enableFileGrouping:
|
||||
widget.enableFileGrouping && widget.groupType.showGroupHeader(),
|
||||
logTag: _logTag,
|
||||
logger: _logger,
|
||||
reloadEvent: widget.reloadEvent,
|
||||
header: widget.header,
|
||||
footer: widget.footer,
|
||||
selectedFiles: widget.selectedFiles,
|
||||
showSelectAllByDefault: widget.showSelectAllByDefault,
|
||||
showSelectAllByDefault:
|
||||
widget.showSelectAllByDefault && widget.groupType.showGroupHeader(),
|
||||
isScrollablePositionedList: widget.isScrollablePositionedList,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<List<EnteFile>> _groupFiles(List<EnteFile> files) {
|
||||
// create groups of 200 files for performance
|
||||
List<List<EnteFile>> _genericGroupForPerf(List<EnteFile> files) {
|
||||
if (widget.groupType == GroupType.size) {
|
||||
// sort files by fileSize on the bases of _sortOrderAsc
|
||||
files.sort((a, b) {
|
||||
if (_sortOrderAsc) {
|
||||
return a.fileSize!.compareTo(b.fileSize!);
|
||||
} else {
|
||||
return b.fileSize!.compareTo(a.fileSize!);
|
||||
}
|
||||
});
|
||||
}
|
||||
// todo:(neeraj) Stick to default group behaviour for magicSearch and editLocationGallery
|
||||
// In case of Magic search, we need to hide the scrollbar title (can be done
|
||||
// by specifying none as groupType)
|
||||
if (widget.groupType != GroupType.size) {
|
||||
return [files];
|
||||
}
|
||||
|
||||
final List<List<EnteFile>> resultGroupedFiles = [];
|
||||
List<EnteFile> singleGroupFile = [];
|
||||
const int groupSize = 40;
|
||||
for (int i = 0; i < files.length; i += 1) {
|
||||
singleGroupFile.add(files[i]);
|
||||
if (singleGroupFile.length == groupSize) {
|
||||
resultGroupedFiles.add(singleGroupFile);
|
||||
singleGroupFile = [];
|
||||
}
|
||||
}
|
||||
if (singleGroupFile.isNotEmpty) {
|
||||
resultGroupedFiles.add(singleGroupFile);
|
||||
}
|
||||
_logger.info('Grouped files into ${resultGroupedFiles.length} groups');
|
||||
return resultGroupedFiles;
|
||||
}
|
||||
|
||||
List<List<EnteFile>> _groupBasedOnTime(List<EnteFile> files) {
|
||||
List<EnteFile> dailyFiles = [];
|
||||
|
||||
final List<List<EnteFile>> resultGroupedFiles = [];
|
||||
|
|
Loading…
Add table
Reference in a new issue