♻️ Refactored the relationship screen according to server updates

This commit is contained in:
2026-01-07 01:42:20 +08:00
parent 757f1b880c
commit c6fd342072
12 changed files with 197 additions and 110 deletions

View File

@@ -283,14 +283,17 @@
"relationshipStatusBlocked": "Blocked", "relationshipStatusBlocked": "Blocked",
"blockUser": "Block User", "blockUser": "Block User",
"unblockUser": "Unblock User", "unblockUser": "Unblock User",
"forgotRelationship": "Forgot Relationship",
"forgotRelationshipConfirm": "Are you sure you want to forget your relationship with {}?",
"relationshipDeleted": "Relationship deleted",
"friendRequestAccepted": "Accepted friend request from {}", "friendRequestAccepted": "Accepted friend request from {}",
"friendRequestDeclined": "Declined friend request from {}", "friendRequestDeclined": "Declined friend request from {}",
"requestExpiredIn": "Expired in {}", "requestExpiredIn": "Expired in {}",
"friendSentRequest": "Sent Friend Requests", "friendRequests": "Friend Requests",
"friendSentRequestEmpty": "No sent friend requests", "friendRequestsEmpty": "No related friend requests",
"friendSentRequestHint": { "friendRequestsHint": {
"one": "{} friend request sent", "one": "{} friend request",
"other": "{} friend requests sent" "other": "{} friend requests"
}, },
"levelingProgress": "Leveling Progress", "levelingProgress": "Leveling Progress",
"levelingProgressExperience": "{} EXP", "levelingProgressExperience": "{} EXP",

View File

@@ -265,6 +265,9 @@
"relationshipStatusBlocked": "Blocked", "relationshipStatusBlocked": "Blocked",
"blockUser": "Block User", "blockUser": "Block User",
"unblockUser": "Unblock User", "unblockUser": "Unblock User",
"forgotRelationship": "Olvidar Relación",
"forgotRelationshipConfirm": "¿Estás seguro de que quieres olvidar tu relación con {}?",
"relationshipDeleted": "Relación eliminada",
"friendRequestAccepted": "Accepted friend request from {}", "friendRequestAccepted": "Accepted friend request from {}",
"friendRequestDeclined": "Declined friend request from {}", "friendRequestDeclined": "Declined friend request from {}",
"requestExpiredIn": "Expired in {}", "requestExpiredIn": "Expired in {}",

View File

@@ -265,6 +265,9 @@
"relationshipStatusBlocked": "Blocked", "relationshipStatusBlocked": "Blocked",
"blockUser": "Block User", "blockUser": "Block User",
"unblockUser": "Unblock User", "unblockUser": "Unblock User",
"forgotRelationship": "関係を忘れる",
"forgotRelationshipConfirm": "{} との関係を忘れてもよろしいですか?",
"relationshipDeleted": "関係が削除されました",
"friendRequestAccepted": "Accepted friend request from {}", "friendRequestAccepted": "Accepted friend request from {}",
"friendRequestDeclined": "Declined friend request from {}", "friendRequestDeclined": "Declined friend request from {}",
"requestExpiredIn": "Expired in {}", "requestExpiredIn": "Expired in {}",

View File

@@ -265,6 +265,9 @@
"relationshipStatusBlocked": "Blocked", "relationshipStatusBlocked": "Blocked",
"blockUser": "Block User", "blockUser": "Block User",
"unblockUser": "Unblock User", "unblockUser": "Unblock User",
"forgotRelationship": "관계 잊기",
"forgotRelationshipConfirm": "{}와의 관계를 잊으시겠습니까?",
"relationshipDeleted": "관계가 삭제되었습니다",
"friendRequestAccepted": "Accepted friend request from {}", "friendRequestAccepted": "Accepted friend request from {}",
"friendRequestDeclined": "Declined friend request from {}", "friendRequestDeclined": "Declined friend request from {}",
"requestExpiredIn": "Expired in {}", "requestExpiredIn": "Expired in {}",

