Channel creation & alter

This commit is contained in:
LittleSheep 2024-11-16 16:55:31 +08:00
parent 0e208cc320
commit 835203706d
7 changed files with 853 additions and 53 deletions

View File

@ -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 {}",

View File

@ -144,6 +144,8 @@
"fieldChatAliasHint": "全站范围内唯一的频道别名,用于在 URL 中表示该频道,留空则自动生成。应遵循 URL-Safe 的原则。",
"fieldChatName": "名称",
"fieldChatDescription": "描述",
"fieldChatBelongToRealm": "所属领域",
"fieldChatBelongToRealmUnset": "未设置频道所属领域",
"channelEditingNotice": "您正在编辑频道 {}",
"channelDeleted": "聊天频道 {} 已被删除" ,
"channelDelete": "删除聊天频道 {}",

View File

@ -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<ChatScreen> {
bool _isBusy = false;
List<SnChannel>? _channels;
Future<void> _fetchChannels({scope = 'global', direct = false}) async {
final sn = context.read<SnNetworkProvider>();
final resp = await sn.client.get(
'/cgi/im/channels/$scope/me/available',
queryParameters: {
'direct': direct,
},
);
setState(() => _isBusy = true);
try {
final sn = context.read<SnNetworkProvider>();
final resp = await sn.client.get(
'/cgi/im/channels/$scope/me/available',
queryParameters: {
'direct': direct,
},
);
_channels = List<SnChannel>.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<ChatScreen> {
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),
),
);
},
),
),
],
),
);
}
}

View File

@ -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<ChatManageScreen> {
final _nameController = TextEditingController();
final _descriptionController = TextEditingController();
List<SnRealm>? _realms;
SnRealm? _belongToRealm;
Future<void> _fetchRealms() async {
setState(() => _isBusy = true);
try {
final sn = context.read<SnNetworkProvider>();
final resp = await sn.client.get('/cgi/id/realms/me/available');
_realms = List<SnRealm>.from(
resp.data?.map((e) => SnRealm.fromJson(e)) ?? [],
);
} catch (err) {
if (mounted) context.showErrorDialog(err);
} finally {
setState(() => _isBusy = false);
}
}
SnChannel? _editingChannel;
Future<void> _fetchChannel() async {
setState(() => _isBusy = true);
try {
final sn = context.read<SnNetworkProvider>();
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<void> _performAction() async {
final uuid = const Uuid();
final sn = context.read<SnNetworkProvider>();
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<ChatManageScreen> {
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<ChatManageScreen> {
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<ChatManageScreen> {
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<SnRealm>(
isExpanded: true,
hint: Text(
'fieldChatBelongToRealm'.tr(),
style: TextStyle(
color: Theme.of(context).hintColor,
),
),
items: [
...(_realms?.map(
(SnRealm item) => DropdownMenuItem<SnRealm>(
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<SnRealm>(
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),
),
),
);
}

30
lib/types/chat.dart Normal file
View File

@ -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<dynamic> 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<String, dynamic> json) =>
_$SnChannelFromJson(json);
}

516
lib/types/chat.freezed.dart Normal file
View File

@ -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>(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<String, dynamic> 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<dynamic> 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<String, dynamic> 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<SnChannel> 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<dynamic> 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<dynamic>,
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<dynamic> 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<dynamic>,
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<dynamic> 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<String, dynamic> 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<dynamic> _members;
@override
List<dynamic> 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<String, dynamic> 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<dynamic> 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<String, dynamic> 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<dynamic> 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;
}

49
lib/types/chat.g.dart Normal file
View File

@ -0,0 +1,49 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'chat.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$SnChannelImpl _$$SnChannelImplFromJson(Map<String, dynamic> 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<dynamic>,
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<String, dynamic>),
realmId: (json['realm_id'] as num?)?.toInt(),
);
Map<String, dynamic> _$$SnChannelImplToJson(_$SnChannelImpl instance) =>
<String, dynamic>{
'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,
};