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<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),
+                  ),
+                );
+              },
+            ),
+          ),
+        ],
+      ),
     );
   }
 }
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<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),
+        ),
       ),
     );
   }
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<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);
+}
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>(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;
+}
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<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,
+    };