View File

@@ -265,6 +265,9 @@
"relationshipStatusBlocked": "已屏蔽", "relationshipStatusBlocked": "已屏蔽",
"blockUser": "屏蔽用户", "blockUser": "屏蔽用户",
"unblockUser": "解除屏蔽用户", "unblockUser": "解除屏蔽用户",
"forgotRelationship": "忘记关系",
"forgotRelationshipConfirm": "确定要忘记与 {} 的关系吗?",
"relationshipDeleted": "关系已删除",
"friendRequestAccepted": "已接受 {} 的好友请求", "friendRequestAccepted": "已接受 {} 的好友请求",
"friendRequestDeclined": "已拒绝 {} 的好友请求", "friendRequestDeclined": "已拒绝 {} 的好友请求",
"requestExpiredIn": "{} 后过期", "requestExpiredIn": "{} 后过期",

View File

@@ -265,6 +265,9 @@
"relationshipStatusBlocked": "已阻", "relationshipStatusBlocked": "已阻",
"blockUser": "禁此戶", "blockUser": "禁此戶",
"unblockUser": "解禁", "unblockUser": "解禁",
"forgotRelationship": "忘締交",
"forgotRelationshipConfirm": "確定要忘與 {} 之締交乎?",
"relationshipDeleted": "締交已忘",
"friendRequestAccepted": "已納 {} 締交書", "friendRequestAccepted": "已納 {} 締交書",
"friendRequestDeclined": "已謝 {} 締交書", "friendRequestDeclined": "已謝 {} 締交書",
"requestExpiredIn": "效期 {}", "requestExpiredIn": "效期 {}",

View File

@@ -265,6 +265,9 @@
"relationshipStatusBlocked": "已屏蔽", "relationshipStatusBlocked": "已屏蔽",
"blockUser": "屏蔽用戶", "blockUser": "屏蔽用戶",
"unblockUser": "解除屏蔽用戶", "unblockUser": "解除屏蔽用戶",
"forgotRelationship": "忘記關係",
"forgotRelationshipConfirm": "確定要忘記與 {} 的關係嗎?",
"relationshipDeleted": "關係已刪除",
"friendRequestAccepted": "已接受 {} 的好友請求", "friendRequestAccepted": "已接受 {} 的好友請求",
"friendRequestDeclined": "已拒絕 {} 的好友請求", "friendRequestDeclined": "已拒絕 {} 的好友請求",
"requestExpiredIn": "{} 後過期", "requestExpiredIn": "{} 後過期",

View File

@@ -12,9 +12,10 @@ sealed class SnRelationship with _$SnRelationship {
required DateTime? updatedAt, required DateTime? updatedAt,
required DateTime? deletedAt, required DateTime? deletedAt,
required String accountId, required String accountId,
required SnAccount account, // Usually the account was not included in the response
required SnAccount? account,
required String relatedId, required String relatedId,
required SnAccount related, required SnAccount? related,
required DateTime? expiredAt, required DateTime? expiredAt,
required int status, required int status,
}) = _SnRelationship; }) = _SnRelationship;

View File

