Able to block anyone

💄 Optimize user profile page
This commit is contained in:
2024-09-26 23:47:19 +08:00
parent 3ac6822ab6
commit 2673c11046
11 changed files with 204 additions and 36 deletions

View File

@ -34,7 +34,7 @@ class Attachment {
String alt;
String mimetype;
String hash;
int destination;
String destination;
bool isAnalyzed;
bool isUploaded;
Map<String, dynamic>? metadata;

View File

@ -36,7 +36,7 @@ Attachment _$AttachmentFromJson(Map<String, dynamic> json) => Attachment(
alt: json['alt'] as String,
mimetype: json['mimetype'] as String,
hash: json['hash'] as String,
destination: (json['destination'] as num).toInt(),
destination: json['destination'] as String,
isAnalyzed: json['is_analyzed'] as bool,
isUploaded: json['is_uploaded'] as bool,
metadata: json['metadata'] as Map<String, dynamic>?,

View File

@ -26,6 +26,19 @@ class RelationshipProvider extends GetxController {
return _friends.any((x) => x.relatedId == account.id);
}
Future<Relationship?> getRelationship(int relatedId) async {
final AuthProvider auth = Get.find();
final client = await auth.configureClient('auth');
final resp = await client.get('/users/me/relations/$relatedId');
if (resp.statusCode == 404) {
return null;
} else if (resp.statusCode != 200) {
throw RequestException(resp);
}
return Relationship.fromJson(resp.body);
}
Future<Response> listRelation() async {
final AuthProvider auth = Get.find();
final client = await auth.configureClient('auth');
@ -38,7 +51,19 @@ class RelationshipProvider extends GetxController {
return client.get('/users/me/relations?status=$status');
}
Future<Response> makeFriend(String username) async {
Future<Relationship?> blockUser(String username) async {
final AuthProvider auth = Get.find();
final client = await auth.configureClient('auth');
final resp =
await client.post('/users/me/relations/block?related=$username', {});
if (resp.statusCode != 200) {
throw RequestException(resp);
}
return Relationship.fromJson(resp.body);
}
Future<Relationship?> makeFriend(String username) async {
final AuthProvider auth = Get.find();
final client = await auth.configureClient('auth');
final resp = await client.post('/users/me/relations?related=$username', {});
@ -46,7 +71,7 @@ class RelationshipProvider extends GetxController {
throw RequestException(resp);
}
return resp;
return Relationship.fromJson(resp.body);
}
Future<Response> handleRelation(
@ -64,17 +89,17 @@ class RelationshipProvider extends GetxController {
return resp;
}
Future<Response> editRelation(Relationship relationship, int status) async {
Future<Relationship?> editRelation(int relatedId, int status) async {
final AuthProvider auth = Get.find();
final client = await auth.configureClient('auth');
final resp = await client.patch(
'/users/me/relations/${relationship.relatedId}',
final resp = await client.put(
'/users/me/relations/$relatedId',
{'status': status},
);
if (resp.statusCode != 200) {
throw RequestException(resp);
}
return resp;
return Relationship.fromJson(resp.body);
}
}

View File

@ -13,6 +13,7 @@ import 'package:solian/models/attachment.dart';
import 'package:solian/models/daily_sign.dart';
import 'package:solian/models/pagination.dart';
import 'package:solian/models/post.dart';
import 'package:solian/models/relations.dart';
import 'package:solian/models/subscription.dart';
import 'package:solian/providers/account_status.dart';
import 'package:solian/providers/relation.dart';
@ -26,6 +27,7 @@ import 'package:solian/widgets/attachments/attachment_list.dart';
import 'package:solian/widgets/daily_sign/history_chart.dart';
import 'package:solian/widgets/posts/post_list.dart';
import 'package:solian/widgets/posts/post_warped_list.dart';
import 'package:solian/widgets/reports/abuse_report.dart';
import 'package:solian/widgets/sized_container.dart';
class AccountProfilePage extends StatefulWidget {
@ -50,6 +52,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
Account? _userinfo;
Subscription? _subscription;
Relationship? _relationship;
List<Post> _pinnedPosts = List.empty();
List<DailySignRecord> _dailySignRecords = List.empty();
int _totalUpvote = 0, _totalDownvote = 0;
@ -61,6 +64,15 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
setState(() => _isSubscribing = false);
}
Future<void> _getRelationship() async {
setState(() => _isBusy = true);
final relations = Get.find<RelationshipProvider>();
_relationship = await relations.getRelationship(_userinfo!.id);
setState(() => _isBusy = false);
}
Future<void> _getUserinfo() async {
setState(() => _isBusy = true);
@ -151,6 +163,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
});
_getUserinfo().then((_) {
_getRelationship();
_getSubscription();
_getPinnedPosts();
_getDailySignRecords();
@ -221,7 +234,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
),
),
if (_userinfo != null && _subscription == null)
OutlinedButton(
IconButton(
style: const ButtonStyle(
visualDensity:
VisualDensity(horizontal: -4, vertical: -2),
@ -235,10 +248,11 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
.subscribeToUser(_userinfo!.id);
setState(() => _isSubscribing = false);
},
child: Text('subscribe'.tr),
icon: const Icon(Icons.add_circle_outline),
tooltip: 'subscribe'.tr,
)
else if (_userinfo != null)
OutlinedButton(
IconButton(
style: const ButtonStyle(
visualDensity:
VisualDensity(horizontal: -4, vertical: -2),
@ -252,10 +266,10 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
_subscription = null;
setState(() => _isSubscribing = false);
},
child: Text('unsubscribe'.tr),
icon: const Icon(Icons.remove_circle_outline),
tooltip: 'unsubscribe'.tr,
),
if (_userinfo != null &&
!_relationshipProvider.hasFriend(_userinfo!))
if (_userinfo != null && _relationship == null)
IconButton(
icon: const Icon(Icons.person_add),
onPressed: _isMakingFriend
@ -263,7 +277,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
: () async {
setState(() => _isMakingFriend = true);
try {
await _relationshipProvider
_relationship = await _relationshipProvider
.makeFriend(widget.name);
context.showSnackbar(
'accountFriendRequestSent'.tr,
@ -274,6 +288,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
setState(() => _isMakingFriend = false);
}
},
tooltip: 'friendAdd'.tr,
)
else
const IconButton(
@ -300,6 +315,7 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
physics: const NeverScrollableScrollPhysics(),
children: [
ListView(
padding: EdgeInsets.zero,
children: [
const Gap(16),
CenteredContainer(
@ -421,9 +437,117 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
),
),
).marginOnly(
right: 24, left: 12, bottom: 8, top: 24),
right: 24,
left: 12,
bottom: 8,
top: 24,
),
)
],
appendWidgets: [
Card(
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 4,
horizontal: 8,
),
width: double.maxFinite,
child: Wrap(
alignment: WrapAlignment.spaceAround,
children: [
TextButton.icon(
style: const ButtonStyle(
visualDensity: VisualDensity(
horizontal: -4,
vertical: -2,
),
),
onPressed: () {
showDialog(
context: context,
builder: (context) => AbuseReportDialog(
resourceId: 'user:${_userinfo!.id}',
),
);
},
icon: const Icon(
Icons.flag,
size: 16,
),
label: Text('reportAbuse'.tr),
),
if (_relationship?.status != 2)
TextButton.icon(
style: const ButtonStyle(
visualDensity: VisualDensity(
horizontal: -4,
vertical: -2,
),
),
onPressed: _isMakingFriend
? null
: () async {
setState(
() => _isMakingFriend = true);
try {
_relationship =
await _relationshipProvider
.blockUser(widget.name);
context.showSnackbar(
'accountBlocked'.tr,
);
} catch (e) {
context.showErrorDialog(e);
} finally {
setState(() =>
_isMakingFriend = false);
}
},
icon: const Icon(
Icons.block,
size: 16,
),
label: Text('blockUser'.tr),
)
else
TextButton.icon(
style: const ButtonStyle(
visualDensity: VisualDensity(
horizontal: -4,
vertical: -2,
),
),
onPressed: _isMakingFriend
? null
: () async {
setState(
() => _isMakingFriend = true);
try {
_relationship =
await _relationshipProvider
.editRelation(
_userinfo!.id, 1);
context.showSnackbar(
'accountUnblocked'.tr,
);
} catch (e) {
context.showErrorDialog(e);
} finally {
setState(() =>
_isMakingFriend = false);
}
},
icon: const Icon(
Icons.add_circle_outline,
size: 16,
),
label: Text('unblockUser'.tr),
),
],
),
),
),
],
),
),
],

View File

@ -23,6 +23,7 @@ class AccountHeadingWidget extends StatelessWidget {
final AccountProfile? profile;
final List<AccountBadge>? badges;
final List<Widget>? extraWidgets;
final List<Widget>? appendWidgets;
final Future<Response>? status;
final Function? onEditStatus;
@ -39,6 +40,7 @@ class AccountHeadingWidget extends StatelessWidget {
this.profile,
this.status,
this.extraWidgets,
this.appendWidgets,
this.onEditStatus,
});
@ -257,6 +259,7 @@ class AccountHeadingWidget extends StatelessWidget {
),
),
).paddingSymmetric(horizontal: 16),
...?appendWidgets?.map((x) => x.paddingSymmetric(horizontal: 16)),
],
),
);

