import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:lemmy_api_client/v3.dart'; import '../../l10n/l10n.dart'; import '../../util/extensions/context.dart'; import '../../util/icons.dart'; import '../../util/mobx_provider.dart'; import '../../util/observer_consumers.dart'; import '../../util/share.dart'; import '../../util/text_color.dart'; import '../../widgets/cached_network_image.dart'; import '../../widgets/failed_to_load.dart'; import '../../widgets/fullscreenable_image.dart'; import '../../widgets/reveal_after_scroll.dart'; import '../../widgets/sortable_infinite_list.dart'; import 'instance_about_tab.dart'; import 'instance_more_menu.dart'; import 'instance_store.dart'; /// Displays posts, comments, and general info about the given instance class InstancePage extends HookWidget { const InstancePage(); @override Widget build(BuildContext context) { final theme = Theme.of(context); final colorOnCard = textColorBasedOnBackground(theme.cardColor); final scrollController = useScrollController(); return ObserverBuilder( builder: (context, store) { final instanceUrl = 'https://${store.instanceHost}'; return store.siteState.map( loading: () => Scaffold( appBar: AppBar(), body: const Center(child: CircularProgressIndicator.adaptive()), ), error: (errorTerm) => Scaffold( appBar: AppBar(), body: Center( child: FailedToLoad( refresh: () => store.fetch( context.defaultJwt(store.instanceHost), ), message: errorTerm.tr(context), ), ), ), data: (site) { final siteView = site.siteView; if (siteView == null) { return Scaffold( appBar: AppBar(), body: Center(child: Text(L10n.of(context).site_not_set_up)), ); } return Scaffold( body: DefaultTabController( length: 3, child: NestedScrollView( controller: scrollController, headerSliverBuilder: (context, innerBoxIsScrolled) => [ SliverAppBar( expandedHeight: 250, pinned: true, backgroundColor: theme.cardColor, title: RevealAfterScroll( after: 150, fade: true, scrollController: scrollController, child: Text( siteView.site.name, style: TextStyle(color: colorOnCard), ), ), actions: [ IconButton( icon: Icon(shareIcon), onPressed: () => share(instanceUrl, context: context), ), IconButton( icon: Icon(moreIcon), onPressed: () => InstanceMoreMenu.open(context, site), ), ], flexibleSpace: FlexibleSpaceBar( background: Stack( children: [ if (siteView.site.banner != null) FullscreenableImage( url: siteView.site.banner!, child: CachedNetworkImage( imageUrl: siteView.site.banner!, errorBuilder: (_, ___) => const SizedBox(), ), ), SafeArea( child: Center( child: Column( children: [ Padding( padding: const EdgeInsets.only(top: 40), child: siteView.site.icon == null ? const SizedBox( height: 100, width: 100, ) : FullscreenableImage( url: siteView.site.icon!, child: CachedNetworkImage( width: 100, height: 100, imageUrl: siteView.site.icon!, errorBuilder: (_, ___) => const Icon(Icons.warning), ), ), ), Text( siteView.site.name, style: theme.textTheme.headline6, ), Text( store.instanceHost, style: theme.textTheme.caption, ) ], ), ), ), ], ), ), bottom: PreferredSize( preferredSize: const TabBar(tabs: []).preferredSize, child: Material( color: theme.cardColor, child: TabBar( tabs: [ Tab(text: L10n.of(context).posts), Tab(text: L10n.of(context).comments), Tab(text: L10n.of(context).about), ], ), ), ), ), ], body: TabBarView( children: [ InfinitePostList( fetcher: (page, batchSize, sort) => LemmyApiV3(store.instanceHost).run(GetPosts( // TODO: switch between all and subscribed type: PostListingType.all, sort: sort, limit: batchSize, page: page, savedOnly: false, auth: context.defaultJwt(store.instanceHost)?.raw, )), ), InfiniteCommentList( fetcher: (page, batchSize, sort) => LemmyApiV3(store.instanceHost).run(GetComments( type: CommentListingType.all, sort: sort, limit: batchSize, page: page, savedOnly: false, auth: context.defaultJwt(store.instanceHost)?.raw, )), ), InstanceAboutTab( site: site, siteView: siteView, ), ], ), ), ), ); }, ); }, ); } static Route route(String instanceHost) { return MaterialPageRoute( builder: (context) { return MobxProvider( create: (context) => InstanceStore(instanceHost) ..fetch(context.defaultJwt(instanceHost)), child: const InstancePage(), ); }, ); } }