live WEB search

This commit is contained in:
Mehul Ahal 2022-12-23 11:20:46 +01:00 committed by Mguy13
parent 47945dbec7
commit 4ade7f1682
19 changed files with 503 additions and 59 deletions

View file

@ -3,10 +3,17 @@ import 'package:flutter/material.dart';
import '/features/core/data/constants/const_colors.dart';
import '/features/core/data/constants/const_durations.dart';
import '/features/core/widgets/gap.dart';
import '/features/core/widgets/mcg_scaffold.dart';
import '/features/core/widgets/view_model_builder.dart';
import '/features/core/widgets/state/multi_value_listenable_builder.dart';
import '/features/core/widgets/state/view_model_builder.dart';
import '../../data/enums/search_option.dart';
import '../../data/models/image_model.dart';
import 'gallery_view_model.dart';
part 'downloaded_gallery_view.dart';
part 'search_gallery_view.dart';
class GalleryView extends StatelessWidget {
const GalleryView({super.key});
@ -18,7 +25,36 @@ class GalleryView extends StatelessWidget {
bodyBuilderWaiter: model.isInitialised,
forceInternetCheck: true,
appBar: AppBar(
title: Text(model.strings.gallery),
centerTitle: true,
primary: true,
title: ValueListenableBuilder<bool>(
valueListenable: model.isSearchingListenable,
builder: (context, final isSearching, _) => AnimatedSwitcher(
duration: ConstDurations.quarterDefaultAnimationDuration,
child: !isSearching
? Center(child: Text(model.strings.gallery))
: _SearchBox(galleryViewModel: model),
),
),
actions: [
Padding(
padding: const EdgeInsets.only(right: 40),
child: MultiValueListenableBuilder(
valueListenables: [
model.isDisplayingPressingPrompt,
model.isSearchingListenable,
],
builder: (context, final values, child) => !model.isDisplayingPressingPrompt.value
? IconButton(
icon: !model.isSearchingListenable.value
? const Icon(Icons.search)
: const Icon(Icons.close),
onPressed: model.searchPressed,
)
: const SizedBox.shrink(),
),
)
],
),
body: Center(
child: ValueListenableBuilder<bool>(
@ -30,34 +66,27 @@ class GalleryView extends StatelessWidget {
onPressed: model.onPromptPressed,
child: Text(model.strings.startLoadingPrompt),
)
: DecoratedBox(
decoration: const BoxDecoration(color: ConstColours.galleryBackgroundColour),
child: SingleChildScrollView(
// Using Wrap instead of GridView, to make use of different image sizes
child: Wrap(
runSpacing: 24,
spacing: 8,
alignment: WrapAlignment.center,
runAlignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
for (final imageModel in model.imageModels)
GestureDetector(
onTap: () => model.pushImageCarouselView(
context,
imageModel: imageModel,
: SingleChildScrollView(
child: FutureBuilder<void>(
future: model.initImageFetchIsDone,
builder: (context, final snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
case ConnectionState.active:
return const CircularProgressIndicator();
case ConnectionState.done:
return ValueListenableBuilder<bool>(
valueListenable: model.isSearchingListenable,
builder: (context, final isSearching, _) => AnimatedSwitcher(
duration: ConstDurations.oneAndHalfDefaultAnimationDuration,
child: !isSearching
? _DownloadedGalleryView(galleryViewModel: model)
: _SearchGalleryView(galleryViewModel: model),
),
child: CachedNetworkImage(
imageUrl: imageModel.uri.toString(),
cacheKey: imageModel.imageIndex.toString(),
progressIndicatorBuilder: (_, __, final progress) =>
CircularProgressIndicator(
value: model.downloadProgressValue(progress: progress),
),
),
),
],
),
);
}
},
),
),
),
@ -67,3 +96,49 @@ class GalleryView extends StatelessWidget {
);
}
}
class _SearchBox extends StatelessWidget {
const _SearchBox({
required this.galleryViewModel,
super.key,
});
final GalleryViewModel galleryViewModel;
@override
Widget build(BuildContext context) {
return Row(
children: [
ValueListenableBuilder<SearchOption>(
valueListenable: galleryViewModel.searchOptionListenable,
builder: (context, final searchOption, _) => Padding(
padding: const EdgeInsets.only(top: 8),
child: DropdownButton<SearchOption>(
underline: const SizedBox.shrink(),
borderRadius: BorderRadius.circular(24),
items: [
for (final searchOption in SearchOption.values)
DropdownMenuItem(
child: Center(child: Text(searchOption.name)),
value: searchOption,
),
],
value: searchOption,
onChanged: galleryViewModel.onSearchOptionChanged,
),
),
),
const Gap(18),
Expanded(
child: TextField(
autofocus: true,
decoration: InputDecoration(
hintText: galleryViewModel.strings.searchForImage,
),
onChanged: galleryViewModel.onSearchTermUpdate,
),
),
],
);
}
}