165 lines
5.4 KiB
Dart
165 lines
5.4 KiB
Dart
|
import "package:dotted_border/dotted_border.dart";
|
||
|
import "package:flutter/material.dart";
|
||
|
import "package:photos/models/search/search_result.dart";
|
||
|
import "package:photos/models/search/search_types.dart";
|
||
|
import "package:photos/theme/ente_theme.dart";
|
||
|
import "package:photos/ui/components/buttons/icon_button_widget.dart";
|
||
|
import "package:photos/ui/viewer/search/result/search_result_page.dart";
|
||
|
import "package:photos/ui/viewer/search/result/search_thumbnail_widget.dart";
|
||
|
import "package:photos/utils/navigation_util.dart";
|
||
|
|
||
|
class SearchableItemWidget extends StatelessWidget {
|
||
|
final SearchResult searchResult;
|
||
|
final Future<int>? resultCount;
|
||
|
final Function? onResultTap;
|
||
|
const SearchableItemWidget(
|
||
|
this.searchResult, {
|
||
|
Key? key,
|
||
|
this.resultCount,
|
||
|
this.onResultTap,
|
||
|
}) : super(key: key);
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
final heroTagPrefix = searchResult.heroTag();
|
||
|
final textTheme = getEnteTextTheme(context);
|
||
|
final colorScheme = getEnteColorScheme(context);
|
||
|
|
||
|
return GestureDetector(
|
||
|
onTap: () {
|
||
|
if (onResultTap != null) {
|
||
|
onResultTap!();
|
||
|
} else {
|
||
|
routeToPage(
|
||
|
context,
|
||
|
SearchResultPage(searchResult),
|
||
|
);
|
||
|
}
|
||
|
},
|
||
|
child: Container(
|
||
|
decoration: BoxDecoration(
|
||
|
border: Border.all(color: colorScheme.strokeFainter),
|
||
|
borderRadius: const BorderRadius.all(
|
||
|
Radius.circular(4),
|
||
|
),
|
||
|
),
|
||
|
child: Row(
|
||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
|
children: [
|
||
|
Flexible(
|
||
|
flex: 6,
|
||
|
child: Row(
|
||
|
children: [
|
||
|
SizedBox(
|
||
|
width: 60,
|
||
|
height: 60,
|
||
|
child: SearchThumbnailWidget(
|
||
|
searchResult.previewThumbnail(),
|
||
|
heroTagPrefix,
|
||
|
),
|
||
|
),
|
||
|
const SizedBox(width: 12),
|
||
|
Flexible(
|
||
|
child: Padding(
|
||
|
padding: const EdgeInsets.symmetric(vertical: 4),
|
||
|
child: Column(
|
||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||
|
children: [
|
||
|
Text(
|
||
|
searchResult.name(),
|
||
|
style: textTheme.body,
|
||
|
overflow: TextOverflow.ellipsis,
|
||
|
),
|
||
|
const SizedBox(
|
||
|
height: 2,
|
||
|
),
|
||
|
FutureBuilder<int>(
|
||
|
future: resultCount ??
|
||
|
Future.value(searchResult.resultFiles().length),
|
||
|
builder: (context, snapshot) {
|
||
|
if (snapshot.hasData && snapshot.data! > 0) {
|
||
|
final noOfMemories = snapshot.data;
|
||
|
final String suffix =
|
||
|
noOfMemories! > 1 ? " memories" : " memory";
|
||
|
|
||
|
return Text(
|
||
|
noOfMemories.toString() + suffix,
|
||
|
style: textTheme.smallMuted,
|
||
|
);
|
||
|
} else {
|
||
|
return const SizedBox.shrink();
|
||
|
}
|
||
|
},
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
const Flexible(
|
||
|
flex: 1,
|
||
|
child: IconButtonWidget(
|
||
|
icon: Icons.chevron_right_outlined,
|
||
|
iconButtonType: IconButtonType.secondary,
|
||
|
),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class SearchableItemPlaceholder extends StatelessWidget {
|
||
|
final SectionType sectionType;
|
||
|
const SearchableItemPlaceholder(this.sectionType, {super.key});
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
if (sectionType.isCTAVisible == false) {
|
||
|
return const SizedBox.shrink();
|
||
|
}
|
||
|
|
||
|
final colorScheme = getEnteColorScheme(context);
|
||
|
final textTheme = getEnteTextTheme(context);
|
||
|
return Padding(
|
||
|
padding: const EdgeInsets.only(right: 1),
|
||
|
child: GestureDetector(
|
||
|
onTap: sectionType.ctaOnTap(context),
|
||
|
child: DottedBorder(
|
||
|
strokeWidth: 2,
|
||
|
borderType: BorderType.RRect,
|
||
|
radius: const Radius.circular(4),
|
||
|
padding: EdgeInsets.zero,
|
||
|
dashPattern: const [4, 4],
|
||
|
color: colorScheme.strokeFainter,
|
||
|
child: Row(
|
||
|
children: [
|
||
|
Container(
|
||
|
width: 60,
|
||
|
height: 60,
|
||
|
decoration: BoxDecoration(
|
||
|
borderRadius:
|
||
|
const BorderRadius.horizontal(left: Radius.circular(4)),
|
||
|
color: colorScheme.fillFaint,
|
||
|
),
|
||
|
child: Icon(
|
||
|
sectionType.getCTAIcon(),
|
||
|
color: colorScheme.strokeMuted,
|
||
|
),
|
||
|
),
|
||
|
const SizedBox(width: 12),
|
||
|
Text(
|
||
|
sectionType.getCTAText(context),
|
||
|
style: textTheme.body,
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
}
|