Add InstancePage

* top section finished
* about section partially done
This commit is contained in:
krawieck 2020-09-07 21:29:07 +02:00
parent 6eb0d10fb9
commit c53cd047b7
1 changed files with 240 additions and 0 deletions

240
lib/pages/instance.dart Normal file
View File

@ -0,0 +1,240 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:lemmy_api_client/lemmy_api_client.dart';
import '../util/text_color.dart';
import '../widgets/badge.dart';
import '../widgets/markdown_text.dart';
class InstancePage extends HookWidget {
final String instanceUrl;
final Future<FullSiteView> siteFuture;
void _share() {
print('SHARE');
}
void _openMoreMenu() {
print('OPEN MORE MENU');
}
InstancePage({@required this.instanceUrl})
: assert(instanceUrl != null),
siteFuture = LemmyApi(instanceUrl).v1.getSite();
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final siteSnap = useFuture(siteFuture);
final colorOnCard = textColorBasedOnBackground(theme.cardColor);
if (!siteSnap.hasData) {
return Scaffold(
appBar: AppBar(
iconTheme: theme.iconTheme,
backgroundColor: theme.cardColor,
elevation: 0,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (siteSnap.hasError) ...[
Icon(Icons.error),
Padding(
padding: const EdgeInsets.all(8),
child: Text('ERROR: ${siteSnap.error}'),
)
] else
CircularProgressIndicator(semanticsLabel: 'loading')
],
),
),
);
}
final site = siteSnap.data;
return Scaffold(
body: DefaultTabController(
length: 3,
child: NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
expandedHeight: 200,
floating: false,
pinned: true,
elevation: 0,
backgroundColor: theme.cardColor,
iconTheme: theme.iconTheme,
title: Text(
'${site.site.name}',
style: TextStyle(color: colorOnCard),
),
actions: [
IconButton(icon: Icon(Icons.share), onPressed: _share),
IconButton(
icon: Icon(Icons.more_vert), onPressed: _openMoreMenu),
],
flexibleSpace: FlexibleSpaceBar(
background: Stack(children: [
if (site.site.banner != null)
CachedNetworkImage(imageUrl: site.site.banner),
SafeArea(
child: Center(
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 40),
child: CachedNetworkImage(
width: 100,
height: 100,
imageUrl: site.site.icon),
),
Text(site.site.name,
style: theme.textTheme.headline6),
Text(instanceUrl, style: theme.textTheme.caption)
],
),
),
),
]),
),
),
SliverPersistentHeader(
delegate: _SliverAppBarDelegate(
TabBar(
labelColor: theme.textTheme.bodyText1.color,
unselectedLabelColor: Colors.grey,
tabs: [
Tab(text: 'Posts'),
Tab(text: 'Comments'),
Tab(text: 'About'),
],
),
),
pinned: true,
),
];
},
body: TabBarView(
children: [
ListView(
children: [
Center(child: Text('posts go here')),
],
),
ListView(
children: [
Center(child: Text('comments go here')),
],
),
_AboutTab(site),
],
),
),
),
);
}
}
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate(this._tabBar);
final TabBar _tabBar;
@override
double get minExtent => _tabBar.preferredSize.height;
@override
double get maxExtent => _tabBar.preferredSize.height;
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
final theme = Theme.of(context);
return Container(child: _tabBar, color: theme.cardColor);
}
@override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
return false;
}
}
class _AboutTab extends StatelessWidget {
final FullSiteView site;
const _AboutTab(this.site);
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: SafeArea(
top: false,
child: Column(
// padding: EdgeInsets.only(top: 0),
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
child: MarkdownText(site.site.description),
),
_Divider(),
SizedBox(
height: 25,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
SizedBox(width: 7),
_Badge('X users online'),
_Badge('${site.site.numberOfUsers} users'),
_Badge('${site.site.numberOfCommunities} communities'),
_Badge('${site.site.numberOfPosts} posts'),
_Badge('${site.site.numberOfComments} comments'),
SizedBox(width: 15),
],
),
),
_Divider(),
Text('Trending communities:'),
// TODO: put here trending communities
],
),
),
);
}
}
class _Badge extends StatelessWidget {
final String text;
_Badge(this.text);
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Padding(
padding: const EdgeInsets.only(left: 8),
child: Badge(
child: Text(
text,
style:
TextStyle(color: textColorBasedOnBackground(theme.accentColor)),
),
// TODO: change border radius
),
);
}
}
class _Divider extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
child: Divider(),
);
}
}