@@ -15,7 +15,8 @@ T _$identity<T>(T value) => value;
/// @nodoc /// @nodoc
mixin _$SnRelationship { mixin _$SnRelationship {
DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; String get accountId; SnAccount get account; String get relatedId; SnAccount get related; DateTime? get expiredAt; int get status; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; String get accountId;// Usually the account was not included in the response
SnAccount? get account; String get relatedId; SnAccount? get related; DateTime? get expiredAt; int get status;
/// Create a copy of SnRelationship /// Create a copy of SnRelationship
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@@ -48,11 +49,11 @@ abstract mixin class $SnRelationshipCopyWith<$Res> {
factory $SnRelationshipCopyWith(SnRelationship value, $Res Function(SnRelationship) _then) = _$SnRelationshipCopyWithImpl; factory $SnRelationshipCopyWith(SnRelationship value, $Res Function(SnRelationship) _then) = _$SnRelationshipCopyWithImpl;
@useResult @useResult
$Res call({ $Res call({
DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String accountId, SnAccount account, String relatedId, SnAccount related, DateTime? expiredAt, int status DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String accountId, SnAccount? account, String relatedId, SnAccount? related, DateTime? expiredAt, int status
}); });
$SnAccountCopyWith<$Res> get account;$SnAccountCopyWith<$Res> get related; $SnAccountCopyWith<$Res>? get account;$SnAccountCopyWith<$Res>? get related;
} }
/// @nodoc /// @nodoc
@@ -65,16 +66,16 @@ class _$SnRelationshipCopyWithImpl<$Res>
/// Create a copy of SnRelationship /// Create a copy of SnRelationship
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? accountId = null,Object? account = null,Object? relatedId = null,Object? related = null,Object? expiredAt = freezed,Object? status = null,}) { @pragma('vm:prefer-inline') @override $Res call({Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? accountId = null,Object? account = freezed,Object? relatedId = null,Object? related = freezed,Object? expiredAt = freezed,Object? status = null,}) {
return _then(_self.copyWith( return _then(_self.copyWith(
createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable as DateTime?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
as String,account: null == account ? _self.account : account // ignore: cast_nullable_to_non_nullable as String,account: freezed == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
as SnAccount,relatedId: null == relatedId ? _self.relatedId : relatedId // ignore: cast_nullable_to_non_nullable as SnAccount?,relatedId: null == relatedId ? _self.relatedId : relatedId // ignore: cast_nullable_to_non_nullable
as String,related: null == related ? _self.related : related // ignore: cast_nullable_to_non_nullable as String,related: freezed == related ? _self.related : related // ignore: cast_nullable_to_non_nullable
as SnAccount,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable as SnAccount?,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
as DateTime?,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable as DateTime?,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
as int, as int,
)); ));
@@ -83,18 +84,24 @@ as int,
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@override @override
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
$SnAccountCopyWith<$Res> get account { $SnAccountCopyWith<$Res>? get account {
if (_self.account == null) {
return $SnAccountCopyWith<$Res>(_self.account, (value) { return null;
}
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
return _then(_self.copyWith(account: value)); return _then(_self.copyWith(account: value));
}); });
}/// Create a copy of SnRelationship }/// Create a copy of SnRelationship
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@override @override
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
$SnAccountCopyWith<$Res> get related { $SnAccountCopyWith<$Res>? get related {
if (_self.related == null) {
return $SnAccountCopyWith<$Res>(_self.related, (value) { return null;
}
return $SnAccountCopyWith<$Res>(_self.related!, (value) {
return _then(_self.copyWith(related: value)); return _then(_self.copyWith(related: value));
}); });
} }
@@ -176,7 +183,7 @@ return $default(_that);case _:
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String accountId, SnAccount account, String relatedId, SnAccount related, DateTime? expiredAt, int status)? $default,{required TResult orElse(),}) {final _that = this; @optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String accountId, SnAccount? account, String relatedId, SnAccount? related, DateTime? expiredAt, int status)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) { switch (_that) {
case _SnRelationship() when $default != null: case _SnRelationship() when $default != null:
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.accountId,_that.account,_that.relatedId,_that.related,_that.expiredAt,_that.status);case _: return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.accountId,_that.account,_that.relatedId,_that.related,_that.expiredAt,_that.status);case _:
@@ -197,7 +204,7 @@ return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.accountId,
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String accountId, SnAccount account, String relatedId, SnAccount related, DateTime? expiredAt, int status) $default,) {final _that = this; @optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String accountId, SnAccount? account, String relatedId, SnAccount? related, DateTime? expiredAt, int status) $default,) {final _that = this;
switch (_that) { switch (_that) {
case _SnRelationship(): case _SnRelationship():
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.accountId,_that.account,_that.relatedId,_that.related,_that.expiredAt,_that.status);} return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.accountId,_that.account,_that.relatedId,_that.related,_that.expiredAt,_that.status);}
@@ -214,7 +221,7 @@ return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.accountId,
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String accountId, SnAccount account, String relatedId, SnAccount related, DateTime? expiredAt, int status)? $default,) {final _that = this; @optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String accountId, SnAccount? account, String relatedId, SnAccount? related, DateTime? expiredAt, int status)? $default,) {final _that = this;
switch (_that) { switch (_that) {
case _SnRelationship() when $default != null: case _SnRelationship() when $default != null:
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.accountId,_that.account,_that.relatedId,_that.related,_that.expiredAt,_that.status);case _: return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.accountId,_that.account,_that.relatedId,_that.related,_that.expiredAt,_that.status);case _:
@@ -236,9 +243,10 @@ class _SnRelationship implements SnRelationship {
@override final DateTime? updatedAt; @override final DateTime? updatedAt;
@override final DateTime? deletedAt; @override final DateTime? deletedAt;
@override final String accountId; @override final String accountId;
@override final SnAccount account; // Usually the account was not included in the response
@override final SnAccount? account;
@override final String relatedId; @override final String relatedId;
@override final SnAccount related; @override final SnAccount? related;
@override final DateTime? expiredAt; @override final DateTime? expiredAt;
@override final int status; @override final int status;
@@ -275,11 +283,11 @@ abstract mixin class _$SnRelationshipCopyWith<$Res> implements $SnRelationshipCo
factory _$SnRelationshipCopyWith(_SnRelationship value, $Res Function(_SnRelationship) _then) = __$SnRelationshipCopyWithImpl; factory _$SnRelationshipCopyWith(_SnRelationship value, $Res Function(_SnRelationship) _then) = __$SnRelationshipCopyWithImpl;
@override @useResult @override @useResult
$Res call({ $Res call({
DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String accountId, SnAccount account, String relatedId, SnAccount related, DateTime? expiredAt, int status DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String accountId, SnAccount? account, String relatedId, SnAccount? related, DateTime? expiredAt, int status
}); });
@override $SnAccountCopyWith<$Res> get account;@override $SnAccountCopyWith<$Res> get related; @override $SnAccountCopyWith<$Res>? get account;@override $SnAccountCopyWith<$Res>? get related;
} }
/// @nodoc /// @nodoc
@@ -292,16 +300,16 @@ class __$SnRelationshipCopyWithImpl<$Res>
/// Create a copy of SnRelationship /// Create a copy of SnRelationship
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? accountId = null,Object? account = null,Object? relatedId = null,Object? related = null,Object? expiredAt = freezed,Object? status = null,}) { @override @pragma('vm:prefer-inline') $Res call({Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? accountId = null,Object? account = freezed,Object? relatedId = null,Object? related = freezed,Object? expiredAt = freezed,Object? status = null,}) {
return _then(_SnRelationship( return _then(_SnRelationship(
createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable as DateTime?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
as String,account: null == account ? _self.account : account // ignore: cast_nullable_to_non_nullable as String,account: freezed == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
as SnAccount,relatedId: null == relatedId ? _self.relatedId : relatedId // ignore: cast_nullable_to_non_nullable as SnAccount?,relatedId: null == relatedId ? _self.relatedId : relatedId // ignore: cast_nullable_to_non_nullable
as String,related: null == related ? _self.related : related // ignore: cast_nullable_to_non_nullable as String,related: freezed == related ? _self.related : related // ignore: cast_nullable_to_non_nullable
as SnAccount,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable as SnAccount?,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
as DateTime?,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable as DateTime?,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
as int, as int,
)); ));
@@ -311,18 +319,24 @@ as int,
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@override @override
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
$SnAccountCopyWith<$Res> get account { $SnAccountCopyWith<$Res>? get account {
if (_self.account == null) {
return $SnAccountCopyWith<$Res>(_self.account, (value) { return null;
}
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
return _then(_self.copyWith(account: value)); return _then(_self.copyWith(account: value));
}); });
}/// Create a copy of SnRelationship }/// Create a copy of SnRelationship
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@override @override
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
$SnAccountCopyWith<$Res> get related { $SnAccountCopyWith<$Res>? get related {
if (_self.related == null) {
return $SnAccountCopyWith<$Res>(_self.related, (value) { return null;
}
return $SnAccountCopyWith<$Res>(_self.related!, (value) {
return _then(_self.copyWith(related: value)); return _then(_self.copyWith(related: value));
}); });
} }

View File

@@ -18,9 +18,13 @@ _SnRelationship _$SnRelationshipFromJson(Map<String, dynamic> json) =>
? null ? null
: DateTime.parse(json['deleted_at'] as String), : DateTime.parse(json['deleted_at'] as String),
accountId: json['account_id'] as String, accountId: json['account_id'] as String,
account: SnAccount.fromJson(json['account'] as Map<String, dynamic>), account: json['account'] == null
? null
: SnAccount.fromJson(json['account'] as Map<String, dynamic>),
relatedId: json['related_id'] as String, relatedId: json['related_id'] as String,
related: SnAccount.fromJson(json['related'] as Map<String, dynamic>), related: json['related'] == null
? null
: SnAccount.fromJson(json['related'] as Map<String, dynamic>),
expiredAt: json['expired_at'] == null expiredAt: json['expired_at'] == null
? null ? null
: DateTime.parse(json['expired_at'] as String), : DateTime.parse(json['expired_at'] as String),
@@ -33,9 +37,9 @@ Map<String, dynamic> _$SnRelationshipToJson(_SnRelationship instance) =>
'updated_at': instance.updatedAt?.toIso8601String(), 'updated_at': instance.updatedAt?.toIso8601String(),
'deleted_at': instance.deletedAt?.toIso8601String(), 'deleted_at': instance.deletedAt?.toIso8601String(),
'account_id': instance.accountId, 'account_id': instance.accountId,
'account': instance.account.toJson(), 'account': instance.account?.toJson(),
'related_id': instance.relatedId, 'related_id': instance.relatedId,
'related': instance.related.toJson(), 'related': instance.related?.toJson(),
'expired_at': instance.expiredAt?.toIso8601String(), 'expired_at': instance.expiredAt?.toIso8601String(),
'status': instance.status, 'status': instance.status,
}; };

