✨ Chat room details, invitions and members management
This commit is contained in:
parent
e2e6de965b
commit
efdddf72e4
@ -33,7 +33,7 @@
|
|||||||
"managedPublisher": "Managed Publishers",
|
"managedPublisher": "Managed Publishers",
|
||||||
"createPublisher": "Create a Publisher",
|
"createPublisher": "Create a Publisher",
|
||||||
"createPublisherHint": "To create posts, collections, etc.",
|
"createPublisherHint": "To create posts, collections, etc.",
|
||||||
"editPublisher": "Edit a Publisher",
|
"editPublisher": "Edit Publisher",
|
||||||
"syncPublisher": "Use Account Data",
|
"syncPublisher": "Use Account Data",
|
||||||
"create": "Create",
|
"create": "Create",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
@ -62,7 +62,7 @@
|
|||||||
"realms": "Realms",
|
"realms": "Realms",
|
||||||
"createRealm": "Create a Realm",
|
"createRealm": "Create a Realm",
|
||||||
"createRealmHint": "Meet friends with same interests, build communities, and more.",
|
"createRealmHint": "Meet friends with same interests, build communities, and more.",
|
||||||
"editRealm": "Edit a Realm",
|
"editRealm": "Edit Realm",
|
||||||
"deleteRealm": "Delete Realm {}",
|
"deleteRealm": "Delete Realm {}",
|
||||||
"deleteRealmHint": "Are you sure to delete this realm? This will also deleted all the channels, publishers, and posts under this realm.",
|
"deleteRealmHint": "Are you sure to delete this realm? This will also deleted all the channels, publishers, and posts under this realm.",
|
||||||
"explore": "Explore",
|
"explore": "Explore",
|
||||||
@ -72,9 +72,20 @@
|
|||||||
"slug": "Slug",
|
"slug": "Slug",
|
||||||
"slugHint": "The slug will be used in the URL to access this resource, it should be unique and URL safe.",
|
"slugHint": "The slug will be used in the URL to access this resource, it should be unique and URL safe.",
|
||||||
"createChatRoom": "Create a Room",
|
"createChatRoom": "Create a Room",
|
||||||
"editChatRoom": "Edit a Room",
|
"editChatRoom": "Edit Room",
|
||||||
|
"deleteChatRoom": "Delete Room",
|
||||||
"chat": "Chat",
|
"chat": "Chat",
|
||||||
"chatMessageHint": "Message in {}",
|
"chatMessageHint": "Message in {}",
|
||||||
"chatDirectMessageHint": "Message to {}",
|
"chatDirectMessageHint": "Message to {}",
|
||||||
"loading": "Loading..."
|
"loading": "Loading...",
|
||||||
|
"descriptionNone": "No description yet.",
|
||||||
|
"invites": "Invites",
|
||||||
|
"invitesEmpty": "No invites yet, such a lonely person...",
|
||||||
|
"chatMembers": {
|
||||||
|
"one": "{} member",
|
||||||
|
"other": "{} members"
|
||||||
|
},
|
||||||
|
"permissionOwner": "Owner",
|
||||||
|
"permissionModerator": "Moderator",
|
||||||
|
"permissionMember": "Member"
|
||||||
}
|
}
|
||||||
|
@ -7,30 +7,13 @@ import 'package:uuid/uuid.dart';
|
|||||||
|
|
||||||
class MessageRepository {
|
class MessageRepository {
|
||||||
final SnChat room;
|
final SnChat room;
|
||||||
|
final SnChatMember identity;
|
||||||
final Dio _apiClient;
|
final Dio _apiClient;
|
||||||
final AppDatabase _database;
|
final AppDatabase _database;
|
||||||
|
|
||||||
SnChatMember? _identity;
|
|
||||||
|
|
||||||
final Map<String, LocalChatMessage> pendingMessages = {};
|
final Map<String, LocalChatMessage> pendingMessages = {};
|
||||||
|
|
||||||
MessageRepository(this.room, this._apiClient, this._database) {
|
MessageRepository(this.room, this.identity, this._apiClient, this._database);
|
||||||
initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool initialized = false;
|
|
||||||
|
|
||||||
Future<void> initialize() async {
|
|
||||||
if (initialized) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
final response = await _apiClient.get('/chat/${room.id}/members/me');
|
|
||||||
_identity = SnChatMember.fromJson(response.data);
|
|
||||||
initialized = true;
|
|
||||||
} catch (e) {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<LocalChatMessage>> listMessages({
|
Future<List<LocalChatMessage>> listMessages({
|
||||||
int offset = 0,
|
int offset = 0,
|
||||||
@ -143,12 +126,6 @@ class MessageRepository {
|
|||||||
List<SnCloudFile>? attachments,
|
List<SnCloudFile>? attachments,
|
||||||
Map<String, dynamic>? meta,
|
Map<String, dynamic>? meta,
|
||||||
}) async {
|
}) async {
|
||||||
if (!initialized || _identity == null) {
|
|
||||||
throw UnsupportedError(
|
|
||||||
"The message repository is not ready for send message.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a unique nonce for this message
|
// Generate a unique nonce for this message
|
||||||
final nonce = const Uuid().v4();
|
final nonce = const Uuid().v4();
|
||||||
|
|
||||||
@ -156,12 +133,12 @@ class MessageRepository {
|
|||||||
final mockMessage = SnChatMessage(
|
final mockMessage = SnChatMessage(
|
||||||
id: 'pending_$nonce',
|
id: 'pending_$nonce',
|
||||||
chatRoomId: roomId,
|
chatRoomId: roomId,
|
||||||
senderId: _identity!.id,
|
senderId: identity.id,
|
||||||
content: content,
|
content: content,
|
||||||
createdAt: DateTime.now(),
|
createdAt: DateTime.now(),
|
||||||
updatedAt: DateTime.now(),
|
updatedAt: DateTime.now(),
|
||||||
nonce: nonce,
|
nonce: nonce,
|
||||||
sender: _identity!,
|
sender: identity,
|
||||||
);
|
);
|
||||||
|
|
||||||
final localMessage = LocalChatMessage.fromRemoteMessage(
|
final localMessage = LocalChatMessage.fromRemoteMessage(
|
||||||
|
@ -81,6 +81,7 @@ abstract class SnChatMember with _$SnChatMember {
|
|||||||
required DateTime? deletedAt,
|
required DateTime? deletedAt,
|
||||||
required String id,
|
required String id,
|
||||||
required int chatRoomId,
|
required int chatRoomId,
|
||||||
|
required SnChat? chatRoom,
|
||||||
required int accountId,
|
required int accountId,
|
||||||
required SnAccount account,
|
required SnAccount account,
|
||||||
required String? nick,
|
required String? nick,
|
||||||
|
@ -709,7 +709,7 @@ $SnChatMemberCopyWith<$Res> get sender {
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnChatMember {
|
mixin _$SnChatMember {
|
||||||
|
|
||||||
DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; String get id; int get chatRoomId; int get accountId; SnAccount get account; String? get nick; int get role; int get notify; DateTime? get joinedAt; bool get isBot;
|
DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; String get id; int get chatRoomId; SnChat? get chatRoom; int get accountId; SnAccount get account; String? get nick; int get role; int get notify; DateTime? get joinedAt; bool get isBot;
|
||||||
/// Create a copy of SnChatMember
|
/// Create a copy of SnChatMember
|
||||||
/// 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)
|
||||||
@ -722,16 +722,16 @@ $SnChatMemberCopyWith<SnChatMember> get copyWith => _$SnChatMemberCopyWithImpl<S
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatMember&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.id, id) || other.id == id)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.role, role) || other.role == role)&&(identical(other.notify, notify) || other.notify == notify)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.isBot, isBot) || other.isBot == isBot));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatMember&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.id, id) || other.id == id)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId)&&(identical(other.chatRoom, chatRoom) || other.chatRoom == chatRoom)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.role, role) || other.role == role)&&(identical(other.notify, notify) || other.notify == notify)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.isBot, isBot) || other.isBot == isBot));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,accountId,account,nick,role,notify,joinedAt,isBot);
|
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,isBot);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnChatMember(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, chatRoomId: $chatRoomId, accountId: $accountId, account: $account, nick: $nick, role: $role, notify: $notify, joinedAt: $joinedAt, isBot: $isBot)';
|
return 'SnChatMember(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, chatRoomId: $chatRoomId, chatRoom: $chatRoom, accountId: $accountId, account: $account, nick: $nick, role: $role, notify: $notify, joinedAt: $joinedAt, isBot: $isBot)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -742,11 +742,11 @@ abstract mixin class $SnChatMemberCopyWith<$Res> {
|
|||||||
factory $SnChatMemberCopyWith(SnChatMember value, $Res Function(SnChatMember) _then) = _$SnChatMemberCopyWithImpl;
|
factory $SnChatMemberCopyWith(SnChatMember value, $Res Function(SnChatMember) _then) = _$SnChatMemberCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, int chatRoomId, int accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, bool isBot
|
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, int chatRoomId, SnChat? chatRoom, int accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, bool isBot
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$SnAccountCopyWith<$Res> get account;
|
$SnChatCopyWith<$Res>? get chatRoom;$SnAccountCopyWith<$Res> get account;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@ -759,14 +759,15 @@ class _$SnChatMemberCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnChatMember
|
/// Create a copy of SnChatMember
|
||||||
/// 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 = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? chatRoomId = null,Object? accountId = null,Object? account = null,Object? nick = freezed,Object? role = null,Object? notify = null,Object? joinedAt = freezed,Object? isBot = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? chatRoomId = null,Object? chatRoom = freezed,Object? accountId = null,Object? account = null,Object? nick = freezed,Object? role = null,Object? notify = null,Object? joinedAt = freezed,Object? isBot = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == 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?,id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
as DateTime?,id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,chatRoomId: null == chatRoomId ? _self.chatRoomId : chatRoomId // ignore: cast_nullable_to_non_nullable
|
as String,chatRoomId: null == chatRoomId ? _self.chatRoomId : chatRoomId // ignore: cast_nullable_to_non_nullable
|
||||||
as int,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
as int,chatRoom: freezed == chatRoom ? _self.chatRoom : chatRoom // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnChat?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
as int,account: null == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
|
as int,account: null == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
|
||||||
as SnAccount,nick: freezed == nick ? _self.nick : nick // ignore: cast_nullable_to_non_nullable
|
as SnAccount,nick: freezed == nick ? _self.nick : nick // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable
|
as String?,role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable
|
||||||
@ -780,6 +781,18 @@ as bool,
|
|||||||
/// 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')
|
||||||
|
$SnChatCopyWith<$Res>? get chatRoom {
|
||||||
|
if (_self.chatRoom == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnChatCopyWith<$Res>(_self.chatRoom!, (value) {
|
||||||
|
return _then(_self.copyWith(chatRoom: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of SnChatMember
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
$SnAccountCopyWith<$Res> get account {
|
$SnAccountCopyWith<$Res> get account {
|
||||||
|
|
||||||
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
||||||
@ -793,7 +806,7 @@ $SnAccountCopyWith<$Res> get account {
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnChatMember implements SnChatMember {
|
class _SnChatMember implements SnChatMember {
|
||||||
const _SnChatMember({required this.createdAt, required this.updatedAt, required this.deletedAt, required this.id, required this.chatRoomId, required this.accountId, required this.account, required this.nick, required this.role, required this.notify, required this.joinedAt, required this.isBot});
|
const _SnChatMember({required this.createdAt, required this.updatedAt, required this.deletedAt, required this.id, required this.chatRoomId, required this.chatRoom, required this.accountId, required this.account, required this.nick, required this.role, required this.notify, required this.joinedAt, required this.isBot});
|
||||||
factory _SnChatMember.fromJson(Map<String, dynamic> json) => _$SnChatMemberFromJson(json);
|
factory _SnChatMember.fromJson(Map<String, dynamic> json) => _$SnChatMemberFromJson(json);
|
||||||
|
|
||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@ -801,6 +814,7 @@ class _SnChatMember implements SnChatMember {
|
|||||||
@override final DateTime? deletedAt;
|
@override final DateTime? deletedAt;
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@override final int chatRoomId;
|
@override final int chatRoomId;
|
||||||
|
@override final SnChat? chatRoom;
|
||||||
@override final int accountId;
|
@override final int accountId;
|
||||||
@override final SnAccount account;
|
@override final SnAccount account;
|
||||||
@override final String? nick;
|
@override final String? nick;
|
||||||
@ -822,16 +836,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnChatMember&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.id, id) || other.id == id)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.role, role) || other.role == role)&&(identical(other.notify, notify) || other.notify == notify)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.isBot, isBot) || other.isBot == isBot));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnChatMember&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.id, id) || other.id == id)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId)&&(identical(other.chatRoom, chatRoom) || other.chatRoom == chatRoom)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.role, role) || other.role == role)&&(identical(other.notify, notify) || other.notify == notify)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.isBot, isBot) || other.isBot == isBot));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,accountId,account,nick,role,notify,joinedAt,isBot);
|
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,isBot);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnChatMember(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, chatRoomId: $chatRoomId, accountId: $accountId, account: $account, nick: $nick, role: $role, notify: $notify, joinedAt: $joinedAt, isBot: $isBot)';
|
return 'SnChatMember(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, chatRoomId: $chatRoomId, chatRoom: $chatRoom, accountId: $accountId, account: $account, nick: $nick, role: $role, notify: $notify, joinedAt: $joinedAt, isBot: $isBot)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -842,11 +856,11 @@ abstract mixin class _$SnChatMemberCopyWith<$Res> implements $SnChatMemberCopyWi
|
|||||||
factory _$SnChatMemberCopyWith(_SnChatMember value, $Res Function(_SnChatMember) _then) = __$SnChatMemberCopyWithImpl;
|
factory _$SnChatMemberCopyWith(_SnChatMember value, $Res Function(_SnChatMember) _then) = __$SnChatMemberCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, int chatRoomId, int accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, bool isBot
|
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, int chatRoomId, SnChat? chatRoom, int accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, bool isBot
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $SnAccountCopyWith<$Res> get account;
|
@override $SnChatCopyWith<$Res>? get chatRoom;@override $SnAccountCopyWith<$Res> get account;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@ -859,14 +873,15 @@ class __$SnChatMemberCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnChatMember
|
/// Create a copy of SnChatMember
|
||||||
/// 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 = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? chatRoomId = null,Object? accountId = null,Object? account = null,Object? nick = freezed,Object? role = null,Object? notify = null,Object? joinedAt = freezed,Object? isBot = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? chatRoomId = null,Object? chatRoom = freezed,Object? accountId = null,Object? account = null,Object? nick = freezed,Object? role = null,Object? notify = null,Object? joinedAt = freezed,Object? isBot = null,}) {
|
||||||
return _then(_SnChatMember(
|
return _then(_SnChatMember(
|
||||||
createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == 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?,id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
as DateTime?,id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,chatRoomId: null == chatRoomId ? _self.chatRoomId : chatRoomId // ignore: cast_nullable_to_non_nullable
|
as String,chatRoomId: null == chatRoomId ? _self.chatRoomId : chatRoomId // ignore: cast_nullable_to_non_nullable
|
||||||
as int,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
as int,chatRoom: freezed == chatRoom ? _self.chatRoom : chatRoom // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnChat?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
as int,account: null == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
|
as int,account: null == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
|
||||||
as SnAccount,nick: freezed == nick ? _self.nick : nick // ignore: cast_nullable_to_non_nullable
|
as SnAccount,nick: freezed == nick ? _self.nick : nick // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable
|
as String?,role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable
|
||||||
@ -881,6 +896,18 @@ as bool,
|
|||||||
/// 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')
|
||||||
|
$SnChatCopyWith<$Res>? get chatRoom {
|
||||||
|
if (_self.chatRoom == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnChatCopyWith<$Res>(_self.chatRoom!, (value) {
|
||||||
|
return _then(_self.copyWith(chatRoom: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of SnChatMember
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
$SnAccountCopyWith<$Res> get account {
|
$SnAccountCopyWith<$Res> get account {
|
||||||
|
|
||||||
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
||||||
|
@ -163,6 +163,10 @@ _SnChatMember _$SnChatMemberFromJson(Map<String, dynamic> json) =>
|
|||||||
: DateTime.parse(json['deleted_at'] as String),
|
: DateTime.parse(json['deleted_at'] as String),
|
||||||
id: json['id'] as String,
|
id: json['id'] as String,
|
||||||
chatRoomId: (json['chat_room_id'] as num).toInt(),
|
chatRoomId: (json['chat_room_id'] as num).toInt(),
|
||||||
|
chatRoom:
|
||||||
|
json['chat_room'] == null
|
||||||
|
? null
|
||||||
|
: SnChat.fromJson(json['chat_room'] as Map<String, dynamic>),
|
||||||
accountId: (json['account_id'] as num).toInt(),
|
accountId: (json['account_id'] as num).toInt(),
|
||||||
account: SnAccount.fromJson(json['account'] as Map<String, dynamic>),
|
account: SnAccount.fromJson(json['account'] as Map<String, dynamic>),
|
||||||
nick: json['nick'] as String?,
|
nick: json['nick'] as String?,
|
||||||
@ -182,6 +186,7 @@ Map<String, dynamic> _$SnChatMemberToJson(_SnChatMember instance) =>
|
|||||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
'id': instance.id,
|
'id': instance.id,
|
||||||
'chat_room_id': instance.chatRoomId,
|
'chat_room_id': instance.chatRoomId,
|
||||||
|
'chat_room': instance.chatRoom?.toJson(),
|
||||||
'account_id': instance.accountId,
|
'account_id': instance.accountId,
|
||||||
'account': instance.account.toJson(),
|
'account': instance.account.toJson(),
|
||||||
'nick': instance.nick,
|
'nick': instance.nick,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/user.dart';
|
import 'package:island/models/user.dart';
|
||||||
@ -21,6 +23,7 @@ class UserInfoNotifier extends StateNotifier<AsyncValue<SnAccount?>> {
|
|||||||
final user = SnAccount.fromJson(response.data);
|
final user = SnAccount.fromJson(response.data);
|
||||||
state = AsyncValue.data(user);
|
state = AsyncValue.data(user);
|
||||||
} catch (error, stackTrace) {
|
} catch (error, stackTrace) {
|
||||||
|
log("[UserInfo] Failed to fetch user info: $error");
|
||||||
state = AsyncValue.error(error, stackTrace);
|
state = AsyncValue.error(error, stackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,6 +32,7 @@ class UserInfoNotifier extends StateNotifier<AsyncValue<SnAccount?>> {
|
|||||||
state = const AsyncValue.data(null);
|
state = const AsyncValue.data(null);
|
||||||
final prefs = _ref.read(sharedPreferencesProvider);
|
final prefs = _ref.read(sharedPreferencesProvider);
|
||||||
await prefs.remove(kTokenPairStoreKey);
|
await prefs.remove(kTokenPairStoreKey);
|
||||||
|
_ref.refresh(userInfoProvider.notifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
@ -8,6 +11,7 @@ import 'package:web_socket_channel/io.dart';
|
|||||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||||
|
|
||||||
part 'websocket.freezed.dart';
|
part 'websocket.freezed.dart';
|
||||||
|
part 'websocket.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class WebSocketState with _$WebSocketState {
|
class WebSocketState with _$WebSocketState {
|
||||||
@ -17,15 +21,35 @@ class WebSocketState with _$WebSocketState {
|
|||||||
const factory WebSocketState.error(String message) = _Error;
|
const factory WebSocketState.error(String message) = _Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class WebSocketPacket with _$WebSocketPacket {
|
||||||
|
const factory WebSocketPacket({
|
||||||
|
required String type,
|
||||||
|
required Map<String, dynamic>? data,
|
||||||
|
required String? errorMessage,
|
||||||
|
}) = _WebSocketPacket;
|
||||||
|
|
||||||
|
factory WebSocketPacket.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$WebSocketPacketFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
final websocketProvider = Provider<WebSocketService>((ref) {
|
final websocketProvider = Provider<WebSocketService>((ref) {
|
||||||
return WebSocketService();
|
return WebSocketService();
|
||||||
});
|
});
|
||||||
|
|
||||||
class WebSocketService {
|
class WebSocketService {
|
||||||
WebSocketChannel? _channel;
|
WebSocketChannel? _channel;
|
||||||
Stream<dynamic>? _broadcastStream;
|
final StreamController<WebSocketPacket> _streamController =
|
||||||
|
StreamController<WebSocketPacket>.broadcast();
|
||||||
|
String? _lastUrl;
|
||||||
|
String? _lastAtk;
|
||||||
|
Timer? _reconnectTimer;
|
||||||
|
|
||||||
|
Stream<WebSocketPacket> get dataStream => _streamController.stream;
|
||||||
|
|
||||||
Future<void> connect(String url, String atk) async {
|
Future<void> connect(String url, String atk) async {
|
||||||
|
_lastUrl = url;
|
||||||
|
_lastAtk = atk;
|
||||||
log('[WebSocket] Trying connecting to $url');
|
log('[WebSocket] Trying connecting to $url');
|
||||||
try {
|
try {
|
||||||
_channel = IOWebSocketChannel.connect(
|
_channel = IOWebSocketChannel.connect(
|
||||||
@ -33,20 +57,48 @@ class WebSocketService {
|
|||||||
headers: {'Authorization': 'Bearer $atk'},
|
headers: {'Authorization': 'Bearer $atk'},
|
||||||
);
|
);
|
||||||
await _channel!.ready;
|
await _channel!.ready;
|
||||||
_broadcastStream = _channel!.stream.asBroadcastStream();
|
_channel!.stream.listen(
|
||||||
|
(data) {
|
||||||
|
final dataStr =
|
||||||
|
data is Uint8List ? utf8.decode(data) : data.toString();
|
||||||
|
final packet = WebSocketPacket.fromJson(jsonDecode(dataStr));
|
||||||
|
_streamController.sink.add(packet);
|
||||||
|
log("[WebSocket] Received packet: ${packet.type}");
|
||||||
|
},
|
||||||
|
onDone: () {
|
||||||
|
log('[WebSocket] Connection closed, attempting to reconnect...');
|
||||||
|
_scheduleReconnect();
|
||||||
|
},
|
||||||
|
onError: (error) {
|
||||||
|
log('[WebSocket] Error occurred: $error, attempting to reconnect...');
|
||||||
|
_scheduleReconnect();
|
||||||
|
},
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log('[WebSocket] Failed to connect: $err');
|
log('[WebSocket] Failed to connect: $err');
|
||||||
|
_scheduleReconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _scheduleReconnect() {
|
||||||
|
_reconnectTimer?.cancel();
|
||||||
|
_reconnectTimer = Timer(const Duration(milliseconds: 500), () {
|
||||||
|
if (_lastUrl != null && _lastAtk != null) {
|
||||||
|
connect(_lastUrl!, _lastAtk!);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
WebSocketChannel? get ws => _channel;
|
WebSocketChannel? get ws => _channel;
|
||||||
Stream<dynamic> get stream => _broadcastStream!;
|
|
||||||
|
|
||||||
void sendMessage(String message) {
|
void sendMessage(String message) {
|
||||||
_channel!.sink.add(message);
|
_channel!.sink.add(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void close() {
|
void close() {
|
||||||
|
_reconnectTimer?.cancel();
|
||||||
|
_lastUrl = null;
|
||||||
|
_lastAtk = null;
|
||||||
_channel?.sink.close();
|
_channel?.sink.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,6 +202,153 @@ as String,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$WebSocketPacket {
|
||||||
|
|
||||||
|
String get type; Map<String, dynamic>? get data; String? get errorMessage;
|
||||||
|
/// Create a copy of WebSocketPacket
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$WebSocketPacketCopyWith<WebSocketPacket> get copyWith => _$WebSocketPacketCopyWithImpl<WebSocketPacket>(this as WebSocketPacket, _$identity);
|
||||||
|
|
||||||
|
/// Serializes this WebSocketPacket to a JSON map.
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is WebSocketPacket&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.data, data)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,type,const DeepCollectionEquality().hash(data),errorMessage);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'WebSocketPacket(type: $type, data: $data, errorMessage: $errorMessage)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $WebSocketPacketCopyWith<$Res> {
|
||||||
|
factory $WebSocketPacketCopyWith(WebSocketPacket value, $Res Function(WebSocketPacket) _then) = _$WebSocketPacketCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String type, Map<String, dynamic>? data, String? errorMessage
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$WebSocketPacketCopyWithImpl<$Res>
|
||||||
|
implements $WebSocketPacketCopyWith<$Res> {
|
||||||
|
_$WebSocketPacketCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final WebSocketPacket _self;
|
||||||
|
final $Res Function(WebSocketPacket) _then;
|
||||||
|
|
||||||
|
/// Create a copy of WebSocketPacket
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? type = null,Object? data = freezed,Object? errorMessage = freezed,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, dynamic>?,errorMessage: freezed == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
|
||||||
|
class _WebSocketPacket implements WebSocketPacket {
|
||||||
|
const _WebSocketPacket({required this.type, required final Map<String, dynamic>? data, required this.errorMessage}): _data = data;
|
||||||
|
factory _WebSocketPacket.fromJson(Map<String, dynamic> json) => _$WebSocketPacketFromJson(json);
|
||||||
|
|
||||||
|
@override final String type;
|
||||||
|
final Map<String, dynamic>? _data;
|
||||||
|
@override Map<String, dynamic>? get data {
|
||||||
|
final value = _data;
|
||||||
|
if (value == null) return null;
|
||||||
|
if (_data is EqualUnmodifiableMapView) return _data;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableMapView(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override final String? errorMessage;
|
||||||
|
|
||||||
|
/// Create a copy of WebSocketPacket
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$WebSocketPacketCopyWith<_WebSocketPacket> get copyWith => __$WebSocketPacketCopyWithImpl<_WebSocketPacket>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$WebSocketPacketToJson(this, );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _WebSocketPacket&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._data, _data)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,type,const DeepCollectionEquality().hash(_data),errorMessage);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'WebSocketPacket(type: $type, data: $data, errorMessage: $errorMessage)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$WebSocketPacketCopyWith<$Res> implements $WebSocketPacketCopyWith<$Res> {
|
||||||
|
factory _$WebSocketPacketCopyWith(_WebSocketPacket value, $Res Function(_WebSocketPacket) _then) = __$WebSocketPacketCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String type, Map<String, dynamic>? data, String? errorMessage
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$WebSocketPacketCopyWithImpl<$Res>
|
||||||
|
implements _$WebSocketPacketCopyWith<$Res> {
|
||||||
|
__$WebSocketPacketCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _WebSocketPacket _self;
|
||||||
|
final $Res Function(_WebSocketPacket) _then;
|
||||||
|
|
||||||
|
/// Create a copy of WebSocketPacket
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? data = freezed,Object? errorMessage = freezed,}) {
|
||||||
|
return _then(_WebSocketPacket(
|
||||||
|
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,data: freezed == data ? _self._data : data // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, dynamic>?,errorMessage: freezed == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dart format on
|
// dart format on
|
||||||
|
21
lib/pods/websocket.g.dart
Normal file
21
lib/pods/websocket.g.dart
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'websocket.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_WebSocketPacket _$WebSocketPacketFromJson(Map<String, dynamic> json) =>
|
||||||
|
_WebSocketPacket(
|
||||||
|
type: json['type'] as String,
|
||||||
|
data: json['data'] as Map<String, dynamic>?,
|
||||||
|
errorMessage: json['error_message'] as String?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$WebSocketPacketToJson(_WebSocketPacket instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'type': instance.type,
|
||||||
|
'data': instance.data,
|
||||||
|
'error_message': instance.errorMessage,
|
||||||
|
};
|
@ -37,5 +37,6 @@ class AppRouter extends RootStackRouter {
|
|||||||
AutoRoute(page: NewChatRoute.page, path: '/chat/new'),
|
AutoRoute(page: NewChatRoute.page, path: '/chat/new'),
|
||||||
AutoRoute(page: EditChatRoute.page, path: '/chat/:id/edit'),
|
AutoRoute(page: EditChatRoute.page, path: '/chat/:id/edit'),
|
||||||
AutoRoute(page: ChatRoomRoute.page, path: '/chat/:id'),
|
AutoRoute(page: ChatRoomRoute.page, path: '/chat/:id'),
|
||||||
|
AutoRoute(page: ChatDetailRoute.page, path: '/chat/:id/detail'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,32 +9,33 @@
|
|||||||
// coverage:ignore-file
|
// coverage:ignore-file
|
||||||
|
|
||||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||||
import 'package:auto_route/auto_route.dart' as _i14;
|
import 'package:auto_route/auto_route.dart' as _i15;
|
||||||
import 'package:flutter/material.dart' as _i15;
|
import 'package:flutter/material.dart' as _i16;
|
||||||
import 'package:island/models/post.dart' as _i16;
|
import 'package:island/models/post.dart' as _i17;
|
||||||
import 'package:island/screens/account.dart' as _i1;
|
import 'package:island/screens/account.dart' as _i1;
|
||||||
import 'package:island/screens/account/me.dart' as _i9;
|
import 'package:island/screens/account/me.dart' as _i10;
|
||||||
import 'package:island/screens/account/me/publishers.dart' as _i5;
|
import 'package:island/screens/account/me/publishers.dart' as _i6;
|
||||||
import 'package:island/screens/account/me/update.dart' as _i13;
|
import 'package:island/screens/account/me/update.dart' as _i14;
|
||||||
import 'package:island/screens/auth/create_account.dart' as _i4;
|
import 'package:island/screens/auth/create_account.dart' as _i5;
|
||||||
import 'package:island/screens/auth/login.dart' as _i8;
|
import 'package:island/screens/auth/login.dart' as _i9;
|
||||||
import 'package:island/screens/auth/tabs.dart' as _i12;
|
import 'package:island/screens/auth/tabs.dart' as _i13;
|
||||||
import 'package:island/screens/chat/chat.dart' as _i2;
|
import 'package:island/screens/chat/chat.dart' as _i3;
|
||||||
import 'package:island/screens/chat/room.dart' as _i3;
|
import 'package:island/screens/chat/room.dart' as _i4;
|
||||||
import 'package:island/screens/explore.dart' as _i7;
|
import 'package:island/screens/chat/room_detail.dart' as _i2;
|
||||||
import 'package:island/screens/posts/compose.dart' as _i10;
|
import 'package:island/screens/explore.dart' as _i8;
|
||||||
import 'package:island/screens/posts/detail.dart' as _i11;
|
import 'package:island/screens/posts/compose.dart' as _i11;
|
||||||
import 'package:island/screens/realm/realms.dart' as _i6;
|
import 'package:island/screens/posts/detail.dart' as _i12;
|
||||||
|
import 'package:island/screens/realm/realms.dart' as _i7;
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i1.AccountScreen]
|
/// [_i1.AccountScreen]
|
||||||
class AccountRoute extends _i14.PageRouteInfo<void> {
|
class AccountRoute extends _i15.PageRouteInfo<void> {
|
||||||
const AccountRoute({List<_i14.PageRouteInfo>? children})
|
const AccountRoute({List<_i15.PageRouteInfo>? children})
|
||||||
: super(AccountRoute.name, initialChildren: children);
|
: super(AccountRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'AccountRoute';
|
static const String name = 'AccountRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i1.AccountScreen();
|
return const _i1.AccountScreen();
|
||||||
@ -43,28 +44,69 @@ class AccountRoute extends _i14.PageRouteInfo<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i2.ChatListScreen]
|
/// [_i2.ChatDetailScreen]
|
||||||
class ChatListRoute extends _i14.PageRouteInfo<void> {
|
class ChatDetailRoute extends _i15.PageRouteInfo<ChatDetailRouteArgs> {
|
||||||
const ChatListRoute({List<_i14.PageRouteInfo>? children})
|
ChatDetailRoute({
|
||||||
|
_i16.Key? key,
|
||||||
|
required int id,
|
||||||
|
List<_i15.PageRouteInfo>? children,
|
||||||
|
}) : super(
|
||||||
|
ChatDetailRoute.name,
|
||||||
|
args: ChatDetailRouteArgs(key: key, id: id),
|
||||||
|
rawPathParams: {'id': id},
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const String name = 'ChatDetailRoute';
|
||||||
|
|
||||||
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
|
name,
|
||||||
|
builder: (data) {
|
||||||
|
final pathParams = data.inheritedPathParams;
|
||||||
|
final args = data.argsAs<ChatDetailRouteArgs>(
|
||||||
|
orElse: () => ChatDetailRouteArgs(id: pathParams.getInt('id')),
|
||||||
|
);
|
||||||
|
return _i2.ChatDetailScreen(key: args.key, id: args.id);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChatDetailRouteArgs {
|
||||||
|
const ChatDetailRouteArgs({this.key, required this.id});
|
||||||
|
|
||||||
|
final _i16.Key? key;
|
||||||
|
|
||||||
|
final int id;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ChatDetailRouteArgs{key: $key, id: $id}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// generated route for
|
||||||
|
/// [_i3.ChatListScreen]
|
||||||
|
class ChatListRoute extends _i15.PageRouteInfo<void> {
|
||||||
|
const ChatListRoute({List<_i15.PageRouteInfo>? children})
|
||||||
: super(ChatListRoute.name, initialChildren: children);
|
: super(ChatListRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'ChatListRoute';
|
static const String name = 'ChatListRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i2.ChatListScreen();
|
return const _i3.ChatListScreen();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i3.ChatRoomScreen]
|
/// [_i4.ChatRoomScreen]
|
||||||
class ChatRoomRoute extends _i14.PageRouteInfo<ChatRoomRouteArgs> {
|
class ChatRoomRoute extends _i15.PageRouteInfo<ChatRoomRouteArgs> {
|
||||||
ChatRoomRoute({
|
ChatRoomRoute({
|
||||||
_i15.Key? key,
|
_i16.Key? key,
|
||||||
required int id,
|
required int id,
|
||||||
List<_i14.PageRouteInfo>? children,
|
List<_i15.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
ChatRoomRoute.name,
|
ChatRoomRoute.name,
|
||||||
args: ChatRoomRouteArgs(key: key, id: id),
|
args: ChatRoomRouteArgs(key: key, id: id),
|
||||||
@ -74,14 +116,14 @@ class ChatRoomRoute extends _i14.PageRouteInfo<ChatRoomRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'ChatRoomRoute';
|
static const String name = 'ChatRoomRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final pathParams = data.inheritedPathParams;
|
final pathParams = data.inheritedPathParams;
|
||||||
final args = data.argsAs<ChatRoomRouteArgs>(
|
final args = data.argsAs<ChatRoomRouteArgs>(
|
||||||
orElse: () => ChatRoomRouteArgs(id: pathParams.getInt('id')),
|
orElse: () => ChatRoomRouteArgs(id: pathParams.getInt('id')),
|
||||||
);
|
);
|
||||||
return _i3.ChatRoomScreen(key: args.key, id: args.id);
|
return _i4.ChatRoomScreen(key: args.key, id: args.id);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -89,7 +131,7 @@ class ChatRoomRoute extends _i14.PageRouteInfo<ChatRoomRouteArgs> {
|
|||||||
class ChatRoomRouteArgs {
|
class ChatRoomRouteArgs {
|
||||||
const ChatRoomRouteArgs({this.key, required this.id});
|
const ChatRoomRouteArgs({this.key, required this.id});
|
||||||
|
|
||||||
final _i15.Key? key;
|
final _i16.Key? key;
|
||||||
|
|
||||||
final int id;
|
final int id;
|
||||||
|
|
||||||
@ -100,25 +142,25 @@ class ChatRoomRouteArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i4.CreateAccountScreen]
|
/// [_i5.CreateAccountScreen]
|
||||||
class CreateAccountRoute extends _i14.PageRouteInfo<void> {
|
class CreateAccountRoute extends _i15.PageRouteInfo<void> {
|
||||||
const CreateAccountRoute({List<_i14.PageRouteInfo>? children})
|
const CreateAccountRoute({List<_i15.PageRouteInfo>? children})
|
||||||
: super(CreateAccountRoute.name, initialChildren: children);
|
: super(CreateAccountRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'CreateAccountRoute';
|
static const String name = 'CreateAccountRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i4.CreateAccountScreen();
|
return const _i5.CreateAccountScreen();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i2.EditChatScreen]
|
/// [_i3.EditChatScreen]
|
||||||
class EditChatRoute extends _i14.PageRouteInfo<EditChatRouteArgs> {
|
class EditChatRoute extends _i15.PageRouteInfo<EditChatRouteArgs> {
|
||||||
EditChatRoute({_i15.Key? key, int? id, List<_i14.PageRouteInfo>? children})
|
EditChatRoute({_i16.Key? key, int? id, List<_i15.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
EditChatRoute.name,
|
EditChatRoute.name,
|
||||||
args: EditChatRouteArgs(key: key, id: id),
|
args: EditChatRouteArgs(key: key, id: id),
|
||||||
@ -128,14 +170,14 @@ class EditChatRoute extends _i14.PageRouteInfo<EditChatRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'EditChatRoute';
|
static const String name = 'EditChatRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final pathParams = data.inheritedPathParams;
|
final pathParams = data.inheritedPathParams;
|
||||||
final args = data.argsAs<EditChatRouteArgs>(
|
final args = data.argsAs<EditChatRouteArgs>(
|
||||||
orElse: () => EditChatRouteArgs(id: pathParams.optInt('id')),
|
orElse: () => EditChatRouteArgs(id: pathParams.optInt('id')),
|
||||||
);
|
);
|
||||||
return _i2.EditChatScreen(key: args.key, id: args.id);
|
return _i3.EditChatScreen(key: args.key, id: args.id);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -143,7 +185,7 @@ class EditChatRoute extends _i14.PageRouteInfo<EditChatRouteArgs> {
|
|||||||
class EditChatRouteArgs {
|
class EditChatRouteArgs {
|
||||||
const EditChatRouteArgs({this.key, this.id});
|
const EditChatRouteArgs({this.key, this.id});
|
||||||
|
|
||||||
final _i15.Key? key;
|
final _i16.Key? key;
|
||||||
|
|
||||||
final int? id;
|
final int? id;
|
||||||
|
|
||||||
@ -154,12 +196,12 @@ class EditChatRouteArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i5.EditPublisherScreen]
|
/// [_i6.EditPublisherScreen]
|
||||||
class EditPublisherRoute extends _i14.PageRouteInfo<EditPublisherRouteArgs> {
|
class EditPublisherRoute extends _i15.PageRouteInfo<EditPublisherRouteArgs> {
|
||||||
EditPublisherRoute({
|
EditPublisherRoute({
|
||||||
_i15.Key? key,
|
_i16.Key? key,
|
||||||
String? name,
|
String? name,
|
||||||
List<_i14.PageRouteInfo>? children,
|
List<_i15.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
EditPublisherRoute.name,
|
EditPublisherRoute.name,
|
||||||
args: EditPublisherRouteArgs(key: key, name: name),
|
args: EditPublisherRouteArgs(key: key, name: name),
|
||||||
@ -169,14 +211,14 @@ class EditPublisherRoute extends _i14.PageRouteInfo<EditPublisherRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'EditPublisherRoute';
|
static const String name = 'EditPublisherRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final pathParams = data.inheritedPathParams;
|
final pathParams = data.inheritedPathParams;
|
||||||
final args = data.argsAs<EditPublisherRouteArgs>(
|
final args = data.argsAs<EditPublisherRouteArgs>(
|
||||||
orElse: () => EditPublisherRouteArgs(name: pathParams.optString('id')),
|
orElse: () => EditPublisherRouteArgs(name: pathParams.optString('id')),
|
||||||
);
|
);
|
||||||
return _i5.EditPublisherScreen(key: args.key, name: args.name);
|
return _i6.EditPublisherScreen(key: args.key, name: args.name);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -184,7 +226,7 @@ class EditPublisherRoute extends _i14.PageRouteInfo<EditPublisherRouteArgs> {
|
|||||||
class EditPublisherRouteArgs {
|
class EditPublisherRouteArgs {
|
||||||
const EditPublisherRouteArgs({this.key, this.name});
|
const EditPublisherRouteArgs({this.key, this.name});
|
||||||
|
|
||||||
final _i15.Key? key;
|
final _i16.Key? key;
|
||||||
|
|
||||||
final String? name;
|
final String? name;
|
||||||
|
|
||||||
@ -195,12 +237,12 @@ class EditPublisherRouteArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i6.EditRealmScreen]
|
/// [_i7.EditRealmScreen]
|
||||||
class EditRealmRoute extends _i14.PageRouteInfo<EditRealmRouteArgs> {
|
class EditRealmRoute extends _i15.PageRouteInfo<EditRealmRouteArgs> {
|
||||||
EditRealmRoute({
|
EditRealmRoute({
|
||||||
_i15.Key? key,
|
_i16.Key? key,
|
||||||
String? slug,
|
String? slug,
|
||||||
List<_i14.PageRouteInfo>? children,
|
List<_i15.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
EditRealmRoute.name,
|
EditRealmRoute.name,
|
||||||
args: EditRealmRouteArgs(key: key, slug: slug),
|
args: EditRealmRouteArgs(key: key, slug: slug),
|
||||||
@ -210,14 +252,14 @@ class EditRealmRoute extends _i14.PageRouteInfo<EditRealmRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'EditRealmRoute';
|
static const String name = 'EditRealmRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final pathParams = data.inheritedPathParams;
|
final pathParams = data.inheritedPathParams;
|
||||||
final args = data.argsAs<EditRealmRouteArgs>(
|
final args = data.argsAs<EditRealmRouteArgs>(
|
||||||
orElse: () => EditRealmRouteArgs(slug: pathParams.optString('slug')),
|
orElse: () => EditRealmRouteArgs(slug: pathParams.optString('slug')),
|
||||||
);
|
);
|
||||||
return _i6.EditRealmScreen(key: args.key, slug: args.slug);
|
return _i7.EditRealmScreen(key: args.key, slug: args.slug);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -225,7 +267,7 @@ class EditRealmRoute extends _i14.PageRouteInfo<EditRealmRouteArgs> {
|
|||||||
class EditRealmRouteArgs {
|
class EditRealmRouteArgs {
|
||||||
const EditRealmRouteArgs({this.key, this.slug});
|
const EditRealmRouteArgs({this.key, this.slug});
|
||||||
|
|
||||||
final _i15.Key? key;
|
final _i16.Key? key;
|
||||||
|
|
||||||
final String? slug;
|
final String? slug;
|
||||||
|
|
||||||
@ -236,124 +278,124 @@ class EditRealmRouteArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i7.ExploreScreen]
|
/// [_i8.ExploreScreen]
|
||||||
class ExploreRoute extends _i14.PageRouteInfo<void> {
|
class ExploreRoute extends _i15.PageRouteInfo<void> {
|
||||||
const ExploreRoute({List<_i14.PageRouteInfo>? children})
|
const ExploreRoute({List<_i15.PageRouteInfo>? children})
|
||||||
: super(ExploreRoute.name, initialChildren: children);
|
: super(ExploreRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'ExploreRoute';
|
static const String name = 'ExploreRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i7.ExploreScreen();
|
return const _i8.ExploreScreen();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i8.LoginScreen]
|
/// [_i9.LoginScreen]
|
||||||
class LoginRoute extends _i14.PageRouteInfo<void> {
|
class LoginRoute extends _i15.PageRouteInfo<void> {
|
||||||
const LoginRoute({List<_i14.PageRouteInfo>? children})
|
const LoginRoute({List<_i15.PageRouteInfo>? children})
|
||||||
: super(LoginRoute.name, initialChildren: children);
|
: super(LoginRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'LoginRoute';
|
static const String name = 'LoginRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i8.LoginScreen();
|
return const _i9.LoginScreen();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i5.ManagedPublisherScreen]
|
/// [_i6.ManagedPublisherScreen]
|
||||||
class ManagedPublisherRoute extends _i14.PageRouteInfo<void> {
|
class ManagedPublisherRoute extends _i15.PageRouteInfo<void> {
|
||||||
const ManagedPublisherRoute({List<_i14.PageRouteInfo>? children})
|
const ManagedPublisherRoute({List<_i15.PageRouteInfo>? children})
|
||||||
: super(ManagedPublisherRoute.name, initialChildren: children);
|
: super(ManagedPublisherRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'ManagedPublisherRoute';
|
static const String name = 'ManagedPublisherRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i5.ManagedPublisherScreen();
|
return const _i6.ManagedPublisherScreen();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i9.MyselfProfileScreen]
|
/// [_i10.MyselfProfileScreen]
|
||||||
class MyselfProfileRoute extends _i14.PageRouteInfo<void> {
|
class MyselfProfileRoute extends _i15.PageRouteInfo<void> {
|
||||||
const MyselfProfileRoute({List<_i14.PageRouteInfo>? children})
|
const MyselfProfileRoute({List<_i15.PageRouteInfo>? children})
|
||||||
: super(MyselfProfileRoute.name, initialChildren: children);
|
: super(MyselfProfileRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'MyselfProfileRoute';
|
static const String name = 'MyselfProfileRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i9.MyselfProfileScreen();
|
return const _i10.MyselfProfileScreen();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i2.NewChatScreen]
|
/// [_i3.NewChatScreen]
|
||||||
class NewChatRoute extends _i14.PageRouteInfo<void> {
|
class NewChatRoute extends _i15.PageRouteInfo<void> {
|
||||||
const NewChatRoute({List<_i14.PageRouteInfo>? children})
|
const NewChatRoute({List<_i15.PageRouteInfo>? children})
|
||||||
: super(NewChatRoute.name, initialChildren: children);
|
: super(NewChatRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'NewChatRoute';
|
static const String name = 'NewChatRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i2.NewChatScreen();
|
return const _i3.NewChatScreen();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i5.NewPublisherScreen]
|
/// [_i6.NewPublisherScreen]
|
||||||
class NewPublisherRoute extends _i14.PageRouteInfo<void> {
|
class NewPublisherRoute extends _i15.PageRouteInfo<void> {
|
||||||
const NewPublisherRoute({List<_i14.PageRouteInfo>? children})
|
const NewPublisherRoute({List<_i15.PageRouteInfo>? children})
|
||||||
: super(NewPublisherRoute.name, initialChildren: children);
|
: super(NewPublisherRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'NewPublisherRoute';
|
static const String name = 'NewPublisherRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i5.NewPublisherScreen();
|
return const _i6.NewPublisherScreen();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i6.NewRealmScreen]
|
/// [_i7.NewRealmScreen]
|
||||||
class NewRealmRoute extends _i14.PageRouteInfo<void> {
|
class NewRealmRoute extends _i15.PageRouteInfo<void> {
|
||||||
const NewRealmRoute({List<_i14.PageRouteInfo>? children})
|
const NewRealmRoute({List<_i15.PageRouteInfo>? children})
|
||||||
: super(NewRealmRoute.name, initialChildren: children);
|
: super(NewRealmRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'NewRealmRoute';
|
static const String name = 'NewRealmRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i6.NewRealmScreen();
|
return const _i7.NewRealmScreen();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i10.PostComposeScreen]
|
/// [_i11.PostComposeScreen]
|
||||||
class PostComposeRoute extends _i14.PageRouteInfo<PostComposeRouteArgs> {
|
class PostComposeRoute extends _i15.PageRouteInfo<PostComposeRouteArgs> {
|
||||||
PostComposeRoute({
|
PostComposeRoute({
|
||||||
_i15.Key? key,
|
_i16.Key? key,
|
||||||
_i16.SnPost? originalPost,
|
_i17.SnPost? originalPost,
|
||||||
List<_i14.PageRouteInfo>? children,
|
List<_i15.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
PostComposeRoute.name,
|
PostComposeRoute.name,
|
||||||
args: PostComposeRouteArgs(key: key, originalPost: originalPost),
|
args: PostComposeRouteArgs(key: key, originalPost: originalPost),
|
||||||
@ -362,13 +404,13 @@ class PostComposeRoute extends _i14.PageRouteInfo<PostComposeRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'PostComposeRoute';
|
static const String name = 'PostComposeRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final args = data.argsAs<PostComposeRouteArgs>(
|
final args = data.argsAs<PostComposeRouteArgs>(
|
||||||
orElse: () => const PostComposeRouteArgs(),
|
orElse: () => const PostComposeRouteArgs(),
|
||||||
);
|
);
|
||||||
return _i10.PostComposeScreen(
|
return _i11.PostComposeScreen(
|
||||||
key: args.key,
|
key: args.key,
|
||||||
originalPost: args.originalPost,
|
originalPost: args.originalPost,
|
||||||
);
|
);
|
||||||
@ -379,9 +421,9 @@ class PostComposeRoute extends _i14.PageRouteInfo<PostComposeRouteArgs> {
|
|||||||
class PostComposeRouteArgs {
|
class PostComposeRouteArgs {
|
||||||
const PostComposeRouteArgs({this.key, this.originalPost});
|
const PostComposeRouteArgs({this.key, this.originalPost});
|
||||||
|
|
||||||
final _i15.Key? key;
|
final _i16.Key? key;
|
||||||
|
|
||||||
final _i16.SnPost? originalPost;
|
final _i17.SnPost? originalPost;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
@ -390,12 +432,12 @@ class PostComposeRouteArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i11.PostDetailScreen]
|
/// [_i12.PostDetailScreen]
|
||||||
class PostDetailRoute extends _i14.PageRouteInfo<PostDetailRouteArgs> {
|
class PostDetailRoute extends _i15.PageRouteInfo<PostDetailRouteArgs> {
|
||||||
PostDetailRoute({
|
PostDetailRoute({
|
||||||
_i15.Key? key,
|
_i16.Key? key,
|
||||||
required int id,
|
required int id,
|
||||||
List<_i14.PageRouteInfo>? children,
|
List<_i15.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
PostDetailRoute.name,
|
PostDetailRoute.name,
|
||||||
args: PostDetailRouteArgs(key: key, id: id),
|
args: PostDetailRouteArgs(key: key, id: id),
|
||||||
@ -405,14 +447,14 @@ class PostDetailRoute extends _i14.PageRouteInfo<PostDetailRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'PostDetailRoute';
|
static const String name = 'PostDetailRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final pathParams = data.inheritedPathParams;
|
final pathParams = data.inheritedPathParams;
|
||||||
final args = data.argsAs<PostDetailRouteArgs>(
|
final args = data.argsAs<PostDetailRouteArgs>(
|
||||||
orElse: () => PostDetailRouteArgs(id: pathParams.getInt('id')),
|
orElse: () => PostDetailRouteArgs(id: pathParams.getInt('id')),
|
||||||
);
|
);
|
||||||
return _i11.PostDetailScreen(key: args.key, id: args.id);
|
return _i12.PostDetailScreen(key: args.key, id: args.id);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -420,7 +462,7 @@ class PostDetailRoute extends _i14.PageRouteInfo<PostDetailRouteArgs> {
|
|||||||
class PostDetailRouteArgs {
|
class PostDetailRouteArgs {
|
||||||
const PostDetailRouteArgs({this.key, required this.id});
|
const PostDetailRouteArgs({this.key, required this.id});
|
||||||
|
|
||||||
final _i15.Key? key;
|
final _i16.Key? key;
|
||||||
|
|
||||||
final int id;
|
final int id;
|
||||||
|
|
||||||
@ -431,12 +473,12 @@ class PostDetailRouteArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i10.PostEditScreen]
|
/// [_i11.PostEditScreen]
|
||||||
class PostEditRoute extends _i14.PageRouteInfo<PostEditRouteArgs> {
|
class PostEditRoute extends _i15.PageRouteInfo<PostEditRouteArgs> {
|
||||||
PostEditRoute({
|
PostEditRoute({
|
||||||
_i15.Key? key,
|
_i16.Key? key,
|
||||||
required int id,
|
required int id,
|
||||||
List<_i14.PageRouteInfo>? children,
|
List<_i15.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
PostEditRoute.name,
|
PostEditRoute.name,
|
||||||
args: PostEditRouteArgs(key: key, id: id),
|
args: PostEditRouteArgs(key: key, id: id),
|
||||||
@ -446,14 +488,14 @@ class PostEditRoute extends _i14.PageRouteInfo<PostEditRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'PostEditRoute';
|
static const String name = 'PostEditRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final pathParams = data.inheritedPathParams;
|
final pathParams = data.inheritedPathParams;
|
||||||
final args = data.argsAs<PostEditRouteArgs>(
|
final args = data.argsAs<PostEditRouteArgs>(
|
||||||
orElse: () => PostEditRouteArgs(id: pathParams.getInt('id')),
|
orElse: () => PostEditRouteArgs(id: pathParams.getInt('id')),
|
||||||
);
|
);
|
||||||
return _i10.PostEditScreen(key: args.key, id: args.id);
|
return _i11.PostEditScreen(key: args.key, id: args.id);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -461,7 +503,7 @@ class PostEditRoute extends _i14.PageRouteInfo<PostEditRouteArgs> {
|
|||||||
class PostEditRouteArgs {
|
class PostEditRouteArgs {
|
||||||
const PostEditRouteArgs({this.key, required this.id});
|
const PostEditRouteArgs({this.key, required this.id});
|
||||||
|
|
||||||
final _i15.Key? key;
|
final _i16.Key? key;
|
||||||
|
|
||||||
final int id;
|
final int id;
|
||||||
|
|
||||||
@ -472,49 +514,49 @@ class PostEditRouteArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i6.RealmListScreen]
|
/// [_i7.RealmListScreen]
|
||||||
class RealmListRoute extends _i14.PageRouteInfo<void> {
|
class RealmListRoute extends _i15.PageRouteInfo<void> {
|
||||||
const RealmListRoute({List<_i14.PageRouteInfo>? children})
|
const RealmListRoute({List<_i15.PageRouteInfo>? children})
|
||||||
: super(RealmListRoute.name, initialChildren: children);
|
: super(RealmListRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'RealmListRoute';
|
static const String name = 'RealmListRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i6.RealmListScreen();
|
return const _i7.RealmListScreen();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i12.TabsScreen]
|
/// [_i13.TabsScreen]
|
||||||
class TabsRoute extends _i14.PageRouteInfo<void> {
|
class TabsRoute extends _i15.PageRouteInfo<void> {
|
||||||
const TabsRoute({List<_i14.PageRouteInfo>? children})
|
const TabsRoute({List<_i15.PageRouteInfo>? children})
|
||||||
: super(TabsRoute.name, initialChildren: children);
|
: super(TabsRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'TabsRoute';
|
static const String name = 'TabsRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i12.TabsScreen();
|
return const _i13.TabsScreen();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i13.UpdateProfileScreen]
|
/// [_i14.UpdateProfileScreen]
|
||||||
class UpdateProfileRoute extends _i14.PageRouteInfo<void> {
|
class UpdateProfileRoute extends _i15.PageRouteInfo<void> {
|
||||||
const UpdateProfileRoute({List<_i14.PageRouteInfo>? children})
|
const UpdateProfileRoute({List<_i15.PageRouteInfo>? children})
|
||||||
: super(UpdateProfileRoute.name, initialChildren: children);
|
: super(UpdateProfileRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'UpdateProfileRoute';
|
static const String name = 'UpdateProfileRoute';
|
||||||
|
|
||||||
static _i14.PageInfo page = _i14.PageInfo(
|
static _i15.PageInfo page = _i15.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i13.UpdateProfileScreen();
|
return const _i14.UpdateProfileScreen();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,9 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final user = ref.watch(userInfoProvider);
|
final user = ref.watch(userInfoProvider);
|
||||||
|
|
||||||
if (!user.hasValue) return _UnauthorizedAccountScreen();
|
if (!user.hasValue || user.value == null) {
|
||||||
|
return _UnauthorizedAccountScreen();
|
||||||
|
}
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(title: const Text('Account')),
|
appBar: AppBar(title: const Text('Account')),
|
||||||
@ -52,7 +54,7 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
spacing: 16,
|
spacing: 16,
|
||||||
children: [
|
children: [
|
||||||
ProfilePictureWidget(
|
ProfilePictureWidget(
|
||||||
fileId: user.value!.profile.pictureId,
|
fileId: user.value?.profile.pictureId,
|
||||||
radius: 24,
|
radius: 24,
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
|
@ -3,6 +3,7 @@ import 'package:dio/dio.dart';
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.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:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:island/models/chat.dart';
|
import 'package:island/models/chat.dart';
|
||||||
@ -15,6 +16,7 @@ import 'package:island/widgets/alert.dart';
|
|||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
@ -36,9 +38,23 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
final chats = ref.watch(chatroomsJoinedProvider);
|
final chats = ref.watch(chatroomsJoinedProvider);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(title: Text('chat').tr()),
|
appBar: AppBar(
|
||||||
|
title: Text('chat').tr(),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.email),
|
||||||
|
onPressed: () {
|
||||||
|
showCupertinoModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => _ChatInvitesSheet(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
],
|
||||||
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
key: Key("chat-page-fab"),
|
heroTag: Key("chat-page-fab"),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.pushRoute(NewChatRoute());
|
context.pushRoute(NewChatRoute());
|
||||||
},
|
},
|
||||||
@ -58,7 +74,7 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
final item = items[index];
|
final item = items[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
leading:
|
leading:
|
||||||
item.picture == null
|
item.pictureId == null
|
||||||
? CircleAvatar(
|
? CircleAvatar(
|
||||||
child: Text(item.name[0].toUpperCase()),
|
child: Text(item.name[0].toUpperCase()),
|
||||||
)
|
)
|
||||||
@ -87,6 +103,14 @@ Future<SnChat?> chatroom(Ref ref, int? identifier) async {
|
|||||||
return SnChat.fromJson(resp.data);
|
return SnChat.fromJson(resp.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<SnChatMember?> chatroomIdentity(Ref ref, int? identifier) async {
|
||||||
|
if (identifier == null) return null;
|
||||||
|
final client = ref.watch(apiClientProvider);
|
||||||
|
final resp = await client.get('/chat/$identifier/members/me');
|
||||||
|
return SnChatMember.fromJson(resp.data);
|
||||||
|
}
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
class NewChatScreen extends StatelessWidget {
|
class NewChatScreen extends StatelessWidget {
|
||||||
const NewChatScreen({super.key});
|
const NewChatScreen({super.key});
|
||||||
@ -275,3 +299,146 @@ class EditChatScreen extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<List<SnChatMember>> chatroomInvites(Ref ref) async {
|
||||||
|
final client = ref.watch(apiClientProvider);
|
||||||
|
final resp = await client.get('/chat/invites');
|
||||||
|
return resp.data
|
||||||
|
.map((e) => SnChatMember.fromJson(e))
|
||||||
|
.cast<SnChatMember>()
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChatInvitesSheet extends HookConsumerWidget {
|
||||||
|
const _ChatInvitesSheet();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final invites = ref.watch(chatroomInvitesProvider);
|
||||||
|
|
||||||
|
Future<void> acceptInvite(SnChatMember invite) async {
|
||||||
|
try {
|
||||||
|
final client = ref.read(apiClientProvider);
|
||||||
|
await client.post('/chat/invites/${invite.chatRoom!.id}/accept');
|
||||||
|
ref.invalidate(chatroomInvitesProvider);
|
||||||
|
ref.invalidate(chatroomsJoinedProvider);
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> declineInvite(SnChatMember invite) async {
|
||||||
|
try {
|
||||||
|
final client = ref.read(apiClientProvider);
|
||||||
|
await client.post('/chat/invites/${invite.chatRoom!.id}/decline');
|
||||||
|
ref.invalidate(chatroomInvitesProvider);
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxHeight: MediaQuery.of(context).size.height * 0.8,
|
||||||
|
),
|
||||||
|
child: Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: 16,
|
||||||
|
left: 20,
|
||||||
|
right: 16,
|
||||||
|
bottom: 12,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'invites'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
letterSpacing: -0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.refresh),
|
||||||
|
style: IconButton.styleFrom(
|
||||||
|
minimumSize: const Size(36, 36),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
ref.refresh(chatroomInvitesProvider.future);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.close),
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
style: IconButton.styleFrom(
|
||||||
|
minimumSize: const Size(36, 36),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 1),
|
||||||
|
Expanded(
|
||||||
|
child: invites.when(
|
||||||
|
data:
|
||||||
|
(items) =>
|
||||||
|
items.isEmpty
|
||||||
|
? Center(
|
||||||
|
child:
|
||||||
|
Text(
|
||||||
|
'invitesEmpty',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
).tr(),
|
||||||
|
)
|
||||||
|
: ListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemCount: items.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final invite = items[index];
|
||||||
|
return ListTile(
|
||||||
|
leading: ProfilePictureWidget(
|
||||||
|
fileId: invite.chatRoom!.pictureId,
|
||||||
|
radius: 24,
|
||||||
|
fallbackIcon: Symbols.group,
|
||||||
|
),
|
||||||
|
title: Text(invite.chatRoom!.name),
|
||||||
|
subtitle:
|
||||||
|
Text(
|
||||||
|
invite.role >= 100
|
||||||
|
? 'permissionOwner'
|
||||||
|
: invite.role >= 50
|
||||||
|
? 'permissionModerator'
|
||||||
|
: 'permissionMember',
|
||||||
|
).tr(),
|
||||||
|
trailing: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.check),
|
||||||
|
onPressed: () => acceptInvite(invite),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.close),
|
||||||
|
onPressed: () => declineInvite(invite),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
|
error: (error, stack) => Center(child: Text('Error: $error')),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -163,5 +163,146 @@ class _ChatroomProviderElement extends AutoDisposeFutureProviderElement<SnChat?>
|
|||||||
int? get identifier => (origin as ChatroomProvider).identifier;
|
int? get identifier => (origin as ChatroomProvider).identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _$chatroomIdentityHash() => r'b20322591279d0336f2f309729e7e0cb9809063f';
|
||||||
|
|
||||||
|
/// See also [chatroomIdentity].
|
||||||
|
@ProviderFor(chatroomIdentity)
|
||||||
|
const chatroomIdentityProvider = ChatroomIdentityFamily();
|
||||||
|
|
||||||
|
/// See also [chatroomIdentity].
|
||||||
|
class ChatroomIdentityFamily extends Family<AsyncValue<SnChatMember?>> {
|
||||||
|
/// See also [chatroomIdentity].
|
||||||
|
const ChatroomIdentityFamily();
|
||||||
|
|
||||||
|
/// See also [chatroomIdentity].
|
||||||
|
ChatroomIdentityProvider call(int? identifier) {
|
||||||
|
return ChatroomIdentityProvider(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ChatroomIdentityProvider getProviderOverride(
|
||||||
|
covariant ChatroomIdentityProvider provider,
|
||||||
|
) {
|
||||||
|
return call(provider.identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||||
|
_allTransitiveDependencies;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get name => r'chatroomIdentityProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [chatroomIdentity].
|
||||||
|
class ChatroomIdentityProvider
|
||||||
|
extends AutoDisposeFutureProvider<SnChatMember?> {
|
||||||
|
/// See also [chatroomIdentity].
|
||||||
|
ChatroomIdentityProvider(int? identifier)
|
||||||
|
: this._internal(
|
||||||
|
(ref) => chatroomIdentity(ref as ChatroomIdentityRef, identifier),
|
||||||
|
from: chatroomIdentityProvider,
|
||||||
|
name: r'chatroomIdentityProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$chatroomIdentityHash,
|
||||||
|
dependencies: ChatroomIdentityFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
ChatroomIdentityFamily._allTransitiveDependencies,
|
||||||
|
identifier: identifier,
|
||||||
|
);
|
||||||
|
|
||||||
|
ChatroomIdentityProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.identifier,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final int? identifier;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(
|
||||||
|
FutureOr<SnChatMember?> Function(ChatroomIdentityRef provider) create,
|
||||||
|
) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: ChatroomIdentityProvider._internal(
|
||||||
|
(ref) => create(ref as ChatroomIdentityRef),
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
identifier: identifier,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeFutureProviderElement<SnChatMember?> createElement() {
|
||||||
|
return _ChatroomIdentityProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is ChatroomIdentityProvider && other.identifier == identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, identifier.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
mixin ChatroomIdentityRef on AutoDisposeFutureProviderRef<SnChatMember?> {
|
||||||
|
/// The parameter `identifier` of this provider.
|
||||||
|
int? get identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChatroomIdentityProviderElement
|
||||||
|
extends AutoDisposeFutureProviderElement<SnChatMember?>
|
||||||
|
with ChatroomIdentityRef {
|
||||||
|
_ChatroomIdentityProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int? get identifier => (origin as ChatroomIdentityProvider).identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$chatroomInvitesHash() => r'c15f06c1e9c6074e6159d9d1f4404f31250ce523';
|
||||||
|
|
||||||
|
/// See also [chatroomInvites].
|
||||||
|
@ProviderFor(chatroomInvites)
|
||||||
|
final chatroomInvitesProvider =
|
||||||
|
AutoDisposeFutureProvider<List<SnChatMember>>.internal(
|
||||||
|
chatroomInvites,
|
||||||
|
name: r'chatroomInvitesProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$chatroomInvitesHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
typedef ChatroomInvitesRef = AutoDisposeFutureProviderRef<List<SnChatMember>>;
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import 'package:auto_route/annotations.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -9,6 +9,7 @@ import 'package:island/database/message.dart';
|
|||||||
import 'package:island/database/message_repository.dart';
|
import 'package:island/database/message_repository.dart';
|
||||||
import 'package:island/pods/message.dart';
|
import 'package:island/pods/message.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/route.gr.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||||
@ -19,9 +20,10 @@ import 'chat.dart';
|
|||||||
final messageRepositoryProvider = FutureProvider.family<MessageRepository, int>(
|
final messageRepositoryProvider = FutureProvider.family<MessageRepository, int>(
|
||||||
(ref, roomId) async {
|
(ref, roomId) async {
|
||||||
final room = await ref.watch(chatroomProvider(roomId).future);
|
final room = await ref.watch(chatroomProvider(roomId).future);
|
||||||
|
final identity = await ref.watch(chatroomIdentityProvider(roomId).future);
|
||||||
final apiClient = ref.watch(apiClientProvider);
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
final database = ref.watch(databaseProvider);
|
final database = ref.watch(databaseProvider);
|
||||||
return MessageRepository(room!, apiClient, database);
|
return MessageRepository(room!, identity!, apiClient, database);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -153,8 +155,10 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final chatRoom = ref.watch(chatroomProvider(id));
|
final chatRoom = ref.watch(chatroomProvider(id));
|
||||||
|
final chatIdentity = ref.watch(chatroomIdentityProvider(id));
|
||||||
final messages = ref.watch(messagesProvider(id));
|
final messages = ref.watch(messagesProvider(id));
|
||||||
final messagesNotifier = ref.read(messagesProvider(id).notifier);
|
final messagesNotifier = ref.read(messagesProvider(id).notifier);
|
||||||
|
final messagesRepo = ref.watch(messageRepositoryProvider(id));
|
||||||
|
|
||||||
final messageController = useTextEditingController();
|
final messageController = useTextEditingController();
|
||||||
final scrollController = useScrollController();
|
final scrollController = useScrollController();
|
||||||
@ -185,7 +189,7 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
height: 26,
|
height: 26,
|
||||||
width: 26,
|
width: 26,
|
||||||
child:
|
child:
|
||||||
room?.picture != null
|
room?.pictureId != null
|
||||||
? ProfilePictureWidget(
|
? ProfilePictureWidget(
|
||||||
fileId: room?.pictureId,
|
fileId: room?.pictureId,
|
||||||
fallbackIcon: Symbols.chat,
|
fallbackIcon: Symbols.chat,
|
||||||
@ -197,14 +201,19 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(room?.name ?? 'unknown').fontSize(19).tr(),
|
Text(room?.name ?? 'unknown'.tr()).fontSize(19),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
loading: () => const Text('Loading...'),
|
loading: () => const Text('Loading...'),
|
||||||
error: (_, __) => const Text('Error'),
|
error: (_, __) => const Text('Error'),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(icon: const Icon(Icons.more_vert), onPressed: () {}),
|
IconButton(
|
||||||
|
icon: const Icon(Icons.more_vert),
|
||||||
|
onPressed: () {
|
||||||
|
context.router.push(ChatDetailRoute(id: id));
|
||||||
|
},
|
||||||
|
),
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -217,12 +226,27 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
messageList.isEmpty
|
messageList.isEmpty
|
||||||
? Center(child: Text('No messages yet'.tr()))
|
? Center(child: Text('No messages yet'.tr()))
|
||||||
: ListView.builder(
|
: ListView.builder(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 16),
|
||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
reverse: true, // Show newest messages at the bottom
|
reverse: true, // Show newest messages at the bottom
|
||||||
itemCount: messageList.length,
|
itemCount: messageList.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final message = messageList[index];
|
final message = messageList[index];
|
||||||
return MessageBubble(message: message);
|
return chatIdentity.when(
|
||||||
|
skipError: true,
|
||||||
|
data:
|
||||||
|
(identity) => MessageBubble(
|
||||||
|
message: message,
|
||||||
|
isCurrentUser:
|
||||||
|
identity?.id == message.senderId,
|
||||||
|
),
|
||||||
|
loading:
|
||||||
|
() => MessageBubble(
|
||||||
|
message: message,
|
||||||
|
isCurrentUser: false,
|
||||||
|
),
|
||||||
|
error: (_, __) => const SizedBox.shrink(),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
@ -302,14 +326,16 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
class MessageBubble extends StatelessWidget {
|
class MessageBubble extends StatelessWidget {
|
||||||
final LocalChatMessage message;
|
final LocalChatMessage message;
|
||||||
|
final bool isCurrentUser;
|
||||||
|
|
||||||
const MessageBubble({Key? key, required this.message}) : super(key: key);
|
const MessageBubble({
|
||||||
|
super.key,
|
||||||
|
required this.message,
|
||||||
|
required this.isCurrentUser,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final isCurrentUser =
|
|
||||||
message.senderId == 'current_user_id'; // Replace with actual check
|
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||||
child: Row(
|
child: Row(
|
||||||
@ -365,7 +391,11 @@ class MessageBubble extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
if (isCurrentUser)
|
if (isCurrentUser)
|
||||||
const SizedBox(width: 32), // Balance with avatar on the other side
|
ProfilePictureWidget(
|
||||||
|
fileId:
|
||||||
|
message.toRemoteMessage().sender.account.profile.pictureId,
|
||||||
|
radius: 16,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
382
lib/screens/chat/room_detail.dart
Normal file
382
lib/screens/chat/room_detail.dart
Normal file
@ -0,0 +1,382 @@
|
|||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:island/models/chat.dart';
|
||||||
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/route.gr.dart';
|
||||||
|
import 'package:island/screens/chat/chat.dart';
|
||||||
|
import 'package:island/widgets/account/account_picker.dart';
|
||||||
|
import 'package:island/widgets/alert.dart';
|
||||||
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
|
part 'room_detail.freezed.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
|
class ChatDetailScreen extends HookConsumerWidget {
|
||||||
|
final int id;
|
||||||
|
const ChatDetailScreen({super.key, @PathParam("id") required this.id});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final roomState = ref.watch(chatroomProvider(id));
|
||||||
|
final roomIdentity = ref.watch(chatroomIdentityProvider(id));
|
||||||
|
|
||||||
|
final isModerator = roomIdentity.when(
|
||||||
|
loading: () => false,
|
||||||
|
error: (error, _) => false,
|
||||||
|
data: (identity) => (identity?.role ?? 0) >= 50,
|
||||||
|
);
|
||||||
|
|
||||||
|
const iconShadow = Shadow(
|
||||||
|
color: Colors.black54,
|
||||||
|
blurRadius: 5.0,
|
||||||
|
offset: Offset(1.0, 1.0),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
body: roomState.when(
|
||||||
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
|
error: (error, _) => Center(child: Text('Error: $error')),
|
||||||
|
data:
|
||||||
|
(currentRoom) => CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
SliverAppBar(
|
||||||
|
expandedHeight: 180,
|
||||||
|
pinned: true,
|
||||||
|
leading: PageBackButton(shadows: [iconShadow]),
|
||||||
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
|
background:
|
||||||
|
currentRoom?.backgroundId != null
|
||||||
|
? CloudImageWidget(
|
||||||
|
fileId: currentRoom!.backgroundId!,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
color:
|
||||||
|
Theme.of(context).appBarTheme.backgroundColor,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
currentRoom?.name ?? 'unknown'.tr(),
|
||||||
|
).textColor(Theme.of(context).appBarTheme.foregroundColor),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.people, shadows: [iconShadow]),
|
||||||
|
onPressed: () {
|
||||||
|
showCupertinoModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) => _ChatMemberListSheet(roomId: id),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (isModerator)
|
||||||
|
_ChatRoomActionMenu(id: id, iconShadow: iconShadow),
|
||||||
|
const Gap(8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
currentRoom?.description ?? 'descriptionNone'.tr(),
|
||||||
|
style: const TextStyle(fontSize: 16),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChatRoomActionMenu extends StatelessWidget {
|
||||||
|
final int id;
|
||||||
|
final Shadow iconShadow;
|
||||||
|
|
||||||
|
const _ChatRoomActionMenu({required this.id, required this.iconShadow});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return PopupMenuButton(
|
||||||
|
icon: Icon(Icons.more_vert, shadows: [iconShadow]),
|
||||||
|
itemBuilder:
|
||||||
|
(context) => [
|
||||||
|
PopupMenuItem(
|
||||||
|
onTap: () {
|
||||||
|
context.router.replace(EditChatRoute(id: id));
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.edit,
|
||||||
|
color: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||||
|
),
|
||||||
|
const Gap(12),
|
||||||
|
const Text('editChatRoom').tr(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.delete, color: Colors.red),
|
||||||
|
const Gap(12),
|
||||||
|
const Text(
|
||||||
|
'deleteChatRoom',
|
||||||
|
style: TextStyle(color: Colors.red),
|
||||||
|
).tr(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) => AlertDialog(
|
||||||
|
title: const Text('Delete Room'),
|
||||||
|
content: const Text(
|
||||||
|
'Are you sure you want to delete this room? This action cannot be undone.',
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: const Text('Cancel'),
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: const Text(
|
||||||
|
'Delete',
|
||||||
|
style: TextStyle(color: Colors.red),
|
||||||
|
),
|
||||||
|
onPressed: () async {},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class ChatRoomMemberState with _$ChatRoomMemberState {
|
||||||
|
const factory ChatRoomMemberState({
|
||||||
|
required List<SnChatMember> members,
|
||||||
|
required bool isLoading,
|
||||||
|
required int total,
|
||||||
|
String? error,
|
||||||
|
}) = _ChatRoomMemberState;
|
||||||
|
}
|
||||||
|
|
||||||
|
final chatMemberStateProvider =
|
||||||
|
StateNotifierProvider.family<ChatMemberNotifier, ChatRoomMemberState, int>((
|
||||||
|
ref,
|
||||||
|
roomId,
|
||||||
|
) {
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
return ChatMemberNotifier(apiClient, roomId);
|
||||||
|
});
|
||||||
|
|
||||||
|
class ChatMemberNotifier extends StateNotifier<ChatRoomMemberState> {
|
||||||
|
final int roomId;
|
||||||
|
final Dio _apiClient;
|
||||||
|
|
||||||
|
ChatMemberNotifier(this._apiClient, this.roomId)
|
||||||
|
: super(const ChatRoomMemberState(members: [], isLoading: false, total: 0));
|
||||||
|
|
||||||
|
Future<void> loadMore({int offset = 0, int take = 20}) async {
|
||||||
|
if (state.isLoading) return;
|
||||||
|
if (state.total > 0 && state.members.length >= state.total) return;
|
||||||
|
|
||||||
|
state = state.copyWith(isLoading: true, error: null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await _apiClient.get(
|
||||||
|
'/chat/$roomId/members',
|
||||||
|
queryParameters: {'offset': offset, 'take': take},
|
||||||
|
);
|
||||||
|
|
||||||
|
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||||
|
final List<dynamic> data = response.data;
|
||||||
|
final members = data.map((e) => SnChatMember.fromJson(e)).toList();
|
||||||
|
|
||||||
|
state = state.copyWith(
|
||||||
|
members: [...state.members, ...members],
|
||||||
|
total: total,
|
||||||
|
isLoading: false,
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
state = state.copyWith(error: e.toString(), isLoading: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
state = const ChatRoomMemberState(members: [], isLoading: false, total: 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChatMemberListSheet extends HookConsumerWidget {
|
||||||
|
final int roomId;
|
||||||
|
const _ChatMemberListSheet({required this.roomId});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final memberState = ref.watch(chatMemberStateProvider(roomId));
|
||||||
|
final memberNotifier = ref.read(chatMemberStateProvider(roomId).notifier);
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
Future(() {
|
||||||
|
memberNotifier.loadMore();
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
Future<void> invitePerson() async {
|
||||||
|
final result = await showCupertinoModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => const AccountPickerSheet(),
|
||||||
|
);
|
||||||
|
if (result == null) return;
|
||||||
|
try {
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
await apiClient.post(
|
||||||
|
'/chat/invites/$roomId',
|
||||||
|
data: {'related_user_id': result.id, 'role': 0},
|
||||||
|
);
|
||||||
|
memberNotifier.reset();
|
||||||
|
await memberNotifier.loadMore();
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxHeight: MediaQuery.of(context).size.height * 0.8,
|
||||||
|
),
|
||||||
|
child: Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: 16,
|
||||||
|
left: 20,
|
||||||
|
right: 16,
|
||||||
|
bottom: 12,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'chatMembers'.plural(memberState.total),
|
||||||
|
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
letterSpacing: -0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.person_add),
|
||||||
|
onPressed: invitePerson,
|
||||||
|
style: IconButton.styleFrom(
|
||||||
|
minimumSize: const Size(36, 36),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.refresh),
|
||||||
|
onPressed: () {
|
||||||
|
memberNotifier.reset();
|
||||||
|
memberNotifier.loadMore();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.close),
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
style: IconButton.styleFrom(
|
||||||
|
minimumSize: const Size(36, 36),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 1),
|
||||||
|
Expanded(
|
||||||
|
child:
|
||||||
|
memberState.error != null
|
||||||
|
? Center(child: Text(memberState.error!))
|
||||||
|
: ListView.builder(
|
||||||
|
itemCount: memberState.members.length + 1,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index == memberState.members.length) {
|
||||||
|
if (memberState.isLoading) {
|
||||||
|
return const Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(16.0),
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (memberState.members.length <
|
||||||
|
memberState.total) {
|
||||||
|
memberNotifier.loadMore(
|
||||||
|
offset: memberState.members.length,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
|
final member = memberState.members[index];
|
||||||
|
return ListTile(
|
||||||
|
leading: ProfilePictureWidget(
|
||||||
|
fileId: member.account.profile.pictureId,
|
||||||
|
),
|
||||||
|
title: Row(
|
||||||
|
spacing: 6,
|
||||||
|
children: [
|
||||||
|
Flexible(child: Text(member.account.nick)),
|
||||||
|
if (member.joinedAt == null)
|
||||||
|
const Icon(Symbols.pending_actions, size: 20),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
subtitle: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
member.role >= 100
|
||||||
|
? 'permissionOwner'
|
||||||
|
: member.role >= 50
|
||||||
|
? 'permissionModerator'
|
||||||
|
: 'permissionMember',
|
||||||
|
).tr(),
|
||||||
|
Text('·').bold().padding(horizontal: 6),
|
||||||
|
Expanded(
|
||||||
|
child: Text("@${member.account.name}"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
157
lib/screens/chat/room_detail.freezed.dart
Normal file
157
lib/screens/chat/room_detail.freezed.dart
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
// dart format width=80
|
||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'room_detail.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// dart format off
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$ChatRoomMemberState {
|
||||||
|
|
||||||
|
List<SnChatMember> get members; bool get isLoading; int get total; String? get error;
|
||||||
|
/// Create a copy of ChatRoomMemberState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$ChatRoomMemberStateCopyWith<ChatRoomMemberState> get copyWith => _$ChatRoomMemberStateCopyWithImpl<ChatRoomMemberState>(this as ChatRoomMemberState, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is ChatRoomMemberState&&const DeepCollectionEquality().equals(other.members, members)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.total, total) || other.total == total)&&(identical(other.error, error) || other.error == error));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(members),isLoading,total,error);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ChatRoomMemberState(members: $members, isLoading: $isLoading, total: $total, error: $error)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $ChatRoomMemberStateCopyWith<$Res> {
|
||||||
|
factory $ChatRoomMemberStateCopyWith(ChatRoomMemberState value, $Res Function(ChatRoomMemberState) _then) = _$ChatRoomMemberStateCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
List<SnChatMember> members, bool isLoading, int total, String? error
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$ChatRoomMemberStateCopyWithImpl<$Res>
|
||||||
|
implements $ChatRoomMemberStateCopyWith<$Res> {
|
||||||
|
_$ChatRoomMemberStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final ChatRoomMemberState _self;
|
||||||
|
final $Res Function(ChatRoomMemberState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of ChatRoomMemberState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? members = null,Object? isLoading = null,Object? total = null,Object? error = freezed,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
members: null == members ? _self.members : members // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SnChatMember>,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _ChatRoomMemberState implements ChatRoomMemberState {
|
||||||
|
const _ChatRoomMemberState({required final List<SnChatMember> members, required this.isLoading, required this.total, this.error}): _members = members;
|
||||||
|
|
||||||
|
|
||||||
|
final List<SnChatMember> _members;
|
||||||
|
@override List<SnChatMember> get members {
|
||||||
|
if (_members is EqualUnmodifiableListView) return _members;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_members);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override final bool isLoading;
|
||||||
|
@override final int total;
|
||||||
|
@override final String? error;
|
||||||
|
|
||||||
|
/// Create a copy of ChatRoomMemberState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$ChatRoomMemberStateCopyWith<_ChatRoomMemberState> get copyWith => __$ChatRoomMemberStateCopyWithImpl<_ChatRoomMemberState>(this, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ChatRoomMemberState&&const DeepCollectionEquality().equals(other._members, _members)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.total, total) || other.total == total)&&(identical(other.error, error) || other.error == error));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_members),isLoading,total,error);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ChatRoomMemberState(members: $members, isLoading: $isLoading, total: $total, error: $error)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$ChatRoomMemberStateCopyWith<$Res> implements $ChatRoomMemberStateCopyWith<$Res> {
|
||||||
|
factory _$ChatRoomMemberStateCopyWith(_ChatRoomMemberState value, $Res Function(_ChatRoomMemberState) _then) = __$ChatRoomMemberStateCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
List<SnChatMember> members, bool isLoading, int total, String? error
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$ChatRoomMemberStateCopyWithImpl<$Res>
|
||||||
|
implements _$ChatRoomMemberStateCopyWith<$Res> {
|
||||||
|
__$ChatRoomMemberStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _ChatRoomMemberState _self;
|
||||||
|
final $Res Function(_ChatRoomMemberState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of ChatRoomMemberState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? members = null,Object? isLoading = null,Object? total = null,Object? error = freezed,}) {
|
||||||
|
return _then(_ChatRoomMemberState(
|
||||||
|
members: null == members ? _self._members : members // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SnChatMember>,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
@ -21,7 +21,7 @@ class ExploreScreen extends ConsumerWidget {
|
|||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(title: const Text('Explore')),
|
appBar: AppBar(title: const Text('Explore')),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
key: Key("explore-page-fab"),
|
heroTag: Key("explore-page-fab"),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.router.push(PostComposeRoute()).then((value) {
|
context.router.push(PostComposeRoute()).then((value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
|
@ -39,7 +39,7 @@ class RealmListScreen extends HookConsumerWidget {
|
|||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(title: const Text('realms').tr()),
|
appBar: AppBar(title: const Text('realms').tr()),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
key: Key("realms-page-fab"),
|
heroTag: Key("realms-page-fab"),
|
||||||
child: const Icon(Symbols.add),
|
child: const Icon(Symbols.add),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.router.push(NewRealmRoute());
|
context.router.push(NewRealmRoute());
|
||||||
|
107
lib/widgets/account/account_picker.dart
Normal file
107
lib/widgets/account/account_picker.dart
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:island/models/user.dart';
|
||||||
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
|
part 'account_picker.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<List<SnAccount>> searchAccounts(Ref ref, {required String query}) async {
|
||||||
|
if (query.isEmpty) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
final response = await apiClient.get(
|
||||||
|
'/accounts/search',
|
||||||
|
queryParameters: {'query': query},
|
||||||
|
);
|
||||||
|
|
||||||
|
return response.data!
|
||||||
|
.map((json) => SnAccount.fromJson(json))
|
||||||
|
.cast<SnAccount>()
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountPickerSheet extends HookConsumerWidget {
|
||||||
|
const AccountPickerSheet({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final searchController = useTextEditingController();
|
||||||
|
final debounceTimer = useState<Timer?>(null);
|
||||||
|
|
||||||
|
void onSearchChanged(String query) {
|
||||||
|
debounceTimer.value?.cancel();
|
||||||
|
debounceTimer.value = Timer(const Duration(milliseconds: 300), () {
|
||||||
|
ref.read(searchAccountsProvider(query: query));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxHeight: MediaQuery.of(context).size.height * 0.4,
|
||||||
|
),
|
||||||
|
child: Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 4),
|
||||||
|
child: TextField(
|
||||||
|
controller: searchController,
|
||||||
|
onChanged: onSearchChanged,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: 'Search accounts...',
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 18,
|
||||||
|
vertical: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
autofocus: true,
|
||||||
|
onTapOutside:
|
||||||
|
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Consumer(
|
||||||
|
builder: (context, ref, child) {
|
||||||
|
final searchResult = ref.watch(
|
||||||
|
searchAccountsProvider(query: searchController.text),
|
||||||
|
);
|
||||||
|
|
||||||
|
return searchResult.when(
|
||||||
|
data:
|
||||||
|
(accounts) => ListView.builder(
|
||||||
|
itemCount: accounts.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final account = accounts[index];
|
||||||
|
return ListTile(
|
||||||
|
leading: ProfilePictureWidget(
|
||||||
|
fileId: account.profile.pictureId,
|
||||||
|
),
|
||||||
|
title: Text(account.nick),
|
||||||
|
subtitle: Text('@${account.name}'),
|
||||||
|
onTap: () => Navigator.of(context).pop(account),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
loading:
|
||||||
|
() => const Center(child: CircularProgressIndicator()),
|
||||||
|
error:
|
||||||
|
(error, stack) => Center(child: Text('Error: $error')),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
153
lib/widgets/account/account_picker.g.dart
Normal file
153
lib/widgets/account/account_picker.g.dart
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'account_picker.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$searchAccountsHash() => r'4923cd06876d04515d95d3c58ee3ea9e05c58e4a';
|
||||||
|
|
||||||
|
/// Copied from Dart SDK
|
||||||
|
class _SystemHash {
|
||||||
|
_SystemHash._();
|
||||||
|
|
||||||
|
static int combine(int hash, int value) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + value);
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||||
|
return hash ^ (hash >> 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int finish(int hash) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = hash ^ (hash >> 11);
|
||||||
|
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [searchAccounts].
|
||||||
|
@ProviderFor(searchAccounts)
|
||||||
|
const searchAccountsProvider = SearchAccountsFamily();
|
||||||
|
|
||||||
|
/// See also [searchAccounts].
|
||||||
|
class SearchAccountsFamily extends Family<AsyncValue<List<SnAccount>>> {
|
||||||
|
/// See also [searchAccounts].
|
||||||
|
const SearchAccountsFamily();
|
||||||
|
|
||||||
|
/// See also [searchAccounts].
|
||||||
|
SearchAccountsProvider call({required String query}) {
|
||||||
|
return SearchAccountsProvider(query: query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
SearchAccountsProvider getProviderOverride(
|
||||||
|
covariant SearchAccountsProvider provider,
|
||||||
|
) {
|
||||||
|
return call(query: provider.query);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||||
|
_allTransitiveDependencies;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get name => r'searchAccountsProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [searchAccounts].
|
||||||
|
class SearchAccountsProvider
|
||||||
|
extends AutoDisposeFutureProvider<List<SnAccount>> {
|
||||||
|
/// See also [searchAccounts].
|
||||||
|
SearchAccountsProvider({required String query})
|
||||||
|
: this._internal(
|
||||||
|
(ref) => searchAccounts(ref as SearchAccountsRef, query: query),
|
||||||
|
from: searchAccountsProvider,
|
||||||
|
name: r'searchAccountsProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$searchAccountsHash,
|
||||||
|
dependencies: SearchAccountsFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
SearchAccountsFamily._allTransitiveDependencies,
|
||||||
|
query: query,
|
||||||
|
);
|
||||||
|
|
||||||
|
SearchAccountsProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.query,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final String query;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(
|
||||||
|
FutureOr<List<SnAccount>> Function(SearchAccountsRef provider) create,
|
||||||
|
) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: SearchAccountsProvider._internal(
|
||||||
|
(ref) => create(ref as SearchAccountsRef),
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
query: query,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeFutureProviderElement<List<SnAccount>> createElement() {
|
||||||
|
return _SearchAccountsProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is SearchAccountsProvider && other.query == query;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, query.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
mixin SearchAccountsRef on AutoDisposeFutureProviderRef<List<SnAccount>> {
|
||||||
|
/// The parameter `query` of this provider.
|
||||||
|
String get query;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SearchAccountsProviderElement
|
||||||
|
extends AutoDisposeFutureProviderElement<List<SnAccount>>
|
||||||
|
with SearchAccountsRef {
|
||||||
|
_SearchAccountsProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get query => (origin as SearchAccountsProvider).query;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/route.dart';
|
import 'package:island/route.dart';
|
||||||
|
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:responsive_framework/responsive_framework.dart';
|
import 'package:responsive_framework/responsive_framework.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
@ -157,14 +158,21 @@ class AppScaffold extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PageBackButton extends StatelessWidget {
|
class PageBackButton extends StatelessWidget {
|
||||||
const PageBackButton({super.key});
|
final List<Shadow>? shadows;
|
||||||
|
const PageBackButton({super.key, this.shadows});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BackButton(
|
return IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.router.maybePop();
|
context.router.maybePop();
|
||||||
},
|
},
|
||||||
|
icon: Icon(
|
||||||
|
(!kIsWeb && (Platform.isMacOS || Platform.isIOS))
|
||||||
|
? Symbols.arrow_back_ios_new
|
||||||
|
: Symbols.arrow_back,
|
||||||
|
shadows: shadows,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,30 @@ class CloudFileWidget extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CloudImageWidget extends ConsumerWidget {
|
||||||
|
final String fileId;
|
||||||
|
final BoxFit fit;
|
||||||
|
final double aspectRatio;
|
||||||
|
final String? blurHash;
|
||||||
|
const CloudImageWidget({
|
||||||
|
super.key,
|
||||||
|
required this.fileId,
|
||||||
|
this.aspectRatio = 1,
|
||||||
|
this.fit = BoxFit.cover,
|
||||||
|
this.blurHash,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final serverUrl = ref.watch(serverUrlProvider);
|
||||||
|
final uri = '$serverUrl/files/$fileId';
|
||||||
|
return AspectRatio(
|
||||||
|
aspectRatio: aspectRatio,
|
||||||
|
child: UniversalImage(uri: uri, blurHash: blurHash),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ProfilePictureWidget extends ConsumerWidget {
|
class ProfilePictureWidget extends ConsumerWidget {
|
||||||
final String? fileId;
|
final String? fileId;
|
||||||
final double radius;
|
final double radius;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
platform :osx, '10.14'
|
platform :osx, '10.15'
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
@ -1,29 +1,264 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- bitsdojo_window_macos (0.0.1):
|
- bitsdojo_window_macos (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- device_info_plus (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- file_picker (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- file_selector_macos (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- Firebase/CoreOnly (11.10.0):
|
||||||
|
- FirebaseCore (~> 11.10.0)
|
||||||
|
- Firebase/Messaging (11.10.0):
|
||||||
|
- Firebase/CoreOnly
|
||||||
|
- FirebaseMessaging (~> 11.10.0)
|
||||||
|
- firebase_core (3.13.0):
|
||||||
|
- Firebase/CoreOnly (~> 11.10.0)
|
||||||
|
- FlutterMacOS
|
||||||
|
- firebase_messaging (15.2.5):
|
||||||
|
- Firebase/CoreOnly (~> 11.10.0)
|
||||||
|
- Firebase/Messaging (~> 11.10.0)
|
||||||
|
- firebase_core
|
||||||
|
- FlutterMacOS
|
||||||
|
- FirebaseCore (11.10.0):
|
||||||
|
- FirebaseCoreInternal (~> 11.10.0)
|
||||||
|
- GoogleUtilities/Environment (~> 8.0)
|
||||||
|
- GoogleUtilities/Logger (~> 8.0)
|
||||||
|
- FirebaseCoreInternal (11.10.0):
|
||||||
|
- "GoogleUtilities/NSData+zlib (~> 8.0)"
|
||||||
|
- FirebaseInstallations (11.10.0):
|
||||||
|
- FirebaseCore (~> 11.10.0)
|
||||||
|
- GoogleUtilities/Environment (~> 8.0)
|
||||||
|
- GoogleUtilities/UserDefaults (~> 8.0)
|
||||||
|
- PromisesObjC (~> 2.4)
|
||||||
|
- FirebaseMessaging (11.10.0):
|
||||||
|
- FirebaseCore (~> 11.10.0)
|
||||||
|
- FirebaseInstallations (~> 11.0)
|
||||||
|
- GoogleDataTransport (~> 10.0)
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
||||||
|
- GoogleUtilities/Environment (~> 8.0)
|
||||||
|
- GoogleUtilities/Reachability (~> 8.0)
|
||||||
|
- GoogleUtilities/UserDefaults (~> 8.0)
|
||||||
|
- nanopb (~> 3.30910.0)
|
||||||
|
- flutter_inappwebview_macos (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- OrderedSet (~> 6.0.3)
|
||||||
|
- flutter_platform_alert (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- flutter_udid (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- SAMKeychain
|
||||||
- FlutterMacOS (1.0.0)
|
- FlutterMacOS (1.0.0)
|
||||||
|
- GoogleDataTransport (10.1.0):
|
||||||
|
- nanopb (~> 3.30910.0)
|
||||||
|
- PromisesObjC (~> 2.4)
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (8.1.0):
|
||||||
|
- GoogleUtilities/Environment
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- GoogleUtilities/Network
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
|
- GoogleUtilities/Environment (8.1.0):
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
|
- GoogleUtilities/Logger (8.1.0):
|
||||||
|
- GoogleUtilities/Environment
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
|
- GoogleUtilities/Network (8.1.0):
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- "GoogleUtilities/NSData+zlib"
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
|
- GoogleUtilities/Reachability
|
||||||
|
- "GoogleUtilities/NSData+zlib (8.1.0)":
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
|
- GoogleUtilities/Privacy (8.1.0)
|
||||||
|
- GoogleUtilities/Reachability (8.1.0):
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
|
- GoogleUtilities/UserDefaults (8.1.0):
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
|
- irondash_engine_context (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- media_kit_libs_macos_video (1.0.4):
|
||||||
|
- FlutterMacOS
|
||||||
|
- media_kit_video (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- nanopb (3.30910.0):
|
||||||
|
- nanopb/decode (= 3.30910.0)
|
||||||
|
- nanopb/encode (= 3.30910.0)
|
||||||
|
- nanopb/decode (3.30910.0)
|
||||||
|
- nanopb/encode (3.30910.0)
|
||||||
|
- OrderedSet (6.0.3)
|
||||||
|
- package_info_plus (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- path_provider_foundation (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
|
- PromisesObjC (2.4.0)
|
||||||
|
- quill_native_bridge_macos (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- SAMKeychain (1.5.3)
|
||||||
- shared_preferences_foundation (0.0.1):
|
- shared_preferences_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- sqflite_darwin (0.0.4):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
|
- sqlite3 (3.49.1):
|
||||||
|
- sqlite3/common (= 3.49.1)
|
||||||
|
- sqlite3/common (3.49.1)
|
||||||
|
- sqlite3/dbstatvtab (3.49.1):
|
||||||
|
- sqlite3/common
|
||||||
|
- sqlite3/fts5 (3.49.1):
|
||||||
|
- sqlite3/common
|
||||||
|
- sqlite3/math (3.49.1):
|
||||||
|
- sqlite3/common
|
||||||
|
- sqlite3/perf-threadsafe (3.49.1):
|
||||||
|
- sqlite3/common
|
||||||
|
- sqlite3/rtree (3.49.1):
|
||||||
|
- sqlite3/common
|
||||||
|
- sqlite3_flutter_libs (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
|
- sqlite3 (~> 3.49.1)
|
||||||
|
- sqlite3/dbstatvtab
|
||||||
|
- sqlite3/fts5
|
||||||
|
- sqlite3/math
|
||||||
|
- sqlite3/perf-threadsafe
|
||||||
|
- sqlite3/rtree
|
||||||
|
- super_native_extensions (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- url_launcher_macos (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- volume_controller (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- wakelock_plus (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- bitsdojo_window_macos (from `Flutter/ephemeral/.symlinks/plugins/bitsdojo_window_macos/macos`)
|
- bitsdojo_window_macos (from `Flutter/ephemeral/.symlinks/plugins/bitsdojo_window_macos/macos`)
|
||||||
|
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
|
||||||
|
- file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`)
|
||||||
|
- file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`)
|
||||||
|
- firebase_core (from `Flutter/ephemeral/.symlinks/plugins/firebase_core/macos`)
|
||||||
|
- firebase_messaging (from `Flutter/ephemeral/.symlinks/plugins/firebase_messaging/macos`)
|
||||||
|
- flutter_inappwebview_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos`)
|
||||||
|
- flutter_platform_alert (from `Flutter/ephemeral/.symlinks/plugins/flutter_platform_alert/macos`)
|
||||||
|
- flutter_udid (from `Flutter/ephemeral/.symlinks/plugins/flutter_udid/macos`)
|
||||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||||
|
- irondash_engine_context (from `Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos`)
|
||||||
|
- media_kit_libs_macos_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos`)
|
||||||
|
- media_kit_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos`)
|
||||||
|
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
|
||||||
|
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
|
- quill_native_bridge_macos (from `Flutter/ephemeral/.symlinks/plugins/quill_native_bridge_macos/macos`)
|
||||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
|
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
|
||||||
|
- sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin`)
|
||||||
|
- super_native_extensions (from `Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos`)
|
||||||
|
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||||
|
- volume_controller (from `Flutter/ephemeral/.symlinks/plugins/volume_controller/macos`)
|
||||||
|
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
|
||||||
|
|
||||||
|
SPEC REPOS:
|
||||||
|
trunk:
|
||||||
|
- Firebase
|
||||||
|
- FirebaseCore
|
||||||
|
- FirebaseCoreInternal
|
||||||
|
- FirebaseInstallations
|
||||||
|
- FirebaseMessaging
|
||||||
|
- GoogleDataTransport
|
||||||
|
- GoogleUtilities
|
||||||
|
- nanopb
|
||||||
|
- OrderedSet
|
||||||
|
- PromisesObjC
|
||||||
|
- SAMKeychain
|
||||||
|
- sqlite3
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
bitsdojo_window_macos:
|
bitsdojo_window_macos:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/bitsdojo_window_macos/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/bitsdojo_window_macos/macos
|
||||||
|
device_info_plus:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
|
||||||
|
file_picker:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos
|
||||||
|
file_selector_macos:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos
|
||||||
|
firebase_core:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/firebase_core/macos
|
||||||
|
firebase_messaging:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/firebase_messaging/macos
|
||||||
|
flutter_inappwebview_macos:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos
|
||||||
|
flutter_platform_alert:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/flutter_platform_alert/macos
|
||||||
|
flutter_udid:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/flutter_udid/macos
|
||||||
FlutterMacOS:
|
FlutterMacOS:
|
||||||
:path: Flutter/ephemeral
|
:path: Flutter/ephemeral
|
||||||
|
irondash_engine_context:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos
|
||||||
|
media_kit_libs_macos_video:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos
|
||||||
|
media_kit_video:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos
|
||||||
|
package_info_plus:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
|
||||||
|
path_provider_foundation:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||||
|
quill_native_bridge_macos:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/quill_native_bridge_macos/macos
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||||
|
sqflite_darwin:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin
|
||||||
|
sqlite3_flutter_libs:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin
|
||||||
|
super_native_extensions:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos
|
||||||
|
url_launcher_macos:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||||
|
volume_controller:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/volume_controller/macos
|
||||||
|
wakelock_plus:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
bitsdojo_window_macos: 7959fb0ca65a3ccda30095c181ecb856fae48ea9
|
bitsdojo_window_macos: 7959fb0ca65a3ccda30095c181ecb856fae48ea9
|
||||||
|
device_info_plus: 4fb280989f669696856f8b129e4a5e3cd6c48f76
|
||||||
|
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
|
||||||
|
file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31
|
||||||
|
Firebase: 1fe1c0a7d9aaea32efe01fbea5f0ebd8d70e53a2
|
||||||
|
firebase_core: efd50ad8177dc489af1b9163a560359cf1b30597
|
||||||
|
firebase_messaging: acf2566068a55d7eb8cddfee5b094754070a5b88
|
||||||
|
FirebaseCore: 8344daef5e2661eb004b177488d6f9f0f24251b7
|
||||||
|
FirebaseCoreInternal: ef4505d2afb1d0ebbc33162cb3795382904b5679
|
||||||
|
FirebaseInstallations: 9980995bdd06ec8081dfb6ab364162bdd64245c3
|
||||||
|
FirebaseMessaging: 2b9f56aa4ed286e1f0ce2ee1d413aabb8f9f5cb9
|
||||||
|
flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d
|
||||||
|
flutter_platform_alert: 8fa7a7c21f95b26d08b4a3891936ca27e375f284
|
||||||
|
flutter_udid: d26e455e8c06174e6aff476e147defc6cae38495
|
||||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||||
|
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||||
|
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||||
|
irondash_engine_context: 893c7d96d20ce361d7e996f39d360c4c2f9869ba
|
||||||
|
media_kit_libs_macos_video: 85a23e549b5f480e72cae3e5634b5514bc692f65
|
||||||
|
media_kit_video: fa6564e3799a0a28bff39442334817088b7ca758
|
||||||
|
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||||
|
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
||||||
|
package_info_plus: f0052d280d17aa382b932f399edf32507174e870
|
||||||
|
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||||
|
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||||
|
quill_native_bridge_macos: 2b005cb56902bb740e0cd9620aa399dfac6b4882
|
||||||
|
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
||||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||||
|
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||||
|
sqlite3: fc1400008a9b3525f5914ed715a5d1af0b8f4983
|
||||||
|
sqlite3_flutter_libs: f6acaa2172e6bb3e2e70c771661905080e8ebcf2
|
||||||
|
super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189
|
||||||
|
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
|
||||||
|
volume_controller: 5c068e6d085c80dadd33fc2c918d2114b775b3dd
|
||||||
|
wakelock_plus: 21ddc249ac4b8d018838dbdabd65c5976c308497
|
||||||
|
|
||||||
PODFILE CHECKSUM: 7eb978b976557c8c1cd717d8185ec483fd090a82
|
PODFILE CHECKSUM: 54d867c82ac51cbd61b565781b9fada492027009
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
@ -122,7 +122,6 @@
|
|||||||
97CE52E8413D7559BF9A7981 /* Pods-RunnerTests.release.xcconfig */,
|
97CE52E8413D7559BF9A7981 /* Pods-RunnerTests.release.xcconfig */,
|
||||||
30FD87E3D579B3530B39AD6D /* Pods-RunnerTests.profile.xcconfig */,
|
30FD87E3D579B3530B39AD6D /* Pods-RunnerTests.profile.xcconfig */,
|
||||||
);
|
);
|
||||||
name = Pods;
|
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@ -244,6 +243,7 @@
|
|||||||
33CC110E2044A8840003C045 /* Bundle Framework */,
|
33CC110E2044A8840003C045 /* Bundle Framework */,
|
||||||
3399D490228B24CF009A79C7 /* ShellScript */,
|
3399D490228B24CF009A79C7 /* ShellScript */,
|
||||||
F1E275A871246799FC3019F6 /* [CP] Embed Pods Frameworks */,
|
F1E275A871246799FC3019F6 /* [CP] Embed Pods Frameworks */,
|
||||||
|
8D06F41203F1FD2FDE04DC7F /* [CP] Copy Pods Resources */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@ -387,6 +387,23 @@
|
|||||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
|
8D06F41203F1FD2FDE04DC7F /* [CP] Copy Pods Resources */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Copy Pods Resources";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
B2D8214A877A92B7299E734E /* [CP] Check Pods Manifest.lock */ = {
|
B2D8214A877A92B7299E734E /* [CP] Check Pods Manifest.lock */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@ -583,6 +600,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
};
|
};
|
||||||
@ -715,6 +733,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
@ -735,6 +754,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user