Compare commits

...

1 Commits

Author SHA1 Message Date
Your Name
83bd3d5e76 selection sheet redesign 2025-08-26 10:55:35 +05:30
7 changed files with 484 additions and 323 deletions

View File

@@ -5,6 +5,7 @@ import 'package:photos/models/selected_files.dart';
import 'package:photos/theme/ente_theme.dart'; import 'package:photos/theme/ente_theme.dart';
class ActionBarWidget extends StatefulWidget { class ActionBarWidget extends StatefulWidget {
final Color? backgroundColor;
final SelectedFiles? selectedFiles; final SelectedFiles? selectedFiles;
final VoidCallback? onCancel; final VoidCallback? onCancel;
@@ -12,6 +13,7 @@ class ActionBarWidget extends StatefulWidget {
required this.onCancel, required this.onCancel,
this.selectedFiles, this.selectedFiles,
super.key, super.key,
required this.backgroundColor,
}); });
@override @override
@@ -42,15 +44,25 @@ class _ActionBarWidgetState extends State<ActionBarWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final textTheme = getEnteTextTheme(context); final textTheme = getEnteTextTheme(context);
return SizedBox( final colorScheme = getEnteColorScheme(context);
child: Padding( return Container(
padding: const EdgeInsets.fromLTRB(20, 8, 20, 8), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 10),
decoration: BoxDecoration(
color: widget.backgroundColor ?? colorScheme.backgroundElevated2,
borderRadius: BorderRadius.circular(100),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 4,
offset: const Offset(0, -1),
),
],
),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [ children: [
Flexible( ValueListenableBuilder(
flex: 1,
child: ValueListenableBuilder(
valueListenable: _selectedFilesNotifier, valueListenable: _selectedFilesNotifier,
builder: (context, value, child) { builder: (context, value, child) {
return Text( return Text(
@@ -63,33 +75,27 @@ class _ActionBarWidgetState extends State<ActionBarWidget> {
: S.of(context).selectedPhotos( : S.of(context).selectedPhotos(
_selectedFilesNotifier.value, _selectedFilesNotifier.value,
), ),
style: textTheme.miniMuted, style: textTheme.mini,
); );
}, },
), ),
), const SizedBox(width: 4),
Flexible( GestureDetector(
flex: 1,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () { onTap: () {
widget.onCancel?.call(); widget.onCancel?.call();
}, },
child: Align( child: Align(
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
child: Text( child: Icon(
S.of(context).cancel, Icons.close,
style: textTheme.mini, size: 16,
), color: textTheme.mini.color,
),
), ),
), ),
), ),
], ],
), ),
),
); );
} }

View File

@@ -5,8 +5,6 @@ import "package:photos/models/gallery_type.dart";
import "package:photos/models/ml/face/person.dart"; import "package:photos/models/ml/face/person.dart";
import 'package:photos/models/selected_files.dart'; import 'package:photos/models/selected_files.dart';
import 'package:photos/theme/ente_theme.dart'; import 'package:photos/theme/ente_theme.dart';
import 'package:photos/ui/components/bottom_action_bar/action_bar_widget.dart';
import "package:photos/ui/components/divider_widget.dart";
import "package:photos/ui/viewer/actions/file_selection_actions_widget.dart"; import "package:photos/ui/viewer/actions/file_selection_actions_widget.dart";
class BottomActionBarWidget extends StatelessWidget { class BottomActionBarWidget extends StatelessWidget {
@@ -16,7 +14,6 @@ class BottomActionBarWidget extends StatelessWidget {
final String? clusterID; final String? clusterID;
final SelectedFiles selectedFiles; final SelectedFiles selectedFiles;
final VoidCallback? onCancel; final VoidCallback? onCancel;
final Color? backgroundColor;
const BottomActionBarWidget({ const BottomActionBarWidget({
required this.galleryType, required this.galleryType,
@@ -25,7 +22,6 @@ class BottomActionBarWidget extends StatelessWidget {
this.person, this.person,
this.clusterID, this.clusterID,
this.onCancel, this.onCancel,
this.backgroundColor,
super.key, super.key,
}); });
@@ -39,10 +35,10 @@ class BottomActionBarWidget extends StatelessWidget {
: 0; : 0;
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: backgroundColor ?? colorScheme.backgroundElevated2, color: colorScheme.backgroundElevated,
borderRadius: const BorderRadius.only( borderRadius: const BorderRadius.only(
topLeft: Radius.circular(8), topLeft: Radius.circular(24),
topRight: Radius.circular(8), topRight: Radius.circular(24),
), ),
), ),
padding: EdgeInsets.only( padding: EdgeInsets.only(
@@ -62,12 +58,7 @@ class BottomActionBarWidget extends StatelessWidget {
person: person, person: person,
clusterID: clusterID, clusterID: clusterID,
), ),
const DividerWidget(dividerType: DividerType.bottomBar), const SizedBox(height: 2),
ActionBarWidget(
selectedFiles: selectedFiles,
onCancel: onCancel,
),
// const SizedBox(height: 2)
], ],
), ),
); );

