From 835203706d2ca42e4a78fa358ed48e70fcc196fe Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 16 Nov 2024 16:55:31 +0800 Subject: [PATCH] :sparkles: Channel creation & alter --- assets/translations/en.json | 2 + assets/translations/zh.json | 2 + lib/screens/chat.dart | 62 ++++- lib/screens/chat/manage.dart | 245 +++++++++++++---- lib/types/chat.dart | 30 ++ lib/types/chat.freezed.dart | 516 +++++++++++++++++++++++++++++++++++ lib/types/chat.g.dart | 49 ++++ 7 files changed, 853 insertions(+), 53 deletions(-) create mode 100644 lib/types/chat.dart create mode 100644 lib/types/chat.freezed.dart create mode 100644 lib/types/chat.g.dart diff --git a/assets/translations/en.json b/assets/translations/en.json index 537ca11..d2eb612 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -144,6 +144,8 @@ "fieldChatAliasHint": "The unique channel alias within the site, used to represent the channel in URL, leave blank to auto generate. Should be URL-Safe.", "fieldChatName": "Name", "fieldChatDescription": "Description", + "fieldChatBelongToRealm": "Belongs to", + "fieldChatBelongToRealmUnset": "Unset Channel Belongs to Realm", "channelEditingNotice": "You are editing channel {}", "channelDeleted": "Chat channel {} has been deleted." , "channelDelete": "Delete channel {}", diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 9820a3b..16565f1 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -144,6 +144,8 @@ "fieldChatAliasHint": "全站范围内唯一的频道别名,用于在 URL 中表示该频道,留空则自动生成。应遵循 URL-Safe 的原则。", "fieldChatName": "名称", "fieldChatDescription": "描述", + "fieldChatBelongToRealm": "所属领域", + "fieldChatBelongToRealmUnset": "未设置频道所属领域", "channelEditingNotice": "您正在编辑频道 {}", "channelDeleted": "聊天频道 {} 已被删除" , "channelDelete": "删除聊天频道 {}", diff --git a/lib/screens/chat.dart b/lib/screens/chat.dart index 0c92fe9..5c176fe 100644 --- a/lib/screens/chat.dart +++ b/lib/screens/chat.dart @@ -4,6 +4,10 @@ import 'package:go_router/go_router.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:provider/provider.dart'; import 'package:surface/providers/sn_network.dart'; +import 'package:surface/types/chat.dart'; +import 'package:surface/widgets/account/account_image.dart'; +import 'package:surface/widgets/dialog.dart'; +import 'package:surface/widgets/loading_indicator.dart'; class ChatScreen extends StatefulWidget { const ChatScreen({super.key}); @@ -13,14 +17,36 @@ class ChatScreen extends StatefulWidget { } class _ChatScreenState extends State { + bool _isBusy = false; + + List? _channels; + Future _fetchChannels({scope = 'global', direct = false}) async { - final sn = context.read(); - final resp = await sn.client.get( - '/cgi/im/channels/$scope/me/available', - queryParameters: { - 'direct': direct, - }, - ); + setState(() => _isBusy = true); + + try { + final sn = context.read(); + final resp = await sn.client.get( + '/cgi/im/channels/$scope/me/available', + queryParameters: { + 'direct': direct, + }, + ); + _channels = List.from( + resp.data?.map((e) => SnChannel.fromJson(e)) ?? [], + ); + } catch (err) { + if (!mounted) return; + context.showErrorDialog(err); + } finally { + setState(() => _isBusy = false); + } + } + + @override + void initState() { + super.initState(); + _fetchChannels(); } @override @@ -35,6 +61,28 @@ class _ChatScreenState extends State { GoRouter.of(context).pushNamed('chatManage'); }, ), + body: Column( + children: [ + LoadingIndicator(isActive: _isBusy), + Expanded( + child: ListView.builder( + itemCount: _channels?.length ?? 0, + itemBuilder: (context, idx) { + final channel = _channels![idx]; + return ListTile( + title: Text(channel.name), + subtitle: Text(channel.description), + contentPadding: const EdgeInsets.symmetric(horizontal: 16), + leading: AccountImage( + content: null, + fallbackWidget: const Icon(Symbols.chat, size: 20), + ), + ); + }, + ), + ), + ], + ), ); } } diff --git a/lib/screens/chat/manage.dart b/lib/screens/chat/manage.dart index bf6fbb4..caebca0 100644 --- a/lib/screens/chat/manage.dart +++ b/lib/screens/chat/manage.dart @@ -1,7 +1,5 @@ -import 'dart:convert'; -import 'dart:developer'; - import 'package:dio/dio.dart'; +import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:gap/gap.dart'; @@ -9,6 +7,9 @@ import 'package:material_symbols_icons/symbols.dart'; import 'package:provider/provider.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:surface/providers/sn_network.dart'; +import 'package:surface/types/chat.dart'; +import 'package:surface/types/realm.dart'; +import 'package:surface/widgets/account/account_image.dart'; import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/loading_indicator.dart'; import 'package:uuid/uuid.dart'; @@ -28,15 +29,50 @@ class _ChatManageScreenState extends State { final _nameController = TextEditingController(); final _descriptionController = TextEditingController(); + List? _realms; + SnRealm? _belongToRealm; + + Future _fetchRealms() async { + setState(() => _isBusy = true); + try { + final sn = context.read(); + final resp = await sn.client.get('/cgi/id/realms/me/available'); + _realms = List.from( + resp.data?.map((e) => SnRealm.fromJson(e)) ?? [], + ); + } catch (err) { + if (mounted) context.showErrorDialog(err); + } finally { + setState(() => _isBusy = false); + } + } + + SnChannel? _editingChannel; + + Future _fetchChannel() async { + setState(() => _isBusy = true); + + try { + final sn = context.read(); + final resp = await sn.client.get( + '/cgi/im/channels/${widget.editingChannelAlias}', + ); + _editingChannel = SnChannel.fromJson(resp.data); + } catch (err) { + if (!mounted) return; + context.showErrorDialog(err); + } finally { + setState(() => _isBusy = false); + } + } + Future _performAction() async { final uuid = const Uuid(); final sn = context.read(); setState(() => _isBusy = true); - // TODO Add realm support - // final scope = widget.realm != null ? widget.realm!.alias : 'global'; - final scope = 'global'; + final scope = _belongToRealm != null ? _belongToRealm!.alias : 'global'; final payload = { 'alias': _aliasController.text.isNotEmpty ? _aliasController.text.toLowerCase() @@ -55,7 +91,6 @@ class _ChatManageScreenState extends State { method: widget.editingChannelAlias != null ? 'PUT' : 'POST', ), ); - log(jsonEncode(resp.data)); // ignore: use_build_context_synchronously if (context.mounted) Navigator.pop(context, resp.data); } catch (err) { @@ -66,6 +101,13 @@ class _ChatManageScreenState extends State { setState(() => _isBusy = false); } + @override + void initState() { + super.initState(); + if (widget.editingChannelAlias != null) _fetchChannel(); + _fetchRealms(); + } + @override void dispose() { super.dispose(); @@ -86,53 +128,164 @@ class _ChatManageScreenState extends State { child: Column( children: [ LoadingIndicator(isActive: _isBusy), - const Gap(24), - TextField( - controller: _aliasController, - decoration: InputDecoration( - border: const UnderlineInputBorder(), - labelText: 'fieldChatAlias'.tr(), - helperText: 'fieldChatAliasHint'.tr(), - helperMaxLines: 2, + if (_editingChannel != null) + MaterialBanner( + leading: const Icon(Icons.edit), + leadingPadding: const EdgeInsets.only(left: 10, right: 20), + dividerColor: Colors.transparent, + content: Text( + 'channelEditingNotice' + .tr(args: ['#${_editingChannel!.alias}']), + ), + actions: [ + TextButton( + child: Text('cancel').tr(), + onPressed: () { + Navigator.pop(context); + }, + ), + ], ), - onTapOutside: (_) => - FocusManager.instance.primaryFocus?.unfocus(), - ), - const Gap(4), - TextField( - controller: _nameController, - decoration: InputDecoration( - border: const UnderlineInputBorder(), - labelText: 'fieldChatName'.tr(), + DropdownButtonHideUnderline( + child: DropdownButton2( + isExpanded: true, + hint: Text( + 'fieldChatBelongToRealm'.tr(), + style: TextStyle( + color: Theme.of(context).hintColor, + ), + ), + items: [ + ...(_realms?.map( + (SnRealm item) => DropdownMenuItem( + value: item, + child: Row( + children: [ + AccountImage( + content: item.avatar, + radius: 16, + fallbackWidget: const Icon( + Symbols.group, + size: 16, + ), + ), + const Gap(12), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(item.name).textStyle(Theme.of(context) + .textTheme + .bodyMedium!), + Text( + item.description, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ).textStyle( + Theme.of(context).textTheme.bodySmall!), + ], + ), + ), + ], + ), + ), + ) ?? + []), + DropdownMenuItem( + value: null, + child: Row( + children: [ + CircleAvatar( + radius: 16, + backgroundColor: Colors.transparent, + foregroundColor: + Theme.of(context).colorScheme.onSurface, + child: const Icon(Symbols.clear), + ), + const Gap(12), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('fieldChatBelongToRealmUnset') + .tr() + .textStyle( + Theme.of(context).textTheme.bodyMedium!, + ), + ], + ), + ), + ], + ), + ), + ], + value: _belongToRealm, + onChanged: (SnRealm? value) { + setState(() => _belongToRealm = value); + }, + buttonStyleData: const ButtonStyleData( + padding: EdgeInsets.only(right: 16), + height: 60, + ), + menuItemStyleData: const MenuItemStyleData( + height: 60, + ), ), - onTapOutside: (_) => - FocusManager.instance.primaryFocus?.unfocus(), - ), - const Gap(4), - TextField( - controller: _descriptionController, - maxLines: null, - minLines: 3, - decoration: InputDecoration( - border: const UnderlineInputBorder(), - labelText: 'fieldChatDescription'.tr(), - ), - onTapOutside: (_) => - FocusManager.instance.primaryFocus?.unfocus(), ), + const Divider(height: 1), const Gap(12), - Row( - mainAxisAlignment: MainAxisAlignment.end, + Column( children: [ - ElevatedButton.icon( - onPressed: _isBusy ? null : _performAction, - icon: const Icon(Symbols.save), - label: Text('apply').tr(), + TextField( + controller: _aliasController, + decoration: InputDecoration( + border: const UnderlineInputBorder(), + labelText: 'fieldChatAlias'.tr(), + helperText: 'fieldChatAliasHint'.tr(), + helperMaxLines: 2, + ), + onTapOutside: (_) => + FocusManager.instance.primaryFocus?.unfocus(), + ), + const Gap(4), + TextField( + controller: _nameController, + decoration: InputDecoration( + border: const UnderlineInputBorder(), + labelText: 'fieldChatName'.tr(), + ), + onTapOutside: (_) => + FocusManager.instance.primaryFocus?.unfocus(), + ), + const Gap(4), + TextField( + controller: _descriptionController, + maxLines: null, + minLines: 3, + decoration: InputDecoration( + border: const UnderlineInputBorder(), + labelText: 'fieldChatDescription'.tr(), + ), + onTapOutside: (_) => + FocusManager.instance.primaryFocus?.unfocus(), + ), + const Gap(12), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + ElevatedButton.icon( + onPressed: _isBusy ? null : _performAction, + icon: const Icon(Symbols.save), + label: Text('apply').tr(), + ), + ], ), ], - ), + ).padding(horizontal: 24), ], - ).padding(horizontal: 24), + ), ), ); } diff --git a/lib/types/chat.dart b/lib/types/chat.dart new file mode 100644 index 0000000..8df3e67 --- /dev/null +++ b/lib/types/chat.dart @@ -0,0 +1,30 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:surface/types/realm.dart'; + +part 'chat.freezed.dart'; +part 'chat.g.dart'; + +@freezed +class SnChannel with _$SnChannel { + const factory SnChannel({ + required int id, + required DateTime createdAt, + required DateTime updatedAt, + required dynamic deletedAt, + required String alias, + required String name, + required String description, + required List members, + required dynamic messages, + required dynamic calls, + required int type, + required int accountId, + required bool isPublic, + required bool isCommunity, + required SnRealm? realm, + required int? realmId, + }) = _SnChannel; + + factory SnChannel.fromJson(Map json) => + _$SnChannelFromJson(json); +} diff --git a/lib/types/chat.freezed.dart b/lib/types/chat.freezed.dart new file mode 100644 index 0000000..0930558 --- /dev/null +++ b/lib/types/chat.freezed.dart @@ -0,0 +1,516 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'chat.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +SnChannel _$SnChannelFromJson(Map json) { + return _SnChannel.fromJson(json); +} + +/// @nodoc +mixin _$SnChannel { + int get id => throw _privateConstructorUsedError; + DateTime get createdAt => throw _privateConstructorUsedError; + DateTime get updatedAt => throw _privateConstructorUsedError; + dynamic get deletedAt => throw _privateConstructorUsedError; + String get alias => throw _privateConstructorUsedError; + String get name => throw _privateConstructorUsedError; + String get description => throw _privateConstructorUsedError; + List get members => throw _privateConstructorUsedError; + dynamic get messages => throw _privateConstructorUsedError; + dynamic get calls => throw _privateConstructorUsedError; + int get type => throw _privateConstructorUsedError; + int get accountId => throw _privateConstructorUsedError; + bool get isPublic => throw _privateConstructorUsedError; + bool get isCommunity => throw _privateConstructorUsedError; + SnRealm? get realm => throw _privateConstructorUsedError; + int? get realmId => throw _privateConstructorUsedError; + + /// Serializes this SnChannel to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SnChannel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SnChannelCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SnChannelCopyWith<$Res> { + factory $SnChannelCopyWith(SnChannel value, $Res Function(SnChannel) then) = + _$SnChannelCopyWithImpl<$Res, SnChannel>; + @useResult + $Res call( + {int id, + DateTime createdAt, + DateTime updatedAt, + dynamic deletedAt, + String alias, + String name, + String description, + List members, + dynamic messages, + dynamic calls, + int type, + int accountId, + bool isPublic, + bool isCommunity, + SnRealm? realm, + int? realmId}); + + $SnRealmCopyWith<$Res>? get realm; +} + +/// @nodoc +class _$SnChannelCopyWithImpl<$Res, $Val extends SnChannel> + implements $SnChannelCopyWith<$Res> { + _$SnChannelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SnChannel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? createdAt = null, + Object? updatedAt = null, + Object? deletedAt = freezed, + Object? alias = null, + Object? name = null, + Object? description = null, + Object? members = null, + Object? messages = freezed, + Object? calls = freezed, + Object? type = null, + Object? accountId = null, + Object? isPublic = null, + Object? isCommunity = null, + Object? realm = freezed, + Object? realmId = freezed, + }) { + return _then(_value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as int, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + deletedAt: freezed == deletedAt + ? _value.deletedAt + : deletedAt // ignore: cast_nullable_to_non_nullable + as dynamic, + alias: null == alias + ? _value.alias + : alias // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + description: null == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String, + members: null == members + ? _value.members + : members // ignore: cast_nullable_to_non_nullable + as List, + messages: freezed == messages + ? _value.messages + : messages // ignore: cast_nullable_to_non_nullable + as dynamic, + calls: freezed == calls + ? _value.calls + : calls // ignore: cast_nullable_to_non_nullable + as dynamic, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as int, + accountId: null == accountId + ? _value.accountId + : accountId // ignore: cast_nullable_to_non_nullable + as int, + isPublic: null == isPublic + ? _value.isPublic + : isPublic // ignore: cast_nullable_to_non_nullable + as bool, + isCommunity: null == isCommunity + ? _value.isCommunity + : isCommunity // ignore: cast_nullable_to_non_nullable + as bool, + realm: freezed == realm + ? _value.realm + : realm // ignore: cast_nullable_to_non_nullable + as SnRealm?, + realmId: freezed == realmId + ? _value.realmId + : realmId // ignore: cast_nullable_to_non_nullable + as int?, + ) as $Val); + } + + /// Create a copy of SnChannel + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $SnRealmCopyWith<$Res>? get realm { + if (_value.realm == null) { + return null; + } + + return $SnRealmCopyWith<$Res>(_value.realm!, (value) { + return _then(_value.copyWith(realm: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$SnChannelImplCopyWith<$Res> + implements $SnChannelCopyWith<$Res> { + factory _$$SnChannelImplCopyWith( + _$SnChannelImpl value, $Res Function(_$SnChannelImpl) then) = + __$$SnChannelImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {int id, + DateTime createdAt, + DateTime updatedAt, + dynamic deletedAt, + String alias, + String name, + String description, + List members, + dynamic messages, + dynamic calls, + int type, + int accountId, + bool isPublic, + bool isCommunity, + SnRealm? realm, + int? realmId}); + + @override + $SnRealmCopyWith<$Res>? get realm; +} + +/// @nodoc +class __$$SnChannelImplCopyWithImpl<$Res> + extends _$SnChannelCopyWithImpl<$Res, _$SnChannelImpl> + implements _$$SnChannelImplCopyWith<$Res> { + __$$SnChannelImplCopyWithImpl( + _$SnChannelImpl _value, $Res Function(_$SnChannelImpl) _then) + : super(_value, _then); + + /// Create a copy of SnChannel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? createdAt = null, + Object? updatedAt = null, + Object? deletedAt = freezed, + Object? alias = null, + Object? name = null, + Object? description = null, + Object? members = null, + Object? messages = freezed, + Object? calls = freezed, + Object? type = null, + Object? accountId = null, + Object? isPublic = null, + Object? isCommunity = null, + Object? realm = freezed, + Object? realmId = freezed, + }) { + return _then(_$SnChannelImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as int, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + deletedAt: freezed == deletedAt + ? _value.deletedAt + : deletedAt // ignore: cast_nullable_to_non_nullable + as dynamic, + alias: null == alias + ? _value.alias + : alias // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + description: null == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String, + members: null == members + ? _value._members + : members // ignore: cast_nullable_to_non_nullable + as List, + messages: freezed == messages + ? _value.messages + : messages // ignore: cast_nullable_to_non_nullable + as dynamic, + calls: freezed == calls + ? _value.calls + : calls // ignore: cast_nullable_to_non_nullable + as dynamic, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as int, + accountId: null == accountId + ? _value.accountId + : accountId // ignore: cast_nullable_to_non_nullable + as int, + isPublic: null == isPublic + ? _value.isPublic + : isPublic // ignore: cast_nullable_to_non_nullable + as bool, + isCommunity: null == isCommunity + ? _value.isCommunity + : isCommunity // ignore: cast_nullable_to_non_nullable + as bool, + realm: freezed == realm + ? _value.realm + : realm // ignore: cast_nullable_to_non_nullable + as SnRealm?, + realmId: freezed == realmId + ? _value.realmId + : realmId // ignore: cast_nullable_to_non_nullable + as int?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$SnChannelImpl implements _SnChannel { + const _$SnChannelImpl( + {required this.id, + required this.createdAt, + required this.updatedAt, + required this.deletedAt, + required this.alias, + required this.name, + required this.description, + required final List members, + required this.messages, + required this.calls, + required this.type, + required this.accountId, + required this.isPublic, + required this.isCommunity, + required this.realm, + required this.realmId}) + : _members = members; + + factory _$SnChannelImpl.fromJson(Map json) => + _$$SnChannelImplFromJson(json); + + @override + final int id; + @override + final DateTime createdAt; + @override + final DateTime updatedAt; + @override + final dynamic deletedAt; + @override + final String alias; + @override + final String name; + @override + final String description; + final List _members; + @override + List get members { + if (_members is EqualUnmodifiableListView) return _members; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_members); + } + + @override + final dynamic messages; + @override + final dynamic calls; + @override + final int type; + @override + final int accountId; + @override + final bool isPublic; + @override + final bool isCommunity; + @override + final SnRealm? realm; + @override + final int? realmId; + + @override + String toString() { + return 'SnChannel(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, alias: $alias, name: $name, description: $description, members: $members, messages: $messages, calls: $calls, type: $type, accountId: $accountId, isPublic: $isPublic, isCommunity: $isCommunity, realm: $realm, realmId: $realmId)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SnChannelImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt) && + const DeepCollectionEquality().equals(other.deletedAt, deletedAt) && + (identical(other.alias, alias) || other.alias == alias) && + (identical(other.name, name) || other.name == name) && + (identical(other.description, description) || + other.description == description) && + const DeepCollectionEquality().equals(other._members, _members) && + const DeepCollectionEquality().equals(other.messages, messages) && + const DeepCollectionEquality().equals(other.calls, calls) && + (identical(other.type, type) || other.type == type) && + (identical(other.accountId, accountId) || + other.accountId == accountId) && + (identical(other.isPublic, isPublic) || + other.isPublic == isPublic) && + (identical(other.isCommunity, isCommunity) || + other.isCommunity == isCommunity) && + (identical(other.realm, realm) || other.realm == realm) && + (identical(other.realmId, realmId) || other.realmId == realmId)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + createdAt, + updatedAt, + const DeepCollectionEquality().hash(deletedAt), + alias, + name, + description, + const DeepCollectionEquality().hash(_members), + const DeepCollectionEquality().hash(messages), + const DeepCollectionEquality().hash(calls), + type, + accountId, + isPublic, + isCommunity, + realm, + realmId); + + /// Create a copy of SnChannel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SnChannelImplCopyWith<_$SnChannelImpl> get copyWith => + __$$SnChannelImplCopyWithImpl<_$SnChannelImpl>(this, _$identity); + + @override + Map toJson() { + return _$$SnChannelImplToJson( + this, + ); + } +} + +abstract class _SnChannel implements SnChannel { + const factory _SnChannel( + {required final int id, + required final DateTime createdAt, + required final DateTime updatedAt, + required final dynamic deletedAt, + required final String alias, + required final String name, + required final String description, + required final List members, + required final dynamic messages, + required final dynamic calls, + required final int type, + required final int accountId, + required final bool isPublic, + required final bool isCommunity, + required final SnRealm? realm, + required final int? realmId}) = _$SnChannelImpl; + + factory _SnChannel.fromJson(Map json) = + _$SnChannelImpl.fromJson; + + @override + int get id; + @override + DateTime get createdAt; + @override + DateTime get updatedAt; + @override + dynamic get deletedAt; + @override + String get alias; + @override + String get name; + @override + String get description; + @override + List get members; + @override + dynamic get messages; + @override + dynamic get calls; + @override + int get type; + @override + int get accountId; + @override + bool get isPublic; + @override + bool get isCommunity; + @override + SnRealm? get realm; + @override + int? get realmId; + + /// Create a copy of SnChannel + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SnChannelImplCopyWith<_$SnChannelImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/types/chat.g.dart b/lib/types/chat.g.dart new file mode 100644 index 0000000..1148898 --- /dev/null +++ b/lib/types/chat.g.dart @@ -0,0 +1,49 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'chat.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$SnChannelImpl _$$SnChannelImplFromJson(Map json) => + _$SnChannelImpl( + 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'], + alias: json['alias'] as String, + name: json['name'] as String, + description: json['description'] as String, + members: json['members'] as List, + messages: json['messages'], + calls: json['calls'], + type: (json['type'] as num).toInt(), + accountId: (json['account_id'] as num).toInt(), + isPublic: json['is_public'] as bool, + isCommunity: json['is_community'] as bool, + realm: json['realm'] == null + ? null + : SnRealm.fromJson(json['realm'] as Map), + realmId: (json['realm_id'] as num?)?.toInt(), + ); + +Map _$$SnChannelImplToJson(_$SnChannelImpl instance) => + { + 'id': instance.id, + 'created_at': instance.createdAt.toIso8601String(), + 'updated_at': instance.updatedAt.toIso8601String(), + 'deleted_at': instance.deletedAt, + 'alias': instance.alias, + 'name': instance.name, + 'description': instance.description, + 'members': instance.members, + 'messages': instance.messages, + 'calls': instance.calls, + 'type': instance.type, + 'account_id': instance.accountId, + 'is_public': instance.isPublic, + 'is_community': instance.isCommunity, + 'realm': instance.realm?.toJson(), + 'realm_id': instance.realmId, + };