2020-08-31 21:04:17 +02:00
|
|
|
import 'package:cached_network_image/cached_network_image.dart';
|
2020-08-31 12:05:45 +02:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
|
|
import 'package:intl/intl.dart';
|
|
|
|
import 'package:lemmy_api_client/lemmy_api_client.dart';
|
|
|
|
import 'package:timeago/timeago.dart' as timeago;
|
|
|
|
|
2020-08-31 15:43:09 +02:00
|
|
|
import '../util/intl.dart';
|
|
|
|
|
2020-08-31 12:05:45 +02:00
|
|
|
class UserProfile extends HookWidget {
|
2020-09-01 11:55:22 +02:00
|
|
|
final int userId;
|
2020-08-31 12:05:45 +02:00
|
|
|
final Future<UserView> _userView;
|
2020-09-01 11:55:22 +02:00
|
|
|
final String instanceUrl;
|
2020-08-31 12:05:45 +02:00
|
|
|
|
2020-09-01 11:55:22 +02:00
|
|
|
UserProfile({@required this.userId, @required this.instanceUrl})
|
|
|
|
: _userView = LemmyApi(instanceUrl)
|
2020-08-31 12:05:45 +02:00
|
|
|
.v1
|
2020-09-01 11:55:22 +02:00
|
|
|
.getUserDetails(
|
|
|
|
userId: userId, savedOnly: true, sort: SortType.active)
|
|
|
|
.then((res) => res.user);
|
2020-08-31 12:05:45 +02:00
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
var theme = Theme.of(context);
|
|
|
|
|
|
|
|
var userViewSnap = useFuture(_userView);
|
|
|
|
|
2020-09-01 11:55:22 +02:00
|
|
|
Widget bio;
|
|
|
|
|
|
|
|
if (userViewSnap.hasData) {
|
|
|
|
if (userViewSnap.data.bio != null) {
|
|
|
|
bio = Text(userViewSnap.data.bio);
|
|
|
|
} else {
|
|
|
|
bio = Center(
|
|
|
|
child: Text(
|
|
|
|
'no bio',
|
|
|
|
style: const TextStyle(fontStyle: FontStyle.italic),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
bio = Center(child: CircularProgressIndicator());
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget tabs() => DefaultTabController(
|
2020-08-31 21:04:17 +02:00
|
|
|
length: 3,
|
|
|
|
child: Column(
|
|
|
|
children: [
|
|
|
|
TabBar(
|
|
|
|
labelColor: theme.textTheme.bodyText1.color,
|
|
|
|
tabs: [
|
|
|
|
Tab(text: 'Posts'),
|
|
|
|
Tab(text: 'Comments'),
|
|
|
|
Tab(text: 'About'),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
Expanded(
|
|
|
|
child: TabBarView(
|
|
|
|
children: [
|
|
|
|
Center(
|
2020-09-01 11:55:22 +02:00
|
|
|
child: Text(
|
|
|
|
'Posts',
|
|
|
|
style: const TextStyle(fontSize: 36),
|
|
|
|
),
|
|
|
|
),
|
2020-08-31 21:04:17 +02:00
|
|
|
Center(
|
2020-09-01 11:55:22 +02:00
|
|
|
child: Text(
|
|
|
|
'Comments',
|
|
|
|
style: const TextStyle(fontSize: 36),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
bio,
|
2020-08-31 21:04:17 +02:00
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
2020-08-31 12:05:45 +02:00
|
|
|
return Center(
|
|
|
|
child: Stack(
|
|
|
|
children: [
|
2020-09-01 11:55:22 +02:00
|
|
|
if (userViewSnap.data?.banner != null)
|
2020-08-31 21:04:17 +02:00
|
|
|
CachedNetworkImage(
|
2020-09-01 11:55:22 +02:00
|
|
|
imageUrl: userViewSnap.data.banner,
|
2020-08-31 21:04:17 +02:00
|
|
|
)
|
|
|
|
else
|
|
|
|
Container(
|
|
|
|
width: double.infinity,
|
|
|
|
height: double.infinity,
|
|
|
|
color: theme.primaryColor,
|
|
|
|
),
|
2020-08-31 12:05:45 +02:00
|
|
|
SafeArea(
|
|
|
|
child: Padding(
|
|
|
|
padding: const EdgeInsets.only(top: 60),
|
|
|
|
child: SizedBox(
|
|
|
|
width: double.infinity,
|
|
|
|
height: double.infinity,
|
|
|
|
child: Container(
|
|
|
|
decoration: BoxDecoration(
|
2020-09-01 11:55:22 +02:00
|
|
|
borderRadius: BorderRadius.only(
|
|
|
|
topRight: Radius.circular(40),
|
|
|
|
topLeft: Radius.circular(40),
|
|
|
|
),
|
2020-08-31 12:05:45 +02:00
|
|
|
color: theme.scaffoldBackgroundColor,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
SafeArea(
|
|
|
|
child: Column(
|
|
|
|
children: [
|
2020-09-01 11:55:22 +02:00
|
|
|
if (userViewSnap.data?.avatar != null)
|
2020-08-31 21:04:17 +02:00
|
|
|
SizedBox(
|
|
|
|
width: 80,
|
|
|
|
height: 80,
|
|
|
|
child: Container(
|
|
|
|
// clipBehavior: Clip.antiAlias,
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
boxShadow: [
|
|
|
|
BoxShadow(blurRadius: 6, color: Colors.black54)
|
|
|
|
],
|
|
|
|
borderRadius: BorderRadius.all(Radius.circular(15)),
|
|
|
|
border: Border.all(color: Colors.white, width: 3),
|
|
|
|
),
|
|
|
|
child: ClipRRect(
|
|
|
|
borderRadius: BorderRadius.all(Radius.circular(12)),
|
|
|
|
child: CachedNetworkImage(
|
2020-09-01 11:55:22 +02:00
|
|
|
imageUrl: userViewSnap.data.avatar,
|
2020-08-31 21:04:17 +02:00
|
|
|
),
|
|
|
|
),
|
2020-08-31 12:05:45 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
Padding(
|
2020-09-01 11:55:22 +02:00
|
|
|
padding: userViewSnap.data?.avatar != null
|
|
|
|
? const EdgeInsets.only(top: 8.0)
|
|
|
|
: const EdgeInsets.only(top: 70),
|
2020-08-31 12:05:45 +02:00
|
|
|
child: Text(
|
2020-09-01 11:55:22 +02:00
|
|
|
userViewSnap.data?.preferredUsername ??
|
|
|
|
userViewSnap.data?.name ??
|
|
|
|
'',
|
2020-08-31 12:05:45 +02:00
|
|
|
style: theme.textTheme.headline6,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsets.only(top: 4.0),
|
|
|
|
child: Text(
|
2020-09-01 11:55:22 +02:00
|
|
|
'@${userViewSnap.data?.name ?? ''}@$instanceUrl',
|
2020-08-31 12:05:45 +02:00
|
|
|
style: theme.textTheme.caption,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsets.only(top: 10.0),
|
|
|
|
child: Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
children: [
|
2020-08-31 21:04:17 +02:00
|
|
|
_Badge(
|
2020-08-31 15:43:09 +02:00
|
|
|
icon: Icons.comment, // TODO: should be article icon
|
2020-08-31 12:05:45 +02:00
|
|
|
text: '''
|
2020-08-31 15:43:09 +02:00
|
|
|
${compactNumber(userViewSnap.data?.numberOfPosts ?? 0)} Post${pluralS(userViewSnap.data?.numberOfPosts ?? 0)}''',
|
2020-08-31 21:04:17 +02:00
|
|
|
isLoading: !userViewSnap.hasData,
|
2020-08-31 12:05:45 +02:00
|
|
|
),
|
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsets.only(left: 16.0),
|
2020-08-31 21:04:17 +02:00
|
|
|
child: _Badge(
|
2020-08-31 12:05:45 +02:00
|
|
|
icon: Icons.comment,
|
|
|
|
text: '''
|
2020-08-31 15:43:09 +02:00
|
|
|
${compactNumber(userViewSnap.data?.numberOfComments ?? 0)} Comment${pluralS(userViewSnap.data?.numberOfComments ?? 1)}''',
|
2020-08-31 21:04:17 +02:00
|
|
|
isLoading: !userViewSnap.hasData,
|
2020-08-31 12:05:45 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsets.only(top: 8.0),
|
|
|
|
child: Text(
|
2020-09-01 11:55:22 +02:00
|
|
|
'''
|
|
|
|
Joined ${userViewSnap.hasData ? timeago.format(userViewSnap.data.published) : ''}''',
|
2020-08-31 12:05:45 +02:00
|
|
|
style: theme.textTheme.bodyText1,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
children: [
|
|
|
|
Icon(
|
|
|
|
Icons.cake,
|
|
|
|
size: 13,
|
|
|
|
),
|
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsets.only(left: 4.0),
|
|
|
|
child: Text(
|
2020-09-01 11:55:22 +02:00
|
|
|
userViewSnap.hasData
|
|
|
|
? DateFormat('MMM dd, yyyy')
|
|
|
|
.format(userViewSnap.data.published)
|
|
|
|
: '',
|
2020-08-31 12:05:45 +02:00
|
|
|
style: theme.textTheme.bodyText1,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
2020-09-01 11:55:22 +02:00
|
|
|
Expanded(child: tabs())
|
2020-08-31 12:05:45 +02:00
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
2020-08-31 21:04:17 +02:00
|
|
|
}
|
2020-08-31 12:05:45 +02:00
|
|
|
|
2020-08-31 21:04:17 +02:00
|
|
|
class _Badge extends StatelessWidget {
|
|
|
|
final IconData icon;
|
|
|
|
final String text;
|
|
|
|
final bool isLoading;
|
2020-08-31 12:05:45 +02:00
|
|
|
|
2020-08-31 21:04:17 +02:00
|
|
|
_Badge({
|
|
|
|
@required this.icon,
|
|
|
|
@required this.isLoading,
|
|
|
|
@required this.text,
|
|
|
|
});
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
var theme = Theme.of(context);
|
|
|
|
|
|
|
|
return Container(
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
color: theme.accentColor,
|
|
|
|
borderRadius: BorderRadius.all(Radius.circular(5)),
|
|
|
|
),
|
|
|
|
child: Padding(
|
|
|
|
padding: const EdgeInsets.all(4.0),
|
|
|
|
child: isLoading
|
|
|
|
? CircularProgressIndicator()
|
|
|
|
: Row(
|
2020-08-31 12:05:45 +02:00
|
|
|
children: [
|
2020-08-31 21:04:17 +02:00
|
|
|
Icon(icon, size: 15, color: Colors.white),
|
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsets.only(left: 4.0),
|
|
|
|
child: Text(text),
|
|
|
|
),
|
2020-08-31 12:05:45 +02:00
|
|
|
],
|
|
|
|
),
|
2020-08-31 21:04:17 +02:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
2020-08-31 12:05:45 +02:00
|
|
|
}
|