diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index ba75915..61711d3 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -212,5 +212,18 @@ "walletCurrencyGolds": "The Solar Dollars", "walletCurrencyShortGolds": "TSD", "retry": "Retry", - "creatorHubUnselectedHint": "Pick / create a publisher to get started." + "creatorHubUnselectedHint": "Pick / create a publisher to get started.", + "relationships": "Relationships", + "addFriend": "Send a Friend Request", + "addFriendHint": "Add a friend to your relationship list.", + "pendingRequest": "Pending", + "waitingRequest": "Waiting", + "friendRequestAccepted": "Accepted friend request from {}", + "friendRequestDeclined": "Declined friend request from {}", + "requestExpiredIn": "Expired in {}", + "friendSentRequest": "Sent Friend Requests", + "friendSentRequestHint": { + "one": "{} friend request sent", + "other": "{} friend requests sent" + } } diff --git a/lib/models/relationship.dart b/lib/models/relationship.dart new file mode 100644 index 0000000..07c5be2 --- /dev/null +++ b/lib/models/relationship.dart @@ -0,0 +1,24 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'package:island/models/user.dart'; + +part 'relationship.freezed.dart'; +part 'relationship.g.dart'; + +@freezed +abstract class SnRelationship with _$SnRelationship { + const factory SnRelationship({ + required DateTime? createdAt, + required DateTime? updatedAt, + required DateTime? deletedAt, + required String accountId, + required SnAccount account, + required String relatedId, + required SnAccount related, + required DateTime? expiredAt, + required int status, + }) = _SnRelationship; + + factory SnRelationship.fromJson(Map json) => + _$SnRelationshipFromJson(json); +} diff --git a/lib/models/relationship.freezed.dart b/lib/models/relationship.freezed.dart new file mode 100644 index 0000000..3225593 --- /dev/null +++ b/lib/models/relationship.freezed.dart @@ -0,0 +1,208 @@ +// 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 'relationship.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$SnRelationship { + + DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; String get accountId; SnAccount get account; String get relatedId; SnAccount get related; DateTime? get expiredAt; int get status; +/// Create a copy of SnRelationship +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$SnRelationshipCopyWith get copyWith => _$SnRelationshipCopyWithImpl(this as SnRelationship, _$identity); + + /// Serializes this SnRelationship to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is SnRelationship&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.relatedId, relatedId) || other.relatedId == relatedId)&&(identical(other.related, related) || other.related == related)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.status, status) || other.status == status)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,accountId,account,relatedId,related,expiredAt,status); + +@override +String toString() { + return 'SnRelationship(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, accountId: $accountId, account: $account, relatedId: $relatedId, related: $related, expiredAt: $expiredAt, status: $status)'; +} + + +} + +/// @nodoc +abstract mixin class $SnRelationshipCopyWith<$Res> { + factory $SnRelationshipCopyWith(SnRelationship value, $Res Function(SnRelationship) _then) = _$SnRelationshipCopyWithImpl; +@useResult +$Res call({ + DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String accountId, SnAccount account, String relatedId, SnAccount related, DateTime? expiredAt, int status +}); + + +$SnAccountCopyWith<$Res> get account;$SnAccountCopyWith<$Res> get related; + +} +/// @nodoc +class _$SnRelationshipCopyWithImpl<$Res> + implements $SnRelationshipCopyWith<$Res> { + _$SnRelationshipCopyWithImpl(this._self, this._then); + + final SnRelationship _self; + final $Res Function(SnRelationship) _then; + +/// Create a copy of SnRelationship +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? accountId = null,Object? account = null,Object? relatedId = null,Object? related = null,Object? expiredAt = freezed,Object? status = null,}) { + return _then(_self.copyWith( +createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable +as DateTime?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable +as String,account: null == account ? _self.account : account // ignore: cast_nullable_to_non_nullable +as SnAccount,relatedId: null == relatedId ? _self.relatedId : relatedId // ignore: cast_nullable_to_non_nullable +as String,related: null == related ? _self.related : related // ignore: cast_nullable_to_non_nullable +as SnAccount,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable +as DateTime?,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as int, + )); +} +/// Create a copy of SnRelationship +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnAccountCopyWith<$Res> get account { + + return $SnAccountCopyWith<$Res>(_self.account, (value) { + return _then(_self.copyWith(account: value)); + }); +}/// Create a copy of SnRelationship +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnAccountCopyWith<$Res> get related { + + return $SnAccountCopyWith<$Res>(_self.related, (value) { + return _then(_self.copyWith(related: value)); + }); +} +} + + +/// @nodoc +@JsonSerializable() + +class _SnRelationship implements SnRelationship { + const _SnRelationship({required this.createdAt, required this.updatedAt, required this.deletedAt, required this.accountId, required this.account, required this.relatedId, required this.related, required this.expiredAt, required this.status}); + factory _SnRelationship.fromJson(Map json) => _$SnRelationshipFromJson(json); + +@override final DateTime? createdAt; +@override final DateTime? updatedAt; +@override final DateTime? deletedAt; +@override final String accountId; +@override final SnAccount account; +@override final String relatedId; +@override final SnAccount related; +@override final DateTime? expiredAt; +@override final int status; + +/// Create a copy of SnRelationship +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$SnRelationshipCopyWith<_SnRelationship> get copyWith => __$SnRelationshipCopyWithImpl<_SnRelationship>(this, _$identity); + +@override +Map toJson() { + return _$SnRelationshipToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnRelationship&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.relatedId, relatedId) || other.relatedId == relatedId)&&(identical(other.related, related) || other.related == related)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.status, status) || other.status == status)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,accountId,account,relatedId,related,expiredAt,status); + +@override +String toString() { + return 'SnRelationship(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, accountId: $accountId, account: $account, relatedId: $relatedId, related: $related, expiredAt: $expiredAt, status: $status)'; +} + + +} + +/// @nodoc +abstract mixin class _$SnRelationshipCopyWith<$Res> implements $SnRelationshipCopyWith<$Res> { + factory _$SnRelationshipCopyWith(_SnRelationship value, $Res Function(_SnRelationship) _then) = __$SnRelationshipCopyWithImpl; +@override @useResult +$Res call({ + DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String accountId, SnAccount account, String relatedId, SnAccount related, DateTime? expiredAt, int status +}); + + +@override $SnAccountCopyWith<$Res> get account;@override $SnAccountCopyWith<$Res> get related; + +} +/// @nodoc +class __$SnRelationshipCopyWithImpl<$Res> + implements _$SnRelationshipCopyWith<$Res> { + __$SnRelationshipCopyWithImpl(this._self, this._then); + + final _SnRelationship _self; + final $Res Function(_SnRelationship) _then; + +/// Create a copy of SnRelationship +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? accountId = null,Object? account = null,Object? relatedId = null,Object? related = null,Object? expiredAt = freezed,Object? status = null,}) { + return _then(_SnRelationship( +createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable +as DateTime?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable +as String,account: null == account ? _self.account : account // ignore: cast_nullable_to_non_nullable +as SnAccount,relatedId: null == relatedId ? _self.relatedId : relatedId // ignore: cast_nullable_to_non_nullable +as String,related: null == related ? _self.related : related // ignore: cast_nullable_to_non_nullable +as SnAccount,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable +as DateTime?,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +/// Create a copy of SnRelationship +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnAccountCopyWith<$Res> get account { + + return $SnAccountCopyWith<$Res>(_self.account, (value) { + return _then(_self.copyWith(account: value)); + }); +}/// Create a copy of SnRelationship +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SnAccountCopyWith<$Res> get related { + + return $SnAccountCopyWith<$Res>(_self.related, (value) { + return _then(_self.copyWith(related: value)); + }); +} +} + +// dart format on diff --git a/lib/models/relationship.g.dart b/lib/models/relationship.g.dart new file mode 100644 index 0000000..c61a124 --- /dev/null +++ b/lib/models/relationship.g.dart @@ -0,0 +1,45 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'relationship.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_SnRelationship _$SnRelationshipFromJson(Map json) => + _SnRelationship( + createdAt: + json['created_at'] == null + ? null + : DateTime.parse(json['created_at'] as String), + updatedAt: + json['updated_at'] == null + ? null + : DateTime.parse(json['updated_at'] as String), + deletedAt: + json['deleted_at'] == null + ? null + : DateTime.parse(json['deleted_at'] as String), + accountId: json['account_id'] as String, + account: SnAccount.fromJson(json['account'] as Map), + relatedId: json['related_id'] as String, + related: SnAccount.fromJson(json['related'] as Map), + expiredAt: + json['expired_at'] == null + ? null + : DateTime.parse(json['expired_at'] as String), + status: (json['status'] as num).toInt(), + ); + +Map _$SnRelationshipToJson(_SnRelationship instance) => + { + 'created_at': instance.createdAt?.toIso8601String(), + 'updated_at': instance.updatedAt?.toIso8601String(), + 'deleted_at': instance.deletedAt?.toIso8601String(), + 'account_id': instance.accountId, + 'account': instance.account.toJson(), + 'related_id': instance.relatedId, + 'related': instance.related.toJson(), + 'expired_at': instance.expiredAt?.toIso8601String(), + 'status': instance.status, + }; diff --git a/lib/pods/websocket.dart b/lib/pods/websocket.dart index 1174b6f..1ca30f2 100644 --- a/lib/pods/websocket.dart +++ b/lib/pods/websocket.dart @@ -1,8 +1,8 @@ import 'dart:async'; import 'dart:convert'; import 'dart:developer'; -import 'dart:typed_data'; +import 'package:flutter/foundation.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:island/pods/config.dart'; @@ -71,10 +71,16 @@ class WebSocketService { log('[WebSocket] Trying connecting to $url'); try { - _channel = IOWebSocketChannel.connect( - Uri.parse(url), - headers: {'Authorization': 'Bearer $atk'}, - ); + if (kIsWeb) { + _channel = WebSocketChannel.connect( + Uri.parse(url)..queryParameters['tk'] = atk, + ); + } else { + _channel = IOWebSocketChannel.connect( + Uri.parse(url), + headers: {'Authorization': 'Bearer $atk'}, + ); + } await _channel!.ready; _statusStreamController.sink.add(WebSocketState.connected()); _channel!.stream.listen( diff --git a/lib/route.dart b/lib/route.dart index 8cb1df7..c61b93b 100644 --- a/lib/route.dart +++ b/lib/route.dart @@ -20,6 +20,7 @@ class AppRouter extends RootStackRouter { ], ), AutoRoute(page: WalletRoute.page, path: '/wallet'), + AutoRoute(page: RelationshipRoute.page, path: '/relationships'), AutoRoute(page: SettingsRoute.page, path: '/settings'), AutoRoute(page: LoginRoute.page, path: '/auth/login'), AutoRoute(page: CreateAccountRoute.page, path: '/auth/create-account'), diff --git a/lib/route.gr.dart b/lib/route.gr.dart index e15903d..f5325f8 100644 --- a/lib/route.gr.dart +++ b/lib/route.gr.dart @@ -9,18 +9,19 @@ // coverage:ignore-file // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:auto_route/auto_route.dart' as _i24; -import 'package:flutter/material.dart' as _i25; -import 'package:island/models/post.dart' as _i26; +import 'package:auto_route/auto_route.dart' as _i25; +import 'package:flutter/material.dart' as _i26; +import 'package:island/models/post.dart' as _i27; import 'package:island/screens/account.dart' as _i2; import 'package:island/screens/account/me.dart' as _i15; import 'package:island/screens/account/me/event_calendar.dart' as _i14; import 'package:island/screens/account/me/publishers.dart' as _i8; -import 'package:island/screens/account/me/update.dart' as _i22; +import 'package:island/screens/account/me/update.dart' as _i23; import 'package:island/screens/account/profile.dart' as _i1; +import 'package:island/screens/account/relationship.dart' as _i20; import 'package:island/screens/auth/create_account.dart' as _i6; import 'package:island/screens/auth/login.dart' as _i13; -import 'package:island/screens/auth/tabs.dart' as _i21; +import 'package:island/screens/auth/tabs.dart' as _i22; import 'package:island/screens/chat/chat.dart' as _i4; import 'package:island/screens/chat/room.dart' as _i5; import 'package:island/screens/chat/room_detail.dart' as _i3; @@ -33,16 +34,16 @@ import 'package:island/screens/posts/detail.dart' as _i17; import 'package:island/screens/posts/pub_profile.dart' as _i18; import 'package:island/screens/realm/detail.dart' as _i19; import 'package:island/screens/realm/realms.dart' as _i9; -import 'package:island/screens/settings.dart' as _i20; -import 'package:island/screens/wallet.dart' as _i23; +import 'package:island/screens/settings.dart' as _i21; +import 'package:island/screens/wallet.dart' as _i24; /// generated route for /// [_i1.AccountProfileScreen] -class AccountProfileRoute extends _i24.PageRouteInfo { +class AccountProfileRoute extends _i25.PageRouteInfo { AccountProfileRoute({ - _i25.Key? key, + _i26.Key? key, required String name, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( AccountProfileRoute.name, args: AccountProfileRouteArgs(key: key, name: name), @@ -52,7 +53,7 @@ class AccountProfileRoute extends _i24.PageRouteInfo { static const String name = 'AccountProfileRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -68,7 +69,7 @@ class AccountProfileRoute extends _i24.PageRouteInfo { class AccountProfileRouteArgs { const AccountProfileRouteArgs({this.key, required this.name}); - final _i25.Key? key; + final _i26.Key? key; final String name; @@ -80,13 +81,13 @@ class AccountProfileRouteArgs { /// generated route for /// [_i2.AccountScreen] -class AccountRoute extends _i24.PageRouteInfo { - const AccountRoute({List<_i24.PageRouteInfo>? children}) +class AccountRoute extends _i25.PageRouteInfo { + const AccountRoute({List<_i25.PageRouteInfo>? children}) : super(AccountRoute.name, initialChildren: children); static const String name = 'AccountRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { return const _i2.AccountScreen(); @@ -96,11 +97,11 @@ class AccountRoute extends _i24.PageRouteInfo { /// generated route for /// [_i3.ChatDetailScreen] -class ChatDetailRoute extends _i24.PageRouteInfo { +class ChatDetailRoute extends _i25.PageRouteInfo { ChatDetailRoute({ - _i25.Key? key, + _i26.Key? key, required String id, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( ChatDetailRoute.name, args: ChatDetailRouteArgs(key: key, id: id), @@ -110,7 +111,7 @@ class ChatDetailRoute extends _i24.PageRouteInfo { static const String name = 'ChatDetailRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -125,7 +126,7 @@ class ChatDetailRoute extends _i24.PageRouteInfo { class ChatDetailRouteArgs { const ChatDetailRouteArgs({this.key, required this.id}); - final _i25.Key? key; + final _i26.Key? key; final String id; @@ -137,13 +138,13 @@ class ChatDetailRouteArgs { /// generated route for /// [_i4.ChatListScreen] -class ChatListRoute extends _i24.PageRouteInfo { - const ChatListRoute({List<_i24.PageRouteInfo>? children}) +class ChatListRoute extends _i25.PageRouteInfo { + const ChatListRoute({List<_i25.PageRouteInfo>? children}) : super(ChatListRoute.name, initialChildren: children); static const String name = 'ChatListRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { return const _i4.ChatListScreen(); @@ -153,11 +154,11 @@ class ChatListRoute extends _i24.PageRouteInfo { /// generated route for /// [_i5.ChatRoomScreen] -class ChatRoomRoute extends _i24.PageRouteInfo { +class ChatRoomRoute extends _i25.PageRouteInfo { ChatRoomRoute({ - _i25.Key? key, + _i26.Key? key, required String id, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( ChatRoomRoute.name, args: ChatRoomRouteArgs(key: key, id: id), @@ -167,7 +168,7 @@ class ChatRoomRoute extends _i24.PageRouteInfo { static const String name = 'ChatRoomRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -182,7 +183,7 @@ class ChatRoomRoute extends _i24.PageRouteInfo { class ChatRoomRouteArgs { const ChatRoomRouteArgs({this.key, required this.id}); - final _i25.Key? key; + final _i26.Key? key; final String id; @@ -194,13 +195,13 @@ class ChatRoomRouteArgs { /// generated route for /// [_i6.CreateAccountScreen] -class CreateAccountRoute extends _i24.PageRouteInfo { - const CreateAccountRoute({List<_i24.PageRouteInfo>? children}) +class CreateAccountRoute extends _i25.PageRouteInfo { + const CreateAccountRoute({List<_i25.PageRouteInfo>? children}) : super(CreateAccountRoute.name, initialChildren: children); static const String name = 'CreateAccountRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { return const _i6.CreateAccountScreen(); @@ -210,13 +211,13 @@ class CreateAccountRoute extends _i24.PageRouteInfo { /// generated route for /// [_i7.CreatorHubScreen] -class CreatorHubRoute extends _i24.PageRouteInfo { - const CreatorHubRoute({List<_i24.PageRouteInfo>? children}) +class CreatorHubRoute extends _i25.PageRouteInfo { + const CreatorHubRoute({List<_i25.PageRouteInfo>? children}) : super(CreatorHubRoute.name, initialChildren: children); static const String name = 'CreatorHubRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { return const _i7.CreatorHubScreen(); @@ -226,8 +227,8 @@ class CreatorHubRoute extends _i24.PageRouteInfo { /// generated route for /// [_i4.EditChatScreen] -class EditChatRoute extends _i24.PageRouteInfo { - EditChatRoute({_i25.Key? key, String? id, List<_i24.PageRouteInfo>? children}) +class EditChatRoute extends _i25.PageRouteInfo { + EditChatRoute({_i26.Key? key, String? id, List<_i25.PageRouteInfo>? children}) : super( EditChatRoute.name, args: EditChatRouteArgs(key: key, id: id), @@ -237,7 +238,7 @@ class EditChatRoute extends _i24.PageRouteInfo { static const String name = 'EditChatRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -252,7 +253,7 @@ class EditChatRoute extends _i24.PageRouteInfo { class EditChatRouteArgs { const EditChatRouteArgs({this.key, this.id}); - final _i25.Key? key; + final _i26.Key? key; final String? id; @@ -264,11 +265,11 @@ class EditChatRouteArgs { /// generated route for /// [_i8.EditPublisherScreen] -class EditPublisherRoute extends _i24.PageRouteInfo { +class EditPublisherRoute extends _i25.PageRouteInfo { EditPublisherRoute({ - _i25.Key? key, + _i26.Key? key, String? name, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( EditPublisherRoute.name, args: EditPublisherRouteArgs(key: key, name: name), @@ -278,7 +279,7 @@ class EditPublisherRoute extends _i24.PageRouteInfo { static const String name = 'EditPublisherRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -293,7 +294,7 @@ class EditPublisherRoute extends _i24.PageRouteInfo { class EditPublisherRouteArgs { const EditPublisherRouteArgs({this.key, this.name}); - final _i25.Key? key; + final _i26.Key? key; final String? name; @@ -305,11 +306,11 @@ class EditPublisherRouteArgs { /// generated route for /// [_i9.EditRealmScreen] -class EditRealmRoute extends _i24.PageRouteInfo { +class EditRealmRoute extends _i25.PageRouteInfo { EditRealmRoute({ - _i25.Key? key, + _i26.Key? key, String? slug, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( EditRealmRoute.name, args: EditRealmRouteArgs(key: key, slug: slug), @@ -319,7 +320,7 @@ class EditRealmRoute extends _i24.PageRouteInfo { static const String name = 'EditRealmRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -334,7 +335,7 @@ class EditRealmRoute extends _i24.PageRouteInfo { class EditRealmRouteArgs { const EditRealmRouteArgs({this.key, this.slug}); - final _i25.Key? key; + final _i26.Key? key; final String? slug; @@ -347,12 +348,12 @@ class EditRealmRouteArgs { /// generated route for /// [_i10.EditStickerPacksScreen] class EditStickerPacksRoute - extends _i24.PageRouteInfo { + extends _i25.PageRouteInfo { EditStickerPacksRoute({ - _i25.Key? key, + _i26.Key? key, required String pubName, String? packId, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( EditStickerPacksRoute.name, args: EditStickerPacksRouteArgs( @@ -366,7 +367,7 @@ class EditStickerPacksRoute static const String name = 'EditStickerPacksRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -393,7 +394,7 @@ class EditStickerPacksRouteArgs { this.packId, }); - final _i25.Key? key; + final _i26.Key? key; final String pubName; @@ -407,12 +408,12 @@ class EditStickerPacksRouteArgs { /// generated route for /// [_i11.EditStickersScreen] -class EditStickersRoute extends _i24.PageRouteInfo { +class EditStickersRoute extends _i25.PageRouteInfo { EditStickersRoute({ - _i25.Key? key, + _i26.Key? key, required String packId, required String? id, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( EditStickersRoute.name, args: EditStickersRouteArgs(key: key, packId: packId, id: id), @@ -422,7 +423,7 @@ class EditStickersRoute extends _i24.PageRouteInfo { static const String name = 'EditStickersRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -449,7 +450,7 @@ class EditStickersRouteArgs { required this.id, }); - final _i25.Key? key; + final _i26.Key? key; final String packId; @@ -463,13 +464,13 @@ class EditStickersRouteArgs { /// generated route for /// [_i12.ExploreScreen] -class ExploreRoute extends _i24.PageRouteInfo { - const ExploreRoute({List<_i24.PageRouteInfo>? children}) +class ExploreRoute extends _i25.PageRouteInfo { + const ExploreRoute({List<_i25.PageRouteInfo>? children}) : super(ExploreRoute.name, initialChildren: children); static const String name = 'ExploreRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { return const _i12.ExploreScreen(); @@ -479,13 +480,13 @@ class ExploreRoute extends _i24.PageRouteInfo { /// generated route for /// [_i13.LoginScreen] -class LoginRoute extends _i24.PageRouteInfo { - const LoginRoute({List<_i24.PageRouteInfo>? children}) +class LoginRoute extends _i25.PageRouteInfo { + const LoginRoute({List<_i25.PageRouteInfo>? children}) : super(LoginRoute.name, initialChildren: children); static const String name = 'LoginRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { return const _i13.LoginScreen(); @@ -495,13 +496,13 @@ class LoginRoute extends _i24.PageRouteInfo { /// generated route for /// [_i8.ManagedPublisherScreen] -class ManagedPublisherRoute extends _i24.PageRouteInfo { - const ManagedPublisherRoute({List<_i24.PageRouteInfo>? children}) +class ManagedPublisherRoute extends _i25.PageRouteInfo { + const ManagedPublisherRoute({List<_i25.PageRouteInfo>? children}) : super(ManagedPublisherRoute.name, initialChildren: children); static const String name = 'ManagedPublisherRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { return const _i8.ManagedPublisherScreen(); @@ -511,13 +512,13 @@ class ManagedPublisherRoute extends _i24.PageRouteInfo { /// generated route for /// [_i14.MyselfEventCalendarScreen] -class MyselfEventCalendarRoute extends _i24.PageRouteInfo { - const MyselfEventCalendarRoute({List<_i24.PageRouteInfo>? children}) +class MyselfEventCalendarRoute extends _i25.PageRouteInfo { + const MyselfEventCalendarRoute({List<_i25.PageRouteInfo>? children}) : super(MyselfEventCalendarRoute.name, initialChildren: children); static const String name = 'MyselfEventCalendarRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { return const _i14.MyselfEventCalendarScreen(); @@ -527,13 +528,13 @@ class MyselfEventCalendarRoute extends _i24.PageRouteInfo { /// generated route for /// [_i15.MyselfProfileScreen] -class MyselfProfileRoute extends _i24.PageRouteInfo { - const MyselfProfileRoute({List<_i24.PageRouteInfo>? children}) +class MyselfProfileRoute extends _i25.PageRouteInfo { + const MyselfProfileRoute({List<_i25.PageRouteInfo>? children}) : super(MyselfProfileRoute.name, initialChildren: children); static const String name = 'MyselfProfileRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { return const _i15.MyselfProfileScreen(); @@ -543,13 +544,13 @@ class MyselfProfileRoute extends _i24.PageRouteInfo { /// generated route for /// [_i4.NewChatScreen] -class NewChatRoute extends _i24.PageRouteInfo { - const NewChatRoute({List<_i24.PageRouteInfo>? children}) +class NewChatRoute extends _i25.PageRouteInfo { + const NewChatRoute({List<_i25.PageRouteInfo>? children}) : super(NewChatRoute.name, initialChildren: children); static const String name = 'NewChatRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { return const _i4.NewChatScreen(); @@ -559,13 +560,13 @@ class NewChatRoute extends _i24.PageRouteInfo { /// generated route for /// [_i8.NewPublisherScreen] -class NewPublisherRoute extends _i24.PageRouteInfo { - const NewPublisherRoute({List<_i24.PageRouteInfo>? children}) +class NewPublisherRoute extends _i25.PageRouteInfo { + const NewPublisherRoute({List<_i25.PageRouteInfo>? children}) : super(NewPublisherRoute.name, initialChildren: children); static const String name = 'NewPublisherRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { return const _i8.NewPublisherScreen(); @@ -575,13 +576,13 @@ class NewPublisherRoute extends _i24.PageRouteInfo { /// generated route for /// [_i9.NewRealmScreen] -class NewRealmRoute extends _i24.PageRouteInfo { - const NewRealmRoute({List<_i24.PageRouteInfo>? children}) +class NewRealmRoute extends _i25.PageRouteInfo { + const NewRealmRoute({List<_i25.PageRouteInfo>? children}) : super(NewRealmRoute.name, initialChildren: children); static const String name = 'NewRealmRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { return const _i9.NewRealmScreen(); @@ -592,11 +593,11 @@ class NewRealmRoute extends _i24.PageRouteInfo { /// generated route for /// [_i10.NewStickerPacksScreen] class NewStickerPacksRoute - extends _i24.PageRouteInfo { + extends _i25.PageRouteInfo { NewStickerPacksRoute({ - _i25.Key? key, + _i26.Key? key, required String pubName, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( NewStickerPacksRoute.name, args: NewStickerPacksRouteArgs(key: key, pubName: pubName), @@ -606,7 +607,7 @@ class NewStickerPacksRoute static const String name = 'NewStickerPacksRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -623,7 +624,7 @@ class NewStickerPacksRoute class NewStickerPacksRouteArgs { const NewStickerPacksRouteArgs({this.key, required this.pubName}); - final _i25.Key? key; + final _i26.Key? key; final String pubName; @@ -635,11 +636,11 @@ class NewStickerPacksRouteArgs { /// generated route for /// [_i11.NewStickersScreen] -class NewStickersRoute extends _i24.PageRouteInfo { +class NewStickersRoute extends _i25.PageRouteInfo { NewStickersRoute({ - _i25.Key? key, + _i26.Key? key, required String packId, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( NewStickersRoute.name, args: NewStickersRouteArgs(key: key, packId: packId), @@ -649,7 +650,7 @@ class NewStickersRoute extends _i24.PageRouteInfo { static const String name = 'NewStickersRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -665,7 +666,7 @@ class NewStickersRoute extends _i24.PageRouteInfo { class NewStickersRouteArgs { const NewStickersRouteArgs({this.key, required this.packId}); - final _i25.Key? key; + final _i26.Key? key; final String packId; @@ -677,11 +678,11 @@ class NewStickersRouteArgs { /// generated route for /// [_i16.PostComposeScreen] -class PostComposeRoute extends _i24.PageRouteInfo { +class PostComposeRoute extends _i25.PageRouteInfo { PostComposeRoute({ - _i25.Key? key, - _i26.SnPost? originalPost, - List<_i24.PageRouteInfo>? children, + _i26.Key? key, + _i27.SnPost? originalPost, + List<_i25.PageRouteInfo>? children, }) : super( PostComposeRoute.name, args: PostComposeRouteArgs(key: key, originalPost: originalPost), @@ -690,7 +691,7 @@ class PostComposeRoute extends _i24.PageRouteInfo { static const String name = 'PostComposeRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final args = data.argsAs( @@ -707,9 +708,9 @@ class PostComposeRoute extends _i24.PageRouteInfo { class PostComposeRouteArgs { const PostComposeRouteArgs({this.key, this.originalPost}); - final _i25.Key? key; + final _i26.Key? key; - final _i26.SnPost? originalPost; + final _i27.SnPost? originalPost; @override String toString() { @@ -719,11 +720,11 @@ class PostComposeRouteArgs { /// generated route for /// [_i17.PostDetailScreen] -class PostDetailRoute extends _i24.PageRouteInfo { +class PostDetailRoute extends _i25.PageRouteInfo { PostDetailRoute({ - _i25.Key? key, + _i26.Key? key, required String id, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( PostDetailRoute.name, args: PostDetailRouteArgs(key: key, id: id), @@ -733,7 +734,7 @@ class PostDetailRoute extends _i24.PageRouteInfo { static const String name = 'PostDetailRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -748,7 +749,7 @@ class PostDetailRoute extends _i24.PageRouteInfo { class PostDetailRouteArgs { const PostDetailRouteArgs({this.key, required this.id}); - final _i25.Key? key; + final _i26.Key? key; final String id; @@ -760,11 +761,11 @@ class PostDetailRouteArgs { /// generated route for /// [_i16.PostEditScreen] -class PostEditRoute extends _i24.PageRouteInfo { +class PostEditRoute extends _i25.PageRouteInfo { PostEditRoute({ - _i25.Key? key, + _i26.Key? key, required String id, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( PostEditRoute.name, args: PostEditRouteArgs(key: key, id: id), @@ -774,7 +775,7 @@ class PostEditRoute extends _i24.PageRouteInfo { static const String name = 'PostEditRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -789,7 +790,7 @@ class PostEditRoute extends _i24.PageRouteInfo { class PostEditRouteArgs { const PostEditRouteArgs({this.key, required this.id}); - final _i25.Key? key; + final _i26.Key? key; final String id; @@ -802,11 +803,11 @@ class PostEditRouteArgs { /// generated route for /// [_i18.PublisherProfileScreen] class PublisherProfileRoute - extends _i24.PageRouteInfo { + extends _i25.PageRouteInfo { PublisherProfileRoute({ - _i25.Key? key, + _i26.Key? key, required String name, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( PublisherProfileRoute.name, args: PublisherProfileRouteArgs(key: key, name: name), @@ -816,7 +817,7 @@ class PublisherProfileRoute static const String name = 'PublisherProfileRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -832,7 +833,7 @@ class PublisherProfileRoute class PublisherProfileRouteArgs { const PublisherProfileRouteArgs({this.key, required this.name}); - final _i25.Key? key; + final _i26.Key? key; final String name; @@ -844,11 +845,11 @@ class PublisherProfileRouteArgs { /// generated route for /// [_i19.RealmDetailScreen] -class RealmDetailRoute extends _i24.PageRouteInfo { +class RealmDetailRoute extends _i25.PageRouteInfo { RealmDetailRoute({ - _i25.Key? key, + _i26.Key? key, required String slug, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( RealmDetailRoute.name, args: RealmDetailRouteArgs(key: key, slug: slug), @@ -858,7 +859,7 @@ class RealmDetailRoute extends _i24.PageRouteInfo { static const String name = 'RealmDetailRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -873,7 +874,7 @@ class RealmDetailRoute extends _i24.PageRouteInfo { class RealmDetailRouteArgs { const RealmDetailRouteArgs({this.key, required this.slug}); - final _i25.Key? key; + final _i26.Key? key; final String slug; @@ -885,13 +886,13 @@ class RealmDetailRouteArgs { /// generated route for /// [_i9.RealmListScreen] -class RealmListRoute extends _i24.PageRouteInfo { - const RealmListRoute({List<_i24.PageRouteInfo>? children}) +class RealmListRoute extends _i25.PageRouteInfo { + const RealmListRoute({List<_i25.PageRouteInfo>? children}) : super(RealmListRoute.name, initialChildren: children); static const String name = 'RealmListRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { return const _i9.RealmListScreen(); @@ -900,17 +901,33 @@ class RealmListRoute extends _i24.PageRouteInfo { } /// generated route for -/// [_i20.SettingsScreen] -class SettingsRoute extends _i24.PageRouteInfo { - const SettingsRoute({List<_i24.PageRouteInfo>? children}) +/// [_i20.RelationshipScreen] +class RelationshipRoute extends _i25.PageRouteInfo { + const RelationshipRoute({List<_i25.PageRouteInfo>? children}) + : super(RelationshipRoute.name, initialChildren: children); + + static const String name = 'RelationshipRoute'; + + static _i25.PageInfo page = _i25.PageInfo( + name, + builder: (data) { + return const _i20.RelationshipScreen(); + }, + ); +} + +/// generated route for +/// [_i21.SettingsScreen] +class SettingsRoute extends _i25.PageRouteInfo { + const SettingsRoute({List<_i25.PageRouteInfo>? children}) : super(SettingsRoute.name, initialChildren: children); static const String name = 'SettingsRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { - return const _i20.SettingsScreen(); + return const _i21.SettingsScreen(); }, ); } @@ -918,12 +935,12 @@ class SettingsRoute extends _i24.PageRouteInfo { /// generated route for /// [_i11.StickerPackDetailScreen] class StickerPackDetailRoute - extends _i24.PageRouteInfo { + extends _i25.PageRouteInfo { StickerPackDetailRoute({ - _i25.Key? key, + _i26.Key? key, required String pubName, required String id, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( StickerPackDetailRoute.name, args: StickerPackDetailRouteArgs(key: key, pubName: pubName, id: id), @@ -933,7 +950,7 @@ class StickerPackDetailRoute static const String name = 'StickerPackDetailRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -960,7 +977,7 @@ class StickerPackDetailRouteArgs { required this.id, }); - final _i25.Key? key; + final _i26.Key? key; final String pubName; @@ -974,11 +991,11 @@ class StickerPackDetailRouteArgs { /// generated route for /// [_i10.StickersScreen] -class StickersRoute extends _i24.PageRouteInfo { +class StickersRoute extends _i25.PageRouteInfo { StickersRoute({ - _i25.Key? key, + _i26.Key? key, required String pubName, - List<_i24.PageRouteInfo>? children, + List<_i25.PageRouteInfo>? children, }) : super( StickersRoute.name, args: StickersRouteArgs(key: key, pubName: pubName), @@ -988,7 +1005,7 @@ class StickersRoute extends _i24.PageRouteInfo { static const String name = 'StickersRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -1003,7 +1020,7 @@ class StickersRoute extends _i24.PageRouteInfo { class StickersRouteArgs { const StickersRouteArgs({this.key, required this.pubName}); - final _i25.Key? key; + final _i26.Key? key; final String pubName; @@ -1014,49 +1031,49 @@ class StickersRouteArgs { } /// generated route for -/// [_i21.TabsScreen] -class TabsRoute extends _i24.PageRouteInfo { - const TabsRoute({List<_i24.PageRouteInfo>? children}) +/// [_i22.TabsScreen] +class TabsRoute extends _i25.PageRouteInfo { + const TabsRoute({List<_i25.PageRouteInfo>? children}) : super(TabsRoute.name, initialChildren: children); static const String name = 'TabsRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { - return const _i21.TabsScreen(); + return const _i22.TabsScreen(); }, ); } /// generated route for -/// [_i22.UpdateProfileScreen] -class UpdateProfileRoute extends _i24.PageRouteInfo { - const UpdateProfileRoute({List<_i24.PageRouteInfo>? children}) +/// [_i23.UpdateProfileScreen] +class UpdateProfileRoute extends _i25.PageRouteInfo { + const UpdateProfileRoute({List<_i25.PageRouteInfo>? children}) : super(UpdateProfileRoute.name, initialChildren: children); static const String name = 'UpdateProfileRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { - return const _i22.UpdateProfileScreen(); + return const _i23.UpdateProfileScreen(); }, ); } /// generated route for -/// [_i23.WalletScreen] -class WalletRoute extends _i24.PageRouteInfo { - const WalletRoute({List<_i24.PageRouteInfo>? children}) +/// [_i24.WalletScreen] +class WalletRoute extends _i25.PageRouteInfo { + const WalletRoute({List<_i25.PageRouteInfo>? children}) : super(WalletRoute.name, initialChildren: children); static const String name = 'WalletRoute'; - static _i24.PageInfo page = _i24.PageInfo( + static _i25.PageInfo page = _i25.PageInfo( name, builder: (data) { - return const _i23.WalletScreen(); + return const _i24.WalletScreen(); }, ); } diff --git a/lib/screens/account.dart b/lib/screens/account.dart index a16f9e9..24e7929 100644 --- a/lib/screens/account.dart +++ b/lib/screens/account.dart @@ -151,6 +151,16 @@ class AccountScreen extends HookConsumerWidget { context.router.push(WalletRoute()); }, ), + ListTile( + minTileHeight: 48, + leading: const Icon(Symbols.people), + trailing: const Icon(Symbols.chevron_right), + contentPadding: EdgeInsets.symmetric(horizontal: 24), + title: Text('relationships').tr(), + onTap: () { + context.router.push(RelationshipRoute()); + }, + ), ListTile( minTileHeight: 48, leading: const Icon(Symbols.edit), diff --git a/lib/screens/account/relationship.dart b/lib/screens/account/relationship.dart new file mode 100644 index 0000000..aea5cc5 --- /dev/null +++ b/lib/screens/account/relationship.dart @@ -0,0 +1,270 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:island/pods/userinfo.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:relative_time/relative_time.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; +import 'package:island/models/relationship.dart'; +import 'package:island/pods/network.dart'; + +part 'relationship.g.dart'; + +@riverpod +Future> sendFriendRequest(Ref ref) async { + final client = ref.read(apiClientProvider); + final resp = await client.post('/relationships/requests'); + return resp.data + .map((e) => SnRelationship.fromJson(e)) + .cast() + .toList(); +} + +@riverpod +class RelationshipListNotifier extends _$RelationshipListNotifier + with CursorPagingNotifierMixin { + @override + Future> build() => fetch(cursor: null); + + @override + Future> fetch({ + required String? cursor, + }) async { + final client = ref.read(apiClientProvider); + final offset = cursor == null ? 0 : int.parse(cursor); + final take = 20; + + final response = await client.get( + '/relationships', + queryParameters: {'offset': offset, 'take': take}, + ); + + final List items = + (response.data as List) + .map((e) => SnRelationship.fromJson(e as Map)) + .toList(); + + final total = int.tryParse(response.headers['x-total']?.first ?? '') ?? 0; + final hasMore = offset + items.length < total; + final nextCursor = hasMore ? (offset + items.length).toString() : null; + + return CursorPagingData( + items: items, + hasMore: hasMore, + nextCursor: nextCursor, + ); + } + + void updateOne(int index, SnRelationship relationship) { + final currentState = state.valueOrNull; + if (currentState == null) return; + + final updatedItems = [...currentState.items]; + updatedItems[index] = relationship; + + state = AsyncData( + CursorPagingData( + items: updatedItems, + hasMore: currentState.hasMore, + nextCursor: currentState.nextCursor, + ), + ); + } +} + +@RoutePage() +class RelationshipScreen extends HookConsumerWidget { + const RelationshipScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final relationshipNotifier = ref.watch( + relationshipListNotifierProvider.notifier, + ); + + Future addFriend() async { + final result = await showModalBottomSheet( + context: context, + builder: (context) => AccountPickerSheet(), + ); + if (result == null) return; + + final client = ref.read(apiClientProvider); + await client.post('/relationships/${result.id}/friends'); + relationshipNotifier.forceRefresh(); + } + + final submitting = useState(false); + + Future handleFriendRequest( + SnRelationship relationship, + bool isAccept, + ) async { + try { + submitting.value = true; + final client = ref.read(apiClientProvider); + await client.post( + '/relationships/${relationship.accountId}/friends/${isAccept ? 'accept' : 'decline'}', + ); + relationshipNotifier.forceRefresh(); + if (!context.mounted) return; + if (isAccept) { + showSnackBar( + context, + 'friendRequestAccepted'.tr(args: ['@${relationship.account.name}']), + ); + } else { + showSnackBar( + context, + 'friendRequestDeclined'.tr(args: ['@${relationship.account.name}']), + ); + } + HapticFeedback.lightImpact(); + } catch (err) { + showErrorAlert(err); + } finally { + submitting.value = false; + } + } + + final user = ref.watch(userInfoProvider); + final requests = ref.watch(sendFriendRequestProvider); + + return AppScaffold( + appBar: AppBar(title: Text('relationships').tr()), + body: Column( + children: [ + ListTile( + leading: const Icon(Symbols.add), + title: Text('addFriend').tr(), + subtitle: Text('addFriendHint').tr(), + contentPadding: const EdgeInsets.symmetric(horizontal: 24), + onTap: addFriend, + ), + if (requests.hasValue && requests.value!.isNotEmpty) + ListTile( + leading: const Icon(Symbols.add), + title: Text('friendSentRequest').tr(), + subtitle: Text( + 'friendSentRequestHint'.plural(requests.value!.length), + ), + contentPadding: const EdgeInsets.symmetric(horizontal: 24), + ), + const Divider(height: 1), + Expanded( + child: PagingHelperView( + provider: relationshipListNotifierProvider, + futureRefreshable: relationshipListNotifierProvider.future, + notifierRefreshable: relationshipListNotifierProvider.notifier, + contentBuilder: + (data, widgetCount, endItemView) => ListView.builder( + padding: EdgeInsets.zero, + itemCount: widgetCount, + itemBuilder: (context, index) { + if (index == widgetCount - 1) { + return endItemView; + } + + final relationship = data.items[index]; + final account = relationship.account; + final isPending = + relationship.status == 0 && + relationship.relatedId == user.value?.id; + final isWaiting = + relationship.status == 0 && + relationship.accountId == user.value?.id; + + return ListTile( + contentPadding: const EdgeInsets.only( + left: 16, + right: 12, + ), + leading: ProfilePictureWidget( + fileId: account.profile.pictureId, + ), + title: Row( + spacing: 6, + children: [ + Flexible(child: Text(account.nick)), + if (isPending) // Pending + Badge( + label: Text('pendingRequest').tr(), + backgroundColor: + Theme.of(context).colorScheme.primary, + textColor: + Theme.of(context).colorScheme.onPrimary, + ) + else if (isWaiting) // Waiting + Badge( + label: Text('pendingRequest').tr(), + backgroundColor: + Theme.of(context).colorScheme.secondary, + textColor: + Theme.of(context).colorScheme.onSecondary, + ), + if (relationship.expiredAt != null) + Badge( + label: Text( + 'requestExpiredIn'.tr( + args: [ + RelativeTime( + context, + ).format(relationship.expiredAt!), + ], + ), + ), + backgroundColor: + Theme.of(context).colorScheme.tertiary, + textColor: + Theme.of(context).colorScheme.onTertiary, + ), + ], + ), + subtitle: Text('@${account.name}'), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (isPending) + IconButton( + padding: EdgeInsets.zero, + onPressed: + submitting.value + ? null + : () => handleFriendRequest( + relationship, + true, + ), + icon: const Icon(Symbols.check), + ), + if (isPending) + IconButton( + padding: EdgeInsets.zero, + onPressed: + submitting.value + ? null + : () => handleFriendRequest( + relationship, + false, + ), + icon: const Icon(Symbols.close), + ), + ], + ), + ); + }, + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/account/relationship.g.dart b/lib/screens/account/relationship.g.dart new file mode 100644 index 0000000..c4b0dd9 --- /dev/null +++ b/lib/screens/account/relationship.g.dart @@ -0,0 +1,51 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'relationship.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$sendFriendRequestHash() => r'0fc0a3866b64df8b547f831fdb7db47929e2c9ff'; + +/// See also [sendFriendRequest]. +@ProviderFor(sendFriendRequest) +final sendFriendRequestProvider = + AutoDisposeFutureProvider>.internal( + sendFriendRequest, + name: r'sendFriendRequestProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$sendFriendRequestHash, + dependencies: null, + allTransitiveDependencies: null, + ); + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +typedef SendFriendRequestRef = + AutoDisposeFutureProviderRef>; +String _$relationshipListNotifierHash() => + r'ad352e8b10641820d5acac27b26ad1bb0b59b67f'; + +/// See also [RelationshipListNotifier]. +@ProviderFor(RelationshipListNotifier) +final relationshipListNotifierProvider = AutoDisposeAsyncNotifierProvider< + RelationshipListNotifier, + CursorPagingData +>.internal( + RelationshipListNotifier.new, + name: r'relationshipListNotifierProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$relationshipListNotifierHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$RelationshipListNotifier = + AutoDisposeAsyncNotifier>; +// 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 diff --git a/lib/screens/auth/captcha.web.dart b/lib/screens/auth/captcha.web.dart index 8bacdd1..7d060d0 100644 --- a/lib/screens/auth/captcha.web.dart +++ b/lib/screens/auth/captcha.web.dart @@ -1,17 +1,23 @@ // ignore_for_file: invalid_runtime_check_with_js_interop_types import 'dart:ui_web' as ui; -import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/pods/config.dart'; import 'package:island/widgets/app_scaffold.dart'; import 'package:web/web.dart' as web; import 'package:flutter/material.dart'; -class CaptchaScreen extends HookConsumerWidget { +class CaptchaScreen extends ConsumerStatefulWidget { const CaptchaScreen({super.key}); - void _setupWebListener(BuildContext context, String serverUrl) { + @override + ConsumerState createState() => _CaptchaScreenState(); +} + +class _CaptchaScreenState extends ConsumerState { + bool _isInitialized = false; + + void _setupWebListener(String serverUrl) { web.window.onMessage.listen((event) { if (event.data != null && event.data is String) { final message = event.data as String; @@ -24,7 +30,7 @@ class CaptchaScreen extends HookConsumerWidget { final iframe = web.HTMLIFrameElement() - ..src = '$serverUrl/captcha' + ..src = '$serverUrl/auth/captcha' ..style.border = 'none' ..width = '100%' ..height = '100%'; @@ -34,18 +40,29 @@ class CaptchaScreen extends HookConsumerWidget { 'captcha-iframe', (int viewId) => iframe, ); + + setState(() { + _isInitialized = true; + }); } @override - Widget build(BuildContext context, WidgetRef ref) { - useCallback(() { + void initState() { + super.initState(); + Future.delayed(Duration.zero, () { final serverUrl = ref.watch(serverUrlProvider); - _setupWebListener(context, serverUrl); - }, []); + _setupWebListener(serverUrl); + }); + } + @override + Widget build(BuildContext context) { return AppScaffold( appBar: AppBar(title: Text("Anti-Robot")), - body: HtmlElementView(viewType: 'captcha-iframe'), + body: + _isInitialized + ? HtmlElementView(viewType: 'captcha-iframe') + : Center(child: CircularProgressIndicator()), ); } } diff --git a/lib/screens/auth/create_account.dart b/lib/screens/auth/create_account.dart index 6c27710..926eb61 100644 --- a/lib/screens/auth/create_account.dart +++ b/lib/screens/auth/create_account.dart @@ -47,6 +47,7 @@ class CreateAccountScreen extends HookConsumerWidget { if (!context.mounted) return; try { + showLoadingModal(context); final client = ref.watch(apiClientProvider); await client.post( '/accounts', @@ -59,10 +60,11 @@ class CreateAccountScreen extends HookConsumerWidget { 'captcha_token': captchaTk, }, ); - if (!context.mounted) return; + hideLoadingModal(context); showPostCreateModal(); } catch (err) { + if (context.mounted) hideLoadingModal(context); showErrorAlert(err); } } diff --git a/lib/screens/auth/login.dart b/lib/screens/auth/login.dart index 2b2ac2e..b86f4c6 100644 --- a/lib/screens/auth/login.dart +++ b/lib/screens/auth/login.dart @@ -4,7 +4,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:flutter_udid/flutter_udid.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:gap/gap.dart'; import 'package:island/models/auth.dart'; @@ -13,6 +12,7 @@ import 'package:island/pods/network.dart'; import 'package:island/pods/userinfo.dart'; import 'package:island/pods/websocket.dart'; import 'package:island/services/notify.dart'; +import 'package:island/services/udid.dart'; import 'package:island/widgets/alert.dart'; import 'package:island/widgets/app_scaffold.dart'; import 'package:material_symbols_icons/symbols.dart'; @@ -150,8 +150,8 @@ class _LoginCheckScreen extends HookConsumerWidget { subscribePushNotification(apiClient); final wsNotifier = ref.read(websocketStateProvider.notifier); wsNotifier.connect(); + if (context.mounted) Navigator.pop(context, true); }); - Navigator.pop(context, true); } catch (err) { showErrorAlert(err); return; @@ -379,7 +379,7 @@ class _LoginLookupScreen extends HookConsumerWidget { '/auth/challenge', data: { 'account': uname, - 'device_id': await FlutterUdid.consistentUdid, + 'device_id': await getUdid(), 'platform': kIsWeb ? 1 diff --git a/lib/screens/explore.dart b/lib/screens/explore.dart index f41091b..2a8bbd3 100644 --- a/lib/screens/explore.dart +++ b/lib/screens/explore.dart @@ -59,6 +59,7 @@ class ExploreScreen extends ConsumerWidget { } final item = data.items[index]; + if (item.data == null) return const SizedBox.shrink(); Widget itemWidget; switch (item.type) { diff --git a/lib/services/udid.dart b/lib/services/udid.dart new file mode 100644 index 0000000..1dff1c3 --- /dev/null +++ b/lib/services/udid.dart @@ -0,0 +1 @@ +export 'udid.native.dart' if (dart.library.html) 'udid.web.dart'; diff --git a/lib/services/udid.native.dart b/lib/services/udid.native.dart new file mode 100644 index 0000000..12ef61a --- /dev/null +++ b/lib/services/udid.native.dart @@ -0,0 +1,5 @@ +import 'package:flutter_udid/flutter_udid.dart'; + +Future getUdid() async { + return await FlutterUdid.consistentUdid; +} diff --git a/lib/services/udid.web.dart b/lib/services/udid.web.dart new file mode 100644 index 0000000..d8052a2 --- /dev/null +++ b/lib/services/udid.web.dart @@ -0,0 +1,11 @@ +import 'dart:convert'; + +import 'package:crypto/crypto.dart'; +import 'package:web/web.dart'; + +Future getUdid() async { + final userAgent = window.navigator.userAgent; + final bytes = utf8.encode(userAgent); + final hash = sha256.convert(bytes); + return hash.toString(); +} diff --git a/lib/widgets/alert.dart b/lib/widgets/alert.dart index 32ae3f0..14a7e59 100644 --- a/lib/widgets/alert.dart +++ b/lib/widgets/alert.dart @@ -1,61 +1,13 @@ -import 'dart:developer'; - -import 'package:dio/dio.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_platform_alert/flutter_platform_alert.dart'; import 'package:gap/gap.dart'; import 'package:styled_widget/styled_widget.dart'; -// TODO support web here +export 'content/alert.native.dart' + if (dart.library.html) 'content/alert.web.dart'; -String _parseRemoteError(DioException err) { - log('${err.requestOptions.method} ${err.requestOptions.uri} ${err.message}'); - if (err.response?.data is String) return err.response?.data; - if (err.response?.data?['errors'] != null) { - final errors = err.response?.data['errors'] as Map; - return errors.values - .map( - (ele) => - (ele as List).map((ele) => ele.toString()).join('\n'), - ) - .join('\n'); - } - return err.message ?? err.toString(); -} - -void showErrorAlert(dynamic err) async { - final text = switch (err) { - String _ => err, - DioException _ => _parseRemoteError(err), - Exception _ => err.toString(), - _ => err.toString(), - }; - FlutterPlatformAlert.showAlert( - windowTitle: 'somethingWentWrong'.tr(), - text: text, - alertStyle: AlertButtonStyle.ok, - iconStyle: IconStyle.error, - ); -} - -void showInfoAlert(String message, String title) async { - FlutterPlatformAlert.showAlert( - windowTitle: title, - text: message, - alertStyle: AlertButtonStyle.ok, - iconStyle: IconStyle.information, - ); -} - -Future showConfirmAlert(String message, String title) async { - final result = await FlutterPlatformAlert.showAlert( - windowTitle: title, - text: message, - alertStyle: AlertButtonStyle.okCancel, - iconStyle: IconStyle.question, - ); - return result == AlertButton.okButton; +void showSnackBar(BuildContext context, String message) { + showSnackBar(context, message); } OverlayEntry? _loadingOverlay; diff --git a/lib/widgets/app_scaffold.dart b/lib/widgets/app_scaffold.dart index 6e1c35e..d76ffae 100644 --- a/lib/widgets/app_scaffold.dart +++ b/lib/widgets/app_scaffold.dart @@ -259,9 +259,13 @@ class _WebSocketIndicator extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final isDesktop = + !kIsWeb && (Platform.isMacOS || Platform.isWindows || Platform.isLinux); + final user = ref.watch(userInfoProvider); final websocketState = ref.watch(websocketStateProvider); - final indicatorHeight = MediaQuery.of(context).padding.top + 60; + final indicatorHeight = + MediaQuery.of(context).padding.top + (isDesktop ? 27.5 : 60); Color indicatorColor; String indicatorText; @@ -287,18 +291,23 @@ class _WebSocketIndicator extends HookConsumerWidget { left: 0, right: 0, height: indicatorHeight, - child: Material( - elevation: 4, - child: AnimatedContainer( - duration: Duration(milliseconds: 300), - color: indicatorColor, - child: Center( - child: - Text( - indicatorText, - style: TextStyle(color: Colors.white, fontSize: 16), - ).tr(), - ).padding(top: MediaQuery.of(context).padding.top), + child: IgnorePointer( + child: Material( + elevation: + !user.hasValue || websocketState == WebSocketState.connected() + ? 0 + : 4, + child: AnimatedContainer( + duration: Duration(milliseconds: 300), + color: indicatorColor, + child: Center( + child: + Text( + indicatorText, + style: TextStyle(color: Colors.white, fontSize: 16), + ).tr(), + ).padding(top: MediaQuery.of(context).padding.top), + ), ), ), ); diff --git a/lib/widgets/content/alert.native.dart b/lib/widgets/content/alert.native.dart new file mode 100644 index 0000000..8b29b56 --- /dev/null +++ b/lib/widgets/content/alert.native.dart @@ -0,0 +1,54 @@ +import 'dart:developer'; + +import 'package:dio/dio.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter_platform_alert/flutter_platform_alert.dart'; + +String _parseRemoteError(DioException err) { + log('${err.requestOptions.method} ${err.requestOptions.uri} ${err.message}'); + if (err.response?.data is String) return err.response?.data; + if (err.response?.data?['errors'] != null) { + final errors = err.response?.data['errors'] as Map; + return errors.values + .map( + (ele) => + (ele as List).map((ele) => ele.toString()).join('\n'), + ) + .join('\n'); + } + return err.message ?? err.toString(); +} + +void showErrorAlert(dynamic err) async { + final text = switch (err) { + String _ => err, + DioException _ => _parseRemoteError(err), + Exception _ => err.toString(), + _ => err.toString(), + }; + FlutterPlatformAlert.showAlert( + windowTitle: 'somethingWentWrong'.tr(), + text: text, + alertStyle: AlertButtonStyle.ok, + iconStyle: IconStyle.error, + ); +} + +void showInfoAlert(String message, String title) async { + FlutterPlatformAlert.showAlert( + windowTitle: title, + text: message, + alertStyle: AlertButtonStyle.ok, + iconStyle: IconStyle.information, + ); +} + +Future showConfirmAlert(String message, String title) async { + final result = await FlutterPlatformAlert.showAlert( + windowTitle: title, + text: message, + alertStyle: AlertButtonStyle.okCancel, + iconStyle: IconStyle.question, + ); + return result == AlertButton.okButton; +} diff --git a/lib/widgets/content/alert.web.dart b/lib/widgets/content/alert.web.dart new file mode 100644 index 0000000..bf27747 --- /dev/null +++ b/lib/widgets/content/alert.web.dart @@ -0,0 +1,46 @@ +// ignore_for_file: avoid_web_libraries_in_flutter + +import 'dart:developer'; +import 'dart:js' as js; + +import 'package:dio/dio.dart'; +import 'package:easy_localization/easy_localization.dart'; + +String _parseRemoteError(DioException err) { + log('${err.requestOptions.method} ${err.requestOptions.uri} ${err.message}'); + if (err.response?.data is String) return err.response?.data; + if (err.response?.data?['errors'] != null) { + final errors = err.response?.data['errors'] as Map; + return errors.values + .map( + (ele) => + (ele as List).map((ele) => ele.toString()).join('\n'), + ) + .join('\n'); + } + return err.message ?? err.toString(); +} + +void showErrorAlert(dynamic err) async { + final text = switch (err) { + String _ => err, + DioException _ => _parseRemoteError(err), + Exception _ => err.toString(), + _ => err.toString(), + }; + js.context.callMethod('swal', ['somethingWentWrong'.tr(), text, 'error']); +} + +void showInfoAlert(String message, String title) async { + js.context.callMethod('swal', [title, message, 'info']); +} + +Future showConfirmAlert(String message, String title) async { + final result = await js.context.callMethod('swal', [ + title, + message, + 'question', + {'buttons': true}, + ]); + return result == true; +} diff --git a/lib/widgets/content/image.web.dart b/lib/widgets/content/image.web.dart index bd5fabe..9c355b9 100644 --- a/lib/widgets/content/image.web.dart +++ b/lib/widgets/content/image.web.dart @@ -7,6 +7,8 @@ class UniversalImage extends StatelessWidget { final BoxFit fit; final double? width; final double? height; + // No cache optimization for web + final bool noCacheOptimization; const UniversalImage({ super.key, @@ -15,6 +17,7 @@ class UniversalImage extends StatelessWidget { this.fit = BoxFit.cover, this.width, this.height, + this.noCacheOptimization = false, }); @override diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 53af326..abf50a3 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -127,10 +127,6 @@ PODS: - sqlite3/rtree - super_native_extensions (0.0.1): - FlutterMacOS - - tencent_rtc_sdk (10.4): - - FlutterMacOS - - TXLiteAVSDK_TRTC_Mac (~> 12.3.16995) - - TXLiteAVSDK_TRTC_Mac (12.3.16995) - url_launcher_macos (0.0.1): - FlutterMacOS - volume_controller (0.0.1): @@ -159,7 +155,6 @@ DEPENDENCIES: - 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`) - - tencent_rtc_sdk (from `Flutter/ephemeral/.symlinks/plugins/tencent_rtc_sdk/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`) @@ -178,7 +173,6 @@ SPEC REPOS: - PromisesObjC - SAMKeychain - sqlite3 - - TXLiteAVSDK_TRTC_Mac EXTERNAL SOURCES: bitsdojo_window_macos: @@ -221,8 +215,6 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin super_native_extensions: :path: Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos - tencent_rtc_sdk: - :path: Flutter/ephemeral/.symlinks/plugins/tencent_rtc_sdk/macos url_launcher_macos: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos volume_controller: @@ -263,8 +255,6 @@ SPEC CHECKSUMS: sqlite3: fc1400008a9b3525f5914ed715a5d1af0b8f4983 sqlite3_flutter_libs: f6acaa2172e6bb3e2e70c771661905080e8ebcf2 super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189 - tencent_rtc_sdk: bedbb2bcdf50f5cff9b551d19ed7228391ba1a5c - TXLiteAVSDK_TRTC_Mac: bd4218d0415c950913f8f893267e18dd4333f633 url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673 volume_controller: 5c068e6d085c80dadd33fc2c918d2114b775b3dd wakelock_plus: 21ddc249ac4b8d018838dbdabd65c5976c308497 diff --git a/pubspec.lock b/pubspec.lock index cc7a57e..743e025 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -322,7 +322,7 @@ packages: source: hosted version: "0.3.4+2" crypto: - dependency: transitive + dependency: "direct main" description: name: crypto sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" @@ -517,10 +517,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: a222f231db4f822fc49e3b753674bda630e981873c84bf8604bceeb77fce0b24 + sha256: "77f8e81d22d2a07d0dee2c62e1dda71dc1da73bf43bb2d45af09727406167964" url: "https://pub.dev" source: hosted - version: "10.1.7" + version: "10.1.9" file_selector_linux: dependency: transitive description: @@ -634,10 +634,10 @@ packages: dependency: "direct main" description: name: flutter_expandable_fab - sha256: "9de10aad89ebff35956d8eb4ceb0d8749835dc1184d3ab17b721eb06c778c519" + sha256: c2936d398169166064d025df91a3bb417109a859e725d9b80c6ef7f04e01b6ab url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.5.1" flutter_highlight: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 22cc9aa..f5bed0e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -95,6 +95,7 @@ dependencies: relative_time: ^5.0.0 dropdown_button2: ^2.3.9 riverpod_paging_utils: ^0.8.0 + crypto: ^3.0.6 dev_dependencies: flutter_test: diff --git a/web/index.html b/web/index.html index 1aa2a74..d322a15 100644 --- a/web/index.html +++ b/web/index.html @@ -33,6 +33,7 @@ +