refractor: extract string + code refractor and improvements
This commit is contained in:
@@ -1737,5 +1737,9 @@
|
||||
"cLFamilyPlanDesc": "You can now set limits on how much storage your family members can use.",
|
||||
"cLBulkEdit": "Bulk Edit dates",
|
||||
"cLBulkEditDesc": "You can now select multiple photos, and edit date/time for all of them with one quick action. Shifting dates is also supported.",
|
||||
"curatedMemories": "Curated memories"
|
||||
"curatedMemories": "Curated memories",
|
||||
"deleteMultipleAlbumDialog": "Also delete the photos (and videos) present in these {count} albums from <bold>all</bold> other albums they are part of?",
|
||||
"addParticipants": "Add participants",
|
||||
"selectedAlbums": "{count} selected",
|
||||
"actionNotSupportedOnFavouritesAlbum": "Action not supported on Favourites album"
|
||||
}
|
||||
@@ -391,8 +391,7 @@ class CollectionActions {
|
||||
),
|
||||
],
|
||||
bodyWidget: StyledText(
|
||||
text:
|
||||
"Also delete the photos (and videos) present in these ${collections.length} albums from <bold>all</bold> other albums they are part of?",
|
||||
text: S.of(bContext).deleteMultipleAlbumDialog(collections.length),
|
||||
style: textTheme.body.copyWith(color: textMutedDark),
|
||||
tags: {
|
||||
'bold': StyledTextTag(
|
||||
|
||||
@@ -31,23 +31,89 @@ class AlbumListItemWidget extends StatelessWidget {
|
||||
final colorScheme = getEnteColorScheme(context);
|
||||
const sideOfThumbnail = 60.0;
|
||||
|
||||
final albumWidget = Flexible(
|
||||
flex: 6,
|
||||
child: Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.horizontal(
|
||||
left: Radius.circular(4),
|
||||
),
|
||||
child: SizedBox(
|
||||
height: sideOfThumbnail,
|
||||
width: sideOfThumbnail,
|
||||
child: FutureBuilder<EnteFile?>(
|
||||
future: CollectionsService.instance.getCover(collection),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
final thumbnail = snapshot.data!;
|
||||
return ThumbnailWidget(
|
||||
thumbnail,
|
||||
showFavForAlbumOnly: true,
|
||||
shouldShowOwnerAvatar: false,
|
||||
);
|
||||
} else {
|
||||
return const NoThumbnailWidget(addBorder: false);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Flexible(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
collection.displayName,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
FutureBuilder<int>(
|
||||
future: CollectionsService.instance.getFileCount(collection),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
return Text(
|
||||
S.of(context).memoryCount(
|
||||
snapshot.data!,
|
||||
NumberFormat().format(snapshot.data!),
|
||||
),
|
||||
style: textTheme.small.copyWith(
|
||||
color: colorScheme.textMuted,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
if (snapshot.hasError) {
|
||||
Logger("AlbumListItemWidget").severe(
|
||||
"Failed to fetch file count of collection",
|
||||
snapshot.error,
|
||||
);
|
||||
}
|
||||
return Text(
|
||||
"",
|
||||
style: textTheme.small.copyWith(
|
||||
color: colorScheme.textMuted,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (onTapCallback != null) {
|
||||
onTapCallback!(collection);
|
||||
}
|
||||
},
|
||||
onLongPress: () {
|
||||
if (onLongPressCallback != null) {
|
||||
onLongPressCallback!(collection);
|
||||
}
|
||||
},
|
||||
onTap: () => onTapCallback?.call(collection),
|
||||
onLongPress: () => onLongPressCallback?.call(collection),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: ListenableBuilder(
|
||||
listenable: selectedAlbums!,
|
||||
builder: (context, _) {
|
||||
final isSelected =
|
||||
selectedAlbums?.isAlbumSelected(collection) ?? false;
|
||||
|
||||
return AnimatedContainer(
|
||||
curve: Curves.easeOut,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
@@ -57,116 +123,31 @@ class AlbumListItemWidget extends StatelessWidget {
|
||||
? colorScheme.strokeMuted
|
||||
: colorScheme.strokeFainter,
|
||||
),
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(4),
|
||||
),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 6,
|
||||
child: Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.horizontal(
|
||||
left: Radius.circular(4),
|
||||
),
|
||||
child: SizedBox(
|
||||
height: sideOfThumbnail,
|
||||
width: sideOfThumbnail,
|
||||
child: FutureBuilder<EnteFile?>(
|
||||
future: CollectionsService.instance
|
||||
.getCover(collection),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
final thumbnail = snapshot.data!;
|
||||
return ThumbnailWidget(
|
||||
thumbnail,
|
||||
showFavForAlbumOnly: true,
|
||||
shouldShowOwnerAvatar: false,
|
||||
);
|
||||
} else {
|
||||
return const NoThumbnailWidget(
|
||||
addBorder: false,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Flexible(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
collection.displayName,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
FutureBuilder<int>(
|
||||
future: CollectionsService.instance
|
||||
.getFileCount(collection),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
return Text(
|
||||
S.of(context).memoryCount(
|
||||
snapshot.data!,
|
||||
NumberFormat().format(snapshot.data!),
|
||||
),
|
||||
style: textTheme.small.copyWith(
|
||||
color: colorScheme.textMuted,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
if (snapshot.hasError) {
|
||||
Logger("AlbumListItemWidget").severe(
|
||||
"Failed to fetch file count of collection",
|
||||
snapshot.error,
|
||||
);
|
||||
}
|
||||
return Text(
|
||||
"",
|
||||
style: textTheme.small.copyWith(
|
||||
color: colorScheme.textMuted,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
albumWidget,
|
||||
Flexible(
|
||||
flex: 1,
|
||||
child: ListenableBuilder(
|
||||
listenable: selectedAlbums!,
|
||||
builder: (context, _) {
|
||||
final isSelected =
|
||||
selectedAlbums?.isAlbumSelected(collection) ?? false;
|
||||
|
||||
return AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
switchInCurve: Curves.easeOut,
|
||||
switchOutCurve: Curves.easeIn,
|
||||
child: isSelected
|
||||
? IconButtonWidget(
|
||||
key: const ValueKey("selected"),
|
||||
icon: Icons.check_circle_rounded,
|
||||
iconButtonType: IconButtonType.secondary,
|
||||
iconColor: colorScheme.blurStrokeBase,
|
||||
)
|
||||
: IconButtonWidget(
|
||||
key: const ValueKey("unselected"),
|
||||
icon: Icons.chevron_right_outlined,
|
||||
iconButtonType: IconButtonType.secondary,
|
||||
iconColor: colorScheme.blurStrokePressed,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
switchInCurve: Curves.easeOut,
|
||||
switchOutCurve: Curves.easeIn,
|
||||
child: isSelected
|
||||
? IconButtonWidget(
|
||||
key: const ValueKey("selected"),
|
||||
icon: Icons.check_circle_rounded,
|
||||
iconButtonType: IconButtonType.secondary,
|
||||
iconColor: colorScheme.blurStrokeBase,
|
||||
)
|
||||
: IconButtonWidget(
|
||||
key: const ValueKey("unselected"),
|
||||
icon: Icons.chevron_right_outlined,
|
||||
iconButtonType: IconButtonType.secondary,
|
||||
iconColor: colorScheme.blurStrokePressed,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -36,7 +36,7 @@ class NewAlbumRowItemWidget extends StatelessWidget {
|
||||
alwaysShowSuccessState: false,
|
||||
initialValue: "",
|
||||
textCapitalization: TextCapitalization.words,
|
||||
popnavAfterSubmission: false,
|
||||
popnavAfterSubmission: true,
|
||||
onSubmit: (String text) async {
|
||||
if (text.trim() == "") {
|
||||
return;
|
||||
@@ -50,7 +50,6 @@ class NewAlbumRowItemWidget extends StatelessWidget {
|
||||
context,
|
||||
CollectionPage(CollectionWithThumbnail(c, null)),
|
||||
);
|
||||
Navigator.of(context).pop();
|
||||
} catch (e, s) {
|
||||
Logger("CreateNewAlbumRowItemWidget")
|
||||
.severe("Failed to rename album", e, s);
|
||||
|
||||
@@ -125,6 +125,7 @@ class _CollectionListPageState extends State<CollectionListPage> {
|
||||
_selectedAlbum,
|
||||
widget.sectionType,
|
||||
collections!,
|
||||
showSelectAllButton: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -217,7 +218,6 @@ class _CollectionListPageState extends State<CollectionListPage> {
|
||||
: AlbumSortDirection.ascending;
|
||||
await localSettings.setAlbumSortDirection(albumSortDirection!);
|
||||
await refreshCollections();
|
||||
setState(() {});
|
||||
Bus.instance.fire(AlbumSortOrderChangeEvent());
|
||||
}
|
||||
},
|
||||
|
||||
@@ -26,8 +26,8 @@ class CollectionsFlexiGridViewWidget extends StatefulWidget {
|
||||
Width changes dynamically with screen width such that we can fit 2 in one row.
|
||||
Keep the width integral (center the albums to distribute excess pixels)
|
||||
*/
|
||||
static const maxThumbnailWidth = 170.0;
|
||||
static const fixedGapBetweenAlbum = 2.0;
|
||||
static const maxThumbnailWidth = 224.0;
|
||||
static const fixedGapBetweenAlbum = 4.0;
|
||||
static const minGapForHorizontalPadding = 8.0;
|
||||
static const collectionItemsToPreload = 20;
|
||||
|
||||
@@ -115,7 +115,7 @@ class _CollectionsFlexiGridViewWidgetState
|
||||
}
|
||||
|
||||
Widget _buildGridView(BuildContext context, Key key) {
|
||||
final double screenWidth = MediaQuery.of(context).size.width;
|
||||
final double screenWidth = MediaQuery.sizeOf(context).width;
|
||||
final int albumsCountInOneRow =
|
||||
max(screenWidth ~/ CollectionsFlexiGridViewWidget.maxThumbnailWidth, 3);
|
||||
final double gapBetweenAlbums = (albumsCountInOneRow - 1) *
|
||||
|
||||
@@ -47,7 +47,9 @@ class _AlbumActionBarWidgetState extends State<AlbumActionBarWidget> {
|
||||
valueListenable: _selectedAlbumNotifier,
|
||||
builder: (context, value, child) {
|
||||
return Text(
|
||||
"${widget.selectedAlbums?.albums.length ?? 0} selected",
|
||||
S.of(context).selectedAlbums(
|
||||
widget.selectedAlbums?.albums.length ?? 0,
|
||||
),
|
||||
style: textTheme.miniMuted,
|
||||
);
|
||||
},
|
||||
|
||||
@@ -24,7 +24,7 @@ class AlbumBottomActionBarWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bottomPadding = MediaQuery.paddingOf(context).bottom;
|
||||
final widthOfScreen = MediaQuery.of(context).size.width;
|
||||
final widthOfScreen = MediaQuery.sizeOf(context).width;
|
||||
final colorScheme = getEnteColorScheme(context);
|
||||
final double leftRightPadding = widthOfScreen > restrictedMaxWidth
|
||||
? (widthOfScreen - restrictedMaxWidth) / 2
|
||||
|
||||
@@ -85,7 +85,7 @@ class _AddParticipantPage extends State<AddParticipantPage> {
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
widget.isMultipleCollections
|
||||
? "Add participants"
|
||||
? S.of(context).addParticipants
|
||||
: widget.isAddingViewer
|
||||
? S.of(context).addViewer
|
||||
: S.of(context).addCollaborator,
|
||||
|
||||
@@ -221,7 +221,7 @@ class _UserCollectionsTabState extends State<UserCollectionsTab>
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child:
|
||||
SizedBox(height: 64 + MediaQuery.of(context).padding.bottom),
|
||||
SizedBox(height: 64 + MediaQuery.paddingOf(context).bottom),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -229,6 +229,7 @@ class _UserCollectionsTabState extends State<UserCollectionsTab>
|
||||
widget.selectedAlbums!,
|
||||
UISectionType.homeCollections,
|
||||
collections,
|
||||
showSelectAllButton: false,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -56,7 +56,7 @@ class _AlbumSelectionActionWidgetState
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.selectedAlbums.albums.isEmpty) {
|
||||
return const SizedBox();
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
final List<SelectionActionButton> items = [];
|
||||
final hasPinnedAlbum =
|
||||
@@ -166,9 +166,6 @@ class _AlbumSelectionActionWidgetState
|
||||
collections: widget.selectedAlbums.albums.toList(),
|
||||
),
|
||||
);
|
||||
if (hasFavorites) {
|
||||
_showFavToast();
|
||||
}
|
||||
widget.selectedAlbums.clearAll();
|
||||
}
|
||||
|
||||
@@ -176,6 +173,7 @@ class _AlbumSelectionActionWidgetState
|
||||
int count = 0;
|
||||
final List<Collection> nonEmptyCollection = [];
|
||||
|
||||
final List errors = [];
|
||||
for (final collection in widget.selectedAlbums.albums) {
|
||||
count = await FilesDB.instance.collectionFileCount(collection.id);
|
||||
final bool isEmptyCollection = count == 0;
|
||||
@@ -184,7 +182,7 @@ class _AlbumSelectionActionWidgetState
|
||||
await CollectionsService.instance.trashEmptyCollection(collection);
|
||||
} catch (e, s) {
|
||||
_logger.warning("failed to trash collection", e, s);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
errors.add(e);
|
||||
}
|
||||
} else if (collection.type == CollectionType.favorites) {
|
||||
continue;
|
||||
@@ -192,6 +190,12 @@ class _AlbumSelectionActionWidgetState
|
||||
nonEmptyCollection.add(collection);
|
||||
}
|
||||
}
|
||||
if (errors.isNotEmpty) {
|
||||
await showGenericErrorDialog(
|
||||
context: context,
|
||||
error: errors.first,
|
||||
);
|
||||
}
|
||||
|
||||
if (nonEmptyCollection.isNotEmpty) {
|
||||
final bool result = await collectionActions.deleteMultipleCollectionSheet(
|
||||
@@ -366,7 +370,7 @@ class _AlbumSelectionActionWidgetState
|
||||
void _showFavToast() {
|
||||
showShortToast(
|
||||
context,
|
||||
"The Favorites album cannot be modified",
|
||||
S.of(context).actionNotSupportedOnFavouritesAlbum,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ class AlbumSelectionOverlayBar extends StatefulWidget {
|
||||
final List<Collection> collections;
|
||||
final Color? backgroundColor;
|
||||
final UISectionType sectionType;
|
||||
final bool showSelectAllButton;
|
||||
|
||||
const AlbumSelectionOverlayBar(
|
||||
this.selectedAlbums,
|
||||
@@ -21,6 +22,7 @@ class AlbumSelectionOverlayBar extends StatefulWidget {
|
||||
super.key,
|
||||
this.onClose,
|
||||
this.backgroundColor,
|
||||
this.showSelectAllButton = false,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -60,14 +62,15 @@ class _AlbumSelectionOverlayBarState extends State<AlbumSelectionOverlayBar> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 4),
|
||||
child: SelectAllAlbumsButton(
|
||||
widget.selectedAlbums,
|
||||
widget.collections,
|
||||
backgroundColor: widget.backgroundColor,
|
||||
if (widget.showSelectAllButton)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 4),
|
||||
child: SelectAllAlbumsButton(
|
||||
widget.selectedAlbums,
|
||||
widget.collections,
|
||||
backgroundColor: widget.backgroundColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Container(
|
||||
decoration: BoxDecoration(boxShadow: shadowFloatFaintLight),
|
||||
@@ -123,7 +126,7 @@ class _SelectAllAlbumsButtonState extends State<SelectAllAlbumsButton> {
|
||||
if (_allSelected) {
|
||||
widget.selectedAlbums.clearAll();
|
||||
} else {
|
||||
widget.selectedAlbums.selectAll(
|
||||
widget.selectedAlbums.select(
|
||||
widget.collections.toSet(),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user