View File

@@ -1,5 +1,6 @@
import 'dart:math' as math; import 'dart:math' as math;
import "package:auto_size_text/auto_size_text.dart";
import "package:flutter/material.dart"; import "package:flutter/material.dart";
import "package:flutter_svg/svg.dart"; import "package:flutter_svg/svg.dart";
import "package:photos/theme/ente_theme.dart"; import "package:photos/theme/ente_theme.dart";
@@ -106,7 +107,7 @@ class __BodyState extends State<_Body> {
children: [ children: [
if (widget.icon == Icons.navigation_rounded) if (widget.icon == Icons.navigation_rounded)
Transform.rotate( Transform.rotate(
angle: math.pi / 2, angle: math.pi * 2,
child: Icon( child: Icon(
widget.icon, widget.icon,
size: 24, size: 24,
@@ -137,7 +138,7 @@ class __BodyState extends State<_Body> {
SvgPicture.asset( SvgPicture.asset(
widget.svgAssetPath!, widget.svgAssetPath!,
colorFilter: ColorFilter.mode( colorFilter: ColorFilter.mode(
getEnteColorScheme(context).textMuted, getEnteColorScheme(context).textBase,
BlendMode.srcIn, BlendMode.srcIn,
), ),
width: 24, width: 24,
@@ -149,14 +150,16 @@ class __BodyState extends State<_Body> {
Icon( Icon(
widget.icon, widget.icon,
size: 24, size: 24,
color: getEnteColorScheme(context).textMuted, color: getEnteColorScheme(context).textBase,
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Flexible(
child: AutoSizeText(
widget.labelText, widget.labelText,
textAlign: TextAlign.center, textAlign: TextAlign.center,
//textTheme in [getWidthOfLongestWord] should be same as this //textTheme in [getWidthOfLongestWord] should be same as this
style: getEnteTextTheme(context).miniMuted, style: getEnteTextTheme(context).mini,
),
), ),
], ],
), ),
@@ -180,8 +183,7 @@ class __BodyState extends State<_Body> {
double maxWidth = 0.0; double maxWidth = 0.0;
for (String word in words) { for (String word in words) {
final width = final width = computeWidthOfWord(word, getEnteTextTheme(context).mini);
computeWidthOfWord(word, getEnteTextTheme(context).miniMuted);
if (width > maxWidth) { if (width > maxWidth) {
maxWidth = width; maxWidth = width;
} }

View File

@@ -50,6 +50,7 @@ import 'package:photos/utils/navigation_util.dart';
import "package:photos/utils/share_util.dart"; import "package:photos/utils/share_util.dart";
import "package:photos/utils/standalone/simple_task_queue.dart"; import "package:photos/utils/standalone/simple_task_queue.dart";
import "package:screenshot/screenshot.dart"; import "package:screenshot/screenshot.dart";
import "package:smooth_page_indicator/smooth_page_indicator.dart";
class FileSelectionActionsWidget extends StatefulWidget { class FileSelectionActionsWidget extends StatefulWidget {
final GalleryType type; final GalleryType type;
@@ -89,6 +90,7 @@ class _FileSelectionActionsWidgetState
Collection? _cachedCollectionForSharedLink; Collection? _cachedCollectionForSharedLink;
final GlobalKey shareButtonKey = GlobalKey(); final GlobalKey shareButtonKey = GlobalKey();
final GlobalKey sendLinkButtonKey = GlobalKey(); final GlobalKey sendLinkButtonKey = GlobalKey();
final PageController _pageController = PageController();
final StreamController<double> _progressController = final StreamController<double> _progressController =
StreamController<double>(); StreamController<double>();
@@ -153,6 +155,31 @@ class _FileSelectionActionsWidgetState
//for items that should be shown. //for items that should be shown.
final List<SelectionActionButton> items = []; final List<SelectionActionButton> items = [];
final showUploadIcon = widget.type == GalleryType.localFolder &&
split.ownedByCurrentUser.isEmpty;
//add to album
if (widget.type.showAddToAlbum()) {
if (showUploadIcon) {
items.add(
SelectionActionButton(
icon: Icons.cloud_upload_outlined,
labelText: S.of(context).addToEnte,
onTap: _addToAlbum,
),
);
} else {
items.add(
SelectionActionButton(
icon: Icons.add_outlined,
labelText: S.of(context).addToAlbum,
onTap: _addToAlbum,
),
);
}
}
//share link
if (widget.type.showCreateLink()) { if (widget.type.showCreateLink()) {
if (_cachedCollectionForSharedLink != null && anyUploadedFiles) { if (_cachedCollectionForSharedLink != null && anyUploadedFiles) {
items.add( items.add(
@@ -166,7 +193,7 @@ class _FileSelectionActionsWidgetState
items.add( items.add(
SelectionActionButton( SelectionActionButton(
icon: Icons.navigation_rounded, icon: Icons.navigation_rounded,
labelText: S.of(context).sendLink, labelText: S.of(context).share,
onTap: anyUploadedFiles ? _onSendLinkTapped : null, onTap: anyUploadedFiles ? _onSendLinkTapped : null,
shouldShow: ownedFilesCount > 0, shouldShow: ownedFilesCount > 0,
key: sendLinkButtonKey, key: sendLinkButtonKey,
@@ -174,6 +201,150 @@ class _FileSelectionActionsWidgetState
); );
} }
} }
//Favorite
if (widget.type.showFavoriteOption()) {
items.add(
SelectionActionButton(
icon: Icons.favorite_border_rounded,
labelText: S.of(context).favorite,
onTap: anyUploadedFiles ? _onFavoriteClick : null,
shouldShow: ownedFilesCount > 0,
),
);
} else if (widget.type.showUnFavoriteOption()) {
items.add(
SelectionActionButton(
icon: Icons.favorite,
labelText: S.of(context).removeFromFavorite,
onTap: _onUnFavoriteClick,
shouldShow: ownedFilesCount > 0,
),
);
}
//Download
if (showDownloadOption) {
items.add(
SelectionActionButton(
labelText: S.of(context).download,
icon: Icons.cloud_download_outlined,
onTap: () => _download(widget.selectedFiles.files.toList()),
),
);
}
//Delete (for owned photos only)
if (widget.type.showDeleteOption()) {
items.add(
SelectionActionButton(
icon: Icons.delete_outline,
labelText: S.of(context).delete,
onTap: anyOwnedFiles ? _onDeleteClick : null,
shouldShow: allOwnedFiles,
),
);
}
//Hide (for owned photos only)
if (widget.type.showHideOption()) {
items.add(
SelectionActionButton(
icon: Icons.visibility_off_outlined,
labelText: S.of(context).hide,
onTap: anyUploadedFiles ? _onHideClick : null,
shouldShow: ownedFilesCount > 0,
),
);
} else if (widget.type.showUnHideOption()) {
items.add(
SelectionActionButton(
icon: Icons.visibility_outlined,
labelText: S.of(context).unhide,
onTap: _onUnhideClick,
shouldShow: ownedFilesCount > 0,
),
);
}
//Archive (for owned photos only)
if (widget.type.showArchiveOption()) {
items.add(
SelectionActionButton(
icon: Icons.archive_outlined,
labelText: S.of(context).archive,
onTap: anyUploadedFiles ? _onArchiveClick : null,
shouldShow: ownedFilesCount > 0,
),
);
} else if (widget.type.showUnArchiveOption()) {
items.add(
SelectionActionButton(
icon: Icons.unarchive,
labelText: S.of(context).unarchive,
onTap: _onUnArchiveClick,
shouldShow: ownedFilesCount > 0,
),
);
}
//Guest view
items.add(
SelectionActionButton(
svgAssetPath: "assets/icons/guest_view_icon.svg",
labelText: S.of(context).guestView,
onTap: _onGuestViewClick,
),
);
//Create collage
if (widget.type != GalleryType.sharedPublicCollection) {
items.add(
SelectionActionButton(
icon: Icons.grid_view_outlined,
labelText: S.of(context).createCollage,
onTap: _onCreateCollageClicked,
shouldShow: showCollageOption,
),
);
}
//Edit (only if single photo is selected)
if (widget.type.showBulkEditTime()) {
items.add(
SelectionActionButton(
shouldShow: widget.selectedFiles.files.every(
(element) => (element.ownerID == currentUserID),
),
labelText: S.of(context).editTime,
icon: Icons.edit_calendar_outlined,
onTap: () async {
final newDate = await showEditDateSheet(
context,
widget.selectedFiles.files,
);
if (newDate != null) {
widget.selectedFiles.clearAll();
}
},
),
);
}
//Edit location (for owned photos only)
if (widget.type.showEditLocation()) {
items.add(
SelectionActionButton(
shouldShow: widget.selectedFiles.files.any(
(element) => (element.ownerID == currentUserID),
),
labelText: S.of(context).editLocation,
icon: Icons.edit_location_alt_outlined,
onTap: _editLocation,
),
);
}
if (widget.type == GalleryType.peopleTag && widget.person != null) { if (widget.type == GalleryType.peopleTag && widget.person != null) {
items.add( items.add(
SelectionActionButton( SelectionActionButton(
@@ -203,28 +374,6 @@ class _FileSelectionActionsWidgetState
); );
} }
final showUploadIcon = widget.type == GalleryType.localFolder &&
split.ownedByCurrentUser.isEmpty;
if (widget.type.showAddToAlbum()) {
if (showUploadIcon) {
items.add(
SelectionActionButton(
icon: Icons.cloud_upload_outlined,
labelText: S.of(context).addToEnte,
onTap: _addToAlbum,
),
);
} else {
items.add(
SelectionActionButton(
icon: Icons.add_outlined,
labelText: S.of(context).addToAlbum,
onTap: _addToAlbum,
),
);
}
}
if (widget.type.showAddtoHiddenAlbum()) { if (widget.type.showAddtoHiddenAlbum()) {
items.add( items.add(
SelectionActionButton( SelectionActionButton(
@@ -256,17 +405,6 @@ class _FileSelectionActionsWidgetState
); );
} }
if (widget.type.showDeleteOption()) {
items.add(
SelectionActionButton(
icon: Icons.delete_outline,
labelText: S.of(context).delete,
onTap: anyOwnedFiles ? _onDeleteClick : null,
shouldShow: allOwnedFiles,
),
);
}
if (widget.type.showRemoveFromAlbum()) { if (widget.type.showRemoveFromAlbum()) {
items.add( items.add(
SelectionActionButton( SelectionActionButton(
@@ -288,42 +426,6 @@ class _FileSelectionActionsWidgetState
); );
} }
if (widget.type.showFavoriteOption()) {
items.add(
SelectionActionButton(
icon: Icons.favorite_border_rounded,
labelText: S.of(context).favorite,
onTap: anyUploadedFiles ? _onFavoriteClick : null,
shouldShow: ownedFilesCount > 0,
),
);
} else if (widget.type.showUnFavoriteOption()) {
items.add(
SelectionActionButton(
icon: Icons.favorite,
labelText: S.of(context).removeFromFavorite,
onTap: _onUnFavoriteClick,
shouldShow: ownedFilesCount > 0,
),
);
}
items.add(
SelectionActionButton(
svgAssetPath: "assets/icons/guest_view_icon.svg",
labelText: S.of(context).guestView,
onTap: _onGuestViewClick,
),
);
if (widget.type != GalleryType.sharedPublicCollection) {
items.add(
SelectionActionButton(
icon: Icons.grid_view_outlined,
labelText: S.of(context).createCollage,
onTap: _onCreateCollageClicked,
shouldShow: showCollageOption,
),
);
}
if (flagService.internalUser && if (flagService.internalUser &&
widget.type != GalleryType.sharedPublicCollection) { widget.type != GalleryType.sharedPublicCollection) {
items.add( items.add(
@@ -335,45 +437,6 @@ class _FileSelectionActionsWidgetState
); );
} }
if (widget.type.showHideOption()) {
items.add(
SelectionActionButton(
icon: Icons.visibility_off_outlined,
labelText: S.of(context).hide,
onTap: anyUploadedFiles ? _onHideClick : null,
shouldShow: ownedFilesCount > 0,
),
);
} else if (widget.type.showUnHideOption()) {
items.add(
SelectionActionButton(
icon: Icons.visibility_outlined,
labelText: S.of(context).unhide,
onTap: _onUnhideClick,
shouldShow: ownedFilesCount > 0,
),
);
}
if (widget.type.showArchiveOption()) {
items.add(
SelectionActionButton(
icon: Icons.archive_outlined,
labelText: S.of(context).archive,
onTap: anyUploadedFiles ? _onArchiveClick : null,
shouldShow: ownedFilesCount > 0,
),
);
} else if (widget.type.showUnArchiveOption()) {
items.add(
SelectionActionButton(
icon: Icons.unarchive,
labelText: S.of(context).unarchive,
onTap: _onUnArchiveClick,
shouldShow: ownedFilesCount > 0,
),
);
}
if (widget.type.showRestoreOption()) { if (widget.type.showRestoreOption()) {
items.add( items.add(
SelectionActionButton( SelectionActionButton(
@@ -394,49 +457,6 @@ class _FileSelectionActionsWidgetState
); );
} }
if (widget.type.showBulkEditTime()) {
items.add(
SelectionActionButton(
shouldShow: widget.selectedFiles.files.every(
(element) => (element.ownerID == currentUserID),
),
labelText: S.of(context).editTime,
icon: Icons.edit_calendar_outlined,
onTap: () async {
final newDate = await showEditDateSheet(
context,
widget.selectedFiles.files,
);
if (newDate != null) {
widget.selectedFiles.clearAll();
}
},
),
);
}
if (widget.type.showEditLocation()) {
items.add(
SelectionActionButton(
shouldShow: widget.selectedFiles.files.any(
(element) => (element.ownerID == currentUserID),
),
labelText: S.of(context).editLocation,
icon: Icons.edit_location_alt_outlined,
onTap: _editLocation,
),
);
}
if (showDownloadOption) {
items.add(
SelectionActionButton(
labelText: S.of(context).download,
icon: Icons.cloud_download_outlined,
onTap: () => _download(widget.selectedFiles.files.toList()),
),
);
}
if (widget.type != GalleryType.sharedPublicCollection) { if (widget.type != GalleryType.sharedPublicCollection) {
items.add( items.add(
SelectionActionButton( SelectionActionButton(
@@ -448,38 +468,147 @@ class _FileSelectionActionsWidgetState
); );
} }
if (items.isNotEmpty) { // Filter items that should be shown first
final scrollController = ScrollController(); final List<SelectionActionButton> visibleItems = items
// h4ck: https://github.com/flutter/flutter/issues/57920#issuecomment-893970066 .where((item) => item.shouldShow == null || item.shouldShow == true)
.toList();
final List<SelectionActionButton> firstThreeItems =
visibleItems.length > 3 ? visibleItems.take(3).toList() : visibleItems;
final List<SelectionActionButton> otherItems =
visibleItems.length > 3 ? visibleItems.sublist(3) : [];
final List<List<SelectionActionButton>> groupedOtherItems = [];
for (int i = 0; i < otherItems.length; i += 4) {
int end = (i + 4 < otherItems.length) ? i + 4 : otherItems.length;
groupedOtherItems.add(otherItems.sublist(i, end));
}
if (visibleItems.isNotEmpty) {
return MediaQuery( return MediaQuery(
data: MediaQuery.of(context).removePadding(removeBottom: true), data: MediaQuery.of(context).removePadding(removeBottom: true),
child: SafeArea( child: SafeArea(
child: Scrollbar(
radius: const Radius.circular(1),
thickness: 2,
controller: scrollController,
thumbVisibility: true,
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(
decelerationRate: ScrollDecelerationRate.fast,
),
scrollDirection: Axis.horizontal,
child: Container( child: Container(
padding: const EdgeInsets.only(bottom: 24), padding: const EdgeInsets.only(bottom: 20),
child: Row( child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox(width: 4), // First Row
...items, const SizedBox(
const SizedBox(width: 4), height: 4,
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 6,
),
child: Row(
children: firstThreeItems
.map(
(item) => Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 6,
),
child: Stack(
alignment: Alignment.center,
children: [
Container(
height: MediaQuery.of(context).size.height *
0.10,
decoration: BoxDecoration(
color: getEnteColorScheme(context)
.backgroundElevated2,
borderRadius: BorderRadius.circular(20),
),
),
item,
], ],
), ),
), ),
), ),
)
.toList(),
),
),
// Second Row
if (groupedOtherItems.isNotEmpty) ...[
const SizedBox(height: 24),
Container(
width: double.infinity,
height: 74,
decoration: BoxDecoration(
color: getEnteColorScheme(context).backgroundElevated2,
borderRadius: BorderRadius.circular(16),
),
margin: const EdgeInsets.symmetric(horizontal: 12),
child: PageView.builder(
controller: _pageController,
itemCount: groupedOtherItems.length,
onPageChanged: (index) {
if (index >= groupedOtherItems.length &&
groupedOtherItems.isNotEmpty) {
_pageController.animateToPage(
groupedOtherItems.length - 1,
duration: const Duration(seconds: 5),
curve: Curves.easeInOut,
);
}
},
itemBuilder: (context, pageIndex) {
if (pageIndex >= groupedOtherItems.length) {
return const SizedBox();
}
final currentGroup = groupedOtherItems[pageIndex];
return Row(
children: currentGroup.map((item) {
return Expanded(
child: AnimatedSwitcher(
duration: const Duration(seconds: 5),
transitionBuilder: (
Widget child,
Animation<double> animation,
) {
return FadeTransition(
opacity: animation,
child: child,
);
},
child: item is Widget
? KeyedSubtree(
key: ValueKey(item.hashCode),
child: item,
)
: const SizedBox(),
),
);
}).toList(),
);
},
),
),
const SizedBox(height: 16),
if (groupedOtherItems.length > 1)
SmoothPageIndicator(
controller: _pageController,
count: groupedOtherItems.length,
effect: const WormEffect(
dotHeight: 6,
dotWidth: 6,
spacing: 6,
activeDotColor: Colors.white,
),
),
],
],
),
), ),
), ),
); );
} }
return const SizedBox(); return const SizedBox();
} }
@@ -495,7 +624,6 @@ class _FileSelectionActionsWidgetState
topControl: Stack( topControl: Stack(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
children: [ children: [
// This container is for increasing the tap area
Container( Container(
width: double.infinity, width: double.infinity,
height: 36, height: 36,

View File

@@ -11,6 +11,7 @@ import "package:photos/models/search/hierarchical/only_them_filter.dart";
import 'package:photos/models/selected_files.dart'; import 'package:photos/models/selected_files.dart';
import "package:photos/theme/effects.dart"; import "package:photos/theme/effects.dart";
import "package:photos/theme/ente_theme.dart"; import "package:photos/theme/ente_theme.dart";
import "package:photos/ui/components/bottom_action_bar/action_bar_widget.dart";
import 'package:photos/ui/components/bottom_action_bar/bottom_action_bar_widget.dart'; import 'package:photos/ui/components/bottom_action_bar/bottom_action_bar_widget.dart';
import "package:photos/ui/viewer/gallery/state/gallery_files_inherited_widget.dart"; import "package:photos/ui/viewer/gallery/state/gallery_files_inherited_widget.dart";
import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart"; import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart";
@@ -25,6 +26,7 @@ class FileSelectionOverlayBar extends StatefulWidget {
final Color? backgroundColor; final Color? backgroundColor;
final PersonEntity? person; final PersonEntity? person;
final String? clusterID; final String? clusterID;
final VoidCallback? onCancel;
const FileSelectionOverlayBar( const FileSelectionOverlayBar(
this.galleryType, this.galleryType,
@@ -33,6 +35,7 @@ class FileSelectionOverlayBar extends StatefulWidget {
this.backgroundColor, this.backgroundColor,
this.person, this.person,
this.clusterID, this.clusterID,
this.onCancel,
super.key, super.key,
}); });
@@ -127,14 +130,31 @@ class _FileSelectionOverlayBarState extends State<FileSelectionOverlayBar> {
duration: const Duration(milliseconds: 400), duration: const Duration(milliseconds: 400),
firstChild: Column( firstChild: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.only(right: 4), padding: const EdgeInsets.only(left: 12),
child: SelectAllButton( child: SelectAllButton(
backgroundColor: widget.backgroundColor, backgroundColor: widget.backgroundColor,
), ),
), ),
const Spacer(),
Padding(
padding: const EdgeInsets.only(right: 12),
child: ActionBarWidget(
selectedFiles: widget.selectedFiles,
onCancel: () {
if (widget.selectedFiles.files.isNotEmpty) {
widget.selectedFiles.clearAll();
}
},
backgroundColor: widget.backgroundColor,
),
),
],
),
const SizedBox(height: 8), const SizedBox(height: 8),
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -151,7 +171,6 @@ class _FileSelectionOverlayBarState extends State<FileSelectionOverlayBar> {
widget.selectedFiles.clearAll(); widget.selectedFiles.clearAll();
} }
}, },
backgroundColor: widget.backgroundColor,
), ),
), ),
], ],
@@ -247,13 +266,11 @@ class _SelectAllButtonState extends State<SelectAllButton> {
_allSelected = !_allSelected; _allSelected = !_allSelected;
}); });
}, },
child: Padding(
padding: const EdgeInsets.only(top: 8),
child: Container( child: Container(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: widget.backgroundColor ?? colorScheme.backgroundElevated2, color: widget.backgroundColor ?? colorScheme.backgroundElevated2,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(100),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.1), color: Colors.black.withOpacity(0.1),
@@ -267,8 +284,8 @@ class _SelectAllButtonState extends State<SelectAllButton> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text( Text(
S.of(context).selectAllShort, S.of(context).selectAll,
style: getEnteTextTheme(context).miniMuted, style: getEnteTextTheme(context).mini,
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
ListenableBuilder( ListenableBuilder(
@@ -284,15 +301,14 @@ class _SelectAllButtonState extends State<SelectAllButton> {
_allSelected _allSelected
? Icons.check_circle ? Icons.check_circle
: Icons.check_circle_outline, : Icons.check_circle_outline,
color: _allSelected ? null : colorScheme.strokeMuted, color: _allSelected ? null : colorScheme.strokeBase,
size: 18, size: 16,
); );
}, },
), ),
], ],
), ),
), ),
),
); );
} }
} }

