2023-01-20 07:21:34 +00:00
|
|
|
import 'package:dotted_border/dotted_border.dart';
|
2023-01-19 13:06:20 +00:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:logging/logging.dart';
|
|
|
|
import 'package:photos/db/files_db.dart';
|
|
|
|
import 'package:photos/models/collection_items.dart';
|
|
|
|
import 'package:photos/theme/ente_theme.dart';
|
|
|
|
import 'package:photos/ui/viewer/file/no_thumbnail_widget.dart';
|
|
|
|
import 'package:photos/ui/viewer/file/thumbnail_widget.dart';
|
|
|
|
|
|
|
|
class AlbumListItemWidget extends StatelessWidget {
|
2023-01-22 12:13:49 +00:00
|
|
|
final CollectionWithThumbnail? item;
|
2023-01-20 07:21:34 +00:00
|
|
|
final bool isNew;
|
|
|
|
const AlbumListItemWidget({
|
2023-01-22 12:13:49 +00:00
|
|
|
this.item,
|
2023-01-20 07:21:34 +00:00
|
|
|
this.isNew = false,
|
|
|
|
super.key,
|
|
|
|
});
|
2023-01-19 13:06:20 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
final logger = Logger("AlbumListItemWidget");
|
|
|
|
final textTheme = getEnteTextTheme(context);
|
|
|
|
final colorScheme = getEnteColorScheme(context);
|
2023-01-20 05:28:10 +00:00
|
|
|
const sideOfThumbnail = 60.0;
|
2023-01-21 03:55:28 +00:00
|
|
|
return LayoutBuilder(
|
|
|
|
builder: (context, constraints) {
|
|
|
|
return Stack(
|
|
|
|
alignment: Alignment.center,
|
2023-01-19 13:06:20 +00:00
|
|
|
children: [
|
2023-01-21 03:55:28 +00:00
|
|
|
Row(
|
|
|
|
children: [
|
|
|
|
ClipRRect(
|
|
|
|
borderRadius: const BorderRadius.horizontal(
|
|
|
|
left: Radius.circular(4),
|
|
|
|
),
|
|
|
|
child: SizedBox(
|
|
|
|
height: sideOfThumbnail,
|
|
|
|
width: sideOfThumbnail,
|
2023-01-22 12:13:49 +00:00
|
|
|
key: Key("collection_item:" + (item?.thumbnail?.tag ?? "")),
|
2023-01-21 03:55:28 +00:00
|
|
|
child: isNew
|
|
|
|
? Icon(
|
|
|
|
Icons.add_outlined,
|
|
|
|
color: colorScheme.strokeMuted,
|
2023-01-20 07:21:34 +00:00
|
|
|
)
|
2023-01-22 12:13:49 +00:00
|
|
|
: item?.thumbnail != null
|
2023-01-21 03:55:28 +00:00
|
|
|
? ThumbnailWidget(
|
2023-01-22 12:13:49 +00:00
|
|
|
item!.thumbnail,
|
2023-01-21 03:55:28 +00:00
|
|
|
showFavForAlbumOnly: true,
|
|
|
|
)
|
2023-01-24 07:20:43 +00:00
|
|
|
: const NoThumbnailWidget(
|
|
|
|
hasBorder: false,
|
|
|
|
),
|
2023-01-21 03:55:28 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsets.only(left: 12),
|
|
|
|
child: isNew
|
|
|
|
? Text(
|
|
|
|
"New album",
|
|
|
|
style: textTheme.body
|
|
|
|
.copyWith(color: colorScheme.textMuted),
|
|
|
|
)
|
|
|
|
: Column(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: [
|
2023-01-22 12:13:49 +00:00
|
|
|
Text(item?.collection.collectionName ?? ""),
|
|
|
|
item != null
|
|
|
|
? FutureBuilder<int>(
|
|
|
|
future:
|
|
|
|
FilesDB.instance.collectionFileCount(
|
|
|
|
item!.collection.id,
|
2023-01-21 03:55:28 +00:00
|
|
|
),
|
2023-01-22 12:13:49 +00:00
|
|
|
builder: (context, snapshot) {
|
|
|
|
if (snapshot.hasData) {
|
|
|
|
final text = snapshot.data == 1
|
|
|
|
? " memory"
|
|
|
|
: " memories";
|
|
|
|
return Text(
|
|
|
|
snapshot.data.toString() + text,
|
|
|
|
style: textTheme.small.copyWith(
|
|
|
|
color: colorScheme.textMuted,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
if (snapshot.hasError) {
|
|
|
|
logger.severe(
|
|
|
|
"Failed to fetch file count of collection id ${item!.collection.id}",
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return Text(
|
|
|
|
"",
|
|
|
|
style: textTheme.small.copyWith(
|
|
|
|
color: colorScheme.textMuted,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
: throw "CollectionWithThumbnail item cannot be null",
|
2023-01-21 03:55:28 +00:00
|
|
|
],
|
2023-01-20 07:21:34 +00:00
|
|
|
),
|
2023-01-21 03:55:28 +00:00
|
|
|
),
|
|
|
|
],
|
2023-01-19 13:06:20 +00:00
|
|
|
),
|
2023-01-21 03:55:28 +00:00
|
|
|
IgnorePointer(
|
|
|
|
child: DottedBorder(
|
|
|
|
dashPattern: isNew ? [4] : [300, 0],
|
|
|
|
color: colorScheme.strokeFainter,
|
|
|
|
strokeWidth: 1,
|
|
|
|
padding: const EdgeInsets.all(0),
|
|
|
|
borderType: BorderType.RRect,
|
|
|
|
radius: const Radius.circular(4),
|
|
|
|
child: SizedBox(
|
|
|
|
//Have to decrease the height and width by 1 pt as the stroke
|
|
|
|
//dotted border gives is of strokeAlign.center, so 0.5 inside and
|
|
|
|
// outside. Here for the row, stroke should be inside so we
|
|
|
|
//decrease the size of this sizedBox by 1 (so it shrinks 0.5 from
|
|
|
|
//every side) so that the strokeAlign.center of this sizedBox
|
|
|
|
//looks like a strokeAlign.inside in the row.
|
|
|
|
height: sideOfThumbnail - 1,
|
|
|
|
//This width will work for this only if the row widget takes up the
|
|
|
|
//full size it's parent (stack).
|
|
|
|
width: constraints.maxWidth - 1,
|
|
|
|
),
|
|
|
|
),
|
2023-01-20 05:28:10 +00:00
|
|
|
),
|
2023-01-21 03:55:28 +00:00
|
|
|
],
|
|
|
|
);
|
|
|
|
},
|
2023-01-19 13:06:20 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|