Solian/lib/screens/posts/post_search.dart

158 lines
4.6 KiB
Dart
Raw Normal View History

2024-10-13 13:48:53 +00:00
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:get/get.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import 'package:solian/models/pagination.dart';
import 'package:solian/providers/content/posts.dart';
import 'package:solian/widgets/loading_indicator.dart';
import 'package:solian/widgets/posts/post_list.dart';
import '../../models/post.dart';
class PostSearchScreen extends StatefulWidget {
final String? tag;
final String? category;
const PostSearchScreen({super.key, this.tag, this.category});
@override
State<PostSearchScreen> createState() => _PostSearchScreenState();
}
class _PostSearchScreenState extends State<PostSearchScreen> {
final TextEditingController _probeController = TextEditingController();
final PagingController<int, Post> _pagingController =
PagingController(firstPageKey: 0);
bool _isBusy = true;
_searchPosts(int pageKey) async {
if (widget.tag == null &&
widget.category == null &&
_probeController.text.isEmpty) {
_pagingController.appendLastPage([]);
return;
}
if (!_isBusy) {
setState(() => _isBusy = true);
}
if (pageKey == 0) {
_pagingController.itemList?.clear();
_pagingController.nextPageKey = 0;
}
final PostProvider provider = Get.find();
Response resp;
try {
if (_probeController.text.isEmpty) {
resp = await provider.listPost(
pageKey,
tag: widget.tag,
category: widget.category,
);
} else {
resp = await provider.searchPost(
_probeController.text,
pageKey,
tag: widget.tag,
category: widget.category,
);
}
} catch (e) {
_pagingController.error = e;
return;
}
final PaginationResult result = PaginationResult.fromJson(resp.body);
final parsed = result.data?.map((e) => Post.fromJson(e)).toList();
if (parsed != null && parsed.length >= 10) {
_pagingController.appendPage(parsed, pageKey + parsed.length);
} else if (parsed != null) {
_pagingController.appendLastPage(parsed);
}
setState(() => _isBusy = false);
}
@override
void initState() {
super.initState();
_pagingController.addPageRequestListener(_searchPosts);
}
@override
void dispose() {
_probeController.dispose();
_pagingController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
if (widget.tag != null)
ListTile(
leading: const Icon(Icons.label),
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
tileColor: Theme.of(context)
.colorScheme
.surfaceContainer
.withOpacity(0.5),
title: Text('postSearchWithTag'.trParams({'key': widget.tag!})),
),
if (widget.category != null)
ListTile(
leading: const Icon(Icons.category),
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
tileColor: Theme.of(context)
.colorScheme
.surfaceContainer
.withOpacity(0.5),
title: Text('postSearchWithCategory'.trParams({
'key': widget.category!,
})),
),
Container(
color: Theme.of(context)
.colorScheme
.secondaryContainer
.withOpacity(0.5),
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: TextField(
controller: _probeController,
decoration: InputDecoration(
isCollapsed: true,
border: InputBorder.none,
hintText: 'search'.tr,
),
onSubmitted: (_) {
_searchPosts(0);
},
),
),
if (_isBusy) const LoadingIndicator(),
Expanded(
child: RefreshIndicator(
onRefresh: () => Future.sync(() => _pagingController.refresh()),
child: CustomScrollView(
slivers: [
ControlledPostListWidget(
controller: _pagingController,
onUpdate: () => _pagingController.refresh(),
),
SliverGap(MediaQuery.of(context).padding.bottom),
],
),
),
),
],
),
);
}
}