View File

@ -106,10 +106,14 @@ class _AccountProfilePopupState extends State<AccountProfilePopup> {
extraWidgets: [
Card(
child: ListTile(
leading: const Icon(
Icons.contact_page_outlined,
),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
title: Text('visitProfilePage'.tr),
subtitle: Text('learMoreAboutPerson'.tr),
visualDensity:
const VisualDensity(horizontal: -4, vertical: -2),
trailing: const Icon(Icons.chevron_right),

View File

@ -28,42 +28,46 @@ class SilverRelativeList extends StatelessWidget {
showModalBottomSheet(
useRootNavigator: true,
isScrollControlled: true,
backgroundColor: Theme
.of(context)
.colorScheme
.surface,
backgroundColor: Theme.of(context).colorScheme.surface,
context: context,
builder: (context) =>
AccountProfilePopup(
name: element.related.name,
),
builder: (context) => AccountProfilePopup(
name: element.related.name,
),
);
},
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
if(element.status != 1 && element.status != 3)
if (element.status != 1 && element.status != 3)
IconButton(
icon: const Icon(Icons.check),
onPressed: () {
final RelationshipProvider provider = Get.find();
if (element.status == 0) {
provider.handleRelation(element, true).then((_) => onUpdate());
provider
.handleRelation(element, true)
.then((_) => onUpdate());
} else {
provider.editRelation(element, 1).then((_) => onUpdate());
provider
.editRelation(element.relatedId, 1)
.then((_) => onUpdate());
}
},
),
if(element.status != 2 && element.status != 3)
if (element.status != 2 && element.status != 3)
IconButton(
icon: const Icon(Icons.close),
onPressed: () {
final RelationshipProvider provider = Get.find();
if (element.status == 0) {
provider.handleRelation(element, false).then((_) => onUpdate());
provider
.handleRelation(element, false)
.then((_) => onUpdate());
} else {
provider.editRelation(element, 2).then((_) => onUpdate());
provider
.editRelation(element.relatedId, 2)
.then((_) => onUpdate());
}
},
),