ente/lib/ui/viewer/search/result/search_section_all_page.dart

198 lines
7.4 KiB
Dart
Raw Normal View History

import "dart:async";
import "package:flutter/material.dart";
2023-11-09 05:40:09 +00:00
import "package:flutter_animate/flutter_animate.dart";
import "package:photos/events/event.dart";
import "package:photos/models/search/album_search_result.dart";
import "package:photos/models/search/generic_search_result.dart";
import "package:photos/models/search/recent_searches.dart";
import "package:photos/models/search/search_result.dart";
import "package:photos/models/search/search_types.dart";
import "package:photos/services/collections_service.dart";
import "package:photos/ui/common/loading_widget.dart";
import "package:photos/ui/components/title_bar_title_widget.dart";
import "package:photos/ui/viewer/gallery/collection_page.dart";
2023-10-18 05:42:57 +00:00
import "package:photos/ui/viewer/search/result/searchable_item.dart";
import "package:photos/utils/navigation_util.dart";
2023-11-01 03:12:42 +00:00
class SearchSectionAllPage extends StatefulWidget {
final SectionType sectionType;
2023-11-01 03:12:42 +00:00
const SearchSectionAllPage({required this.sectionType, super.key});
@override
2023-11-01 03:12:42 +00:00
State<SearchSectionAllPage> createState() => _SearchSectionAllPageState();
}
2023-11-01 03:12:42 +00:00
class _SearchSectionAllPageState extends State<SearchSectionAllPage> {
late Future<List<SearchResult>> sectionData;
final streamSubscriptions = <StreamSubscription>[];
@override
void initState() {
super.initState();
final streamsToListenTo = widget.sectionType.viewAllUpdateEvents();
for (Stream<Event> stream in streamsToListenTo) {
streamSubscriptions.add(
stream.listen((event) async {
setState(() {
sectionData = widget.sectionType.getData();
});
}),
);
}
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
sectionData = widget.sectionType.getData(limit: null, context: context);
}
@override
void dispose() {
for (var subscriptions in streamSubscriptions) {
subscriptions.cancel();
}
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
toolbarHeight: 48,
leadingWidth: 48,
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: const Icon(
Icons.arrow_back_outlined,
),
),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TitleBarTitleWidget(
title: widget.sectionType.sectionTitle(context),
),
FutureBuilder(
future: sectionData,
builder: (context, snapshot) {
if (snapshot.hasData) {
final sectionResults = snapshot.data!;
2023-11-09 05:40:09 +00:00
return Text(sectionResults.length.toString())
.animate()
.fadeIn(
duration: const Duration(milliseconds: 150),
curve: Curves.easeIn,
);
} else {
return const SizedBox.shrink();
}
},
),
],
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 20,
horizontal: 16,
),
child: FutureBuilder(
future: sectionData,
builder: (context, snapshot) {
if (snapshot.hasData) {
final sectionResults = snapshot.data!;
return ListView.separated(
itemBuilder: (context, index) {
if (sectionResults.length == index) {
return SearchableItemPlaceholder(
widget.sectionType,
);
}
if (sectionResults[index] is AlbumSearchResult) {
final albumSectionResult =
sectionResults[index] as AlbumSearchResult;
2023-10-18 05:42:57 +00:00
return SearchableItemWidget(
albumSectionResult,
resultCount:
CollectionsService.instance.getFileCount(
albumSectionResult
.collectionWithThumbnail.collection,
),
onResultTap: () {
RecentSearches()
.add(sectionResults[index].name());
routeToPage(
context,
CollectionPage(
albumSectionResult.collectionWithThumbnail,
tagPrefix: "searchable_item" +
albumSectionResult.heroTag(),
),
);
},
);
} else if (sectionResults[index]
is GenericSearchResult) {
final result =
sectionResults[index] as GenericSearchResult;
return SearchableItemWidget(
sectionResults[index],
onResultTap: result.onResultTap != null
? () => result.onResultTap!(context)
: null,
);
}
return SearchableItemWidget(
sectionResults[index],
);
},
separatorBuilder: (context, index) {
return const SizedBox(height: 10);
},
2023-11-16 07:22:15 +00:00
itemCount: sectionResults.length +
(widget.sectionType.isCTAVisible ? 1 : 0),
physics: const BouncingScrollPhysics(),
//This cache extend is needed for creating a new album
//using SearchSectionCTATile to work. This is so that
//SearchSectionCTATile doesn't get disposed when keyboard
//is open and the widget is out of view.
cacheExtent:
widget.sectionType == SectionType.album ? 400 : null,
2023-11-09 05:40:09 +00:00
)
.animate()
.fadeIn(
duration: const Duration(milliseconds: 225),
curve: Curves.easeIn,
)
.slide(
begin: const Offset(0, -0.01),
curve: Curves.easeIn,
duration: const Duration(
milliseconds: 225,
),
);
} else {
return const EnteLoadingWidget();
}
},
),
),
),
],
),
);
}
}