import 'dart:async'; import 'package:event_bus/event_bus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:kiwi/kiwi.dart'; import 'package:logging/logging.dart'; import 'package:nc_photos/account.dart'; import 'package:nc_photos/app_localizations.dart'; import 'package:nc_photos/controller/account_controller.dart'; import 'package:nc_photos/di_container.dart'; import 'package:nc_photos/entity/album.dart'; import 'package:nc_photos/entity/album/data_source.dart'; import 'package:nc_photos/entity/file.dart'; import 'package:nc_photos/entity/file/data_source.dart'; import 'package:nc_photos/k.dart' as k; import 'package:nc_photos/or_null.dart'; import 'package:nc_photos/pref.dart'; import 'package:nc_photos/theme.dart'; import 'package:nc_photos/use_case/import_potential_shared_album.dart'; import 'package:nc_photos/widget/home_collections.dart'; import 'package:nc_photos/widget/home_photos.dart'; import 'package:nc_photos/widget/home_search.dart'; import 'package:np_codegen/np_codegen.dart'; part 'home.g.dart'; class HomeArguments { HomeArguments(this.account); final Account account; } class Home extends StatefulWidget { static const routeName = "/home"; static Route buildRoute(HomeArguments args) => MaterialPageRoute( builder: (context) => Home.fromArgs(args), ); const Home({ Key? key, required this.account, }) : super(key: key); Home.fromArgs(HomeArguments args, {Key? key}) : this( key: key, account: args.account, ); @override createState() => _HomeState(); final Account account; } @npLog class _HomeState extends State with TickerProviderStateMixin { @override initState() { super.initState(); _importPotentialSharedAlbum().then((value) { if (value.isNotEmpty) { AccountPref.of(widget.account).setNewSharedAlbum(true); } }); _animationController.value = 1; // call once to pre-cache the value unawaited(context .read() .serverController .status .first .then((value) { _log.info("Server status: $value"); })); } @override dispose() { _animationController.dispose(); super.dispose(); } @override build(BuildContext context) { return Scaffold( bottomNavigationBar: _buildBottomNavigationBar(context), body: Builder(builder: (context) => _buildContent(context)), extendBody: true, resizeToAvoidBottomInset: false, ); } Widget _buildBottomNavigationBar(BuildContext context) { return NavigationBar( destinations: [ NavigationDestination( icon: const Icon(Icons.photo_outlined), selectedIcon: const Icon(Icons.photo), label: L10n.global().photosTabLabel, ), NavigationDestination( icon: const Icon(Icons.search), label: L10n.global().searchTooltip, ), NavigationDestination( icon: const Icon(Icons.grid_view_outlined), selectedIcon: const Icon(Icons.grid_view_sharp), label: L10n.global().collectionsTooltip, ), ], selectedIndex: _nextPage, onDestinationSelected: _onTapNavItem, backgroundColor: Theme.of(context).homeNavigationBarBackgroundColor, ); } Widget _buildContent(BuildContext context) { return PageView.builder( controller: _pageController, physics: const NeverScrollableScrollPhysics(), itemCount: 3, itemBuilder: (context, index) => SlideTransition( position: Tween( begin: const Offset(0, .05), end: Offset.zero, ).animate(_animation), child: FadeTransition( opacity: _animation, child: _buildPage(context, index), ), ), ); } Widget _buildPage(BuildContext context, int index) { switch (index) { case 0: return HomePhotos( account: widget.account, ); case 1: return HomeSearch( account: widget.account, ); case 2: return const HomeCollections(); default: throw ArgumentError("Invalid page index: $index"); } } void _onTapNavItem(int index) { if (index == _nextPage) { if (index == 0) { KiwiContainer() .resolve() .fire(const HomePhotosBackToTopEvent()); } return; } _pageController.jumpToPage(index); setState(() { _nextPage = index; }); _animationController ..reset() ..forward(); } Future> _importPotentialSharedAlbum() async { final c = KiwiContainer().resolve().copyWith( // don't want the potential albums to be cached at this moment fileRepo: OrNull(const FileRepo(FileWebdavDataSource())), albumRepo: OrNull(AlbumRepo(AlbumRemoteDataSource())), ); try { return await ImportPotentialSharedAlbum(c)( widget.account, AccountPref.of(widget.account)); } catch (e, stacktrace) { _log.shout( "[_importPotentialSharedAlbum] Failed while ImportPotentialSharedAlbum", e, stacktrace); return []; } } final _pageController = PageController(initialPage: 0, keepPage: false); int _nextPage = 0; late final _animationController = AnimationController( duration: k.animationDurationTabTransition, vsync: this, ); late final _animation = CurvedAnimation( parent: _animationController, curve: Curves.easeIn, ); }