View File

@@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/pods/paging.dart'; import 'package:island/pods/paging.dart';
import 'package:island/pods/userinfo.dart'; import 'package:island/pods/userinfo.dart';
@@ -31,11 +32,9 @@ Future<List<SnRelationship>> sentFriendRequest(Ref ref) async {
.toList(); .toList();
} }
final relationshipListNotifierProvider = final relationshipListNotifierProvider = AsyncNotifierProvider.autoDispose(
AsyncNotifierProvider.autoDispose< RelationshipListNotifier.new,
RelationshipListNotifier, );
PaginationState<SnRelationship>
>(RelationshipListNotifier.new);
class RelationshipListNotifier class RelationshipListNotifier
extends AsyncNotifier<PaginationState<SnRelationship>> extends AsyncNotifier<PaginationState<SnRelationship>>
@@ -84,6 +83,7 @@ class RelationshipListTile extends StatelessWidget {
final String? currentUserId; final String? currentUserId;
final bool showRelatedAccount; final bool showRelatedAccount;
final Function(SnRelationship, int)? onUpdateStatus; final Function(SnRelationship, int)? onUpdateStatus;
final Function(SnRelationship)? onDelete;
const RelationshipListTile({ const RelationshipListTile({
super.key, super.key,
@@ -96,18 +96,19 @@ class RelationshipListTile extends StatelessWidget {
required this.currentUserId, required this.currentUserId,
this.showRelatedAccount = false, this.showRelatedAccount = false,
this.onUpdateStatus, this.onUpdateStatus,
this.onDelete,
}); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final account = showRelatedAccount final account = showRelatedAccount
? relationship.related ? relationship.related!
: relationship.account; : relationship.account!;
final isPending = final isPending =
relationship.status == 0 && relationship.relatedId == currentUserId; relationship.status == 0 && relationship.relatedId == currentUserId;
final isWaiting = final isWaiting =
relationship.status == 0 && relationship.accountId == currentUserId; relationship.status == 0 && relationship.accountId == currentUserId;
final isEstablished = relationship.status == 1 || relationship.status == 2; final isEstablished = relationship.status != 0;
return ListTile( return ListTile(
contentPadding: const EdgeInsets.only(left: 16, right: 12), contentPadding: const EdgeInsets.only(left: 16, right: 12),
@@ -185,21 +186,36 @@ class RelationshipListTile extends StatelessWidget {
itemBuilder: (context) => [ itemBuilder: (context) => [
if (relationship.status >= 100) // If friend if (relationship.status >= 100) // If friend
PopupMenuItem( PopupMenuItem(
child: ListTile(
leading: const Icon(Symbols.block),
title: Text('blockUser').tr(),
contentPadding: EdgeInsets.zero,
),
onTap: () => onUpdateStatus?.call(relationship, -100), onTap: () => onUpdateStatus?.call(relationship, -100),
child: Row(
children: [
const Icon(Symbols.block),
const Gap(12),
Text('blockUser').tr(),
],
),
) )
else if (relationship.status <= -100) // If blocked else if (relationship.status <= -100) // If blocked
PopupMenuItem( PopupMenuItem(
child: ListTile(
leading: const Icon(Symbols.person_add),
title: Text('unblockUser').tr(),
contentPadding: EdgeInsets.zero,
),
onTap: () => onUpdateStatus?.call(relationship, 100), onTap: () => onUpdateStatus?.call(relationship, 100),
child: Row(
children: [
const Icon(Symbols.person_add),
const Gap(12),
Text('unblockUser').tr(),
],
),
),
if (onDelete != null)
PopupMenuItem(
onTap: () => onDelete?.call(relationship),
child: Row(
children: [
const Icon(Symbols.delete),
const Gap(12),
Text('forgotRelationship').tr(),
],
),
), ),
], ],
), ),
@@ -230,40 +246,11 @@ class RelationshipScreen extends HookConsumerWidget {
final client = ref.read(apiClientProvider); final client = ref.read(apiClientProvider);
await client.post('/pass/relationships/${result.id}/friends'); await client.post('/pass/relationships/${result.id}/friends');
ref.invalidate(sentFriendRequestProvider); ref.invalidate(friendRequestProvider);
} }
final submitting = useState(false); final submitting = useState(false);
Future<void> handleFriendRequest(
SnRelationship relationship,
bool isAccept,
) async {
try {
submitting.value = true;
final client = ref.read(apiClientProvider);
await client.post(
'/pass/relationships/${relationship.accountId}/friends/${isAccept ? 'accept' : 'decline'}',
);
relationshipNotifier.refresh();
if (!context.mounted) return;
if (isAccept) {
showSnackBar(
'friendRequestAccepted'.tr(args: ['@${relationship.account.name}']),
);
} else {
showSnackBar(
'friendRequestDeclined'.tr(args: ['@${relationship.account.name}']),
);
}
HapticFeedback.lightImpact();
} catch (err) {
showErrorAlert(err);
} finally {
submitting.value = false;
}
}
Future<void> updateRelationship( Future<void> updateRelationship(
SnRelationship relationship, SnRelationship relationship,
int newStatus, int newStatus,
@@ -276,8 +263,32 @@ class RelationshipScreen extends HookConsumerWidget {
relationshipNotifier.refresh(); relationshipNotifier.refresh();
} }
Future<void> deleteRelationship(SnRelationship relationship) async {
final confirmed = await showConfirmAlert(
'forgotRelationshipConfirm'.tr(
args: ['@${relationship.related!.name}'],
),
'forgotRelationship'.tr(),
isDanger: true,
);
if (!confirmed) return;
if (!context.mounted) return;
showLoadingModal(context);
try {
final client = ref.read(apiClientProvider);
await client.delete('/pass/relationships/${relationship.accountId}');
relationshipNotifier.refresh();
showSnackBar('relationshipDeleted'.tr());
} catch (err) {
showErrorAlert(err);
} finally {
if (context.mounted) hideLoadingModal(context);
}
}
final user = ref.watch(userInfoProvider); final user = ref.watch(userInfoProvider);
final requests = ref.watch(sentFriendRequestProvider); final requests = ref.watch(friendRequestProvider);
return AppScaffold( return AppScaffold(
appBar: AppBar(title: Text('relationships').tr()), appBar: AppBar(title: Text('relationships').tr()),
@@ -293,9 +304,9 @@ class RelationshipScreen extends HookConsumerWidget {
if (requests.hasValue && requests.value!.isNotEmpty) if (requests.hasValue && requests.value!.isNotEmpty)
ListTile( ListTile(
leading: const Icon(Symbols.send), leading: const Icon(Symbols.send),
title: Text('friendSentRequest').tr(), title: Text('friendRequests').tr(),
subtitle: Text( subtitle: Text(
'friendSentRequestHint'.plural(requests.value!.length), 'friendRequestsHint'.plural(requests.value!.length),
), ),
contentPadding: const EdgeInsets.symmetric(horizontal: 24), contentPadding: const EdgeInsets.symmetric(horizontal: 24),
onTap: () { onTap: () {
@@ -316,11 +327,10 @@ class RelationshipScreen extends HookConsumerWidget {
return RelationshipListTile( return RelationshipListTile(
relationship: relationship, relationship: relationship,
submitting: submitting.value, submitting: submitting.value,
onAccept: () => handleFriendRequest(relationship, true),
onDecline: () => handleFriendRequest(relationship, false),
currentUserId: user.value?.id, currentUserId: user.value?.id,
showRelatedAccount: false, showRelatedAccount: true,
onUpdateStatus: updateRelationship, onUpdateStatus: updateRelationship,
onDelete: deleteRelationship,
); );
}, },
), ),
@@ -336,19 +346,54 @@ class _SentFriendRequestsSheet extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final requests = ref.watch(sentFriendRequestProvider); final requests = ref.watch(friendRequestProvider);
final user = ref.watch(userInfoProvider); final user = ref.watch(userInfoProvider);
Future<void> cancelRequest(SnRelationship request) async { Future<void> cancelRequest(SnRelationship request) async {
try { try {
final client = ref.read(apiClientProvider); final client = ref.read(apiClientProvider);
await client.delete('/pass/relationships/${request.relatedId}/friends'); await client.delete('/pass/relationships/${request.relatedId}/friends');
ref.invalidate(sentFriendRequestProvider); ref.invalidate(friendRequestProvider);
} catch (err) { } catch (err) {
showErrorAlert(err); showErrorAlert(err);
} }
} }
final submitting = useState(false);
Future<void> handleFriendRequest(
SnRelationship relationship,
bool isAccept,
) async {
try {
submitting.value = true;
final client = ref.read(apiClientProvider);
await client.post(
'/pass/relationships/${relationship.accountId}/friends/${isAccept ? 'accept' : 'decline'}',
);
ref.invalidate(friendRequestProvider);
if (!context.mounted) return;
if (isAccept) {
showSnackBar(
'friendRequestAccepted'.tr(
args: ['@${relationship.account!.name}'],
),
);
} else {
showSnackBar(
'friendRequestDeclined'.tr(
args: ['@${relationship.account!.name}'],
),
);
}
HapticFeedback.lightImpact();
} catch (err) {
showErrorAlert(err);
} finally {
submitting.value = false;
}
}
return Container( return Container(
constraints: BoxConstraints( constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.8, maxHeight: MediaQuery.of(context).size.height * 0.8,
@@ -366,7 +411,7 @@ class _SentFriendRequestsSheet extends HookConsumerWidget {
child: Row( child: Row(
children: [ children: [
Text( Text(
'friendSentRequest'.tr(), 'friendRequests'.tr(),
style: Theme.of(context).textTheme.headlineSmall?.copyWith( style: Theme.of(context).textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
letterSpacing: -0.5, letterSpacing: -0.5,
@@ -377,7 +422,7 @@ class _SentFriendRequestsSheet extends HookConsumerWidget {
icon: const Icon(Symbols.refresh), icon: const Icon(Symbols.refresh),
style: IconButton.styleFrom(minimumSize: const Size(36, 36)), style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
onPressed: () { onPressed: () {
ref.invalidate(sentFriendRequestProvider); ref.invalidate(friendRequestProvider);
}, },
), ),
IconButton( IconButton(
@@ -394,7 +439,7 @@ class _SentFriendRequestsSheet extends HookConsumerWidget {
data: (items) => items.isEmpty data: (items) => items.isEmpty
? Center( ? Center(
child: Text( child: Text(
'friendSentRequestEmpty'.tr(), 'friendRequestsEmpty'.tr(),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
) )
@@ -406,6 +451,8 @@ class _SentFriendRequestsSheet extends HookConsumerWidget {
return RelationshipListTile( return RelationshipListTile(
relationship: request, relationship: request,
onCancel: () => cancelRequest(request), onCancel: () => cancelRequest(request),
onAccept: () => handleFriendRequest(request, true),
onDecline: () => handleFriendRequest(request, false),
currentUserId: user.value?.id, currentUserId: user.value?.id,
showRelatedAccount: true, showRelatedAccount: true,
); );

View File

@@ -9,10 +9,10 @@ part of 'relationship.dart';
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, type=warning // ignore_for_file: type=lint, type=warning
@ProviderFor(sentFriendRequest) @ProviderFor(friendRequest)
final sentFriendRequestProvider = SentFriendRequestProvider._(); final friendRequestProvider = FriendRequestProvider._();
final class SentFriendRequestProvider final class FriendRequestProvider
extends extends
$FunctionalProvider< $FunctionalProvider<
AsyncValue<List<SnRelationship>>, AsyncValue<List<SnRelationship>>,
@@ -22,19 +22,19 @@ final class SentFriendRequestProvider
with with
$FutureModifier<List<SnRelationship>>, $FutureModifier<List<SnRelationship>>,
$FutureProvider<List<SnRelationship>> { $FutureProvider<List<SnRelationship>> {
SentFriendRequestProvider._() FriendRequestProvider._()
: super( : super(
from: null, from: null,
argument: null, argument: null,
retry: null, retry: null,
name: r'sentFriendRequestProvider', name: r'friendRequestProvider',
isAutoDispose: true, isAutoDispose: true,
dependencies: null, dependencies: null,
$allTransitiveDependencies: null, $allTransitiveDependencies: null,
); );
@override @override
String debugGetCreateSourceHash() => _$sentFriendRequestHash(); String debugGetCreateSourceHash() => _$friendRequestHash();
@$internal @$internal
@override @override
@@ -44,8 +44,8 @@ final class SentFriendRequestProvider
@override @override
FutureOr<List<SnRelationship>> create(Ref ref) { FutureOr<List<SnRelationship>> create(Ref ref) {
return sentFriendRequest(ref); return friendRequest(ref);
} }
} }
String _$sentFriendRequestHash() => r'0c52813eb6f86c05f6e0b1e4e840d0d9c350aa9e'; String _$friendRequestHash() => r'b066553f9bd0505a7a272cf10cb3ca312152acd6';