View File

@@ -5,10 +5,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _fe_analyzer_shared name: _fe_analyzer_shared
sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "76.0.0" version: "72.0.0"
_flutterfire_internals: _flutterfire_internals:
dependency: transitive dependency: transitive
description: description:
@@ -21,7 +21,7 @@ packages:
dependency: transitive dependency: transitive
description: dart description: dart
source: sdk source: sdk
version: "0.3.3" version: "0.3.2"
adaptive_theme: adaptive_theme:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -34,10 +34,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.11.0" version: "6.7.0"
android_intent_plus: android_intent_plus:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -134,6 +134,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.11.0" version: "2.11.0"
auto_size_text:
dependency: "direct main"
description:
name: auto_size_text
sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
battery_info: battery_info:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -317,10 +325,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: collection name: collection
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.19.0" version: "1.18.0"
computer: computer:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -1392,18 +1400,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker name: leak_tracker
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.7" version: "10.0.5"
leak_tracker_flutter_testing: leak_tracker_flutter_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_flutter_testing name: leak_tracker_flutter_testing
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.8" version: "3.0.5"
leak_tracker_testing: leak_tracker_testing:
dependency: transitive dependency: transitive
description: description:
@@ -1512,10 +1520,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: macros name: macros
sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656" sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.3-main.0" version: "0.1.2-main.4"
maps_launcher: maps_launcher:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -2293,7 +2301,15 @@ packages:
dependency: transitive dependency: transitive
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.99"
smooth_page_indicator:
dependency: "direct main"
description:
name: smooth_page_indicator
sha256: b21ebb8bc39cf72d11c7cfd809162a48c3800668ced1c9da3aade13a32cf6c1c
url: "https://pub.dev"
source: hosted
version: "1.2.1"
source_gen: source_gen:
dependency: transitive dependency: transitive
description: description:
@@ -2418,10 +2434,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: stack_trace name: stack_trace
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.12.0" version: "1.11.1"
step_progress_indicator: step_progress_indicator:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -2450,10 +2466,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: string_scanner name: string_scanner
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.2.0"
styled_text: styled_text:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -2514,26 +2530,26 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: test name: test
sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f" sha256: "7ee44229615f8f642b68120165ae4c2a75fe77ae2065b1e55ae4711f6cf0899e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.25.8" version: "1.25.7"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.3" version: "0.7.2"
test_core: test_core:
dependency: transitive dependency: transitive
description: description:
name: test_core name: test_core
sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d" sha256: "55ea5a652e38a1dfb32943a7973f3681a60f872f8c3a05a14664ad54ef9c6696"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.6.5" version: "0.6.4"
thermal: thermal:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -2813,10 +2829,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.3.0" version: "14.2.5"
volume_controller: volume_controller:
dependency: transitive dependency: transitive
description: description:
@@ -2877,10 +2893,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: webdriver name: webdriver
sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8" sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.4" version: "3.0.3"
webkit_inspection_protocol: webkit_inspection_protocol:
dependency: transitive dependency: transitive
description: description:

View File

@@ -25,6 +25,7 @@ dependencies:
app_links: ^6.4.0 app_links: ^6.4.0
archive: ^3.6.1 archive: ^3.6.1
async: ^2.11.0 async: ^2.11.0
auto_size_text: ^3.0.0
battery_info: # replace with battery_plus battery_info: # replace with battery_plus
git: git:
url: https://github.com/ente-io/battery_info url: https://github.com/ente-io/battery_info
@@ -184,6 +185,7 @@ dependencies:
sentry_flutter: ^8.14.1 sentry_flutter: ^8.14.1
share_plus: ^10.0.2 share_plus: ^10.0.2
shared_preferences: ^2.0.5 shared_preferences: ^2.0.5
smooth_page_indicator: ^1.2.1
sqflite: ^2.3.0 sqflite: ^2.3.0
sqflite_migration: ^0.3.0 sqflite_migration: ^0.3.0
sqlite3_flutter_libs: ^0.5.20 sqlite3_flutter_libs: ^0.5.20