Files
blog_app/lib/pages/home_page.dart
2025-11-21 14:11:35 +08:00

219 lines
4.9 KiB
Dart

import 'package:blog_app/apis/blog.dart';
import 'package:blog_app/layout/app_drawer.dart';
import 'package:blog_app/layout/app_navbar.dart';
import 'package:blog_app/layout/menu.dart';
import 'package:blog_app/models/blog.dart';
import 'package:blog_app/widget/search.dart';
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _currentPageIndex = 0;
late PageController _pageController;
bool _isSearching = false;
final TextEditingController _searchController = TextEditingController();
final FocusNode _searchFocusNode = FocusNode();
List<BlogSearch> _searchResults = [];
String _searchQuery = '';
@override
void initState() {
super.initState();
_pageController = PageController(initialPage: _currentPageIndex);
}
@override
void dispose() {
_pageController.dispose();
_searchController.dispose();
_searchFocusNode.dispose();
super.dispose();
}
void _startSearch() {
setState(() {
_isSearching = true;
});
Future.delayed(Duration(milliseconds: 100), () {
_searchFocusNode.requestFocus();
});
}
void _exitSearch() {
setState(() {
_isSearching = false;
_searchController.clear();
_searchResults.clear();
_searchQuery = '';
});
FocusScope.of(context).unfocus();
}
void _clearSearch() {
_searchController.clear();
setState(() {
_searchResults.clear();
_searchQuery = '';
});
}
void _onSearchTextChanged(String query) async {
setState(() {
_searchQuery = query;
});
if (query.isEmpty) {
setState(() {
_searchResults.clear();
});
return;
}
final result = await searchBlog(query);
setState(() {
_searchResults = result;
});
}
Widget _buildLeading() {
if (_isSearching) {
return IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: _exitSearch,
);
}
return Builder(
builder:
(context) => IconButton(
icon: Icon(Icons.menu, color: Colors.white),
onPressed: () => Scaffold.of(context).openDrawer(),
),
);
}
Widget _buildAppBarTitle() {
if (_isSearching) {
return buildSearchField(
controller: _searchController,
focusNode: _searchFocusNode,
onChanged: _onSearchTextChanged,
);
}
return Text(
pages[_currentPageIndex].title,
style: TextStyle(color: Colors.white),
);
}
List<Widget> _buildAppBarActions() {
if (_isSearching) {
return [
if (_searchController.text.isNotEmpty)
IconButton(
icon: Icon(Icons.clear, color: Colors.white),
onPressed: _clearSearch,
),
];
} else {
return [
IconButton(
icon: Icon(Icons.search, color: Colors.white),
onPressed: _startSearch,
),
];
}
}
Widget _buildPageView() {
return _isSearching ? _buildSearchResults() : _buildNormalPageView();
}
Widget _buildNormalPageView() {
return PageView(
controller: _pageController,
onPageChanged: (index) {
setState(() {
_currentPageIndex = index;
if (_isSearching) {
_exitSearch();
}
});
},
children: pageWidgets,
);
}
Widget _buildSearchResults() {
if (_searchQuery.isEmpty) {
return buildSearchQueryEmpty();
}
if (_searchResults.isEmpty) {
return buildSearchResultEmpty(_searchQuery);
}
return buildSearchResultList(context, _searchResults);
}
void _onTapNavbarItem(int index) {
setState(() {
_currentPageIndex = index;
if (_isSearching) {
_exitSearch();
}
});
_pageController.animateToPage(
index,
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
void onTapDrawerItem(int index) {
setState(() {
_currentPageIndex = index;
if (_isSearching) {
_exitSearch();
}
});
_pageController.animateToPage(
index,
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
Navigator.pop(context);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: _buildAppBarTitle(),
backgroundColor: Theme.of(context).colorScheme.primary,
elevation: 0,
leading: _buildLeading(),
actions: _buildAppBarActions(),
),
drawer: AppDrawer(
currentPageIndex: _currentPageIndex,
onTapDrawerItem: onTapDrawerItem,
),
body: Padding(padding: EdgeInsets.all(10), child: _buildPageView()),
bottomNavigationBar: AppNavbar(
currentPageIndex: _currentPageIndex,
onTapNavbarItem: _onTapNavbarItem,
),
);
}
}