[mob][photos] feat: update selection logic to exclude favorite collections from actions
This commit is contained in:
@@ -30,30 +30,31 @@ class AlbumListItemWidget extends StatelessWidget {
|
||||
final textTheme = getEnteTextTheme(context);
|
||||
final colorScheme = getEnteColorScheme(context);
|
||||
const sideOfThumbnail = 60.0;
|
||||
final bool isFavCollection = collection.type == CollectionType.favorites;
|
||||
|
||||
return ListenableBuilder(
|
||||
listenable: selectedAlbums!,
|
||||
builder: (context, _) {
|
||||
final isSelected = selectedAlbums?.isAlbumSelected(collection) ?? false;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (onTapCallback != null) {
|
||||
onTapCallback!(collection);
|
||||
}
|
||||
},
|
||||
onLongPress: () {
|
||||
if (onLongPressCallback != null) {
|
||||
onLongPressCallback!(collection);
|
||||
}
|
||||
},
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: AnimatedContainer(
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (onTapCallback != null) {
|
||||
onTapCallback!(collection);
|
||||
}
|
||||
},
|
||||
onLongPress: () {
|
||||
if (onLongPressCallback != null) {
|
||||
onLongPressCallback!(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),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: isSelected
|
||||
color: isSelected & !isFavCollection
|
||||
? colorScheme.strokeMuted
|
||||
: colorScheme.strokeFainter,
|
||||
),
|
||||
@@ -81,7 +82,6 @@ class AlbumListItemWidget extends StatelessWidget {
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
final thumbnail = snapshot.data!;
|
||||
|
||||
return ThumbnailWidget(
|
||||
thumbnail,
|
||||
showFavForAlbumOnly: true,
|
||||
@@ -143,29 +143,37 @@ class AlbumListItemWidget extends StatelessWidget {
|
||||
),
|
||||
Flexible(
|
||||
flex: 1,
|
||||
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,
|
||||
)
|
||||
: const IconButtonWidget(
|
||||
key: ValueKey("unselected"),
|
||||
icon: Icons.chevron_right_outlined,
|
||||
iconButtonType: IconButtonType.secondary,
|
||||
),
|
||||
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 & !isFavCollection
|
||||
? IconButtonWidget(
|
||||
key: const ValueKey("selected"),
|
||||
icon: Icons.check_circle_rounded,
|
||||
iconButtonType: IconButtonType.secondary,
|
||||
iconColor: colorScheme.blurStrokeBase,
|
||||
)
|
||||
: const IconButtonWidget(
|
||||
key: ValueKey("unselected"),
|
||||
icon: Icons.chevron_right_outlined,
|
||||
iconButtonType: IconButtonType.secondary,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,80 +53,82 @@ class AlbumRowItemWidget extends StatelessWidget {
|
||||
color: c.publicURLs.first.isExpired ? warning500 : strokeBaseDark,
|
||||
)
|
||||
: null;
|
||||
return ListenableBuilder(
|
||||
listenable: selectedAlbums ?? ValueNotifier(false),
|
||||
builder: (context, _) {
|
||||
final bool isSelected = selectedAlbums?.isAlbumSelected(c) ?? false;
|
||||
return GestureDetector(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(1),
|
||||
child: SizedBox(
|
||||
height: sideOfThumbnail,
|
||||
width: sideOfThumbnail,
|
||||
child: Stack(
|
||||
children: [
|
||||
FutureBuilder<EnteFile?>(
|
||||
future: CollectionsService.instance.getCover(c),
|
||||
builder: (context, snapshot) {
|
||||
EnteFile? thumbnail;
|
||||
if (snapshot.hasData) {
|
||||
thumbnail = snapshot.data!;
|
||||
} else {
|
||||
//Need to use cached thumbnail so that the hero
|
||||
//animation works as expected.
|
||||
thumbnail = CollectionsService.instance
|
||||
.getCoverCache(c);
|
||||
}
|
||||
if (thumbnail != null) {
|
||||
final String heroTag =
|
||||
tagPrefix + thumbnail.tag;
|
||||
return Hero(
|
||||
tag: heroTag,
|
||||
transitionOnUserGestures: true,
|
||||
child: ThumbnailWidget(
|
||||
thumbnail,
|
||||
shouldShowArchiveStatus: isOwner
|
||||
? c.isArchived()
|
||||
: c.hasShareeArchived(),
|
||||
showFavForAlbumOnly: true,
|
||||
shouldShowSyncStatus: false,
|
||||
shouldShowPinIcon: isOwner && c.isPinned,
|
||||
key: Key(heroTag),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const NoThumbnailWidget();
|
||||
}
|
||||
},
|
||||
),
|
||||
if (isOwner && (c.hasSharees || c.hasLink))
|
||||
Hero(
|
||||
tag: tagPrefix + "_sharees",
|
||||
final bool isFavCollection = c.type == CollectionType.favorites;
|
||||
|
||||
return GestureDetector(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(1),
|
||||
child: SizedBox(
|
||||
height: sideOfThumbnail,
|
||||
width: sideOfThumbnail,
|
||||
child: Stack(
|
||||
children: [
|
||||
FutureBuilder<EnteFile?>(
|
||||
future: CollectionsService.instance.getCover(c),
|
||||
builder: (context, snapshot) {
|
||||
EnteFile? thumbnail;
|
||||
if (snapshot.hasData) {
|
||||
thumbnail = snapshot.data!;
|
||||
} else {
|
||||
//Need to use cached thumbnail so that the hero
|
||||
//animation works as expected.
|
||||
thumbnail =
|
||||
CollectionsService.instance.getCoverCache(c);
|
||||
}
|
||||
if (thumbnail != null) {
|
||||
final String heroTag = tagPrefix + thumbnail.tag;
|
||||
return Hero(
|
||||
tag: heroTag,
|
||||
transitionOnUserGestures: true,
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: AlbumSharesIcons(
|
||||
sharees: c.getSharees(),
|
||||
type: AvatarType.mini,
|
||||
trailingWidget: linkIcon,
|
||||
),
|
||||
child: ThumbnailWidget(
|
||||
thumbnail,
|
||||
shouldShowArchiveStatus: isOwner
|
||||
? c.isArchived()
|
||||
: c.hasShareeArchived(),
|
||||
showFavForAlbumOnly: true,
|
||||
shouldShowSyncStatus: false,
|
||||
shouldShowPinIcon: isOwner && c.isPinned,
|
||||
key: Key(heroTag),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const NoThumbnailWidget();
|
||||
}
|
||||
},
|
||||
),
|
||||
if (isOwner && (c.hasSharees || c.hasLink))
|
||||
Hero(
|
||||
tag: tagPrefix + "_sharees",
|
||||
transitionOnUserGestures: true,
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: AlbumSharesIcons(
|
||||
sharees: c.getSharees(),
|
||||
type: AvatarType.mini,
|
||||
trailingWidget: linkIcon,
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: Hero(
|
||||
tag: tagPrefix + "_album_selection",
|
||||
transitionOnUserGestures: true,
|
||||
child: AnimatedSwitcher(
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: Hero(
|
||||
tag: tagPrefix + "_album_selection",
|
||||
transitionOnUserGestures: true,
|
||||
child: ListenableBuilder(
|
||||
listenable: selectedAlbums ?? ValueNotifier(false),
|
||||
builder: (context, _) {
|
||||
final bool isSelected =
|
||||
selectedAlbums?.isAlbumSelected(c) ?? false;
|
||||
return AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
switchInCurve: Curves.easeOut,
|
||||
switchOutCurve: Curves.easeIn,
|
||||
child: isSelected
|
||||
child: isSelected && !isFavCollection
|
||||
? IconButtonWidget(
|
||||
key: const ValueKey("selected"),
|
||||
icon: Icons.check_circle_rounded,
|
||||
@@ -135,117 +137,116 @@ class AlbumRowItemWidget extends StatelessWidget {
|
||||
iconColor: colorScheme.blurStrokeBase,
|
||||
)
|
||||
: null,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!isOwner)
|
||||
Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: Hero(
|
||||
tag: tagPrefix + "_owner_other",
|
||||
transitionOnUserGestures: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
right: 8.0,
|
||||
bottom: 8.0,
|
||||
),
|
||||
child: UserAvatarWidget(
|
||||
c.owner,
|
||||
thumbnailView: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!isOwner)
|
||||
Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: Hero(
|
||||
tag: tagPrefix + "_owner_other",
|
||||
transitionOnUserGestures: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
right: 8.0,
|
||||
bottom: 8.0,
|
||||
),
|
||||
child: UserAvatarWidget(
|
||||
c.owner,
|
||||
thumbnailView: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Hero(
|
||||
tag: tagPrefix + "_title",
|
||||
transitionOnUserGestures: true,
|
||||
child: SizedBox(
|
||||
width: sideOfThumbnail,
|
||||
child: FutureBuilder<int>(
|
||||
future: showFileCount
|
||||
? CollectionsService.instance.getFileCount(c)
|
||||
: Future.value(0),
|
||||
builder: (context, snapshot) {
|
||||
int? cachedCount;
|
||||
if (showFileCount) {
|
||||
if (snapshot.hasData) {
|
||||
cachedCount = snapshot.data;
|
||||
} else {
|
||||
//Need to use cached count so that the hero
|
||||
//animation works as expected without flickering.
|
||||
cachedCount =
|
||||
CollectionsService.instance.getCachedFileCount(c);
|
||||
}
|
||||
}
|
||||
if (cachedCount != null && cachedCount > 0) {
|
||||
final String textCount =
|
||||
NumberFormat().format(cachedCount);
|
||||
return Row(
|
||||
children: [
|
||||
Container(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: sideOfThumbnail -
|
||||
((textCount.length + 3) * 10),
|
||||
),
|
||||
child: Text(
|
||||
c.displayName,
|
||||
style: enteTextTheme.small,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: enteTextTheme.smallMuted,
|
||||
children: [
|
||||
TextSpan(text: ' \u2022 $textCount'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Text(
|
||||
c.displayName,
|
||||
style: enteTextTheme.small,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () async {
|
||||
if (onTapCallback != null) {
|
||||
onTapCallback!(c);
|
||||
return;
|
||||
}
|
||||
final thumbnail = await CollectionsService.instance.getCover(c);
|
||||
// ignore: unawaited_futures
|
||||
routeToPage(
|
||||
context,
|
||||
CollectionPage(
|
||||
CollectionWithThumbnail(c, thumbnail),
|
||||
tagPrefix: tagPrefix,
|
||||
hasVerifiedLock: hasVerifiedLock,
|
||||
const SizedBox(height: 4),
|
||||
Hero(
|
||||
tag: tagPrefix + "_title",
|
||||
transitionOnUserGestures: true,
|
||||
child: SizedBox(
|
||||
width: sideOfThumbnail,
|
||||
child: FutureBuilder<int>(
|
||||
future: showFileCount
|
||||
? CollectionsService.instance.getFileCount(c)
|
||||
: Future.value(0),
|
||||
builder: (context, snapshot) {
|
||||
int? cachedCount;
|
||||
if (showFileCount) {
|
||||
if (snapshot.hasData) {
|
||||
cachedCount = snapshot.data;
|
||||
} else {
|
||||
//Need to use cached count so that the hero
|
||||
//animation works as expected without flickering.
|
||||
cachedCount =
|
||||
CollectionsService.instance.getCachedFileCount(c);
|
||||
}
|
||||
}
|
||||
if (cachedCount != null && cachedCount > 0) {
|
||||
final String textCount = NumberFormat().format(cachedCount);
|
||||
return Row(
|
||||
children: [
|
||||
Container(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth:
|
||||
sideOfThumbnail - ((textCount.length + 3) * 10),
|
||||
),
|
||||
child: Text(
|
||||
c.displayName,
|
||||
style: enteTextTheme.small,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: enteTextTheme.smallMuted,
|
||||
children: [
|
||||
TextSpan(text: ' \u2022 $textCount'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Text(
|
||||
c.displayName,
|
||||
style: enteTextTheme.small,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
onLongPress: () {
|
||||
if (onLongPressCallback != null) {
|
||||
onLongPressCallback!(c);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () async {
|
||||
if (onTapCallback != null) {
|
||||
onTapCallback!(c);
|
||||
return;
|
||||
}
|
||||
final thumbnail = await CollectionsService.instance.getCover(c);
|
||||
// ignore: unawaited_futures
|
||||
routeToPage(
|
||||
context,
|
||||
CollectionPage(
|
||||
CollectionWithThumbnail(c, thumbnail),
|
||||
tagPrefix: tagPrefix,
|
||||
hasVerifiedLock: hasVerifiedLock,
|
||||
),
|
||||
);
|
||||
},
|
||||
onLongPress: () {
|
||||
if (onLongPressCallback != null) {
|
||||
onLongPressCallback!(c);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +122,8 @@ class _AlbumSelectionActionWidgetState
|
||||
_logger.warning("failed to trash collection", e, s);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
} else if (collection.type == CollectionType.favorites) {
|
||||
continue;
|
||||
} else {
|
||||
nonEmptyCollection.add(collection);
|
||||
}
|
||||
@@ -143,7 +145,10 @@ class _AlbumSelectionActionWidgetState
|
||||
|
||||
Future<void> _onPinClick() async {
|
||||
for (final collection in widget.selectedAlbums.albums) {
|
||||
if (collection.isPinned) continue;
|
||||
if (collection.type == CollectionType.favorites || collection.isPinned) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await updateOrder(
|
||||
context,
|
||||
collection,
|
||||
@@ -155,6 +160,9 @@ class _AlbumSelectionActionWidgetState
|
||||
|
||||
Future<void> _onHideClick() async {
|
||||
for (final collection in widget.selectedAlbums.albums) {
|
||||
if (collection.type == CollectionType.favorites) {
|
||||
continue;
|
||||
}
|
||||
final isHidden = collection.isHidden();
|
||||
final int prevVisiblity = isHidden ? hiddenVisibility : visibleVisibility;
|
||||
final int newVisiblity = isHidden ? visibleVisibility : hiddenVisibility;
|
||||
|
||||
Reference in New Issue
Block a user