Show border around album row items

This commit is contained in:
AmanRajSinghMourya
2025-06-27 15:55:51 +05:30
parent 6c53421e36
commit 04ae708f33
2 changed files with 137 additions and 109 deletions

View File

@@ -1,3 +1,4 @@
import "package:figma_squircle/figma_squircle.dart";
import 'package:flutter/material.dart';
import "package:intl/intl.dart";
import "package:photos/core/configuration.dart";
@@ -24,6 +25,9 @@ class AlbumRowItemWidget extends StatelessWidget {
final void Function(Collection)? onTapCallback;
final void Function(Collection)? onLongPressCallback;
final SelectedAlbums? selectedAlbums;
final double borderWidth;
static const _cornerRadius = 12.0;
static const _cornerSmoothing = 1.0;
const AlbumRowItemWidget(
this.c,
@@ -35,6 +39,7 @@ class AlbumRowItemWidget extends StatelessWidget {
this.onTapCallback,
this.onLongPressCallback,
this.selectedAlbums,
this.borderWidth = 1.0,
});
@override
@@ -56,125 +61,146 @@ class AlbumRowItemWidget extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(12),
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 bool isSelected =
selectedAlbums?.isAlbumSelected(c) ?? false;
final String heroTag = tagPrefix + thumbnail.tag;
final thumbnailWidget = ThumbnailWidget(
thumbnail,
shouldShowArchiveStatus: isOwner
? c.isArchived()
: c.hasShareeArchived(),
showFavForAlbumOnly: true,
shouldShowSyncStatus: false,
shouldShowPinIcon: isOwner && c.isPinned,
key: Key(heroTag),
);
return Hero(
tag: heroTag,
transitionOnUserGestures: true,
child: isSelected
? ColorFiltered(
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(
0.4,
),
BlendMode.darken,
),
child: thumbnailWidget,
)
: thumbnailWidget,
);
} else {
return const NoThumbnailWidget(
borderRadius: 12,
);
}
},
),
if (isOwner && (c.hasSharees || c.hasLink))
Hero(
tag: tagPrefix + "_sharees",
transitionOnUserGestures: true,
child: Align(
alignment: Alignment.topLeft,
child: AlbumSharesIcons(
padding: const EdgeInsets.only(left: 4, top: 4),
sharees: c.getSharees(),
type: AvatarType.mini,
trailingWidget: linkIcon,
),
),
),
Positioned(
top: 5,
right: 5,
child: Hero(
tag: tagPrefix + "_album_selection",
transitionOnUserGestures: true,
child: ListenableBuilder(
listenable: selectedAlbums ?? ValueNotifier(false),
builder: (context, _) {
SizedBox(
height: sideOfThumbnail + borderWidth * 2,
width: sideOfThumbnail + borderWidth * 2,
child: Stack(
clipBehavior: Clip.none,
alignment: Alignment.center,
children: [
ClipSmoothRect(
radius: SmoothBorderRadius(
cornerRadius: _cornerRadius + borderWidth,
cornerSmoothing: _cornerSmoothing,
),
child: Container(
color: getEnteColorScheme(context).strokeMuted,
width: sideOfThumbnail + borderWidth * 2,
height: sideOfThumbnail + borderWidth * 2,
),
),
ClipSmoothRect(
radius: SmoothBorderRadius(
cornerRadius: _cornerRadius,
cornerSmoothing: _cornerSmoothing,
),
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 bool isSelected =
selectedAlbums?.isAlbumSelected(c) ?? false;
return AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
switchInCurve: Curves.easeOut,
switchOutCurve: Curves.easeIn,
child: isSelected
? const Icon(
Icons.check_circle_rounded,
color: Colors.white,
size: 22,
)
: null,
final String heroTag = tagPrefix + thumbnail.tag;
final thumbnailWidget = ThumbnailWidget(
thumbnail,
shouldShowArchiveStatus: isOwner
? c.isArchived()
: c.hasShareeArchived(),
showFavForAlbumOnly: true,
shouldShowSyncStatus: false,
shouldShowPinIcon: isOwner && c.isPinned,
key: Key(heroTag),
);
},
),
return Hero(
tag: heroTag,
transitionOnUserGestures: true,
child: isSelected
? ColorFiltered(
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(
0.4,
),
BlendMode.darken,
),
child: thumbnailWidget,
)
: thumbnailWidget,
);
} else {
return const NoThumbnailWidget(
borderRadius: 12,
);
}
},
),
),
if (!isOwner)
Align(
alignment: Alignment.bottomRight,
child: Hero(
tag: tagPrefix + "_owner_other",
if (isOwner && (c.hasSharees || c.hasLink))
Hero(
tag: tagPrefix + "_sharees",
transitionOnUserGestures: true,
child: Padding(
padding:
const EdgeInsets.only(right: 4, bottom: 4),
child: UserAvatarWidget(
c.owner,
thumbnailView: true,
child: Align(
alignment: Alignment.topLeft,
child: AlbumSharesIcons(
padding: const EdgeInsets.only(left: 4, top: 4),
sharees: c.getSharees(),
type: AvatarType.mini,
trailingWidget: linkIcon,
),
),
),
Positioned(
top: 5,
right: 5,
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
? const Icon(
Icons.check_circle_rounded,
color: Colors.white,
size: 22,
)
: null,
);
},
),
),
),
],
if (!isOwner)
Align(
alignment: Alignment.bottomRight,
child: Hero(
tag: tagPrefix + "_owner_other",
transitionOnUserGestures: true,
child: Padding(
padding:
const EdgeInsets.only(right: 4, bottom: 4),
child: UserAvatarWidget(
c.owner,
thumbnailView: true,
),
),
),
),
],
),
),
),
),
],
],
),
),
const SizedBox(height: 6),
Hero(

View File

@@ -29,6 +29,7 @@ class CollectionsFlexiGridViewWidget extends StatefulWidget {
static const maxThumbnailWidth = 224.0;
static const crossAxisSpacing = 8.0;
static const horizontalPadding = 16.0;
static const borderWidth = 1.0;
final List<Collection>? collections;
// At max how many albums to display
final int displayLimitCount;
@@ -137,7 +138,8 @@ class _CollectionsFlexiGridViewWidgetState
final double sideOfThumbnail = (screenWidth -
totalCrossAxisSpacing -
CollectionsFlexiGridViewWidget.horizontalPadding) /
CollectionsFlexiGridViewWidget.horizontalPadding -
CollectionsFlexiGridViewWidget.borderWidth * 2) /
albumsCountInCrossAxis;
final int totalCollections = widget.collections!.length;