✨ Basic message sending and listing
This commit is contained in:
		
							
								
								
									
										183
									
								
								lib/controllers/chat_message_controller.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								lib/controllers/chat_message_controller.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,183 @@ | |||||||
|  | import 'dart:math' as math; | ||||||
|  |  | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:hive/hive.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  | import 'package:surface/providers/sn_network.dart'; | ||||||
|  | import 'package:surface/providers/user_directory.dart'; | ||||||
|  | import 'package:surface/types/chat.dart'; | ||||||
|  | import 'package:uuid/uuid.dart'; | ||||||
|  |  | ||||||
|  | class ChatMessageController extends ChangeNotifier { | ||||||
|  |   static const kChatMessageBoxPrefix = 'nex_chat_messages_'; | ||||||
|  |   static const kSingleBatchLoadLimit = 100; | ||||||
|  |  | ||||||
|  |   late final SnNetworkProvider _sn; | ||||||
|  |   late final UserDirectoryProvider _ud; | ||||||
|  |  | ||||||
|  |   ChatMessageController(BuildContext context) { | ||||||
|  |     _sn = context.read<SnNetworkProvider>(); | ||||||
|  |     _ud = context.read<UserDirectoryProvider>(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool isPending = true; | ||||||
|  |   bool isLoading = false; | ||||||
|  |  | ||||||
|  |   int? messageTotal; | ||||||
|  |  | ||||||
|  |   bool get isAllLoaded => | ||||||
|  |       messageTotal != null && messages.length >= messageTotal!; | ||||||
|  |  | ||||||
|  |   String? _boxKey; | ||||||
|  |   SnChannel? _channel; | ||||||
|  |  | ||||||
|  |   List<SnChatMessage> messages = List.empty(growable: true); | ||||||
|  |  | ||||||
|  |   Box<SnChatMessage>? get _box => | ||||||
|  |       (_boxKey == null || isPending) ? null : Hive.box<SnChatMessage>(_boxKey!); | ||||||
|  |  | ||||||
|  |   Future<void> initialize(SnChannel channel) async { | ||||||
|  |     _channel = channel; | ||||||
|  |     _boxKey = '$kChatMessageBoxPrefix${channel.id}'; | ||||||
|  |     await Hive.openBox<SnChatMessage>(_boxKey!); | ||||||
|  |     isPending = false; | ||||||
|  |     notifyListeners(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Future<void> _saveMessageToLocal(Iterable<SnChatMessage> messages) async { | ||||||
|  |     if (_box == null) return; | ||||||
|  |     await _box!.putAll({ | ||||||
|  |       for (final message in messages) message.id: message, | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Future<void> _addMessage(SnChatMessage message) async { | ||||||
|  |     messages.add(message); | ||||||
|  |     notifyListeners(); | ||||||
|  |  | ||||||
|  |     if (_box == null) return; | ||||||
|  |     await _box!.put(message.id, message); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Future<void> sendMessage( | ||||||
|  |     String type, | ||||||
|  |     String content, { | ||||||
|  |     int? quoteId, | ||||||
|  |     int? relatedId, | ||||||
|  |     List<String>? attachments, | ||||||
|  |   }) async { | ||||||
|  |     if (_channel == null) return; | ||||||
|  |     const uuid = Uuid(); | ||||||
|  |     final nonce = uuid.v4(); | ||||||
|  |     final resp = await _sn.client.post( | ||||||
|  |       '/cgi/im/channels/${_channel!.keyPath}/messages', | ||||||
|  |       data: { | ||||||
|  |         'type': type, | ||||||
|  |         'uuid': nonce, | ||||||
|  |         'body': { | ||||||
|  |           'text': content, | ||||||
|  |           'algorithm': 'plain', | ||||||
|  |           if (quoteId != null) 'quote_id': quoteId, | ||||||
|  |           if (relatedId != null) 'related_id': relatedId, | ||||||
|  |           if (attachments != null) 'attachments': attachments, | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     ); | ||||||
|  |     final out = SnChatMessage.fromJson( | ||||||
|  |       resp.data['data'] as Map<String, dynamic>, | ||||||
|  |     ); | ||||||
|  |     await _addMessage(out); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /// Check the local storage is up to date with the server. | ||||||
|  |   /// If the local storage is not up to date, it will be updated. | ||||||
|  |   Future<void> checkUpdate() async { | ||||||
|  |     if (_box == null) return; | ||||||
|  |     if (_box!.isEmpty) return; | ||||||
|  |  | ||||||
|  |     isLoading = true; | ||||||
|  |     notifyListeners(); | ||||||
|  |  | ||||||
|  |     try { | ||||||
|  |       final resp = await _sn.client.get( | ||||||
|  |         '/cgi/im/channels/${_channel!.keyPath}/events/update', | ||||||
|  |         queryParameters: { | ||||||
|  |           'pivot': _box!.values.last.id, | ||||||
|  |         }, | ||||||
|  |       ); | ||||||
|  |       if (resp.data['up_to_date'] == true) { | ||||||
|  |         await loadMessages(); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       // Only preload the first 100 messages to prevent first time check update cause load to server and waste local storage. | ||||||
|  |       // FIXME If the local is missing more than 100 messages, it won't be fetched, this is a problem, we need to fix it. | ||||||
|  |       final countToFetch = math.min(resp.data['count'] as int, 100); | ||||||
|  |  | ||||||
|  |       for (int idx = 0; idx < countToFetch; idx += kSingleBatchLoadLimit) { | ||||||
|  |         await getMessages(kSingleBatchLoadLimit, idx); | ||||||
|  |       } | ||||||
|  |     } catch (err) { | ||||||
|  |       rethrow; | ||||||
|  |     } finally { | ||||||
|  |       isLoading = false; | ||||||
|  |       notifyListeners(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /// Get message from local storage first, then from the server. | ||||||
|  |   /// Will not check local storage is up to date with the server. | ||||||
|  |   /// If you need to do the sync, do the `checkUpdate` instead. | ||||||
|  |   Future<List<SnChatMessage>> getMessages( | ||||||
|  |     int take, | ||||||
|  |     int offset, { | ||||||
|  |     bool forceLocal = false, | ||||||
|  |   }) async { | ||||||
|  |     if (_box != null) { | ||||||
|  |       // Try retrieve these messages from the local storage | ||||||
|  |       if (_box!.length >= take + offset || forceLocal) { | ||||||
|  |         return _box!.values.skip(offset).take(take).toList(); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     final resp = await _sn.client.get( | ||||||
|  |       '/cgi/im/channels/${_channel!.keyPath}/events', | ||||||
|  |       queryParameters: { | ||||||
|  |         'take': take, | ||||||
|  |         'offset': offset, | ||||||
|  |       }, | ||||||
|  |     ); | ||||||
|  |     messageTotal = resp.data['count'] as int?; | ||||||
|  |     final out = List<SnChatMessage>.from( | ||||||
|  |       resp.data['data']?.map((e) => SnChatMessage.fromJson(e)) ?? [], | ||||||
|  |     ); | ||||||
|  |     _saveMessageToLocal(out); | ||||||
|  |  | ||||||
|  |     // Preload sender accounts | ||||||
|  |     await _ud.listAccount(out.map((ele) => ele.sender.accountId).toSet()); | ||||||
|  |  | ||||||
|  |     return out; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /// The load messages method work as same as the `getMessages` method. | ||||||
|  |   /// But it won't return the messages instead append them to the value that controller has. | ||||||
|  |   /// At the same time, this method provide the `isLoading` state. | ||||||
|  |   /// The `skip` parameter is no longer required since it will skip the messages count that already loaded. | ||||||
|  |   Future<void> loadMessages({int take = 20}) async { | ||||||
|  |     isLoading = true; | ||||||
|  |     notifyListeners(); | ||||||
|  |  | ||||||
|  |     try { | ||||||
|  |       final out = await getMessages(take, messages.length); | ||||||
|  |       messages.addAll(out); | ||||||
|  |     } catch (err) { | ||||||
|  |       rethrow; | ||||||
|  |     } finally { | ||||||
|  |       isLoading = false; | ||||||
|  |       notifyListeners(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   close() { | ||||||
|  |     _box?.close(); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -12,10 +12,12 @@ import 'package:surface/providers/navigation.dart'; | |||||||
| import 'package:surface/providers/sn_attachment.dart'; | import 'package:surface/providers/sn_attachment.dart'; | ||||||
| import 'package:surface/providers/sn_network.dart'; | import 'package:surface/providers/sn_network.dart'; | ||||||
| import 'package:surface/providers/theme.dart'; | import 'package:surface/providers/theme.dart'; | ||||||
|  | import 'package:surface/providers/user_directory.dart'; | ||||||
| import 'package:surface/providers/userinfo.dart'; | import 'package:surface/providers/userinfo.dart'; | ||||||
| import 'package:surface/providers/websocket.dart'; | import 'package:surface/providers/websocket.dart'; | ||||||
| import 'package:surface/router.dart'; | import 'package:surface/router.dart'; | ||||||
| import 'package:surface/types/chat.dart'; | import 'package:surface/types/chat.dart'; | ||||||
|  | import 'package:surface/types/realm.dart'; | ||||||
|  |  | ||||||
| void main() async { | void main() async { | ||||||
|   WidgetsFlutterBinding.ensureInitialized(); |   WidgetsFlutterBinding.ensureInitialized(); | ||||||
| @@ -23,6 +25,9 @@ void main() async { | |||||||
|  |  | ||||||
|   await Hive.initFlutter(); |   await Hive.initFlutter(); | ||||||
|   Hive.registerAdapter(SnChannelImplAdapter()); |   Hive.registerAdapter(SnChannelImplAdapter()); | ||||||
|  |   Hive.registerAdapter(SnRealmImplAdapter()); | ||||||
|  |   Hive.registerAdapter(SnChannelMemberImplAdapter()); | ||||||
|  |   Hive.registerAdapter(SnChatMessageImplAdapter()); | ||||||
|  |  | ||||||
|   if (!kReleaseMode) { |   if (!kReleaseMode) { | ||||||
|     debugInvertOversizedImages = true; |     debugInvertOversizedImages = true; | ||||||
| @@ -53,6 +58,7 @@ class SolianApp extends StatelessWidget { | |||||||
|             // Data layer |             // Data layer | ||||||
|             Provider(create: (_) => SnNetworkProvider()), |             Provider(create: (_) => SnNetworkProvider()), | ||||||
|             Provider(create: (ctx) => SnAttachmentProvider(ctx)), |             Provider(create: (ctx) => SnAttachmentProvider(ctx)), | ||||||
|  |             Provider(create: (ctx) => UserDirectoryProvider(ctx)), | ||||||
|             ChangeNotifierProvider(create: (ctx) => UserProvider(ctx)), |             ChangeNotifierProvider(create: (ctx) => UserProvider(ctx)), | ||||||
|             ChangeNotifierProvider(create: (ctx) => WebSocketProvider(ctx)), |             ChangeNotifierProvider(create: (ctx) => WebSocketProvider(ctx)), | ||||||
|             ChangeNotifierProvider(create: (ctx) => ChatChannelProvider(ctx)), |             ChangeNotifierProvider(create: (ctx) => ChatChannelProvider(ctx)), | ||||||
|   | |||||||
| @@ -28,8 +28,11 @@ class ChatChannelProvider extends ChangeNotifier { | |||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Future<List<SnChannel>> _fetchChannelsFromServer( |   Future<List<SnChannel>> _fetchChannelsFromServer({ | ||||||
|       {scope = 'global', direct = false}) async { |     String scope = 'global', | ||||||
|  |     bool direct = false, | ||||||
|  |     bool doNotSave = false, | ||||||
|  |   }) async { | ||||||
|     final resp = await _sn.client.get( |     final resp = await _sn.client.get( | ||||||
|       '/cgi/im/channels/$scope/me/available', |       '/cgi/im/channels/$scope/me/available', | ||||||
|       queryParameters: { |       queryParameters: { | ||||||
| @@ -39,15 +42,37 @@ class ChatChannelProvider extends ChangeNotifier { | |||||||
|     final out = List<SnChannel>.from( |     final out = List<SnChannel>.from( | ||||||
|       resp.data?.map((e) => SnChannel.fromJson(e)) ?? [], |       resp.data?.map((e) => SnChannel.fromJson(e)) ?? [], | ||||||
|     ); |     ); | ||||||
|     _saveChannelToLocal(out); |     if (!doNotSave) _saveChannelToLocal(out); | ||||||
|     return out; |     return out; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // The fetch channel method return a stream, which will emit twice. |   /// The get channel method will return the channel with the given alias. | ||||||
|   // The first time is when the data was fetched from the local storage. |   /// It will use the local storage as much as possible. | ||||||
|   // And the second time is when the data was fetched from the server. |   /// The alias should include the scope, formatted as `scope:alias`. | ||||||
|   // But there is some exception that will only cause one of them to be emitted. |   Future<SnChannel> getChannel(String key) async { | ||||||
|   // Like the local storage is broken or the server is down. |     if (_channelBox != null) { | ||||||
|  |       final local = _channelBox!.get(key); | ||||||
|  |       if (local != null) return local; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     var resp = await _sn.client.get('/cgi/im/channels/$key'); | ||||||
|  |     var out = SnChannel.fromJson(resp.data); | ||||||
|  |  | ||||||
|  |     // Preload realm of the channel | ||||||
|  |     if (out.realmId != null) { | ||||||
|  |       resp = await _sn.client.get('/cgi/id/realms/${out.realmId}'); | ||||||
|  |       out = out.copyWith(realm: SnRealm.fromJson(resp.data)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     _saveChannelToLocal([out]); | ||||||
|  |     return out; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /// The fetch channel method return a stream, which will emit twice. | ||||||
|  |   /// The first time is when the data was fetched from the local storage. | ||||||
|  |   /// And the second time is when the data was fetched from the server. | ||||||
|  |   /// But there is some exception that will only cause one of them to be emitted. | ||||||
|  |   /// Like the local storage is broken or the server is down. | ||||||
|   Stream<List<SnChannel>> fetchChannels() async* { |   Stream<List<SnChannel>> fetchChannels() async* { | ||||||
|     if (_channelBox != null) yield _channelBox!.values.toList(); |     if (_channelBox != null) yield _channelBox!.values.toList(); | ||||||
|  |  | ||||||
| @@ -55,18 +80,34 @@ class ChatChannelProvider extends ChangeNotifier { | |||||||
|     final realms = List<SnRealm>.from( |     final realms = List<SnRealm>.from( | ||||||
|       resp.data?.map((e) => SnRealm.fromJson(e)) ?? [], |       resp.data?.map((e) => SnRealm.fromJson(e)) ?? [], | ||||||
|     ); |     ); | ||||||
|  |     final realmMap = { | ||||||
|  |       for (final realm in realms) realm.alias: realm, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     final scopeToFetch = {'global', ...realms.map((e) => e.alias)}; |     final scopeToFetch = {'global', ...realms.map((e) => e.alias)}; | ||||||
|  |  | ||||||
|     final List<SnChannel> result = List.empty(growable: true); |     final List<SnChannel> result = List.empty(growable: true); | ||||||
|     final dm = |     final directMessages = await _fetchChannelsFromServer( | ||||||
|         await _fetchChannelsFromServer(scope: scopeToFetch.first, direct: true); |       scope: scopeToFetch.first, | ||||||
|     result.addAll(dm); |       direct: true, | ||||||
|  |     ); | ||||||
|  |     result.addAll(directMessages); | ||||||
|  |  | ||||||
|     for (final scope in scopeToFetch) { |     final nonBelongsChannels = await _fetchChannelsFromServer( | ||||||
|       final channel = |       scope: scopeToFetch.first, | ||||||
|           await _fetchChannelsFromServer(scope: scope, direct: false); |       direct: false, | ||||||
|       result.addAll(channel); |     ); | ||||||
|  |     result.addAll(nonBelongsChannels); | ||||||
|  |  | ||||||
|  |     for (final scope in scopeToFetch.skip(1)) { | ||||||
|  |       final channel = await _fetchChannelsFromServer( | ||||||
|  |         scope: scope, | ||||||
|  |         direct: false, | ||||||
|  |         doNotSave: true, | ||||||
|  |       ); | ||||||
|  |       final out = channel.map((ele) => ele.copyWith(realm: realmMap[scope])); | ||||||
|  |       _saveChannelToLocal(out); | ||||||
|  |       result.addAll(out); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     yield result; |     yield result; | ||||||
|   | |||||||
							
								
								
									
										50
									
								
								lib/providers/user_directory.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								lib/providers/user_directory.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  | import 'package:surface/providers/sn_network.dart'; | ||||||
|  | import 'package:surface/types/account.dart'; | ||||||
|  |  | ||||||
|  | class UserDirectoryProvider { | ||||||
|  |   late final SnNetworkProvider _sn; | ||||||
|  |  | ||||||
|  |   UserDirectoryProvider(BuildContext context) { | ||||||
|  |     _sn = context.read<SnNetworkProvider>(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   final Map<String, int> _idCache = {}; | ||||||
|  |   final Map<int, SnAccount> _cache = {}; | ||||||
|  |  | ||||||
|  |   Future<List<SnAccount?>> listAccount(Iterable<dynamic> id) async { | ||||||
|  |     final out = await Future.wait( | ||||||
|  |       id.map((e) => getAccount(e)), | ||||||
|  |     ); | ||||||
|  |     return out; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Future<SnAccount?> getAccount(dynamic id) async { | ||||||
|  |     if (id is String && _idCache.containsKey(id)) { | ||||||
|  |       id = _idCache[id]; | ||||||
|  |     } | ||||||
|  |     if (_cache.containsKey(id)) { | ||||||
|  |       return _cache[id]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     try { | ||||||
|  |       final resp = await _sn.client.get('/cgi/id/users/$id'); | ||||||
|  |       final account = SnAccount.fromJson( | ||||||
|  |         resp.data as Map<String, dynamic>, | ||||||
|  |       ); | ||||||
|  |       _cache[account.id] = account; | ||||||
|  |       if (id is String) _idCache[id] = account.id; | ||||||
|  |       return account; | ||||||
|  |     } catch (err) { | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SnAccount? getAccountFromCache(dynamic id) { | ||||||
|  |     if (id is String && _idCache.containsKey(id)) { | ||||||
|  |       id = _idCache[id]; | ||||||
|  |     } | ||||||
|  |     return _cache[id]; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -10,6 +10,7 @@ import 'package:surface/screens/auth/login.dart'; | |||||||
| import 'package:surface/screens/auth/register.dart'; | import 'package:surface/screens/auth/register.dart'; | ||||||
| import 'package:surface/screens/chat.dart'; | import 'package:surface/screens/chat.dart'; | ||||||
| import 'package:surface/screens/chat/manage.dart'; | import 'package:surface/screens/chat/manage.dart'; | ||||||
|  | import 'package:surface/screens/chat/room.dart'; | ||||||
| import 'package:surface/screens/explore.dart'; | import 'package:surface/screens/explore.dart'; | ||||||
| import 'package:surface/screens/home.dart'; | import 'package:surface/screens/home.dart'; | ||||||
| import 'package:surface/screens/post/post_detail.dart'; | import 'package:surface/screens/post/post_detail.dart'; | ||||||
| @@ -102,6 +103,16 @@ final _appRoutes = [ | |||||||
|           child: const ChatScreen(), |           child: const ChatScreen(), | ||||||
|         ), |         ), | ||||||
|         routes: [ |         routes: [ | ||||||
|  |           GoRoute( | ||||||
|  |             path: '/chat/:scope/:alias', | ||||||
|  |             name: 'chatRoom', | ||||||
|  |             builder: (context, state) => AppBackground( | ||||||
|  |               child: ChatRoomScreen( | ||||||
|  |                 scope: state.pathParameters['scope']!, | ||||||
|  |                 alias: state.pathParameters['alias']!, | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|           GoRoute( |           GoRoute( | ||||||
|             path: '/chat/manage', |             path: '/chat/manage', | ||||||
|             name: 'chatManage', |             name: 'chatManage', | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ import 'package:provider/provider.dart'; | |||||||
| import 'package:surface/providers/channel.dart'; | import 'package:surface/providers/channel.dart'; | ||||||
| import 'package:surface/types/chat.dart'; | import 'package:surface/types/chat.dart'; | ||||||
| import 'package:surface/widgets/account/account_image.dart'; | import 'package:surface/widgets/account/account_image.dart'; | ||||||
|  | import 'package:surface/widgets/dialog.dart'; | ||||||
| import 'package:surface/widgets/loading_indicator.dart'; | import 'package:surface/widgets/loading_indicator.dart'; | ||||||
|  |  | ||||||
| class ChatScreen extends StatefulWidget { | class ChatScreen extends StatefulWidget { | ||||||
| @@ -27,10 +28,13 @@ class _ChatScreenState extends State<ChatScreen> { | |||||||
|     chan.fetchChannels().listen((channels) { |     chan.fetchChannels().listen((channels) { | ||||||
|       if (mounted) setState(() => _channels = channels); |       if (mounted) setState(() => _channels = channels); | ||||||
|     }) |     }) | ||||||
|       ..onError((_) { |       ..onError((err) { | ||||||
|  |         if (!mounted) return; | ||||||
|  |         context.showErrorDialog(err); | ||||||
|         setState(() => _isBusy = false); |         setState(() => _isBusy = false); | ||||||
|       }) |       }) | ||||||
|       ..onDone(() { |       ..onDone(() { | ||||||
|  |         if (!mounted) return; | ||||||
|         setState(() => _isBusy = false); |         setState(() => _isBusy = false); | ||||||
|       }); |       }); | ||||||
|   } |   } | ||||||
| @@ -67,6 +71,15 @@ class _ChatScreenState extends State<ChatScreen> { | |||||||
|                     content: null, |                     content: null, | ||||||
|                     fallbackWidget: const Icon(Symbols.chat, size: 20), |                     fallbackWidget: const Icon(Symbols.chat, size: 20), | ||||||
|                   ), |                   ), | ||||||
|  |                   onTap: () { | ||||||
|  |                     GoRouter.of(context).pushNamed( | ||||||
|  |                       'chatRoom', | ||||||
|  |                       pathParameters: { | ||||||
|  |                         'scope': channel.realm?.alias ?? 'global', | ||||||
|  |                         'alias': channel.alias, | ||||||
|  |                       }, | ||||||
|  |                     ); | ||||||
|  |                   }, | ||||||
|                 ); |                 ); | ||||||
|               }, |               }, | ||||||
|             ), |             ), | ||||||
|   | |||||||
							
								
								
									
										102
									
								
								lib/screens/chat/room.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								lib/screens/chat/room.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | |||||||
|  | import 'package:easy_localization/easy_localization.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  | import 'package:styled_widget/styled_widget.dart'; | ||||||
|  | import 'package:surface/controllers/chat_message_controller.dart'; | ||||||
|  | import 'package:surface/providers/channel.dart'; | ||||||
|  | import 'package:surface/types/chat.dart'; | ||||||
|  | import 'package:surface/widgets/chat/chat_message.dart'; | ||||||
|  | import 'package:surface/widgets/chat/chat_message_input.dart'; | ||||||
|  | import 'package:surface/widgets/dialog.dart'; | ||||||
|  | import 'package:surface/widgets/loading_indicator.dart'; | ||||||
|  | import 'package:very_good_infinite_list/very_good_infinite_list.dart'; | ||||||
|  |  | ||||||
|  | class ChatRoomScreen extends StatefulWidget { | ||||||
|  |   final String scope; | ||||||
|  |   final String alias; | ||||||
|  |   const ChatRoomScreen({super.key, required this.scope, required this.alias}); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   State<ChatRoomScreen> createState() => _ChatRoomScreenState(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class _ChatRoomScreenState extends State<ChatRoomScreen> { | ||||||
|  |   bool _isBusy = false; | ||||||
|  |  | ||||||
|  |   SnChannel? _channel; | ||||||
|  |  | ||||||
|  |   late final ChatMessageController _messageController; | ||||||
|  |  | ||||||
|  |   Future<void> _fetchChannel() async { | ||||||
|  |     setState(() => _isBusy = true); | ||||||
|  |  | ||||||
|  |     try { | ||||||
|  |       final chan = context.read<ChatChannelProvider>(); | ||||||
|  |       _channel = await chan.getChannel('${widget.scope}:${widget.alias}'); | ||||||
|  |     } catch (err) { | ||||||
|  |       if (!mounted) return; | ||||||
|  |       context.showErrorDialog(err); | ||||||
|  |     } finally { | ||||||
|  |       setState(() => _isBusy = false); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   void initState() { | ||||||
|  |     super.initState(); | ||||||
|  |     _messageController = ChatMessageController(context); | ||||||
|  |     _fetchChannel().then((_) async { | ||||||
|  |       await _messageController.initialize(_channel!); | ||||||
|  |       await _messageController.checkUpdate(); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   void dispose() { | ||||||
|  |     super.dispose(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Scaffold( | ||||||
|  |       appBar: AppBar( | ||||||
|  |         title: Text(_channel?.name ?? 'loading'.tr()), | ||||||
|  |       ), | ||||||
|  |       body: ListenableBuilder( | ||||||
|  |         listenable: _messageController, | ||||||
|  |         builder: (context, _) { | ||||||
|  |           return Column( | ||||||
|  |             children: [ | ||||||
|  |               LoadingIndicator(isActive: _isBusy), | ||||||
|  |               if (_messageController.isPending) | ||||||
|  |                 Expanded( | ||||||
|  |                   child: const CircularProgressIndicator().center(), | ||||||
|  |                 ), | ||||||
|  |               if (!_messageController.isPending) | ||||||
|  |                 Expanded( | ||||||
|  |                   child: InfiniteList( | ||||||
|  |                     hasReachedMax: _messageController.isAllLoaded, | ||||||
|  |                     itemCount: _messageController.messages.length, | ||||||
|  |                     isLoading: _messageController.isLoading, | ||||||
|  |                     onFetchData: () { | ||||||
|  |                       _messageController.loadMessages(); | ||||||
|  |                     }, | ||||||
|  |                     itemBuilder: (context, idx) { | ||||||
|  |                       final message = _messageController.messages[idx]; | ||||||
|  |                       return ChatMessage(data: message); | ||||||
|  |                     }, | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |               if (!_messageController.isPending) | ||||||
|  |                 Material( | ||||||
|  |                   elevation: 2, | ||||||
|  |                   child: ChatMessageInput(controller: _messageController) | ||||||
|  |                       .padding(bottom: MediaQuery.of(context).padding.bottom), | ||||||
|  |                 ), | ||||||
|  |             ], | ||||||
|  |           ); | ||||||
|  |         }, | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -1,29 +1,32 @@ | |||||||
| import 'package:freezed_annotation/freezed_annotation.dart'; | import 'package:freezed_annotation/freezed_annotation.dart'; | ||||||
|  | import 'package:hive_flutter/hive_flutter.dart'; | ||||||
|  |  | ||||||
| part 'account.freezed.dart'; | part 'account.freezed.dart'; | ||||||
| part 'account.g.dart'; | part 'account.g.dart'; | ||||||
|  |  | ||||||
| @freezed | @freezed | ||||||
| class SnAccount with _$SnAccount { | class SnAccount with _$SnAccount { | ||||||
|  |   const SnAccount._(); | ||||||
|  |  | ||||||
|   const factory SnAccount({ |   const factory SnAccount({ | ||||||
|     required int id, |     @HiveField(0) required int id, | ||||||
|     required int? affiliatedId, |     required DateTime createdAt, | ||||||
|     required int? affiliatedTo, |     required DateTime updatedAt, | ||||||
|     required int? automatedBy, |     required DateTime? deletedAt, | ||||||
|     required int? automatedId, |     required DateTime? confirmedAt, | ||||||
|  |     required List<SnAccountContact>? contacts, | ||||||
|     required String avatar, |     required String avatar, | ||||||
|     required String banner, |     required String banner, | ||||||
|     required DateTime? confirmedAt, |  | ||||||
|     required List<SnAccountContact> contacts, |  | ||||||
|     required DateTime createdAt, |  | ||||||
|     required DateTime? deletedAt, |  | ||||||
|     required String description, |     required String description, | ||||||
|     required String name, |     required String name, | ||||||
|     required String nick, |     required String nick, | ||||||
|     required Map<String, dynamic> permNodes, |     required Map<String, dynamic> permNodes, | ||||||
|     required SnAccountProfile? profile, |     required SnAccountProfile? profile, | ||||||
|     required DateTime? suspendedAt, |     required DateTime? suspendedAt, | ||||||
|     required DateTime updatedAt, |     required int? affiliatedId, | ||||||
|  |     required int? affiliatedTo, | ||||||
|  |     required int? automatedBy, | ||||||
|  |     required int? automatedId, | ||||||
|   }) = _SnAccount; |   }) = _SnAccount; | ||||||
|  |  | ||||||
|   factory SnAccount.fromJson(Map<String, Object?> json) => |   factory SnAccount.fromJson(Map<String, Object?> json) => | ||||||
|   | |||||||
| @@ -20,24 +20,25 @@ SnAccount _$SnAccountFromJson(Map<String, dynamic> json) { | |||||||
|  |  | ||||||
| /// @nodoc | /// @nodoc | ||||||
| mixin _$SnAccount { | mixin _$SnAccount { | ||||||
|  |   @HiveField(0) | ||||||
|   int get id => throw _privateConstructorUsedError; |   int get id => throw _privateConstructorUsedError; | ||||||
|   int? get affiliatedId => throw _privateConstructorUsedError; |   DateTime get createdAt => throw _privateConstructorUsedError; | ||||||
|   int? get affiliatedTo => throw _privateConstructorUsedError; |   DateTime get updatedAt => throw _privateConstructorUsedError; | ||||||
|   int? get automatedBy => throw _privateConstructorUsedError; |   DateTime? get deletedAt => throw _privateConstructorUsedError; | ||||||
|   int? get automatedId => throw _privateConstructorUsedError; |   DateTime? get confirmedAt => throw _privateConstructorUsedError; | ||||||
|  |   List<SnAccountContact>? get contacts => throw _privateConstructorUsedError; | ||||||
|   String get avatar => throw _privateConstructorUsedError; |   String get avatar => throw _privateConstructorUsedError; | ||||||
|   String get banner => throw _privateConstructorUsedError; |   String get banner => throw _privateConstructorUsedError; | ||||||
|   DateTime? get confirmedAt => throw _privateConstructorUsedError; |  | ||||||
|   List<SnAccountContact> get contacts => throw _privateConstructorUsedError; |  | ||||||
|   DateTime get createdAt => throw _privateConstructorUsedError; |  | ||||||
|   DateTime? get deletedAt => throw _privateConstructorUsedError; |  | ||||||
|   String get description => throw _privateConstructorUsedError; |   String get description => throw _privateConstructorUsedError; | ||||||
|   String get name => throw _privateConstructorUsedError; |   String get name => throw _privateConstructorUsedError; | ||||||
|   String get nick => throw _privateConstructorUsedError; |   String get nick => throw _privateConstructorUsedError; | ||||||
|   Map<String, dynamic> get permNodes => throw _privateConstructorUsedError; |   Map<String, dynamic> get permNodes => throw _privateConstructorUsedError; | ||||||
|   SnAccountProfile? get profile => throw _privateConstructorUsedError; |   SnAccountProfile? get profile => throw _privateConstructorUsedError; | ||||||
|   DateTime? get suspendedAt => throw _privateConstructorUsedError; |   DateTime? get suspendedAt => throw _privateConstructorUsedError; | ||||||
|   DateTime get updatedAt => throw _privateConstructorUsedError; |   int? get affiliatedId => throw _privateConstructorUsedError; | ||||||
|  |   int? get affiliatedTo => throw _privateConstructorUsedError; | ||||||
|  |   int? get automatedBy => throw _privateConstructorUsedError; | ||||||
|  |   int? get automatedId => throw _privateConstructorUsedError; | ||||||
|  |  | ||||||
|   /// Serializes this SnAccount to a JSON map. |   /// Serializes this SnAccount to a JSON map. | ||||||
|   Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |   Map<String, dynamic> toJson() => throw _privateConstructorUsedError; | ||||||
| @@ -55,24 +56,24 @@ abstract class $SnAccountCopyWith<$Res> { | |||||||
|       _$SnAccountCopyWithImpl<$Res, SnAccount>; |       _$SnAccountCopyWithImpl<$Res, SnAccount>; | ||||||
|   @useResult |   @useResult | ||||||
|   $Res call( |   $Res call( | ||||||
|       {int id, |       {@HiveField(0) int id, | ||||||
|       int? affiliatedId, |       DateTime createdAt, | ||||||
|       int? affiliatedTo, |       DateTime updatedAt, | ||||||
|       int? automatedBy, |       DateTime? deletedAt, | ||||||
|       int? automatedId, |       DateTime? confirmedAt, | ||||||
|  |       List<SnAccountContact>? contacts, | ||||||
|       String avatar, |       String avatar, | ||||||
|       String banner, |       String banner, | ||||||
|       DateTime? confirmedAt, |  | ||||||
|       List<SnAccountContact> contacts, |  | ||||||
|       DateTime createdAt, |  | ||||||
|       DateTime? deletedAt, |  | ||||||
|       String description, |       String description, | ||||||
|       String name, |       String name, | ||||||
|       String nick, |       String nick, | ||||||
|       Map<String, dynamic> permNodes, |       Map<String, dynamic> permNodes, | ||||||
|       SnAccountProfile? profile, |       SnAccountProfile? profile, | ||||||
|       DateTime? suspendedAt, |       DateTime? suspendedAt, | ||||||
|       DateTime updatedAt}); |       int? affiliatedId, | ||||||
|  |       int? affiliatedTo, | ||||||
|  |       int? automatedBy, | ||||||
|  |       int? automatedId}); | ||||||
|  |  | ||||||
|   $SnAccountProfileCopyWith<$Res>? get profile; |   $SnAccountProfileCopyWith<$Res>? get profile; | ||||||
| } | } | ||||||
| @@ -93,45 +94,49 @@ class _$SnAccountCopyWithImpl<$Res, $Val extends SnAccount> | |||||||
|   @override |   @override | ||||||
|   $Res call({ |   $Res call({ | ||||||
|     Object? id = null, |     Object? id = null, | ||||||
|     Object? affiliatedId = freezed, |     Object? createdAt = null, | ||||||
|     Object? affiliatedTo = freezed, |     Object? updatedAt = null, | ||||||
|     Object? automatedBy = freezed, |     Object? deletedAt = freezed, | ||||||
|     Object? automatedId = freezed, |     Object? confirmedAt = freezed, | ||||||
|  |     Object? contacts = freezed, | ||||||
|     Object? avatar = null, |     Object? avatar = null, | ||||||
|     Object? banner = null, |     Object? banner = null, | ||||||
|     Object? confirmedAt = freezed, |  | ||||||
|     Object? contacts = null, |  | ||||||
|     Object? createdAt = null, |  | ||||||
|     Object? deletedAt = freezed, |  | ||||||
|     Object? description = null, |     Object? description = null, | ||||||
|     Object? name = null, |     Object? name = null, | ||||||
|     Object? nick = null, |     Object? nick = null, | ||||||
|     Object? permNodes = null, |     Object? permNodes = null, | ||||||
|     Object? profile = freezed, |     Object? profile = freezed, | ||||||
|     Object? suspendedAt = freezed, |     Object? suspendedAt = freezed, | ||||||
|     Object? updatedAt = null, |     Object? affiliatedId = freezed, | ||||||
|  |     Object? affiliatedTo = freezed, | ||||||
|  |     Object? automatedBy = freezed, | ||||||
|  |     Object? automatedId = freezed, | ||||||
|   }) { |   }) { | ||||||
|     return _then(_value.copyWith( |     return _then(_value.copyWith( | ||||||
|       id: null == id |       id: null == id | ||||||
|           ? _value.id |           ? _value.id | ||||||
|           : id // ignore: cast_nullable_to_non_nullable |           : id // ignore: cast_nullable_to_non_nullable | ||||||
|               as int, |               as int, | ||||||
|       affiliatedId: freezed == affiliatedId |       createdAt: null == createdAt | ||||||
|           ? _value.affiliatedId |           ? _value.createdAt | ||||||
|           : affiliatedId // ignore: cast_nullable_to_non_nullable |           : createdAt // ignore: cast_nullable_to_non_nullable | ||||||
|               as int?, |               as DateTime, | ||||||
|       affiliatedTo: freezed == affiliatedTo |       updatedAt: null == updatedAt | ||||||
|           ? _value.affiliatedTo |           ? _value.updatedAt | ||||||
|           : affiliatedTo // ignore: cast_nullable_to_non_nullable |           : updatedAt // ignore: cast_nullable_to_non_nullable | ||||||
|               as int?, |               as DateTime, | ||||||
|       automatedBy: freezed == automatedBy |       deletedAt: freezed == deletedAt | ||||||
|           ? _value.automatedBy |           ? _value.deletedAt | ||||||
|           : automatedBy // ignore: cast_nullable_to_non_nullable |           : deletedAt // ignore: cast_nullable_to_non_nullable | ||||||
|               as int?, |               as DateTime?, | ||||||
|       automatedId: freezed == automatedId |       confirmedAt: freezed == confirmedAt | ||||||
|           ? _value.automatedId |           ? _value.confirmedAt | ||||||
|           : automatedId // ignore: cast_nullable_to_non_nullable |           : confirmedAt // ignore: cast_nullable_to_non_nullable | ||||||
|               as int?, |               as DateTime?, | ||||||
|  |       contacts: freezed == contacts | ||||||
|  |           ? _value.contacts | ||||||
|  |           : contacts // ignore: cast_nullable_to_non_nullable | ||||||
|  |               as List<SnAccountContact>?, | ||||||
|       avatar: null == avatar |       avatar: null == avatar | ||||||
|           ? _value.avatar |           ? _value.avatar | ||||||
|           : avatar // ignore: cast_nullable_to_non_nullable |           : avatar // ignore: cast_nullable_to_non_nullable | ||||||
| @@ -140,22 +145,6 @@ class _$SnAccountCopyWithImpl<$Res, $Val extends SnAccount> | |||||||
|           ? _value.banner |           ? _value.banner | ||||||
|           : banner // ignore: cast_nullable_to_non_nullable |           : banner // ignore: cast_nullable_to_non_nullable | ||||||
|               as String, |               as String, | ||||||
|       confirmedAt: freezed == confirmedAt |  | ||||||
|           ? _value.confirmedAt |  | ||||||
|           : confirmedAt // ignore: cast_nullable_to_non_nullable |  | ||||||
|               as DateTime?, |  | ||||||
|       contacts: null == contacts |  | ||||||
|           ? _value.contacts |  | ||||||
|           : contacts // ignore: cast_nullable_to_non_nullable |  | ||||||
|               as List<SnAccountContact>, |  | ||||||
|       createdAt: null == createdAt |  | ||||||
|           ? _value.createdAt |  | ||||||
|           : createdAt // ignore: cast_nullable_to_non_nullable |  | ||||||
|               as DateTime, |  | ||||||
|       deletedAt: freezed == deletedAt |  | ||||||
|           ? _value.deletedAt |  | ||||||
|           : deletedAt // ignore: cast_nullable_to_non_nullable |  | ||||||
|               as DateTime?, |  | ||||||
|       description: null == description |       description: null == description | ||||||
|           ? _value.description |           ? _value.description | ||||||
|           : description // ignore: cast_nullable_to_non_nullable |           : description // ignore: cast_nullable_to_non_nullable | ||||||
| @@ -180,10 +169,22 @@ class _$SnAccountCopyWithImpl<$Res, $Val extends SnAccount> | |||||||
|           ? _value.suspendedAt |           ? _value.suspendedAt | ||||||
|           : suspendedAt // ignore: cast_nullable_to_non_nullable |           : suspendedAt // ignore: cast_nullable_to_non_nullable | ||||||
|               as DateTime?, |               as DateTime?, | ||||||
|       updatedAt: null == updatedAt |       affiliatedId: freezed == affiliatedId | ||||||
|           ? _value.updatedAt |           ? _value.affiliatedId | ||||||
|           : updatedAt // ignore: cast_nullable_to_non_nullable |           : affiliatedId // ignore: cast_nullable_to_non_nullable | ||||||
|               as DateTime, |               as int?, | ||||||
|  |       affiliatedTo: freezed == affiliatedTo | ||||||
|  |           ? _value.affiliatedTo | ||||||
|  |           : affiliatedTo // ignore: cast_nullable_to_non_nullable | ||||||
|  |               as int?, | ||||||
|  |       automatedBy: freezed == automatedBy | ||||||
|  |           ? _value.automatedBy | ||||||
|  |           : automatedBy // ignore: cast_nullable_to_non_nullable | ||||||
|  |               as int?, | ||||||
|  |       automatedId: freezed == automatedId | ||||||
|  |           ? _value.automatedId | ||||||
|  |           : automatedId // ignore: cast_nullable_to_non_nullable | ||||||
|  |               as int?, | ||||||
|     ) as $Val); |     ) as $Val); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -211,24 +212,24 @@ abstract class _$$SnAccountImplCopyWith<$Res> | |||||||
|   @override |   @override | ||||||
|   @useResult |   @useResult | ||||||
|   $Res call( |   $Res call( | ||||||
|       {int id, |       {@HiveField(0) int id, | ||||||
|       int? affiliatedId, |       DateTime createdAt, | ||||||
|       int? affiliatedTo, |       DateTime updatedAt, | ||||||
|       int? automatedBy, |       DateTime? deletedAt, | ||||||
|       int? automatedId, |       DateTime? confirmedAt, | ||||||
|  |       List<SnAccountContact>? contacts, | ||||||
|       String avatar, |       String avatar, | ||||||
|       String banner, |       String banner, | ||||||
|       DateTime? confirmedAt, |  | ||||||
|       List<SnAccountContact> contacts, |  | ||||||
|       DateTime createdAt, |  | ||||||
|       DateTime? deletedAt, |  | ||||||
|       String description, |       String description, | ||||||
|       String name, |       String name, | ||||||
|       String nick, |       String nick, | ||||||
|       Map<String, dynamic> permNodes, |       Map<String, dynamic> permNodes, | ||||||
|       SnAccountProfile? profile, |       SnAccountProfile? profile, | ||||||
|       DateTime? suspendedAt, |       DateTime? suspendedAt, | ||||||
|       DateTime updatedAt}); |       int? affiliatedId, | ||||||
|  |       int? affiliatedTo, | ||||||
|  |       int? automatedBy, | ||||||
|  |       int? automatedId}); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   $SnAccountProfileCopyWith<$Res>? get profile; |   $SnAccountProfileCopyWith<$Res>? get profile; | ||||||
| @@ -248,45 +249,49 @@ class __$$SnAccountImplCopyWithImpl<$Res> | |||||||
|   @override |   @override | ||||||
|   $Res call({ |   $Res call({ | ||||||
|     Object? id = null, |     Object? id = null, | ||||||
|     Object? affiliatedId = freezed, |     Object? createdAt = null, | ||||||
|     Object? affiliatedTo = freezed, |     Object? updatedAt = null, | ||||||
|     Object? automatedBy = freezed, |     Object? deletedAt = freezed, | ||||||
|     Object? automatedId = freezed, |     Object? confirmedAt = freezed, | ||||||
|  |     Object? contacts = freezed, | ||||||
|     Object? avatar = null, |     Object? avatar = null, | ||||||
|     Object? banner = null, |     Object? banner = null, | ||||||
|     Object? confirmedAt = freezed, |  | ||||||
|     Object? contacts = null, |  | ||||||
|     Object? createdAt = null, |  | ||||||
|     Object? deletedAt = freezed, |  | ||||||
|     Object? description = null, |     Object? description = null, | ||||||
|     Object? name = null, |     Object? name = null, | ||||||
|     Object? nick = null, |     Object? nick = null, | ||||||
|     Object? permNodes = null, |     Object? permNodes = null, | ||||||
|     Object? profile = freezed, |     Object? profile = freezed, | ||||||
|     Object? suspendedAt = freezed, |     Object? suspendedAt = freezed, | ||||||
|     Object? updatedAt = null, |     Object? affiliatedId = freezed, | ||||||
|  |     Object? affiliatedTo = freezed, | ||||||
|  |     Object? automatedBy = freezed, | ||||||
|  |     Object? automatedId = freezed, | ||||||
|   }) { |   }) { | ||||||
|     return _then(_$SnAccountImpl( |     return _then(_$SnAccountImpl( | ||||||
|       id: null == id |       id: null == id | ||||||
|           ? _value.id |           ? _value.id | ||||||
|           : id // ignore: cast_nullable_to_non_nullable |           : id // ignore: cast_nullable_to_non_nullable | ||||||
|               as int, |               as int, | ||||||
|       affiliatedId: freezed == affiliatedId |       createdAt: null == createdAt | ||||||
|           ? _value.affiliatedId |           ? _value.createdAt | ||||||
|           : affiliatedId // ignore: cast_nullable_to_non_nullable |           : createdAt // ignore: cast_nullable_to_non_nullable | ||||||
|               as int?, |               as DateTime, | ||||||
|       affiliatedTo: freezed == affiliatedTo |       updatedAt: null == updatedAt | ||||||
|           ? _value.affiliatedTo |           ? _value.updatedAt | ||||||
|           : affiliatedTo // ignore: cast_nullable_to_non_nullable |           : updatedAt // ignore: cast_nullable_to_non_nullable | ||||||
|               as int?, |               as DateTime, | ||||||
|       automatedBy: freezed == automatedBy |       deletedAt: freezed == deletedAt | ||||||
|           ? _value.automatedBy |           ? _value.deletedAt | ||||||
|           : automatedBy // ignore: cast_nullable_to_non_nullable |           : deletedAt // ignore: cast_nullable_to_non_nullable | ||||||
|               as int?, |               as DateTime?, | ||||||
|       automatedId: freezed == automatedId |       confirmedAt: freezed == confirmedAt | ||||||
|           ? _value.automatedId |           ? _value.confirmedAt | ||||||
|           : automatedId // ignore: cast_nullable_to_non_nullable |           : confirmedAt // ignore: cast_nullable_to_non_nullable | ||||||
|               as int?, |               as DateTime?, | ||||||
|  |       contacts: freezed == contacts | ||||||
|  |           ? _value._contacts | ||||||
|  |           : contacts // ignore: cast_nullable_to_non_nullable | ||||||
|  |               as List<SnAccountContact>?, | ||||||
|       avatar: null == avatar |       avatar: null == avatar | ||||||
|           ? _value.avatar |           ? _value.avatar | ||||||
|           : avatar // ignore: cast_nullable_to_non_nullable |           : avatar // ignore: cast_nullable_to_non_nullable | ||||||
| @@ -295,22 +300,6 @@ class __$$SnAccountImplCopyWithImpl<$Res> | |||||||
|           ? _value.banner |           ? _value.banner | ||||||
|           : banner // ignore: cast_nullable_to_non_nullable |           : banner // ignore: cast_nullable_to_non_nullable | ||||||
|               as String, |               as String, | ||||||
|       confirmedAt: freezed == confirmedAt |  | ||||||
|           ? _value.confirmedAt |  | ||||||
|           : confirmedAt // ignore: cast_nullable_to_non_nullable |  | ||||||
|               as DateTime?, |  | ||||||
|       contacts: null == contacts |  | ||||||
|           ? _value._contacts |  | ||||||
|           : contacts // ignore: cast_nullable_to_non_nullable |  | ||||||
|               as List<SnAccountContact>, |  | ||||||
|       createdAt: null == createdAt |  | ||||||
|           ? _value.createdAt |  | ||||||
|           : createdAt // ignore: cast_nullable_to_non_nullable |  | ||||||
|               as DateTime, |  | ||||||
|       deletedAt: freezed == deletedAt |  | ||||||
|           ? _value.deletedAt |  | ||||||
|           : deletedAt // ignore: cast_nullable_to_non_nullable |  | ||||||
|               as DateTime?, |  | ||||||
|       description: null == description |       description: null == description | ||||||
|           ? _value.description |           ? _value.description | ||||||
|           : description // ignore: cast_nullable_to_non_nullable |           : description // ignore: cast_nullable_to_non_nullable | ||||||
| @@ -335,71 +324,81 @@ class __$$SnAccountImplCopyWithImpl<$Res> | |||||||
|           ? _value.suspendedAt |           ? _value.suspendedAt | ||||||
|           : suspendedAt // ignore: cast_nullable_to_non_nullable |           : suspendedAt // ignore: cast_nullable_to_non_nullable | ||||||
|               as DateTime?, |               as DateTime?, | ||||||
|       updatedAt: null == updatedAt |       affiliatedId: freezed == affiliatedId | ||||||
|           ? _value.updatedAt |           ? _value.affiliatedId | ||||||
|           : updatedAt // ignore: cast_nullable_to_non_nullable |           : affiliatedId // ignore: cast_nullable_to_non_nullable | ||||||
|               as DateTime, |               as int?, | ||||||
|  |       affiliatedTo: freezed == affiliatedTo | ||||||
|  |           ? _value.affiliatedTo | ||||||
|  |           : affiliatedTo // ignore: cast_nullable_to_non_nullable | ||||||
|  |               as int?, | ||||||
|  |       automatedBy: freezed == automatedBy | ||||||
|  |           ? _value.automatedBy | ||||||
|  |           : automatedBy // ignore: cast_nullable_to_non_nullable | ||||||
|  |               as int?, | ||||||
|  |       automatedId: freezed == automatedId | ||||||
|  |           ? _value.automatedId | ||||||
|  |           : automatedId // ignore: cast_nullable_to_non_nullable | ||||||
|  |               as int?, | ||||||
|     )); |     )); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| /// @nodoc | /// @nodoc | ||||||
| @JsonSerializable() | @JsonSerializable() | ||||||
| class _$SnAccountImpl implements _SnAccount { | class _$SnAccountImpl extends _SnAccount { | ||||||
|   const _$SnAccountImpl( |   const _$SnAccountImpl( | ||||||
|       {required this.id, |       {@HiveField(0) required this.id, | ||||||
|       required this.affiliatedId, |       required this.createdAt, | ||||||
|       required this.affiliatedTo, |       required this.updatedAt, | ||||||
|       required this.automatedBy, |       required this.deletedAt, | ||||||
|       required this.automatedId, |       required this.confirmedAt, | ||||||
|  |       required final List<SnAccountContact>? contacts, | ||||||
|       required this.avatar, |       required this.avatar, | ||||||
|       required this.banner, |       required this.banner, | ||||||
|       required this.confirmedAt, |  | ||||||
|       required final List<SnAccountContact> contacts, |  | ||||||
|       required this.createdAt, |  | ||||||
|       required this.deletedAt, |  | ||||||
|       required this.description, |       required this.description, | ||||||
|       required this.name, |       required this.name, | ||||||
|       required this.nick, |       required this.nick, | ||||||
|       required final Map<String, dynamic> permNodes, |       required final Map<String, dynamic> permNodes, | ||||||
|       required this.profile, |       required this.profile, | ||||||
|       required this.suspendedAt, |       required this.suspendedAt, | ||||||
|       required this.updatedAt}) |       required this.affiliatedId, | ||||||
|  |       required this.affiliatedTo, | ||||||
|  |       required this.automatedBy, | ||||||
|  |       required this.automatedId}) | ||||||
|       : _contacts = contacts, |       : _contacts = contacts, | ||||||
|         _permNodes = permNodes; |         _permNodes = permNodes, | ||||||
|  |         super._(); | ||||||
|  |  | ||||||
|   factory _$SnAccountImpl.fromJson(Map<String, dynamic> json) => |   factory _$SnAccountImpl.fromJson(Map<String, dynamic> json) => | ||||||
|       _$$SnAccountImplFromJson(json); |       _$$SnAccountImplFromJson(json); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(0) | ||||||
|   final int id; |   final int id; | ||||||
|   @override |   @override | ||||||
|   final int? affiliatedId; |   final DateTime createdAt; | ||||||
|   @override |   @override | ||||||
|   final int? affiliatedTo; |   final DateTime updatedAt; | ||||||
|   @override |   @override | ||||||
|   final int? automatedBy; |   final DateTime? deletedAt; | ||||||
|   @override |   @override | ||||||
|   final int? automatedId; |   final DateTime? confirmedAt; | ||||||
|  |   final List<SnAccountContact>? _contacts; | ||||||
|  |   @override | ||||||
|  |   List<SnAccountContact>? get contacts { | ||||||
|  |     final value = _contacts; | ||||||
|  |     if (value == null) return null; | ||||||
|  |     if (_contacts is EqualUnmodifiableListView) return _contacts; | ||||||
|  |     // ignore: implicit_dynamic_type | ||||||
|  |     return EqualUnmodifiableListView(value); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   final String avatar; |   final String avatar; | ||||||
|   @override |   @override | ||||||
|   final String banner; |   final String banner; | ||||||
|   @override |   @override | ||||||
|   final DateTime? confirmedAt; |  | ||||||
|   final List<SnAccountContact> _contacts; |  | ||||||
|   @override |  | ||||||
|   List<SnAccountContact> get contacts { |  | ||||||
|     if (_contacts is EqualUnmodifiableListView) return _contacts; |  | ||||||
|     // ignore: implicit_dynamic_type |  | ||||||
|     return EqualUnmodifiableListView(_contacts); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   @override |  | ||||||
|   final DateTime createdAt; |  | ||||||
|   @override |  | ||||||
|   final DateTime? deletedAt; |  | ||||||
|   @override |  | ||||||
|   final String description; |   final String description; | ||||||
|   @override |   @override | ||||||
|   final String name; |   final String name; | ||||||
| @@ -418,11 +417,17 @@ class _$SnAccountImpl implements _SnAccount { | |||||||
|   @override |   @override | ||||||
|   final DateTime? suspendedAt; |   final DateTime? suspendedAt; | ||||||
|   @override |   @override | ||||||
|   final DateTime updatedAt; |   final int? affiliatedId; | ||||||
|  |   @override | ||||||
|  |   final int? affiliatedTo; | ||||||
|  |   @override | ||||||
|  |   final int? automatedBy; | ||||||
|  |   @override | ||||||
|  |   final int? automatedId; | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   String toString() { |   String toString() { | ||||||
|     return 'SnAccount(id: $id, affiliatedId: $affiliatedId, affiliatedTo: $affiliatedTo, automatedBy: $automatedBy, automatedId: $automatedId, avatar: $avatar, banner: $banner, confirmedAt: $confirmedAt, contacts: $contacts, createdAt: $createdAt, deletedAt: $deletedAt, description: $description, name: $name, nick: $nick, permNodes: $permNodes, profile: $profile, suspendedAt: $suspendedAt, updatedAt: $updatedAt)'; |     return 'SnAccount(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, confirmedAt: $confirmedAt, contacts: $contacts, avatar: $avatar, banner: $banner, description: $description, name: $name, nick: $nick, permNodes: $permNodes, profile: $profile, suspendedAt: $suspendedAt, affiliatedId: $affiliatedId, affiliatedTo: $affiliatedTo, automatedBy: $automatedBy, automatedId: $automatedId)'; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -431,23 +436,17 @@ class _$SnAccountImpl implements _SnAccount { | |||||||
|         (other.runtimeType == runtimeType && |         (other.runtimeType == runtimeType && | ||||||
|             other is _$SnAccountImpl && |             other is _$SnAccountImpl && | ||||||
|             (identical(other.id, id) || other.id == id) && |             (identical(other.id, id) || other.id == id) && | ||||||
|             (identical(other.affiliatedId, affiliatedId) || |             (identical(other.createdAt, createdAt) || | ||||||
|                 other.affiliatedId == affiliatedId) && |                 other.createdAt == createdAt) && | ||||||
|             (identical(other.affiliatedTo, affiliatedTo) || |             (identical(other.updatedAt, updatedAt) || | ||||||
|                 other.affiliatedTo == affiliatedTo) && |                 other.updatedAt == updatedAt) && | ||||||
|             (identical(other.automatedBy, automatedBy) || |             (identical(other.deletedAt, deletedAt) || | ||||||
|                 other.automatedBy == automatedBy) && |                 other.deletedAt == deletedAt) && | ||||||
|             (identical(other.automatedId, automatedId) || |  | ||||||
|                 other.automatedId == automatedId) && |  | ||||||
|             (identical(other.avatar, avatar) || other.avatar == avatar) && |  | ||||||
|             (identical(other.banner, banner) || other.banner == banner) && |  | ||||||
|             (identical(other.confirmedAt, confirmedAt) || |             (identical(other.confirmedAt, confirmedAt) || | ||||||
|                 other.confirmedAt == confirmedAt) && |                 other.confirmedAt == confirmedAt) && | ||||||
|             const DeepCollectionEquality().equals(other._contacts, _contacts) && |             const DeepCollectionEquality().equals(other._contacts, _contacts) && | ||||||
|             (identical(other.createdAt, createdAt) || |             (identical(other.avatar, avatar) || other.avatar == avatar) && | ||||||
|                 other.createdAt == createdAt) && |             (identical(other.banner, banner) || other.banner == banner) && | ||||||
|             (identical(other.deletedAt, deletedAt) || |  | ||||||
|                 other.deletedAt == deletedAt) && |  | ||||||
|             (identical(other.description, description) || |             (identical(other.description, description) || | ||||||
|                 other.description == description) && |                 other.description == description) && | ||||||
|             (identical(other.name, name) || other.name == name) && |             (identical(other.name, name) || other.name == name) && | ||||||
| @@ -457,8 +456,14 @@ class _$SnAccountImpl implements _SnAccount { | |||||||
|             (identical(other.profile, profile) || other.profile == profile) && |             (identical(other.profile, profile) || other.profile == profile) && | ||||||
|             (identical(other.suspendedAt, suspendedAt) || |             (identical(other.suspendedAt, suspendedAt) || | ||||||
|                 other.suspendedAt == suspendedAt) && |                 other.suspendedAt == suspendedAt) && | ||||||
|             (identical(other.updatedAt, updatedAt) || |             (identical(other.affiliatedId, affiliatedId) || | ||||||
|                 other.updatedAt == updatedAt)); |                 other.affiliatedId == affiliatedId) && | ||||||
|  |             (identical(other.affiliatedTo, affiliatedTo) || | ||||||
|  |                 other.affiliatedTo == affiliatedTo) && | ||||||
|  |             (identical(other.automatedBy, automatedBy) || | ||||||
|  |                 other.automatedBy == automatedBy) && | ||||||
|  |             (identical(other.automatedId, automatedId) || | ||||||
|  |                 other.automatedId == automatedId)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @JsonKey(includeFromJson: false, includeToJson: false) |   @JsonKey(includeFromJson: false, includeToJson: false) | ||||||
| @@ -466,23 +471,23 @@ class _$SnAccountImpl implements _SnAccount { | |||||||
|   int get hashCode => Object.hash( |   int get hashCode => Object.hash( | ||||||
|       runtimeType, |       runtimeType, | ||||||
|       id, |       id, | ||||||
|       affiliatedId, |       createdAt, | ||||||
|       affiliatedTo, |       updatedAt, | ||||||
|       automatedBy, |       deletedAt, | ||||||
|       automatedId, |  | ||||||
|       avatar, |  | ||||||
|       banner, |  | ||||||
|       confirmedAt, |       confirmedAt, | ||||||
|       const DeepCollectionEquality().hash(_contacts), |       const DeepCollectionEquality().hash(_contacts), | ||||||
|       createdAt, |       avatar, | ||||||
|       deletedAt, |       banner, | ||||||
|       description, |       description, | ||||||
|       name, |       name, | ||||||
|       nick, |       nick, | ||||||
|       const DeepCollectionEquality().hash(_permNodes), |       const DeepCollectionEquality().hash(_permNodes), | ||||||
|       profile, |       profile, | ||||||
|       suspendedAt, |       suspendedAt, | ||||||
|       updatedAt); |       affiliatedId, | ||||||
|  |       affiliatedTo, | ||||||
|  |       automatedBy, | ||||||
|  |       automatedId); | ||||||
|  |  | ||||||
|   /// Create a copy of SnAccount |   /// Create a copy of SnAccount | ||||||
|   /// with the given fields replaced by the non-null parameter values. |   /// with the given fields replaced by the non-null parameter values. | ||||||
| @@ -500,53 +505,49 @@ class _$SnAccountImpl implements _SnAccount { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| abstract class _SnAccount implements SnAccount { | abstract class _SnAccount extends SnAccount { | ||||||
|   const factory _SnAccount( |   const factory _SnAccount( | ||||||
|       {required final int id, |       {@HiveField(0) required final int id, | ||||||
|       required final int? affiliatedId, |       required final DateTime createdAt, | ||||||
|       required final int? affiliatedTo, |       required final DateTime updatedAt, | ||||||
|       required final int? automatedBy, |       required final DateTime? deletedAt, | ||||||
|       required final int? automatedId, |       required final DateTime? confirmedAt, | ||||||
|  |       required final List<SnAccountContact>? contacts, | ||||||
|       required final String avatar, |       required final String avatar, | ||||||
|       required final String banner, |       required final String banner, | ||||||
|       required final DateTime? confirmedAt, |  | ||||||
|       required final List<SnAccountContact> contacts, |  | ||||||
|       required final DateTime createdAt, |  | ||||||
|       required final DateTime? deletedAt, |  | ||||||
|       required final String description, |       required final String description, | ||||||
|       required final String name, |       required final String name, | ||||||
|       required final String nick, |       required final String nick, | ||||||
|       required final Map<String, dynamic> permNodes, |       required final Map<String, dynamic> permNodes, | ||||||
|       required final SnAccountProfile? profile, |       required final SnAccountProfile? profile, | ||||||
|       required final DateTime? suspendedAt, |       required final DateTime? suspendedAt, | ||||||
|       required final DateTime updatedAt}) = _$SnAccountImpl; |       required final int? affiliatedId, | ||||||
|  |       required final int? affiliatedTo, | ||||||
|  |       required final int? automatedBy, | ||||||
|  |       required final int? automatedId}) = _$SnAccountImpl; | ||||||
|  |   const _SnAccount._() : super._(); | ||||||
|  |  | ||||||
|   factory _SnAccount.fromJson(Map<String, dynamic> json) = |   factory _SnAccount.fromJson(Map<String, dynamic> json) = | ||||||
|       _$SnAccountImpl.fromJson; |       _$SnAccountImpl.fromJson; | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(0) | ||||||
|   int get id; |   int get id; | ||||||
|   @override |   @override | ||||||
|   int? get affiliatedId; |   DateTime get createdAt; | ||||||
|   @override |   @override | ||||||
|   int? get affiliatedTo; |   DateTime get updatedAt; | ||||||
|   @override |   @override | ||||||
|   int? get automatedBy; |   DateTime? get deletedAt; | ||||||
|   @override |   @override | ||||||
|   int? get automatedId; |   DateTime? get confirmedAt; | ||||||
|  |   @override | ||||||
|  |   List<SnAccountContact>? get contacts; | ||||||
|   @override |   @override | ||||||
|   String get avatar; |   String get avatar; | ||||||
|   @override |   @override | ||||||
|   String get banner; |   String get banner; | ||||||
|   @override |   @override | ||||||
|   DateTime? get confirmedAt; |  | ||||||
|   @override |  | ||||||
|   List<SnAccountContact> get contacts; |  | ||||||
|   @override |  | ||||||
|   DateTime get createdAt; |  | ||||||
|   @override |  | ||||||
|   DateTime? get deletedAt; |  | ||||||
|   @override |  | ||||||
|   String get description; |   String get description; | ||||||
|   @override |   @override | ||||||
|   String get name; |   String get name; | ||||||
| @@ -559,7 +560,13 @@ abstract class _SnAccount implements SnAccount { | |||||||
|   @override |   @override | ||||||
|   DateTime? get suspendedAt; |   DateTime? get suspendedAt; | ||||||
|   @override |   @override | ||||||
|   DateTime get updatedAt; |   int? get affiliatedId; | ||||||
|  |   @override | ||||||
|  |   int? get affiliatedTo; | ||||||
|  |   @override | ||||||
|  |   int? get automatedBy; | ||||||
|  |   @override | ||||||
|  |   int? get automatedId; | ||||||
|  |  | ||||||
|   /// Create a copy of SnAccount |   /// Create a copy of SnAccount | ||||||
|   /// with the given fields replaced by the non-null parameter values. |   /// with the given fields replaced by the non-null parameter values. | ||||||
|   | |||||||
| @@ -9,22 +9,19 @@ part of 'account.dart'; | |||||||
| _$SnAccountImpl _$$SnAccountImplFromJson(Map<String, dynamic> json) => | _$SnAccountImpl _$$SnAccountImplFromJson(Map<String, dynamic> json) => | ||||||
|     _$SnAccountImpl( |     _$SnAccountImpl( | ||||||
|       id: (json['id'] as num).toInt(), |       id: (json['id'] as num).toInt(), | ||||||
|       affiliatedId: (json['affiliated_id'] as num?)?.toInt(), |  | ||||||
|       affiliatedTo: (json['affiliated_to'] as num?)?.toInt(), |  | ||||||
|       automatedBy: (json['automated_by'] as num?)?.toInt(), |  | ||||||
|       automatedId: (json['automated_id'] as num?)?.toInt(), |  | ||||||
|       avatar: json['avatar'] as String, |  | ||||||
|       banner: json['banner'] as String, |  | ||||||
|       confirmedAt: json['confirmed_at'] == null |  | ||||||
|           ? null |  | ||||||
|           : DateTime.parse(json['confirmed_at'] as String), |  | ||||||
|       contacts: (json['contacts'] as List<dynamic>) |  | ||||||
|           .map((e) => SnAccountContact.fromJson(e as Map<String, dynamic>)) |  | ||||||
|           .toList(), |  | ||||||
|       createdAt: DateTime.parse(json['created_at'] as String), |       createdAt: DateTime.parse(json['created_at'] as String), | ||||||
|  |       updatedAt: DateTime.parse(json['updated_at'] as String), | ||||||
|       deletedAt: json['deleted_at'] == null |       deletedAt: json['deleted_at'] == null | ||||||
|           ? null |           ? null | ||||||
|           : DateTime.parse(json['deleted_at'] as String), |           : DateTime.parse(json['deleted_at'] as String), | ||||||
|  |       confirmedAt: json['confirmed_at'] == null | ||||||
|  |           ? null | ||||||
|  |           : DateTime.parse(json['confirmed_at'] as String), | ||||||
|  |       contacts: (json['contacts'] as List<dynamic>?) | ||||||
|  |           ?.map((e) => SnAccountContact.fromJson(e as Map<String, dynamic>)) | ||||||
|  |           .toList(), | ||||||
|  |       avatar: json['avatar'] as String, | ||||||
|  |       banner: json['banner'] as String, | ||||||
|       description: json['description'] as String, |       description: json['description'] as String, | ||||||
|       name: json['name'] as String, |       name: json['name'] as String, | ||||||
|       nick: json['nick'] as String, |       nick: json['nick'] as String, | ||||||
| @@ -35,29 +32,32 @@ _$SnAccountImpl _$$SnAccountImplFromJson(Map<String, dynamic> json) => | |||||||
|       suspendedAt: json['suspended_at'] == null |       suspendedAt: json['suspended_at'] == null | ||||||
|           ? null |           ? null | ||||||
|           : DateTime.parse(json['suspended_at'] as String), |           : DateTime.parse(json['suspended_at'] as String), | ||||||
|       updatedAt: DateTime.parse(json['updated_at'] as String), |       affiliatedId: (json['affiliated_id'] as num?)?.toInt(), | ||||||
|  |       affiliatedTo: (json['affiliated_to'] as num?)?.toInt(), | ||||||
|  |       automatedBy: (json['automated_by'] as num?)?.toInt(), | ||||||
|  |       automatedId: (json['automated_id'] as num?)?.toInt(), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
| Map<String, dynamic> _$$SnAccountImplToJson(_$SnAccountImpl instance) => | Map<String, dynamic> _$$SnAccountImplToJson(_$SnAccountImpl instance) => | ||||||
|     <String, dynamic>{ |     <String, dynamic>{ | ||||||
|       'id': instance.id, |       'id': instance.id, | ||||||
|       'affiliated_id': instance.affiliatedId, |       'created_at': instance.createdAt.toIso8601String(), | ||||||
|       'affiliated_to': instance.affiliatedTo, |       'updated_at': instance.updatedAt.toIso8601String(), | ||||||
|       'automated_by': instance.automatedBy, |       'deleted_at': instance.deletedAt?.toIso8601String(), | ||||||
|       'automated_id': instance.automatedId, |       'confirmed_at': instance.confirmedAt?.toIso8601String(), | ||||||
|  |       'contacts': instance.contacts?.map((e) => e.toJson()).toList(), | ||||||
|       'avatar': instance.avatar, |       'avatar': instance.avatar, | ||||||
|       'banner': instance.banner, |       'banner': instance.banner, | ||||||
|       'confirmed_at': instance.confirmedAt?.toIso8601String(), |  | ||||||
|       'contacts': instance.contacts.map((e) => e.toJson()).toList(), |  | ||||||
|       'created_at': instance.createdAt.toIso8601String(), |  | ||||||
|       'deleted_at': instance.deletedAt?.toIso8601String(), |  | ||||||
|       'description': instance.description, |       'description': instance.description, | ||||||
|       'name': instance.name, |       'name': instance.name, | ||||||
|       'nick': instance.nick, |       'nick': instance.nick, | ||||||
|       'perm_nodes': instance.permNodes, |       'perm_nodes': instance.permNodes, | ||||||
|       'profile': instance.profile?.toJson(), |       'profile': instance.profile?.toJson(), | ||||||
|       'suspended_at': instance.suspendedAt?.toIso8601String(), |       'suspended_at': instance.suspendedAt?.toIso8601String(), | ||||||
|       'updated_at': instance.updatedAt.toIso8601String(), |       'affiliated_id': instance.affiliatedId, | ||||||
|  |       'affiliated_to': instance.affiliatedTo, | ||||||
|  |       'automated_by': instance.automatedBy, | ||||||
|  |       'automated_id': instance.automatedId, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| _$SnAccountContactImpl _$$SnAccountContactImplFromJson( | _$SnAccountContactImpl _$$SnAccountContactImplFromJson( | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| import 'package:freezed_annotation/freezed_annotation.dart'; | import 'package:freezed_annotation/freezed_annotation.dart'; | ||||||
| import 'package:hive_flutter/hive_flutter.dart'; | import 'package:hive_flutter/hive_flutter.dart'; | ||||||
|  | import 'package:surface/types/account.dart'; | ||||||
| import 'package:surface/types/realm.dart'; | import 'package:surface/types/realm.dart'; | ||||||
|  |  | ||||||
| part 'chat.freezed.dart'; | part 'chat.freezed.dart'; | ||||||
| @@ -18,8 +19,8 @@ class SnChannel with _$SnChannel { | |||||||
|     @HiveField(4) required String alias, |     @HiveField(4) required String alias, | ||||||
|     @HiveField(5) required String name, |     @HiveField(5) required String name, | ||||||
|     @HiveField(6) required String description, |     @HiveField(6) required String description, | ||||||
|     @HiveField(7) required List<dynamic> members, |     @HiveField(7) required List<dynamic>? members, | ||||||
|     dynamic messages, |     List<SnChatMessage>? messages, | ||||||
|     dynamic calls, |     dynamic calls, | ||||||
|     @HiveField(8) required int type, |     @HiveField(8) required int type, | ||||||
|     @HiveField(9) required int accountId, |     @HiveField(9) required int accountId, | ||||||
| @@ -33,4 +34,53 @@ class SnChannel with _$SnChannel { | |||||||
|       _$SnChannelFromJson(json); |       _$SnChannelFromJson(json); | ||||||
|  |  | ||||||
|   String get key => '${realm?.alias ?? 'global'}:$alias'; |   String get key => '${realm?.alias ?? 'global'}:$alias'; | ||||||
|  |   String get keyPath => '${realm?.alias ?? 'global'}/$alias'; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @freezed | ||||||
|  | class SnChannelMember with _$SnChannelMember { | ||||||
|  |   const SnChannelMember._(); | ||||||
|  |  | ||||||
|  |   @HiveType(typeId: 3) | ||||||
|  |   const factory SnChannelMember({ | ||||||
|  |     @HiveField(0) required int id, | ||||||
|  |     @HiveField(1) required DateTime createdAt, | ||||||
|  |     @HiveField(2) required DateTime updatedAt, | ||||||
|  |     @HiveField(3) required DateTime? deletedAt, | ||||||
|  |     @HiveField(4) required int channelId, | ||||||
|  |     @HiveField(5) required int accountId, | ||||||
|  |     @HiveField(6) required String? nick, | ||||||
|  |     @HiveField(7) required SnChannel? channel, | ||||||
|  |     @HiveField(8) required SnAccount? account, | ||||||
|  |     @Default(0) int notify, | ||||||
|  |     @HiveField(9) required int powerLevel, | ||||||
|  |     dynamic calls, | ||||||
|  |     dynamic events, | ||||||
|  |   }) = _SnChannelMember; | ||||||
|  |  | ||||||
|  |   factory SnChannelMember.fromJson(Map<String, dynamic> json) => | ||||||
|  |       _$SnChannelMemberFromJson(json); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @freezed | ||||||
|  | class SnChatMessage with _$SnChatMessage { | ||||||
|  |   const SnChatMessage._(); | ||||||
|  |  | ||||||
|  |   @HiveType(typeId: 4) | ||||||
|  |   const factory SnChatMessage({ | ||||||
|  |     @HiveField(0) required int id, | ||||||
|  |     @HiveField(1) required DateTime createdAt, | ||||||
|  |     @HiveField(2) required DateTime updatedAt, | ||||||
|  |     @HiveField(3) required DateTime? deletedAt, | ||||||
|  |     @HiveField(4) required String uuid, | ||||||
|  |     @HiveField(5) required Map<String, dynamic> body, | ||||||
|  |     @HiveField(6) required String type, | ||||||
|  |     @HiveField(7) required SnChannel channel, | ||||||
|  |     @HiveField(8) required SnChannelMember sender, | ||||||
|  |     @HiveField(9) required int channelId, | ||||||
|  |     @HiveField(10) required int senderId, | ||||||
|  |   }) = _SnChatMessage; | ||||||
|  |  | ||||||
|  |   factory SnChatMessage.fromJson(Map<String, dynamic> json) => | ||||||
|  |       _$SnChatMessageFromJson(json); | ||||||
| } | } | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -24,7 +24,7 @@ class SnChannelImplAdapter extends TypeAdapter<_$SnChannelImpl> { | |||||||
|       alias: fields[4] as String, |       alias: fields[4] as String, | ||||||
|       name: fields[5] as String, |       name: fields[5] as String, | ||||||
|       description: fields[6] as String, |       description: fields[6] as String, | ||||||
|       members: (fields[7] as List).cast<dynamic>(), |       members: (fields[7] as List?)?.cast<dynamic>(), | ||||||
|       type: fields[8] as int, |       type: fields[8] as int, | ||||||
|       accountId: fields[9] as int, |       accountId: fields[9] as int, | ||||||
|       realm: fields[10] as SnRealm?, |       realm: fields[10] as SnRealm?, | ||||||
| @@ -79,6 +79,131 @@ class SnChannelImplAdapter extends TypeAdapter<_$SnChannelImpl> { | |||||||
|           typeId == other.typeId; |           typeId == other.typeId; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | class SnChannelMemberImplAdapter extends TypeAdapter<_$SnChannelMemberImpl> { | ||||||
|  |   @override | ||||||
|  |   final int typeId = 3; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   _$SnChannelMemberImpl read(BinaryReader reader) { | ||||||
|  |     final numOfFields = reader.readByte(); | ||||||
|  |     final fields = <int, dynamic>{ | ||||||
|  |       for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), | ||||||
|  |     }; | ||||||
|  |     return _$SnChannelMemberImpl( | ||||||
|  |       id: fields[0] as int, | ||||||
|  |       createdAt: fields[1] as DateTime, | ||||||
|  |       updatedAt: fields[2] as DateTime, | ||||||
|  |       deletedAt: fields[3] as DateTime?, | ||||||
|  |       channelId: fields[4] as int, | ||||||
|  |       accountId: fields[5] as int, | ||||||
|  |       nick: fields[6] as String?, | ||||||
|  |       channel: fields[7] as SnChannel?, | ||||||
|  |       account: fields[8] as SnAccount?, | ||||||
|  |       powerLevel: fields[9] as int, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   void write(BinaryWriter writer, _$SnChannelMemberImpl obj) { | ||||||
|  |     writer | ||||||
|  |       ..writeByte(10) | ||||||
|  |       ..writeByte(0) | ||||||
|  |       ..write(obj.id) | ||||||
|  |       ..writeByte(1) | ||||||
|  |       ..write(obj.createdAt) | ||||||
|  |       ..writeByte(2) | ||||||
|  |       ..write(obj.updatedAt) | ||||||
|  |       ..writeByte(3) | ||||||
|  |       ..write(obj.deletedAt) | ||||||
|  |       ..writeByte(4) | ||||||
|  |       ..write(obj.channelId) | ||||||
|  |       ..writeByte(5) | ||||||
|  |       ..write(obj.accountId) | ||||||
|  |       ..writeByte(6) | ||||||
|  |       ..write(obj.nick) | ||||||
|  |       ..writeByte(7) | ||||||
|  |       ..write(obj.channel) | ||||||
|  |       ..writeByte(8) | ||||||
|  |       ..write(obj.account) | ||||||
|  |       ..writeByte(9) | ||||||
|  |       ..write(obj.powerLevel); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   int get hashCode => typeId.hashCode; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   bool operator ==(Object other) => | ||||||
|  |       identical(this, other) || | ||||||
|  |       other is SnChannelMemberImplAdapter && | ||||||
|  |           runtimeType == other.runtimeType && | ||||||
|  |           typeId == other.typeId; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class SnChatMessageImplAdapter extends TypeAdapter<_$SnChatMessageImpl> { | ||||||
|  |   @override | ||||||
|  |   final int typeId = 4; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   _$SnChatMessageImpl read(BinaryReader reader) { | ||||||
|  |     final numOfFields = reader.readByte(); | ||||||
|  |     final fields = <int, dynamic>{ | ||||||
|  |       for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), | ||||||
|  |     }; | ||||||
|  |     return _$SnChatMessageImpl( | ||||||
|  |       id: fields[0] as int, | ||||||
|  |       createdAt: fields[1] as DateTime, | ||||||
|  |       updatedAt: fields[2] as DateTime, | ||||||
|  |       deletedAt: fields[3] as DateTime?, | ||||||
|  |       uuid: fields[4] as String, | ||||||
|  |       body: (fields[5] as Map).cast<String, dynamic>(), | ||||||
|  |       type: fields[6] as String, | ||||||
|  |       channel: fields[7] as SnChannel, | ||||||
|  |       sender: fields[8] as SnChannelMember, | ||||||
|  |       channelId: fields[9] as int, | ||||||
|  |       senderId: fields[10] as int, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   void write(BinaryWriter writer, _$SnChatMessageImpl obj) { | ||||||
|  |     writer | ||||||
|  |       ..writeByte(11) | ||||||
|  |       ..writeByte(0) | ||||||
|  |       ..write(obj.id) | ||||||
|  |       ..writeByte(1) | ||||||
|  |       ..write(obj.createdAt) | ||||||
|  |       ..writeByte(2) | ||||||
|  |       ..write(obj.updatedAt) | ||||||
|  |       ..writeByte(3) | ||||||
|  |       ..write(obj.deletedAt) | ||||||
|  |       ..writeByte(4) | ||||||
|  |       ..write(obj.uuid) | ||||||
|  |       ..writeByte(6) | ||||||
|  |       ..write(obj.type) | ||||||
|  |       ..writeByte(7) | ||||||
|  |       ..write(obj.channel) | ||||||
|  |       ..writeByte(8) | ||||||
|  |       ..write(obj.sender) | ||||||
|  |       ..writeByte(9) | ||||||
|  |       ..write(obj.channelId) | ||||||
|  |       ..writeByte(10) | ||||||
|  |       ..write(obj.senderId) | ||||||
|  |       ..writeByte(5) | ||||||
|  |       ..write(obj.body); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   int get hashCode => typeId.hashCode; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   bool operator ==(Object other) => | ||||||
|  |       identical(this, other) || | ||||||
|  |       other is SnChatMessageImplAdapter && | ||||||
|  |           runtimeType == other.runtimeType && | ||||||
|  |           typeId == other.typeId; | ||||||
|  | } | ||||||
|  |  | ||||||
| // ************************************************************************** | // ************************************************************************** | ||||||
| // JsonSerializableGenerator | // JsonSerializableGenerator | ||||||
| // ************************************************************************** | // ************************************************************************** | ||||||
| @@ -92,8 +217,10 @@ _$SnChannelImpl _$$SnChannelImplFromJson(Map<String, dynamic> json) => | |||||||
|       alias: json['alias'] as String, |       alias: json['alias'] as String, | ||||||
|       name: json['name'] as String, |       name: json['name'] as String, | ||||||
|       description: json['description'] as String, |       description: json['description'] as String, | ||||||
|       members: json['members'] as List<dynamic>, |       members: json['members'] as List<dynamic>?, | ||||||
|       messages: json['messages'], |       messages: (json['messages'] as List<dynamic>?) | ||||||
|  |           ?.map((e) => SnChatMessage.fromJson(e as Map<String, dynamic>)) | ||||||
|  |           .toList(), | ||||||
|       calls: json['calls'], |       calls: json['calls'], | ||||||
|       type: (json['type'] as num).toInt(), |       type: (json['type'] as num).toInt(), | ||||||
|       accountId: (json['account_id'] as num).toInt(), |       accountId: (json['account_id'] as num).toInt(), | ||||||
| @@ -115,7 +242,7 @@ Map<String, dynamic> _$$SnChannelImplToJson(_$SnChannelImpl instance) => | |||||||
|       'name': instance.name, |       'name': instance.name, | ||||||
|       'description': instance.description, |       'description': instance.description, | ||||||
|       'members': instance.members, |       'members': instance.members, | ||||||
|       'messages': instance.messages, |       'messages': instance.messages?.map((e) => e.toJson()).toList(), | ||||||
|       'calls': instance.calls, |       'calls': instance.calls, | ||||||
|       'type': instance.type, |       'type': instance.type, | ||||||
|       'account_id': instance.accountId, |       'account_id': instance.accountId, | ||||||
| @@ -124,3 +251,77 @@ Map<String, dynamic> _$$SnChannelImplToJson(_$SnChannelImpl instance) => | |||||||
|       'is_public': instance.isPublic, |       'is_public': instance.isPublic, | ||||||
|       'is_community': instance.isCommunity, |       'is_community': instance.isCommunity, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | _$SnChannelMemberImpl _$$SnChannelMemberImplFromJson( | ||||||
|  |         Map<String, dynamic> json) => | ||||||
|  |     _$SnChannelMemberImpl( | ||||||
|  |       id: (json['id'] as num).toInt(), | ||||||
|  |       createdAt: DateTime.parse(json['created_at'] as String), | ||||||
|  |       updatedAt: DateTime.parse(json['updated_at'] as String), | ||||||
|  |       deletedAt: json['deleted_at'] == null | ||||||
|  |           ? null | ||||||
|  |           : DateTime.parse(json['deleted_at'] as String), | ||||||
|  |       channelId: (json['channel_id'] as num).toInt(), | ||||||
|  |       accountId: (json['account_id'] as num).toInt(), | ||||||
|  |       nick: json['nick'] as String?, | ||||||
|  |       channel: json['channel'] == null | ||||||
|  |           ? null | ||||||
|  |           : SnChannel.fromJson(json['channel'] as Map<String, dynamic>), | ||||||
|  |       account: json['account'] == null | ||||||
|  |           ? null | ||||||
|  |           : SnAccount.fromJson(json['account'] as Map<String, dynamic>), | ||||||
|  |       notify: (json['notify'] as num?)?.toInt() ?? 0, | ||||||
|  |       powerLevel: (json['power_level'] as num).toInt(), | ||||||
|  |       calls: json['calls'], | ||||||
|  |       events: json['events'], | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  | Map<String, dynamic> _$$SnChannelMemberImplToJson( | ||||||
|  |         _$SnChannelMemberImpl instance) => | ||||||
|  |     <String, dynamic>{ | ||||||
|  |       'id': instance.id, | ||||||
|  |       'created_at': instance.createdAt.toIso8601String(), | ||||||
|  |       'updated_at': instance.updatedAt.toIso8601String(), | ||||||
|  |       'deleted_at': instance.deletedAt?.toIso8601String(), | ||||||
|  |       'channel_id': instance.channelId, | ||||||
|  |       'account_id': instance.accountId, | ||||||
|  |       'nick': instance.nick, | ||||||
|  |       'channel': instance.channel?.toJson(), | ||||||
|  |       'account': instance.account?.toJson(), | ||||||
|  |       'notify': instance.notify, | ||||||
|  |       'power_level': instance.powerLevel, | ||||||
|  |       'calls': instance.calls, | ||||||
|  |       'events': instance.events, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  | _$SnChatMessageImpl _$$SnChatMessageImplFromJson(Map<String, dynamic> json) => | ||||||
|  |     _$SnChatMessageImpl( | ||||||
|  |       id: (json['id'] as num).toInt(), | ||||||
|  |       createdAt: DateTime.parse(json['created_at'] as String), | ||||||
|  |       updatedAt: DateTime.parse(json['updated_at'] as String), | ||||||
|  |       deletedAt: json['deleted_at'] == null | ||||||
|  |           ? null | ||||||
|  |           : DateTime.parse(json['deleted_at'] as String), | ||||||
|  |       uuid: json['uuid'] as String, | ||||||
|  |       body: json['body'] as Map<String, dynamic>, | ||||||
|  |       type: json['type'] as String, | ||||||
|  |       channel: SnChannel.fromJson(json['channel'] as Map<String, dynamic>), | ||||||
|  |       sender: SnChannelMember.fromJson(json['sender'] as Map<String, dynamic>), | ||||||
|  |       channelId: (json['channel_id'] as num).toInt(), | ||||||
|  |       senderId: (json['sender_id'] as num).toInt(), | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  | Map<String, dynamic> _$$SnChatMessageImplToJson(_$SnChatMessageImpl instance) => | ||||||
|  |     <String, dynamic>{ | ||||||
|  |       'id': instance.id, | ||||||
|  |       'created_at': instance.createdAt.toIso8601String(), | ||||||
|  |       'updated_at': instance.updatedAt.toIso8601String(), | ||||||
|  |       'deleted_at': instance.deletedAt?.toIso8601String(), | ||||||
|  |       'uuid': instance.uuid, | ||||||
|  |       'body': instance.body, | ||||||
|  |       'type': instance.type, | ||||||
|  |       'channel': instance.channel.toJson(), | ||||||
|  |       'sender': instance.sender.toJson(), | ||||||
|  |       'channel_id': instance.channelId, | ||||||
|  |       'sender_id': instance.senderId, | ||||||
|  |     }; | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| import 'package:freezed_annotation/freezed_annotation.dart'; | import 'package:freezed_annotation/freezed_annotation.dart'; | ||||||
|  | import 'package:hive_flutter/hive_flutter.dart'; | ||||||
| import 'package:surface/types/account.dart'; | import 'package:surface/types/account.dart'; | ||||||
|  |  | ||||||
| part 'realm.freezed.dart'; | part 'realm.freezed.dart'; | ||||||
| @@ -24,21 +25,24 @@ class SnRealmMember with _$SnRealmMember { | |||||||
|  |  | ||||||
| @freezed | @freezed | ||||||
| class SnRealm with _$SnRealm { | class SnRealm with _$SnRealm { | ||||||
|  |   const SnRealm._(); | ||||||
|  |  | ||||||
|  |   @HiveType(typeId: 1) | ||||||
|   const factory SnRealm({ |   const factory SnRealm({ | ||||||
|     required int id, |     @HiveField(0) required int id, | ||||||
|     required DateTime createdAt, |     @HiveField(1) required DateTime createdAt, | ||||||
|     required DateTime updatedAt, |     @HiveField(2) required DateTime updatedAt, | ||||||
|     required DateTime? deletedAt, |     @HiveField(3) required DateTime? deletedAt, | ||||||
|     required String alias, |     @HiveField(4) required String alias, | ||||||
|     required String name, |     @HiveField(5) required String name, | ||||||
|     required String description, |     @HiveField(6) required String description, | ||||||
|     required List<SnRealmMember>? members, |     List<SnRealmMember>? members, | ||||||
|     required String? avatar, |     @HiveField(7) required String? avatar, | ||||||
|     required String? banner, |     @HiveField(8) required String? banner, | ||||||
|     required Map<String, dynamic>? accessPolicy, |     @HiveField(9) required Map<String, dynamic>? accessPolicy, | ||||||
|     required bool isPublic, |     @HiveField(10) required int accountId, | ||||||
|     required bool isCommunity, |     @HiveField(11) required bool isPublic, | ||||||
|     required int accountId, |     @HiveField(12) required bool isCommunity, | ||||||
|   }) = _SnRealm; |   }) = _SnRealm; | ||||||
|  |  | ||||||
|   factory SnRealm.fromJson(Map<String, dynamic> json) => |   factory SnRealm.fromJson(Map<String, dynamic> json) => | ||||||
|   | |||||||
| @@ -367,20 +367,33 @@ SnRealm _$SnRealmFromJson(Map<String, dynamic> json) { | |||||||
|  |  | ||||||
| /// @nodoc | /// @nodoc | ||||||
| mixin _$SnRealm { | mixin _$SnRealm { | ||||||
|  |   @HiveField(0) | ||||||
|   int get id => throw _privateConstructorUsedError; |   int get id => throw _privateConstructorUsedError; | ||||||
|  |   @HiveField(1) | ||||||
|   DateTime get createdAt => throw _privateConstructorUsedError; |   DateTime get createdAt => throw _privateConstructorUsedError; | ||||||
|  |   @HiveField(2) | ||||||
|   DateTime get updatedAt => throw _privateConstructorUsedError; |   DateTime get updatedAt => throw _privateConstructorUsedError; | ||||||
|  |   @HiveField(3) | ||||||
|   DateTime? get deletedAt => throw _privateConstructorUsedError; |   DateTime? get deletedAt => throw _privateConstructorUsedError; | ||||||
|  |   @HiveField(4) | ||||||
|   String get alias => throw _privateConstructorUsedError; |   String get alias => throw _privateConstructorUsedError; | ||||||
|  |   @HiveField(5) | ||||||
|   String get name => throw _privateConstructorUsedError; |   String get name => throw _privateConstructorUsedError; | ||||||
|  |   @HiveField(6) | ||||||
|   String get description => throw _privateConstructorUsedError; |   String get description => throw _privateConstructorUsedError; | ||||||
|   List<SnRealmMember>? get members => throw _privateConstructorUsedError; |   List<SnRealmMember>? get members => throw _privateConstructorUsedError; | ||||||
|  |   @HiveField(7) | ||||||
|   String? get avatar => throw _privateConstructorUsedError; |   String? get avatar => throw _privateConstructorUsedError; | ||||||
|  |   @HiveField(8) | ||||||
|   String? get banner => throw _privateConstructorUsedError; |   String? get banner => throw _privateConstructorUsedError; | ||||||
|  |   @HiveField(9) | ||||||
|   Map<String, dynamic>? get accessPolicy => throw _privateConstructorUsedError; |   Map<String, dynamic>? get accessPolicy => throw _privateConstructorUsedError; | ||||||
|   bool get isPublic => throw _privateConstructorUsedError; |   @HiveField(10) | ||||||
|   bool get isCommunity => throw _privateConstructorUsedError; |  | ||||||
|   int get accountId => throw _privateConstructorUsedError; |   int get accountId => throw _privateConstructorUsedError; | ||||||
|  |   @HiveField(11) | ||||||
|  |   bool get isPublic => throw _privateConstructorUsedError; | ||||||
|  |   @HiveField(12) | ||||||
|  |   bool get isCommunity => throw _privateConstructorUsedError; | ||||||
|  |  | ||||||
|   /// Serializes this SnRealm to a JSON map. |   /// Serializes this SnRealm to a JSON map. | ||||||
|   Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |   Map<String, dynamic> toJson() => throw _privateConstructorUsedError; | ||||||
| @@ -397,20 +410,20 @@ abstract class $SnRealmCopyWith<$Res> { | |||||||
|       _$SnRealmCopyWithImpl<$Res, SnRealm>; |       _$SnRealmCopyWithImpl<$Res, SnRealm>; | ||||||
|   @useResult |   @useResult | ||||||
|   $Res call( |   $Res call( | ||||||
|       {int id, |       {@HiveField(0) int id, | ||||||
|       DateTime createdAt, |       @HiveField(1) DateTime createdAt, | ||||||
|       DateTime updatedAt, |       @HiveField(2) DateTime updatedAt, | ||||||
|       DateTime? deletedAt, |       @HiveField(3) DateTime? deletedAt, | ||||||
|       String alias, |       @HiveField(4) String alias, | ||||||
|       String name, |       @HiveField(5) String name, | ||||||
|       String description, |       @HiveField(6) String description, | ||||||
|       List<SnRealmMember>? members, |       List<SnRealmMember>? members, | ||||||
|       String? avatar, |       @HiveField(7) String? avatar, | ||||||
|       String? banner, |       @HiveField(8) String? banner, | ||||||
|       Map<String, dynamic>? accessPolicy, |       @HiveField(9) Map<String, dynamic>? accessPolicy, | ||||||
|       bool isPublic, |       @HiveField(10) int accountId, | ||||||
|       bool isCommunity, |       @HiveField(11) bool isPublic, | ||||||
|       int accountId}); |       @HiveField(12) bool isCommunity}); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// @nodoc | /// @nodoc | ||||||
| @@ -439,9 +452,9 @@ class _$SnRealmCopyWithImpl<$Res, $Val extends SnRealm> | |||||||
|     Object? avatar = freezed, |     Object? avatar = freezed, | ||||||
|     Object? banner = freezed, |     Object? banner = freezed, | ||||||
|     Object? accessPolicy = freezed, |     Object? accessPolicy = freezed, | ||||||
|  |     Object? accountId = null, | ||||||
|     Object? isPublic = null, |     Object? isPublic = null, | ||||||
|     Object? isCommunity = null, |     Object? isCommunity = null, | ||||||
|     Object? accountId = null, |  | ||||||
|   }) { |   }) { | ||||||
|     return _then(_value.copyWith( |     return _then(_value.copyWith( | ||||||
|       id: null == id |       id: null == id | ||||||
| @@ -488,6 +501,10 @@ class _$SnRealmCopyWithImpl<$Res, $Val extends SnRealm> | |||||||
|           ? _value.accessPolicy |           ? _value.accessPolicy | ||||||
|           : accessPolicy // ignore: cast_nullable_to_non_nullable |           : accessPolicy // ignore: cast_nullable_to_non_nullable | ||||||
|               as Map<String, dynamic>?, |               as Map<String, dynamic>?, | ||||||
|  |       accountId: null == accountId | ||||||
|  |           ? _value.accountId | ||||||
|  |           : accountId // ignore: cast_nullable_to_non_nullable | ||||||
|  |               as int, | ||||||
|       isPublic: null == isPublic |       isPublic: null == isPublic | ||||||
|           ? _value.isPublic |           ? _value.isPublic | ||||||
|           : isPublic // ignore: cast_nullable_to_non_nullable |           : isPublic // ignore: cast_nullable_to_non_nullable | ||||||
| @@ -496,10 +513,6 @@ class _$SnRealmCopyWithImpl<$Res, $Val extends SnRealm> | |||||||
|           ? _value.isCommunity |           ? _value.isCommunity | ||||||
|           : isCommunity // ignore: cast_nullable_to_non_nullable |           : isCommunity // ignore: cast_nullable_to_non_nullable | ||||||
|               as bool, |               as bool, | ||||||
|       accountId: null == accountId |  | ||||||
|           ? _value.accountId |  | ||||||
|           : accountId // ignore: cast_nullable_to_non_nullable |  | ||||||
|               as int, |  | ||||||
|     ) as $Val); |     ) as $Val); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -512,20 +525,20 @@ abstract class _$$SnRealmImplCopyWith<$Res> implements $SnRealmCopyWith<$Res> { | |||||||
|   @override |   @override | ||||||
|   @useResult |   @useResult | ||||||
|   $Res call( |   $Res call( | ||||||
|       {int id, |       {@HiveField(0) int id, | ||||||
|       DateTime createdAt, |       @HiveField(1) DateTime createdAt, | ||||||
|       DateTime updatedAt, |       @HiveField(2) DateTime updatedAt, | ||||||
|       DateTime? deletedAt, |       @HiveField(3) DateTime? deletedAt, | ||||||
|       String alias, |       @HiveField(4) String alias, | ||||||
|       String name, |       @HiveField(5) String name, | ||||||
|       String description, |       @HiveField(6) String description, | ||||||
|       List<SnRealmMember>? members, |       List<SnRealmMember>? members, | ||||||
|       String? avatar, |       @HiveField(7) String? avatar, | ||||||
|       String? banner, |       @HiveField(8) String? banner, | ||||||
|       Map<String, dynamic>? accessPolicy, |       @HiveField(9) Map<String, dynamic>? accessPolicy, | ||||||
|       bool isPublic, |       @HiveField(10) int accountId, | ||||||
|       bool isCommunity, |       @HiveField(11) bool isPublic, | ||||||
|       int accountId}); |       @HiveField(12) bool isCommunity}); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// @nodoc | /// @nodoc | ||||||
| @@ -552,9 +565,9 @@ class __$$SnRealmImplCopyWithImpl<$Res> | |||||||
|     Object? avatar = freezed, |     Object? avatar = freezed, | ||||||
|     Object? banner = freezed, |     Object? banner = freezed, | ||||||
|     Object? accessPolicy = freezed, |     Object? accessPolicy = freezed, | ||||||
|  |     Object? accountId = null, | ||||||
|     Object? isPublic = null, |     Object? isPublic = null, | ||||||
|     Object? isCommunity = null, |     Object? isCommunity = null, | ||||||
|     Object? accountId = null, |  | ||||||
|   }) { |   }) { | ||||||
|     return _then(_$SnRealmImpl( |     return _then(_$SnRealmImpl( | ||||||
|       id: null == id |       id: null == id | ||||||
| @@ -601,6 +614,10 @@ class __$$SnRealmImplCopyWithImpl<$Res> | |||||||
|           ? _value._accessPolicy |           ? _value._accessPolicy | ||||||
|           : accessPolicy // ignore: cast_nullable_to_non_nullable |           : accessPolicy // ignore: cast_nullable_to_non_nullable | ||||||
|               as Map<String, dynamic>?, |               as Map<String, dynamic>?, | ||||||
|  |       accountId: null == accountId | ||||||
|  |           ? _value.accountId | ||||||
|  |           : accountId // ignore: cast_nullable_to_non_nullable | ||||||
|  |               as int, | ||||||
|       isPublic: null == isPublic |       isPublic: null == isPublic | ||||||
|           ? _value.isPublic |           ? _value.isPublic | ||||||
|           : isPublic // ignore: cast_nullable_to_non_nullable |           : isPublic // ignore: cast_nullable_to_non_nullable | ||||||
| @@ -609,51 +626,56 @@ class __$$SnRealmImplCopyWithImpl<$Res> | |||||||
|           ? _value.isCommunity |           ? _value.isCommunity | ||||||
|           : isCommunity // ignore: cast_nullable_to_non_nullable |           : isCommunity // ignore: cast_nullable_to_non_nullable | ||||||
|               as bool, |               as bool, | ||||||
|       accountId: null == accountId |  | ||||||
|           ? _value.accountId |  | ||||||
|           : accountId // ignore: cast_nullable_to_non_nullable |  | ||||||
|               as int, |  | ||||||
|     )); |     )); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| /// @nodoc | /// @nodoc | ||||||
| @JsonSerializable() | @JsonSerializable() | ||||||
| class _$SnRealmImpl implements _SnRealm { | @HiveType(typeId: 1) | ||||||
|  | class _$SnRealmImpl extends _SnRealm { | ||||||
|   const _$SnRealmImpl( |   const _$SnRealmImpl( | ||||||
|       {required this.id, |       {@HiveField(0) required this.id, | ||||||
|       required this.createdAt, |       @HiveField(1) required this.createdAt, | ||||||
|       required this.updatedAt, |       @HiveField(2) required this.updatedAt, | ||||||
|       required this.deletedAt, |       @HiveField(3) required this.deletedAt, | ||||||
|       required this.alias, |       @HiveField(4) required this.alias, | ||||||
|       required this.name, |       @HiveField(5) required this.name, | ||||||
|       required this.description, |       @HiveField(6) required this.description, | ||||||
|       required final List<SnRealmMember>? members, |       final List<SnRealmMember>? members, | ||||||
|       required this.avatar, |       @HiveField(7) required this.avatar, | ||||||
|       required this.banner, |       @HiveField(8) required this.banner, | ||||||
|       required final Map<String, dynamic>? accessPolicy, |       @HiveField(9) required final Map<String, dynamic>? accessPolicy, | ||||||
|       required this.isPublic, |       @HiveField(10) required this.accountId, | ||||||
|       required this.isCommunity, |       @HiveField(11) required this.isPublic, | ||||||
|       required this.accountId}) |       @HiveField(12) required this.isCommunity}) | ||||||
|       : _members = members, |       : _members = members, | ||||||
|         _accessPolicy = accessPolicy; |         _accessPolicy = accessPolicy, | ||||||
|  |         super._(); | ||||||
|  |  | ||||||
|   factory _$SnRealmImpl.fromJson(Map<String, dynamic> json) => |   factory _$SnRealmImpl.fromJson(Map<String, dynamic> json) => | ||||||
|       _$$SnRealmImplFromJson(json); |       _$$SnRealmImplFromJson(json); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(0) | ||||||
|   final int id; |   final int id; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(1) | ||||||
|   final DateTime createdAt; |   final DateTime createdAt; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(2) | ||||||
|   final DateTime updatedAt; |   final DateTime updatedAt; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(3) | ||||||
|   final DateTime? deletedAt; |   final DateTime? deletedAt; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(4) | ||||||
|   final String alias; |   final String alias; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(5) | ||||||
|   final String name; |   final String name; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(6) | ||||||
|   final String description; |   final String description; | ||||||
|   final List<SnRealmMember>? _members; |   final List<SnRealmMember>? _members; | ||||||
|   @override |   @override | ||||||
| @@ -666,11 +688,14 @@ class _$SnRealmImpl implements _SnRealm { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(7) | ||||||
|   final String? avatar; |   final String? avatar; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(8) | ||||||
|   final String? banner; |   final String? banner; | ||||||
|   final Map<String, dynamic>? _accessPolicy; |   final Map<String, dynamic>? _accessPolicy; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(9) | ||||||
|   Map<String, dynamic>? get accessPolicy { |   Map<String, dynamic>? get accessPolicy { | ||||||
|     final value = _accessPolicy; |     final value = _accessPolicy; | ||||||
|     if (value == null) return null; |     if (value == null) return null; | ||||||
| @@ -680,15 +705,18 @@ class _$SnRealmImpl implements _SnRealm { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(10) | ||||||
|  |   final int accountId; | ||||||
|  |   @override | ||||||
|  |   @HiveField(11) | ||||||
|   final bool isPublic; |   final bool isPublic; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(12) | ||||||
|   final bool isCommunity; |   final bool isCommunity; | ||||||
|   @override |  | ||||||
|   final int accountId; |  | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   String toString() { |   String toString() { | ||||||
|     return 'SnRealm(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, alias: $alias, name: $name, description: $description, members: $members, avatar: $avatar, banner: $banner, accessPolicy: $accessPolicy, isPublic: $isPublic, isCommunity: $isCommunity, accountId: $accountId)'; |     return 'SnRealm(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, alias: $alias, name: $name, description: $description, members: $members, avatar: $avatar, banner: $banner, accessPolicy: $accessPolicy, accountId: $accountId, isPublic: $isPublic, isCommunity: $isCommunity)'; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -712,12 +740,12 @@ class _$SnRealmImpl implements _SnRealm { | |||||||
|             (identical(other.banner, banner) || other.banner == banner) && |             (identical(other.banner, banner) || other.banner == banner) && | ||||||
|             const DeepCollectionEquality() |             const DeepCollectionEquality() | ||||||
|                 .equals(other._accessPolicy, _accessPolicy) && |                 .equals(other._accessPolicy, _accessPolicy) && | ||||||
|  |             (identical(other.accountId, accountId) || | ||||||
|  |                 other.accountId == accountId) && | ||||||
|             (identical(other.isPublic, isPublic) || |             (identical(other.isPublic, isPublic) || | ||||||
|                 other.isPublic == isPublic) && |                 other.isPublic == isPublic) && | ||||||
|             (identical(other.isCommunity, isCommunity) || |             (identical(other.isCommunity, isCommunity) || | ||||||
|                 other.isCommunity == isCommunity) && |                 other.isCommunity == isCommunity)); | ||||||
|             (identical(other.accountId, accountId) || |  | ||||||
|                 other.accountId == accountId)); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @JsonKey(includeFromJson: false, includeToJson: false) |   @JsonKey(includeFromJson: false, includeToJson: false) | ||||||
| @@ -735,9 +763,9 @@ class _$SnRealmImpl implements _SnRealm { | |||||||
|       avatar, |       avatar, | ||||||
|       banner, |       banner, | ||||||
|       const DeepCollectionEquality().hash(_accessPolicy), |       const DeepCollectionEquality().hash(_accessPolicy), | ||||||
|  |       accountId, | ||||||
|       isPublic, |       isPublic, | ||||||
|       isCommunity, |       isCommunity); | ||||||
|       accountId); |  | ||||||
|  |  | ||||||
|   /// Create a copy of SnRealm |   /// Create a copy of SnRealm | ||||||
|   /// with the given fields replaced by the non-null parameter values. |   /// with the given fields replaced by the non-null parameter values. | ||||||
| @@ -755,53 +783,67 @@ class _$SnRealmImpl implements _SnRealm { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| abstract class _SnRealm implements SnRealm { | abstract class _SnRealm extends SnRealm { | ||||||
|   const factory _SnRealm( |   const factory _SnRealm( | ||||||
|       {required final int id, |       {@HiveField(0) required final int id, | ||||||
|       required final DateTime createdAt, |       @HiveField(1) required final DateTime createdAt, | ||||||
|       required final DateTime updatedAt, |       @HiveField(2) required final DateTime updatedAt, | ||||||
|       required final DateTime? deletedAt, |       @HiveField(3) required final DateTime? deletedAt, | ||||||
|       required final String alias, |       @HiveField(4) required final String alias, | ||||||
|       required final String name, |       @HiveField(5) required final String name, | ||||||
|       required final String description, |       @HiveField(6) required final String description, | ||||||
|       required final List<SnRealmMember>? members, |       final List<SnRealmMember>? members, | ||||||
|       required final String? avatar, |       @HiveField(7) required final String? avatar, | ||||||
|       required final String? banner, |       @HiveField(8) required final String? banner, | ||||||
|       required final Map<String, dynamic>? accessPolicy, |       @HiveField(9) required final Map<String, dynamic>? accessPolicy, | ||||||
|       required final bool isPublic, |       @HiveField(10) required final int accountId, | ||||||
|       required final bool isCommunity, |       @HiveField(11) required final bool isPublic, | ||||||
|       required final int accountId}) = _$SnRealmImpl; |       @HiveField(12) required final bool isCommunity}) = _$SnRealmImpl; | ||||||
|  |   const _SnRealm._() : super._(); | ||||||
|  |  | ||||||
|   factory _SnRealm.fromJson(Map<String, dynamic> json) = _$SnRealmImpl.fromJson; |   factory _SnRealm.fromJson(Map<String, dynamic> json) = _$SnRealmImpl.fromJson; | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(0) | ||||||
|   int get id; |   int get id; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(1) | ||||||
|   DateTime get createdAt; |   DateTime get createdAt; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(2) | ||||||
|   DateTime get updatedAt; |   DateTime get updatedAt; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(3) | ||||||
|   DateTime? get deletedAt; |   DateTime? get deletedAt; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(4) | ||||||
|   String get alias; |   String get alias; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(5) | ||||||
|   String get name; |   String get name; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(6) | ||||||
|   String get description; |   String get description; | ||||||
|   @override |   @override | ||||||
|   List<SnRealmMember>? get members; |   List<SnRealmMember>? get members; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(7) | ||||||
|   String? get avatar; |   String? get avatar; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(8) | ||||||
|   String? get banner; |   String? get banner; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(9) | ||||||
|   Map<String, dynamic>? get accessPolicy; |   Map<String, dynamic>? get accessPolicy; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(10) | ||||||
|  |   int get accountId; | ||||||
|  |   @override | ||||||
|  |   @HiveField(11) | ||||||
|   bool get isPublic; |   bool get isPublic; | ||||||
|   @override |   @override | ||||||
|  |   @HiveField(12) | ||||||
|   bool get isCommunity; |   bool get isCommunity; | ||||||
|   @override |  | ||||||
|   int get accountId; |  | ||||||
|  |  | ||||||
|   /// Create a copy of SnRealm |   /// Create a copy of SnRealm | ||||||
|   /// with the given fields replaced by the non-null parameter values. |   /// with the given fields replaced by the non-null parameter values. | ||||||
|   | |||||||
| @@ -2,6 +2,80 @@ | |||||||
|  |  | ||||||
| part of 'realm.dart'; | part of 'realm.dart'; | ||||||
|  |  | ||||||
|  | // ************************************************************************** | ||||||
|  | // TypeAdapterGenerator | ||||||
|  | // ************************************************************************** | ||||||
|  |  | ||||||
|  | class SnRealmImplAdapter extends TypeAdapter<_$SnRealmImpl> { | ||||||
|  |   @override | ||||||
|  |   final int typeId = 1; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   _$SnRealmImpl read(BinaryReader reader) { | ||||||
|  |     final numOfFields = reader.readByte(); | ||||||
|  |     final fields = <int, dynamic>{ | ||||||
|  |       for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), | ||||||
|  |     }; | ||||||
|  |     return _$SnRealmImpl( | ||||||
|  |       id: fields[0] as int, | ||||||
|  |       createdAt: fields[1] as DateTime, | ||||||
|  |       updatedAt: fields[2] as DateTime, | ||||||
|  |       deletedAt: fields[3] as DateTime?, | ||||||
|  |       alias: fields[4] as String, | ||||||
|  |       name: fields[5] as String, | ||||||
|  |       description: fields[6] as String, | ||||||
|  |       avatar: fields[7] as String?, | ||||||
|  |       banner: fields[8] as String?, | ||||||
|  |       accessPolicy: (fields[9] as Map?)?.cast<String, dynamic>(), | ||||||
|  |       accountId: fields[10] as int, | ||||||
|  |       isPublic: fields[11] as bool, | ||||||
|  |       isCommunity: fields[12] as bool, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   void write(BinaryWriter writer, _$SnRealmImpl obj) { | ||||||
|  |     writer | ||||||
|  |       ..writeByte(13) | ||||||
|  |       ..writeByte(0) | ||||||
|  |       ..write(obj.id) | ||||||
|  |       ..writeByte(1) | ||||||
|  |       ..write(obj.createdAt) | ||||||
|  |       ..writeByte(2) | ||||||
|  |       ..write(obj.updatedAt) | ||||||
|  |       ..writeByte(3) | ||||||
|  |       ..write(obj.deletedAt) | ||||||
|  |       ..writeByte(4) | ||||||
|  |       ..write(obj.alias) | ||||||
|  |       ..writeByte(5) | ||||||
|  |       ..write(obj.name) | ||||||
|  |       ..writeByte(6) | ||||||
|  |       ..write(obj.description) | ||||||
|  |       ..writeByte(7) | ||||||
|  |       ..write(obj.avatar) | ||||||
|  |       ..writeByte(8) | ||||||
|  |       ..write(obj.banner) | ||||||
|  |       ..writeByte(10) | ||||||
|  |       ..write(obj.accountId) | ||||||
|  |       ..writeByte(11) | ||||||
|  |       ..write(obj.isPublic) | ||||||
|  |       ..writeByte(12) | ||||||
|  |       ..write(obj.isCommunity) | ||||||
|  |       ..writeByte(9) | ||||||
|  |       ..write(obj.accessPolicy); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   int get hashCode => typeId.hashCode; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   bool operator ==(Object other) => | ||||||
|  |       identical(this, other) || | ||||||
|  |       other is SnRealmImplAdapter && | ||||||
|  |           runtimeType == other.runtimeType && | ||||||
|  |           typeId == other.typeId; | ||||||
|  | } | ||||||
|  |  | ||||||
| // ************************************************************************** | // ************************************************************************** | ||||||
| // JsonSerializableGenerator | // JsonSerializableGenerator | ||||||
| // ************************************************************************** | // ************************************************************************** | ||||||
| @@ -51,9 +125,9 @@ _$SnRealmImpl _$$SnRealmImplFromJson(Map<String, dynamic> json) => | |||||||
|       avatar: json['avatar'] as String?, |       avatar: json['avatar'] as String?, | ||||||
|       banner: json['banner'] as String?, |       banner: json['banner'] as String?, | ||||||
|       accessPolicy: json['access_policy'] as Map<String, dynamic>?, |       accessPolicy: json['access_policy'] as Map<String, dynamic>?, | ||||||
|  |       accountId: (json['account_id'] as num).toInt(), | ||||||
|       isPublic: json['is_public'] as bool, |       isPublic: json['is_public'] as bool, | ||||||
|       isCommunity: json['is_community'] as bool, |       isCommunity: json['is_community'] as bool, | ||||||
|       accountId: (json['account_id'] as num).toInt(), |  | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
| Map<String, dynamic> _$$SnRealmImplToJson(_$SnRealmImpl instance) => | Map<String, dynamic> _$$SnRealmImplToJson(_$SnRealmImpl instance) => | ||||||
| @@ -69,7 +143,7 @@ Map<String, dynamic> _$$SnRealmImplToJson(_$SnRealmImpl instance) => | |||||||
|       'avatar': instance.avatar, |       'avatar': instance.avatar, | ||||||
|       'banner': instance.banner, |       'banner': instance.banner, | ||||||
|       'access_policy': instance.accessPolicy, |       'access_policy': instance.accessPolicy, | ||||||
|  |       'account_id': instance.accountId, | ||||||
|       'is_public': instance.isPublic, |       'is_public': instance.isPublic, | ||||||
|       'is_community': instance.isCommunity, |       'is_community': instance.isCommunity, | ||||||
|       'account_id': instance.accountId, |  | ||||||
|     }; |     }; | ||||||
|   | |||||||
							
								
								
									
										43
									
								
								lib/widgets/chat/chat_message.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								lib/widgets/chat/chat_message.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:gap/gap.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  | import 'package:styled_widget/styled_widget.dart'; | ||||||
|  | import 'package:surface/providers/user_directory.dart'; | ||||||
|  | import 'package:surface/types/chat.dart'; | ||||||
|  | import 'package:surface/widgets/account/account_image.dart'; | ||||||
|  | import 'package:surface/widgets/markdown_content.dart'; | ||||||
|  |  | ||||||
|  | class ChatMessage extends StatelessWidget { | ||||||
|  |   final SnChatMessage data; | ||||||
|  |   const ChatMessage({super.key, required this.data}); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     final ud = context.read<UserDirectoryProvider>(); | ||||||
|  |     final user = ud.getAccountFromCache(data.sender.accountId); | ||||||
|  |  | ||||||
|  |     return Row( | ||||||
|  |       crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |       children: [ | ||||||
|  |         AccountImage( | ||||||
|  |           content: user?.avatar, | ||||||
|  |         ), | ||||||
|  |         const Gap(8), | ||||||
|  |         Expanded( | ||||||
|  |           child: Column( | ||||||
|  |             crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |             children: [ | ||||||
|  |               Text( | ||||||
|  |                 (data.sender.nick?.isNotEmpty ?? false) | ||||||
|  |                     ? data.sender.nick! | ||||||
|  |                     : user!.nick, | ||||||
|  |               ).bold(), | ||||||
|  |               if (data.body['text'] != null) | ||||||
|  |                 MarkdownTextContent(content: data.body['text']), | ||||||
|  |             ], | ||||||
|  |           ), | ||||||
|  |         ) | ||||||
|  |       ], | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										76
									
								
								lib/widgets/chat/chat_message_input.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								lib/widgets/chat/chat_message_input.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:gap/gap.dart'; | ||||||
|  | import 'package:material_symbols_icons/symbols.dart'; | ||||||
|  | import 'package:styled_widget/styled_widget.dart'; | ||||||
|  | import 'package:surface/controllers/chat_message_controller.dart'; | ||||||
|  |  | ||||||
|  | class ChatMessageInput extends StatefulWidget { | ||||||
|  |   final ChatMessageController controller; | ||||||
|  |   const ChatMessageInput({super.key, required this.controller}); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   State<ChatMessageInput> createState() => _ChatMessageInputState(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class _ChatMessageInputState extends State<ChatMessageInput> { | ||||||
|  |   final TextEditingController _contentController = TextEditingController(); | ||||||
|  |   final FocusNode _focusNode = FocusNode(); | ||||||
|  |  | ||||||
|  |   void _sendMessage() { | ||||||
|  |     widget.controller.sendMessage( | ||||||
|  |       'messages.new', | ||||||
|  |       _contentController.text, | ||||||
|  |     ); | ||||||
|  |     _contentController.clear(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   void dispose() { | ||||||
|  |     _contentController.dispose(); | ||||||
|  |     _focusNode.dispose(); | ||||||
|  |     super.dispose(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return SizedBox( | ||||||
|  |       height: 72, | ||||||
|  |       child: Column( | ||||||
|  |         mainAxisAlignment: MainAxisAlignment.center, | ||||||
|  |         children: [ | ||||||
|  |           Row( | ||||||
|  |             children: [ | ||||||
|  |               Expanded( | ||||||
|  |                 child: TextField( | ||||||
|  |                   focusNode: _focusNode, | ||||||
|  |                   controller: _contentController, | ||||||
|  |                   decoration: InputDecoration( | ||||||
|  |                     isCollapsed: true, | ||||||
|  |                     hintText: 'Type a message...', | ||||||
|  |                     border: InputBorder.none, | ||||||
|  |                   ), | ||||||
|  |                   onSubmitted: (_) { | ||||||
|  |                     _sendMessage(); | ||||||
|  |                     _focusNode.requestFocus(); | ||||||
|  |                   }, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |               const Gap(8), | ||||||
|  |               IconButton( | ||||||
|  |                 onPressed: _sendMessage, | ||||||
|  |                 icon: Icon( | ||||||
|  |                   Symbols.send, | ||||||
|  |                   color: Theme.of(context).colorScheme.primary, | ||||||
|  |                 ), | ||||||
|  |                 visualDensity: const VisualDensity( | ||||||
|  |                   horizontal: -4, | ||||||
|  |                   vertical: -4, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ], | ||||||
|  |           ).padding(horizontal: 16, vertical: 12), | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -950,10 +950,10 @@ packages: | |||||||
|     dependency: "direct main" |     dependency: "direct main" | ||||||
|     description: |     description: | ||||||
|       name: material_symbols_icons |       name: material_symbols_icons | ||||||
|       sha256: "7b723abea4ad37e16fe921f1f1971cbb9b0f66d223a8c99981168a2306416b98" |       sha256: "1dea2aef1c83434f832f14341a5ffa1254e76b68e4d90333f95f8a2643bf1024" | ||||||
|       url: "https://pub.dev" |       url: "https://pub.dev" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "4.2791.1" |     version: "4.2799.0" | ||||||
|   meta: |   meta: | ||||||
|     dependency: transitive |     dependency: transitive | ||||||
|     description: |     description: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user