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';
class ActionBarWidget extends StatefulWidget {
final Color? backgroundColor;
final SelectedFiles? selectedFiles;
final VoidCallback? onCancel;
@@ -12,6 +13,7 @@ class ActionBarWidget extends StatefulWidget {
required this.onCancel,
this.selectedFiles,
super.key,
required this.backgroundColor,
});
@override
@@ -42,53 +44,57 @@ class _ActionBarWidgetState extends State<ActionBarWidget> {
@override
Widget build(BuildContext context) {
final textTheme = getEnteTextTheme(context);
return SizedBox(
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 8, 20, 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
flex: 1,
child: ValueListenableBuilder(
valueListenable: _selectedFilesNotifier,
builder: (context, value, child) {
return Text(
_selectedOwnedFilesNotifier.value !=
_selectedFilesNotifier.value
? S.of(context).selectedPhotosWithYours(
_selectedFilesNotifier.value,
_selectedOwnedFilesNotifier.value,
)
: S.of(context).selectedPhotos(
_selectedFilesNotifier.value,
),
style: textTheme.miniMuted,
);
},
final colorScheme = getEnteColorScheme(context);
return Container(
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(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [
ValueListenableBuilder(
valueListenable: _selectedFilesNotifier,
builder: (context, value, child) {
return Text(
_selectedOwnedFilesNotifier.value !=
_selectedFilesNotifier.value
? S.of(context).selectedPhotosWithYours(
_selectedFilesNotifier.value,
_selectedOwnedFilesNotifier.value,
)
: S.of(context).selectedPhotos(
_selectedFilesNotifier.value,
),
style: textTheme.mini,
);
},
),
const SizedBox(width: 4),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
widget.onCancel?.call();
},
child: Align(
alignment: Alignment.centerRight,
child: Icon(
Icons.close,
size: 16,
color: textTheme.mini.color,
),
),
Flexible(
flex: 1,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
widget.onCancel?.call();
},
child: Align(
alignment: Alignment.centerRight,
child: Text(
S.of(context).cancel,
style: textTheme.mini,
),
),
),
),
),
],
),
),
],
),
);
}

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/selected_files.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";
class BottomActionBarWidget extends StatelessWidget {
@@ -16,7 +14,6 @@ class BottomActionBarWidget extends StatelessWidget {
final String? clusterID;
final SelectedFiles selectedFiles;
final VoidCallback? onCancel;
final Color? backgroundColor;
const BottomActionBarWidget({
required this.galleryType,
@@ -25,7 +22,6 @@ class BottomActionBarWidget extends StatelessWidget {
this.person,
this.clusterID,
this.onCancel,
this.backgroundColor,
super.key,
});
@@ -39,10 +35,10 @@ class BottomActionBarWidget extends StatelessWidget {
: 0;
return Container(
decoration: BoxDecoration(
color: backgroundColor ?? colorScheme.backgroundElevated2,
color: colorScheme.backgroundElevated,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(8),
topRight: Radius.circular(8),
topLeft: Radius.circular(24),
topRight: Radius.circular(24),
),
),
padding: EdgeInsets.only(
@@ -62,12 +58,7 @@ class BottomActionBarWidget extends StatelessWidget {
person: person,
clusterID: clusterID,
),
const DividerWidget(dividerType: DividerType.bottomBar),
ActionBarWidget(
selectedFiles: selectedFiles,
onCancel: onCancel,
),
// const SizedBox(height: 2)
const SizedBox(height: 2),
],
),
);

View File

@@ -1,5 +1,6 @@
import 'dart:math' as math;
import "package:auto_size_text/auto_size_text.dart";
import "package:flutter/material.dart";
import "package:flutter_svg/svg.dart";
import "package:photos/theme/ente_theme.dart";
@@ -106,7 +107,7 @@ class __BodyState extends State<_Body> {
children: [
if (widget.icon == Icons.navigation_rounded)
Transform.rotate(
angle: math.pi / 2,
angle: math.pi * 2,
child: Icon(
widget.icon,
size: 24,
@@ -137,7 +138,7 @@ class __BodyState extends State<_Body> {
SvgPicture.asset(
widget.svgAssetPath!,
colorFilter: ColorFilter.mode(
getEnteColorScheme(context).textMuted,
getEnteColorScheme(context).textBase,
BlendMode.srcIn,
),
width: 24,
@@ -149,14 +150,16 @@ class __BodyState extends State<_Body> {
Icon(
widget.icon,
size: 24,
color: getEnteColorScheme(context).textMuted,
color: getEnteColorScheme(context).textBase,
),
const SizedBox(height: 4),
Text(
widget.labelText,
textAlign: TextAlign.center,
//textTheme in [getWidthOfLongestWord] should be same as this
style: getEnteTextTheme(context).miniMuted,
Flexible(
child: AutoSizeText(
widget.labelText,
textAlign: TextAlign.center,
//textTheme in [getWidthOfLongestWord] should be same as this
style: getEnteTextTheme(context).mini,
),
),
],
),
@@ -180,8 +183,7 @@ class __BodyState extends State<_Body> {
double maxWidth = 0.0;
for (String word in words) {
final width =
computeWidthOfWord(word, getEnteTextTheme(context).miniMuted);
final width = computeWidthOfWord(word, getEnteTextTheme(context).mini);
if (width > maxWidth) {
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/standalone/simple_task_queue.dart";
import "package:screenshot/screenshot.dart";
import "package:smooth_page_indicator/smooth_page_indicator.dart";
class FileSelectionActionsWidget extends StatefulWidget {
final GalleryType type;
@@ -89,6 +90,7 @@ class _FileSelectionActionsWidgetState
Collection? _cachedCollectionForSharedLink;
final GlobalKey shareButtonKey = GlobalKey();
final GlobalKey sendLinkButtonKey = GlobalKey();
final PageController _pageController = PageController();
final StreamController<double> _progressController =
StreamController<double>();
@@ -153,6 +155,31 @@ class _FileSelectionActionsWidgetState
//for items that should be shown.
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 (_cachedCollectionForSharedLink != null && anyUploadedFiles) {
items.add(
@@ -166,7 +193,7 @@ class _FileSelectionActionsWidgetState
items.add(
SelectionActionButton(
icon: Icons.navigation_rounded,
labelText: S.of(context).sendLink,
labelText: S.of(context).share,
onTap: anyUploadedFiles ? _onSendLinkTapped : null,
shouldShow: ownedFilesCount > 0,
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) {
items.add(
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()) {
items.add(
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()) {
items.add(
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 &&
widget.type != GalleryType.sharedPublicCollection) {
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()) {
items.add(
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) {
items.add(
SelectionActionButton(
@@ -448,38 +468,147 @@ class _FileSelectionActionsWidgetState
);
}
if (items.isNotEmpty) {
final scrollController = ScrollController();
// h4ck: https://github.com/flutter/flutter/issues/57920#issuecomment-893970066
// Filter items that should be shown first
final List<SelectionActionButton> visibleItems = items
.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(
data: MediaQuery.of(context).removePadding(removeBottom: true),
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(
padding: const EdgeInsets.only(bottom: 24),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(width: 4),
...items,
const SizedBox(width: 4),
],
child: Container(
padding: const EdgeInsets.only(bottom: 20),
child: Column(
children: [
// First Row
const SizedBox(
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();
}
@@ -495,7 +624,6 @@ class _FileSelectionActionsWidgetState
topControl: Stack(
alignment: Alignment.bottomCenter,
children: [
// This container is for increasing the tap area
Container(
width: double.infinity,
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/theme/effects.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/viewer/gallery/state/gallery_files_inherited_widget.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 PersonEntity? person;
final String? clusterID;
final VoidCallback? onCancel;
const FileSelectionOverlayBar(
this.galleryType,
@@ -33,6 +35,7 @@ class FileSelectionOverlayBar extends StatefulWidget {
this.backgroundColor,
this.person,
this.clusterID,
this.onCancel,
super.key,
});
@@ -127,13 +130,30 @@ class _FileSelectionOverlayBarState extends State<FileSelectionOverlayBar> {
duration: const Duration(milliseconds: 400),
firstChild: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(right: 4),
child: SelectAllButton(
backgroundColor: widget.backgroundColor,
),
Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 12),
child: SelectAllButton(
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),
Container(
@@ -151,7 +171,6 @@ class _FileSelectionOverlayBarState extends State<FileSelectionOverlayBar> {
widget.selectedFiles.clearAll();
}
},
backgroundColor: widget.backgroundColor,
),
),
],
@@ -247,50 +266,47 @@ class _SelectAllButtonState extends State<SelectAllButton> {
_allSelected = !_allSelected;
});
},
child: Padding(
padding: const EdgeInsets.only(top: 8),
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: widget.backgroundColor ?? colorScheme.backgroundElevated2,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 4,
offset: const Offset(0, -1),
),
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [
Text(
S.of(context).selectAllShort,
style: getEnteTextTheme(context).miniMuted,
),
const SizedBox(width: 4),
ListenableBuilder(
listenable: selectionState!.selectedFiles,
builder: (context, _) {
if (selectionState.selectedFiles.files.length ==
allGalleryFiles.length) {
_allSelected = true;
} else {
_allSelected = false;
}
return Icon(
_allSelected
? Icons.check_circle
: Icons.check_circle_outline,
color: _allSelected ? null : colorScheme.strokeMuted,
size: 18,
);
},
),
],
),
child: Container(
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(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [
Text(
S.of(context).selectAll,
style: getEnteTextTheme(context).mini,
),
const SizedBox(width: 4),
ListenableBuilder(
listenable: selectionState!.selectedFiles,
builder: (context, _) {
if (selectionState.selectedFiles.files.length ==
allGalleryFiles.length) {
_allSelected = true;
} else {
_allSelected = false;
}
return Icon(
_allSelected
? Icons.check_circle
: Icons.check_circle_outline,
color: _allSelected ? null : colorScheme.strokeBase,
size: 16,
);
},
),
],
),
),
);

View File

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

View File

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