✨ Social credit points & quick send friend request
This commit is contained in:
@ -7,13 +7,12 @@ import 'package:solian/models/account.dart';
|
||||
import 'package:solian/models/attachment.dart';
|
||||
import 'package:solian/models/pagination.dart';
|
||||
import 'package:solian/models/post.dart';
|
||||
import 'package:solian/screens/account/notification.dart';
|
||||
import 'package:solian/providers/relation.dart';
|
||||
import 'package:solian/services.dart';
|
||||
import 'package:solian/theme.dart';
|
||||
import 'package:solian/widgets/account/account_avatar.dart';
|
||||
import 'package:solian/widgets/app_bar_leading.dart';
|
||||
import 'package:solian/widgets/attachments/attachment_list.dart';
|
||||
import 'package:solian/widgets/current_state_action.dart';
|
||||
import 'package:solian/widgets/feed/feed_list.dart';
|
||||
import 'package:solian/widgets/posts/post_list.dart';
|
||||
import 'package:solian/widgets/sized_container.dart';
|
||||
@ -28,11 +27,13 @@ class AccountProfilePage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _AccountProfilePageState extends State<AccountProfilePage> {
|
||||
late final RelationshipProvider _relationshipProvider;
|
||||
late final PostListController _postController;
|
||||
final PagingController<int, Attachment> _albumPagingController =
|
||||
PagingController(firstPageKey: 0);
|
||||
|
||||
bool _isBusy = true;
|
||||
bool _isMakingFriend = false;
|
||||
bool _showMature = false;
|
||||
|
||||
Account? _userinfo;
|
||||
@ -63,22 +64,35 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
|
||||
_totalDownvote = resp.body['total_downvote'];
|
||||
}
|
||||
|
||||
resp = await client.get('/users/${widget.name}/pin');
|
||||
setState(() => _isBusy = false);
|
||||
}
|
||||
|
||||
Future<void> getPinnedPosts() async {
|
||||
final client = ServiceFinder.configureClient('interactive');
|
||||
final resp = await client.get('/users/${widget.name}/pin');
|
||||
if (resp.statusCode != 200) {
|
||||
context.showErrorDialog(resp.bodyString).then((_) {
|
||||
Navigator.pop(context);
|
||||
});
|
||||
} else {
|
||||
_pinnedPosts =
|
||||
resp.body.map((x) => Post.fromJson(x)).toList().cast<Post>();
|
||||
setState(() {
|
||||
_pinnedPosts =
|
||||
resp.body.map((x) => Post.fromJson(x)).toList().cast<Post>();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
setState(() => _isBusy = false);
|
||||
int get _userSocialCreditPoints {
|
||||
int birthPart =
|
||||
DateTime.now().difference(_userinfo!.createdAt.toLocal()).inSeconds;
|
||||
birthPart = birthPart >> 16;
|
||||
return _totalUpvote * 2 - _totalDownvote + birthPart;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_relationshipProvider = Get.find();
|
||||
_postController = PostListController(author: widget.name);
|
||||
_albumPagingController.addPageRequestListener((pageKey) async {
|
||||
final client = ServiceFinder.configureClient('files');
|
||||
@ -99,7 +113,26 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
|
||||
_albumPagingController.error = resp.bodyString;
|
||||
}
|
||||
});
|
||||
|
||||
getUserinfo();
|
||||
getPinnedPosts();
|
||||
}
|
||||
|
||||
Widget _buildStatisticsEntry(String label, String content) {
|
||||
return Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
Text(
|
||||
content,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -147,8 +180,29 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
|
||||
],
|
||||
),
|
||||
),
|
||||
const BackgroundStateWidget(),
|
||||
const NotificationButton(),
|
||||
if (_userinfo != null &&
|
||||
!_relationshipProvider.hasFriend(_userinfo!))
|
||||
IconButton(
|
||||
icon: const Icon(Icons.person_add),
|
||||
onPressed: _isMakingFriend
|
||||
? null
|
||||
: () async {
|
||||
setState(() => _isMakingFriend = true);
|
||||
try {
|
||||
await _relationshipProvider.makeFriend(widget.name);
|
||||
context.showSnackbar('accountFriendRequestSent'.tr);
|
||||
} catch (e) {
|
||||
context.showErrorDialog(e);
|
||||
} finally {
|
||||
setState(() => _isMakingFriend = false);
|
||||
}
|
||||
},
|
||||
)
|
||||
else
|
||||
const IconButton(
|
||||
icon: Icon(Icons.handshake),
|
||||
onPressed: null,
|
||||
),
|
||||
SizedBox(
|
||||
width: SolianTheme.isLargeScreen(context) ? 8 : 16,
|
||||
),
|
||||
@ -167,33 +221,42 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
RefreshIndicator(
|
||||
onRefresh: () => _postController.reloadAllOver(),
|
||||
onRefresh: () => Future.wait([
|
||||
_postController.reloadAllOver(),
|
||||
getPinnedPosts(),
|
||||
]),
|
||||
child: CustomScrollView(slivers: [
|
||||
SliverToBoxAdapter(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
child: Column(
|
||||
children: [
|
||||
Column(
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Text(
|
||||
'totalUpvote'.tr,
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
Text(
|
||||
_totalUpvote.toString(),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
_buildStatisticsEntry(
|
||||
'totalSocialCreditPoints'.tr,
|
||||
_userinfo != null
|
||||
? _userSocialCreditPoints.toString()
|
||||
: 0.toString(),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Text(
|
||||
'totalDownvote'.tr,
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
Obx(
|
||||
() => _buildStatisticsEntry(
|
||||
'totalPostCount'.tr,
|
||||
_postController.postTotal.value.toString(),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
_buildStatisticsEntry(
|
||||
'totalUpvote'.tr,
|
||||
_totalUpvote.toString(),
|
||||
),
|
||||
_buildStatisticsEntry(
|
||||
'totalDownvote'.tr,
|
||||
_totalDownvote.toString(),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -62,8 +62,10 @@ class _SignInPopupState extends State<SignInPopup> with ProtocolListener {
|
||||
|
||||
try {
|
||||
await auth.signin(context, username, password);
|
||||
await auth.refreshAuthorizeStatus();
|
||||
await auth.refreshUserProfile();
|
||||
await Future.delayed(const Duration(milliseconds: 250), () async {
|
||||
await auth.refreshAuthorizeStatus();
|
||||
await auth.refreshUserProfile();
|
||||
});
|
||||
} on RiskyAuthenticateException catch (e) {
|
||||
showDialog(
|
||||
context: context,
|
||||
@ -77,7 +79,8 @@ class _SignInPopupState extends State<SignInPopup> with ProtocolListener {
|
||||
onPressed: () {
|
||||
const redirect = 'solink://auth?status=done';
|
||||
launchUrlString(
|
||||
ServiceFinder.buildUrl('passport', '/mfa?redirect_uri=$redirect&ticketId=${e.ticketId}'),
|
||||
ServiceFinder.buildUrl('passport',
|
||||
'/mfa?redirect_uri=$redirect&ticketId=${e.ticketId}'),
|
||||
mode: LaunchMode.inAppWebView,
|
||||
);
|
||||
Navigator.pop(context);
|
||||
|
Reference in New Issue
Block a user