✨ Chat room layout
This commit is contained in:
		| @@ -70,5 +70,10 @@ | ||||
|   "name": "Name", | ||||
|   "description": "Description", | ||||
|   "slug": "Slug", | ||||
|   "slugHint": "The slug will be used in the URL to access this resource, it should be unique and URL safe." | ||||
|   "slugHint": "The slug will be used in the URL to access this resource, it should be unique and URL safe.", | ||||
|   "createChatRoom": "Create a Room", | ||||
|   "editChatRoom": "Edit a Room", | ||||
|   "chat": "Chat", | ||||
|   "chatMessageHint": "Message in {}", | ||||
|   "chatDirectMessageHint": "Message to {}" | ||||
| } | ||||
|   | ||||
| @@ -16,6 +16,7 @@ class AppRouter extends RootStackRouter { | ||||
|         AutoRoute(page: ExploreRoute.page, path: 'explore'), | ||||
|         AutoRoute(page: AccountRoute.page, path: 'account'), | ||||
|         AutoRoute(page: RealmListRoute.page, path: 'realms'), | ||||
|         AutoRoute(page: ChatListRoute.page, path: 'chat'), | ||||
|       ], | ||||
|     ), | ||||
|     AutoRoute(page: LoginRoute.page, path: '/auth/login'), | ||||
| @@ -33,5 +34,8 @@ class AppRouter extends RootStackRouter { | ||||
|     AutoRoute(page: PostEditRoute.page, path: '/posts/:id/edit'), | ||||
|     AutoRoute(page: NewRealmRoute.page, path: '/realms/new'), | ||||
|     AutoRoute(page: EditRealmRoute.page, path: '/realms/:slug/edit'), | ||||
|     AutoRoute(page: NewChatRoute.page, path: '/chat/new'), | ||||
|     AutoRoute(page: EditChatRoute.page, path: '/chat/:id/edit'), | ||||
|     AutoRoute(page: ChatRoomRoute.page, path: '/chat/:id'), | ||||
|   ]; | ||||
| } | ||||
|   | ||||
| @@ -9,30 +9,32 @@ | ||||
| // coverage:ignore-file | ||||
|  | ||||
| // ignore_for_file: no_leading_underscores_for_library_prefixes | ||||
| import 'package:auto_route/auto_route.dart' as _i12; | ||||
| import 'package:flutter/material.dart' as _i13; | ||||
| import 'package:island/models/post.dart' as _i14; | ||||
| import 'package:auto_route/auto_route.dart' as _i14; | ||||
| import 'package:flutter/material.dart' as _i15; | ||||
| import 'package:island/models/post.dart' as _i16; | ||||
| import 'package:island/screens/account.dart' as _i1; | ||||
| import 'package:island/screens/account/me.dart' as _i7; | ||||
| import 'package:island/screens/account/me/publishers.dart' as _i3; | ||||
| import 'package:island/screens/account/me/update.dart' as _i11; | ||||
| import 'package:island/screens/auth/create_account.dart' as _i2; | ||||
| import 'package:island/screens/auth/login.dart' as _i6; | ||||
| import 'package:island/screens/auth/tabs.dart' as _i10; | ||||
| import 'package:island/screens/explore.dart' as _i5; | ||||
| import 'package:island/screens/posts/compose.dart' as _i8; | ||||
| import 'package:island/screens/posts/detail.dart' as _i9; | ||||
| import 'package:island/screens/realm/realms.dart' as _i4; | ||||
| import 'package:island/screens/account/me.dart' as _i9; | ||||
| import 'package:island/screens/account/me/publishers.dart' as _i5; | ||||
| import 'package:island/screens/account/me/update.dart' as _i13; | ||||
| import 'package:island/screens/auth/create_account.dart' as _i4; | ||||
| import 'package:island/screens/auth/login.dart' as _i8; | ||||
| import 'package:island/screens/auth/tabs.dart' as _i12; | ||||
| import 'package:island/screens/chat/chat.dart' as _i2; | ||||
| import 'package:island/screens/chat/room.dart' as _i3; | ||||
| import 'package:island/screens/explore.dart' as _i7; | ||||
| import 'package:island/screens/posts/compose.dart' as _i10; | ||||
| import 'package:island/screens/posts/detail.dart' as _i11; | ||||
| import 'package:island/screens/realm/realms.dart' as _i6; | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i1.AccountScreen] | ||||
| class AccountRoute extends _i12.PageRouteInfo<void> { | ||||
|   const AccountRoute({List<_i12.PageRouteInfo>? children}) | ||||
| class AccountRoute extends _i14.PageRouteInfo<void> { | ||||
|   const AccountRoute({List<_i14.PageRouteInfo>? children}) | ||||
|     : super(AccountRoute.name, initialChildren: children); | ||||
|  | ||||
|   static const String name = 'AccountRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       return const _i1.AccountScreen(); | ||||
| @@ -41,28 +43,123 @@ class AccountRoute extends _i12.PageRouteInfo<void> { | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i2.CreateAccountScreen] | ||||
| class CreateAccountRoute extends _i12.PageRouteInfo<void> { | ||||
|   const CreateAccountRoute({List<_i12.PageRouteInfo>? children}) | ||||
|     : super(CreateAccountRoute.name, initialChildren: children); | ||||
| /// [_i2.ChatListScreen] | ||||
| class ChatListRoute extends _i14.PageRouteInfo<void> { | ||||
|   const ChatListRoute({List<_i14.PageRouteInfo>? children}) | ||||
|     : super(ChatListRoute.name, initialChildren: children); | ||||
|  | ||||
|   static const String name = 'CreateAccountRoute'; | ||||
|   static const String name = 'ChatListRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       return const _i2.CreateAccountScreen(); | ||||
|       return const _i2.ChatListScreen(); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i3.EditPublisherScreen] | ||||
| class EditPublisherRoute extends _i12.PageRouteInfo<EditPublisherRouteArgs> { | ||||
| /// [_i3.ChatRoomScreen] | ||||
| class ChatRoomRoute extends _i14.PageRouteInfo<ChatRoomRouteArgs> { | ||||
|   ChatRoomRoute({ | ||||
|     _i15.Key? key, | ||||
|     required int id, | ||||
|     List<_i14.PageRouteInfo>? children, | ||||
|   }) : super( | ||||
|          ChatRoomRoute.name, | ||||
|          args: ChatRoomRouteArgs(key: key, id: id), | ||||
|          rawPathParams: {'id': id}, | ||||
|          initialChildren: children, | ||||
|        ); | ||||
|  | ||||
|   static const String name = 'ChatRoomRoute'; | ||||
|  | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       final pathParams = data.inheritedPathParams; | ||||
|       final args = data.argsAs<ChatRoomRouteArgs>( | ||||
|         orElse: () => ChatRoomRouteArgs(id: pathParams.getInt('id')), | ||||
|       ); | ||||
|       return _i3.ChatRoomScreen(key: args.key, id: args.id); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
|  | ||||
| class ChatRoomRouteArgs { | ||||
|   const ChatRoomRouteArgs({this.key, required this.id}); | ||||
|  | ||||
|   final _i15.Key? key; | ||||
|  | ||||
|   final int id; | ||||
|  | ||||
|   @override | ||||
|   String toString() { | ||||
|     return 'ChatRoomRouteArgs{key: $key, id: $id}'; | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i4.CreateAccountScreen] | ||||
| class CreateAccountRoute extends _i14.PageRouteInfo<void> { | ||||
|   const CreateAccountRoute({List<_i14.PageRouteInfo>? children}) | ||||
|     : super(CreateAccountRoute.name, initialChildren: children); | ||||
|  | ||||
|   static const String name = 'CreateAccountRoute'; | ||||
|  | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       return const _i4.CreateAccountScreen(); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i2.EditChatScreen] | ||||
| class EditChatRoute extends _i14.PageRouteInfo<EditChatRouteArgs> { | ||||
|   EditChatRoute({_i15.Key? key, int? id, List<_i14.PageRouteInfo>? children}) | ||||
|     : super( | ||||
|         EditChatRoute.name, | ||||
|         args: EditChatRouteArgs(key: key, id: id), | ||||
|         rawPathParams: {'id': id}, | ||||
|         initialChildren: children, | ||||
|       ); | ||||
|  | ||||
|   static const String name = 'EditChatRoute'; | ||||
|  | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       final pathParams = data.inheritedPathParams; | ||||
|       final args = data.argsAs<EditChatRouteArgs>( | ||||
|         orElse: () => EditChatRouteArgs(id: pathParams.optInt('id')), | ||||
|       ); | ||||
|       return _i2.EditChatScreen(key: args.key, id: args.id); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
|  | ||||
| class EditChatRouteArgs { | ||||
|   const EditChatRouteArgs({this.key, this.id}); | ||||
|  | ||||
|   final _i15.Key? key; | ||||
|  | ||||
|   final int? id; | ||||
|  | ||||
|   @override | ||||
|   String toString() { | ||||
|     return 'EditChatRouteArgs{key: $key, id: $id}'; | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i5.EditPublisherScreen] | ||||
| class EditPublisherRoute extends _i14.PageRouteInfo<EditPublisherRouteArgs> { | ||||
|   EditPublisherRoute({ | ||||
|     _i13.Key? key, | ||||
|     _i15.Key? key, | ||||
|     String? name, | ||||
|     List<_i12.PageRouteInfo>? children, | ||||
|     List<_i14.PageRouteInfo>? children, | ||||
|   }) : super( | ||||
|          EditPublisherRoute.name, | ||||
|          args: EditPublisherRouteArgs(key: key, name: name), | ||||
| @@ -72,14 +169,14 @@ class EditPublisherRoute extends _i12.PageRouteInfo<EditPublisherRouteArgs> { | ||||
|  | ||||
|   static const String name = 'EditPublisherRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       final pathParams = data.inheritedPathParams; | ||||
|       final args = data.argsAs<EditPublisherRouteArgs>( | ||||
|         orElse: () => EditPublisherRouteArgs(name: pathParams.optString('id')), | ||||
|       ); | ||||
|       return _i3.EditPublisherScreen(key: args.key, name: args.name); | ||||
|       return _i5.EditPublisherScreen(key: args.key, name: args.name); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
| @@ -87,7 +184,7 @@ class EditPublisherRoute extends _i12.PageRouteInfo<EditPublisherRouteArgs> { | ||||
| class EditPublisherRouteArgs { | ||||
|   const EditPublisherRouteArgs({this.key, this.name}); | ||||
|  | ||||
|   final _i13.Key? key; | ||||
|   final _i15.Key? key; | ||||
|  | ||||
|   final String? name; | ||||
|  | ||||
| @@ -98,12 +195,12 @@ class EditPublisherRouteArgs { | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i4.EditRealmScreen] | ||||
| class EditRealmRoute extends _i12.PageRouteInfo<EditRealmRouteArgs> { | ||||
| /// [_i6.EditRealmScreen] | ||||
| class EditRealmRoute extends _i14.PageRouteInfo<EditRealmRouteArgs> { | ||||
|   EditRealmRoute({ | ||||
|     _i13.Key? key, | ||||
|     _i15.Key? key, | ||||
|     String? slug, | ||||
|     List<_i12.PageRouteInfo>? children, | ||||
|     List<_i14.PageRouteInfo>? children, | ||||
|   }) : super( | ||||
|          EditRealmRoute.name, | ||||
|          args: EditRealmRouteArgs(key: key, slug: slug), | ||||
| @@ -113,14 +210,14 @@ class EditRealmRoute extends _i12.PageRouteInfo<EditRealmRouteArgs> { | ||||
|  | ||||
|   static const String name = 'EditRealmRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       final pathParams = data.inheritedPathParams; | ||||
|       final args = data.argsAs<EditRealmRouteArgs>( | ||||
|         orElse: () => EditRealmRouteArgs(slug: pathParams.optString('slug')), | ||||
|       ); | ||||
|       return _i4.EditRealmScreen(key: args.key, slug: args.slug); | ||||
|       return _i6.EditRealmScreen(key: args.key, slug: args.slug); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
| @@ -128,7 +225,7 @@ class EditRealmRoute extends _i12.PageRouteInfo<EditRealmRouteArgs> { | ||||
| class EditRealmRouteArgs { | ||||
|   const EditRealmRouteArgs({this.key, this.slug}); | ||||
|  | ||||
|   final _i13.Key? key; | ||||
|   final _i15.Key? key; | ||||
|  | ||||
|   final String? slug; | ||||
|  | ||||
| @@ -139,108 +236,124 @@ class EditRealmRouteArgs { | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i5.ExploreScreen] | ||||
| class ExploreRoute extends _i12.PageRouteInfo<void> { | ||||
|   const ExploreRoute({List<_i12.PageRouteInfo>? children}) | ||||
| /// [_i7.ExploreScreen] | ||||
| class ExploreRoute extends _i14.PageRouteInfo<void> { | ||||
|   const ExploreRoute({List<_i14.PageRouteInfo>? children}) | ||||
|     : super(ExploreRoute.name, initialChildren: children); | ||||
|  | ||||
|   static const String name = 'ExploreRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       return const _i5.ExploreScreen(); | ||||
|       return const _i7.ExploreScreen(); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i6.LoginScreen] | ||||
| class LoginRoute extends _i12.PageRouteInfo<void> { | ||||
|   const LoginRoute({List<_i12.PageRouteInfo>? children}) | ||||
| /// [_i8.LoginScreen] | ||||
| class LoginRoute extends _i14.PageRouteInfo<void> { | ||||
|   const LoginRoute({List<_i14.PageRouteInfo>? children}) | ||||
|     : super(LoginRoute.name, initialChildren: children); | ||||
|  | ||||
|   static const String name = 'LoginRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       return const _i6.LoginScreen(); | ||||
|       return const _i8.LoginScreen(); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i3.ManagedPublisherScreen] | ||||
| class ManagedPublisherRoute extends _i12.PageRouteInfo<void> { | ||||
|   const ManagedPublisherRoute({List<_i12.PageRouteInfo>? children}) | ||||
| /// [_i5.ManagedPublisherScreen] | ||||
| class ManagedPublisherRoute extends _i14.PageRouteInfo<void> { | ||||
|   const ManagedPublisherRoute({List<_i14.PageRouteInfo>? children}) | ||||
|     : super(ManagedPublisherRoute.name, initialChildren: children); | ||||
|  | ||||
|   static const String name = 'ManagedPublisherRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       return const _i3.ManagedPublisherScreen(); | ||||
|       return const _i5.ManagedPublisherScreen(); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i7.MyselfProfileScreen] | ||||
| class MyselfProfileRoute extends _i12.PageRouteInfo<void> { | ||||
|   const MyselfProfileRoute({List<_i12.PageRouteInfo>? children}) | ||||
| /// [_i9.MyselfProfileScreen] | ||||
| class MyselfProfileRoute extends _i14.PageRouteInfo<void> { | ||||
|   const MyselfProfileRoute({List<_i14.PageRouteInfo>? children}) | ||||
|     : super(MyselfProfileRoute.name, initialChildren: children); | ||||
|  | ||||
|   static const String name = 'MyselfProfileRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       return const _i7.MyselfProfileScreen(); | ||||
|       return const _i9.MyselfProfileScreen(); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i3.NewPublisherScreen] | ||||
| class NewPublisherRoute extends _i12.PageRouteInfo<void> { | ||||
|   const NewPublisherRoute({List<_i12.PageRouteInfo>? children}) | ||||
| /// [_i2.NewChatScreen] | ||||
| class NewChatRoute extends _i14.PageRouteInfo<void> { | ||||
|   const NewChatRoute({List<_i14.PageRouteInfo>? children}) | ||||
|     : super(NewChatRoute.name, initialChildren: children); | ||||
|  | ||||
|   static const String name = 'NewChatRoute'; | ||||
|  | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       return const _i2.NewChatScreen(); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i5.NewPublisherScreen] | ||||
| class NewPublisherRoute extends _i14.PageRouteInfo<void> { | ||||
|   const NewPublisherRoute({List<_i14.PageRouteInfo>? children}) | ||||
|     : super(NewPublisherRoute.name, initialChildren: children); | ||||
|  | ||||
|   static const String name = 'NewPublisherRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       return const _i3.NewPublisherScreen(); | ||||
|       return const _i5.NewPublisherScreen(); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i4.NewRealmScreen] | ||||
| class NewRealmRoute extends _i12.PageRouteInfo<void> { | ||||
|   const NewRealmRoute({List<_i12.PageRouteInfo>? children}) | ||||
| /// [_i6.NewRealmScreen] | ||||
| class NewRealmRoute extends _i14.PageRouteInfo<void> { | ||||
|   const NewRealmRoute({List<_i14.PageRouteInfo>? children}) | ||||
|     : super(NewRealmRoute.name, initialChildren: children); | ||||
|  | ||||
|   static const String name = 'NewRealmRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       return const _i4.NewRealmScreen(); | ||||
|       return const _i6.NewRealmScreen(); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i8.PostComposeScreen] | ||||
| class PostComposeRoute extends _i12.PageRouteInfo<PostComposeRouteArgs> { | ||||
| /// [_i10.PostComposeScreen] | ||||
| class PostComposeRoute extends _i14.PageRouteInfo<PostComposeRouteArgs> { | ||||
|   PostComposeRoute({ | ||||
|     _i13.Key? key, | ||||
|     _i14.SnPost? originalPost, | ||||
|     List<_i12.PageRouteInfo>? children, | ||||
|     _i15.Key? key, | ||||
|     _i16.SnPost? originalPost, | ||||
|     List<_i14.PageRouteInfo>? children, | ||||
|   }) : super( | ||||
|          PostComposeRoute.name, | ||||
|          args: PostComposeRouteArgs(key: key, originalPost: originalPost), | ||||
| @@ -249,13 +362,13 @@ class PostComposeRoute extends _i12.PageRouteInfo<PostComposeRouteArgs> { | ||||
|  | ||||
|   static const String name = 'PostComposeRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       final args = data.argsAs<PostComposeRouteArgs>( | ||||
|         orElse: () => const PostComposeRouteArgs(), | ||||
|       ); | ||||
|       return _i8.PostComposeScreen( | ||||
|       return _i10.PostComposeScreen( | ||||
|         key: args.key, | ||||
|         originalPost: args.originalPost, | ||||
|       ); | ||||
| @@ -266,9 +379,9 @@ class PostComposeRoute extends _i12.PageRouteInfo<PostComposeRouteArgs> { | ||||
| class PostComposeRouteArgs { | ||||
|   const PostComposeRouteArgs({this.key, this.originalPost}); | ||||
|  | ||||
|   final _i13.Key? key; | ||||
|   final _i15.Key? key; | ||||
|  | ||||
|   final _i14.SnPost? originalPost; | ||||
|   final _i16.SnPost? originalPost; | ||||
|  | ||||
|   @override | ||||
|   String toString() { | ||||
| @@ -277,12 +390,12 @@ class PostComposeRouteArgs { | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i9.PostDetailScreen] | ||||
| class PostDetailRoute extends _i12.PageRouteInfo<PostDetailRouteArgs> { | ||||
| /// [_i11.PostDetailScreen] | ||||
| class PostDetailRoute extends _i14.PageRouteInfo<PostDetailRouteArgs> { | ||||
|   PostDetailRoute({ | ||||
|     _i13.Key? key, | ||||
|     _i15.Key? key, | ||||
|     required int id, | ||||
|     List<_i12.PageRouteInfo>? children, | ||||
|     List<_i14.PageRouteInfo>? children, | ||||
|   }) : super( | ||||
|          PostDetailRoute.name, | ||||
|          args: PostDetailRouteArgs(key: key, id: id), | ||||
| @@ -292,14 +405,14 @@ class PostDetailRoute extends _i12.PageRouteInfo<PostDetailRouteArgs> { | ||||
|  | ||||
|   static const String name = 'PostDetailRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       final pathParams = data.inheritedPathParams; | ||||
|       final args = data.argsAs<PostDetailRouteArgs>( | ||||
|         orElse: () => PostDetailRouteArgs(id: pathParams.getInt('id')), | ||||
|       ); | ||||
|       return _i9.PostDetailScreen(key: args.key, id: args.id); | ||||
|       return _i11.PostDetailScreen(key: args.key, id: args.id); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
| @@ -307,7 +420,7 @@ class PostDetailRoute extends _i12.PageRouteInfo<PostDetailRouteArgs> { | ||||
| class PostDetailRouteArgs { | ||||
|   const PostDetailRouteArgs({this.key, required this.id}); | ||||
|  | ||||
|   final _i13.Key? key; | ||||
|   final _i15.Key? key; | ||||
|  | ||||
|   final int id; | ||||
|  | ||||
| @@ -318,12 +431,12 @@ class PostDetailRouteArgs { | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i8.PostEditScreen] | ||||
| class PostEditRoute extends _i12.PageRouteInfo<PostEditRouteArgs> { | ||||
| /// [_i10.PostEditScreen] | ||||
| class PostEditRoute extends _i14.PageRouteInfo<PostEditRouteArgs> { | ||||
|   PostEditRoute({ | ||||
|     _i13.Key? key, | ||||
|     _i15.Key? key, | ||||
|     required int id, | ||||
|     List<_i12.PageRouteInfo>? children, | ||||
|     List<_i14.PageRouteInfo>? children, | ||||
|   }) : super( | ||||
|          PostEditRoute.name, | ||||
|          args: PostEditRouteArgs(key: key, id: id), | ||||
| @@ -333,14 +446,14 @@ class PostEditRoute extends _i12.PageRouteInfo<PostEditRouteArgs> { | ||||
|  | ||||
|   static const String name = 'PostEditRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       final pathParams = data.inheritedPathParams; | ||||
|       final args = data.argsAs<PostEditRouteArgs>( | ||||
|         orElse: () => PostEditRouteArgs(id: pathParams.getInt('id')), | ||||
|       ); | ||||
|       return _i8.PostEditScreen(key: args.key, id: args.id); | ||||
|       return _i10.PostEditScreen(key: args.key, id: args.id); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
| @@ -348,7 +461,7 @@ class PostEditRoute extends _i12.PageRouteInfo<PostEditRouteArgs> { | ||||
| class PostEditRouteArgs { | ||||
|   const PostEditRouteArgs({this.key, required this.id}); | ||||
|  | ||||
|   final _i13.Key? key; | ||||
|   final _i15.Key? key; | ||||
|  | ||||
|   final int id; | ||||
|  | ||||
| @@ -359,49 +472,49 @@ class PostEditRouteArgs { | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i4.RealmListScreen] | ||||
| class RealmListRoute extends _i12.PageRouteInfo<void> { | ||||
|   const RealmListRoute({List<_i12.PageRouteInfo>? children}) | ||||
| /// [_i6.RealmListScreen] | ||||
| class RealmListRoute extends _i14.PageRouteInfo<void> { | ||||
|   const RealmListRoute({List<_i14.PageRouteInfo>? children}) | ||||
|     : super(RealmListRoute.name, initialChildren: children); | ||||
|  | ||||
|   static const String name = 'RealmListRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       return const _i4.RealmListScreen(); | ||||
|       return const _i6.RealmListScreen(); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i10.TabsScreen] | ||||
| class TabsRoute extends _i12.PageRouteInfo<void> { | ||||
|   const TabsRoute({List<_i12.PageRouteInfo>? children}) | ||||
| /// [_i12.TabsScreen] | ||||
| class TabsRoute extends _i14.PageRouteInfo<void> { | ||||
|   const TabsRoute({List<_i14.PageRouteInfo>? children}) | ||||
|     : super(TabsRoute.name, initialChildren: children); | ||||
|  | ||||
|   static const String name = 'TabsRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       return const _i10.TabsScreen(); | ||||
|       return const _i12.TabsScreen(); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
|  | ||||
| /// generated route for | ||||
| /// [_i11.UpdateProfileScreen] | ||||
| class UpdateProfileRoute extends _i12.PageRouteInfo<void> { | ||||
|   const UpdateProfileRoute({List<_i12.PageRouteInfo>? children}) | ||||
| /// [_i13.UpdateProfileScreen] | ||||
| class UpdateProfileRoute extends _i14.PageRouteInfo<void> { | ||||
|   const UpdateProfileRoute({List<_i14.PageRouteInfo>? children}) | ||||
|     : super(UpdateProfileRoute.name, initialChildren: children); | ||||
|  | ||||
|   static const String name = 'UpdateProfileRoute'; | ||||
|  | ||||
|   static _i12.PageInfo page = _i12.PageInfo( | ||||
|   static _i14.PageInfo page = _i14.PageInfo( | ||||
|     name, | ||||
|     builder: (data) { | ||||
|       return const _i11.UpdateProfileScreen(); | ||||
|       return const _i13.UpdateProfileScreen(); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
|   | ||||
| @@ -11,7 +11,12 @@ class TabsScreen extends StatelessWidget { | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return AutoTabsRouter.pageView( | ||||
|       routes: const [ExploreRoute(), RealmListRoute(), AccountRoute()], | ||||
|       routes: const [ | ||||
|         ExploreRoute(), | ||||
|         ChatListRoute(), | ||||
|         RealmListRoute(), | ||||
|         AccountRoute(), | ||||
|       ], | ||||
|       builder: (context, child, _) { | ||||
|         final tabsRouter = AutoTabsRouter.of(context); | ||||
|         return Scaffold( | ||||
| @@ -26,6 +31,10 @@ class TabsScreen extends StatelessWidget { | ||||
|                 label: 'explore'.tr(), | ||||
|                 icon: const Icon(Symbols.explore), | ||||
|               ), | ||||
|               NavigationDestination( | ||||
|                 label: 'chat'.tr(), | ||||
|                 icon: const Icon(Symbols.chat), | ||||
|               ), | ||||
|               NavigationDestination( | ||||
|                 label: 'realms'.tr(), | ||||
|                 icon: const Icon(Symbols.workspaces), | ||||
|   | ||||
							
								
								
									
										276
									
								
								lib/screens/chat/chat.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										276
									
								
								lib/screens/chat/chat.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,276 @@ | ||||
| import 'package:auto_route/auto_route.dart'; | ||||
| import 'package:dio/dio.dart'; | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_hooks/flutter_hooks.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:image_picker/image_picker.dart'; | ||||
| import 'package:island/models/chat.dart'; | ||||
| import 'package:island/models/file.dart'; | ||||
| import 'package:island/pods/config.dart'; | ||||
| import 'package:island/pods/network.dart'; | ||||
| import 'package:island/route.gr.dart'; | ||||
| import 'package:island/services/file.dart'; | ||||
| import 'package:island/widgets/alert.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:island/widgets/content/cloud_files.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
|  | ||||
| part 'chat.g.dart'; | ||||
|  | ||||
| @riverpod | ||||
| Future<List<SnChat>> chatroomsJoined(Ref ref) async { | ||||
|   final client = ref.watch(apiClientProvider); | ||||
|   final resp = await client.get('/chat'); | ||||
|   return resp.data.map((e) => SnChat.fromJson(e)).cast<SnChat>().toList(); | ||||
| } | ||||
|  | ||||
| @RoutePage() | ||||
| class ChatListScreen extends HookConsumerWidget { | ||||
|   const ChatListScreen({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final chats = ref.watch(chatroomsJoinedProvider); | ||||
|  | ||||
|     return AppScaffold( | ||||
|       appBar: AppBar(title: Text('chat').tr()), | ||||
|       floatingActionButton: FloatingActionButton( | ||||
|         onPressed: () { | ||||
|           context.pushRoute(NewChatRoute()); | ||||
|         }, | ||||
|         child: const Icon(Symbols.add), | ||||
|       ), | ||||
|       body: chats.when( | ||||
|         data: | ||||
|             (items) => RefreshIndicator( | ||||
|               onRefresh: | ||||
|                   () => Future.sync(() { | ||||
|                     ref.invalidate(chatroomsJoinedProvider); | ||||
|                   }), | ||||
|               child: ListView.builder( | ||||
|                 padding: EdgeInsets.zero, | ||||
|                 itemCount: items.length, | ||||
|                 itemBuilder: (context, index) { | ||||
|                   final item = items[index]; | ||||
|                   return ListTile( | ||||
|                     leading: | ||||
|                         item.picture == null | ||||
|                             ? CircleAvatar( | ||||
|                               child: Text(item.name[0].toUpperCase()), | ||||
|                             ) | ||||
|                             : ProfilePictureWidget(item: item.picture), | ||||
|                     title: Text(item.name), | ||||
|                     subtitle: Text(item.description), | ||||
|                     onTap: () { | ||||
|                       context.pushRoute(ChatRoomRoute(id: item.id)); | ||||
|                     }, | ||||
|                   ); | ||||
|                 }, | ||||
|               ), | ||||
|             ), | ||||
|         loading: () => const Center(child: CircularProgressIndicator()), | ||||
|         error: (error, stack) => Center(child: Text('Error: $error')), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @riverpod | ||||
| Future<SnChat?> chatroom(Ref ref, int? identifier) async { | ||||
|   if (identifier == null) return null; | ||||
|   final client = ref.watch(apiClientProvider); | ||||
|   final resp = await client.get('/chat/$identifier'); | ||||
|   return SnChat.fromJson(resp.data); | ||||
| } | ||||
|  | ||||
| @RoutePage() | ||||
| class NewChatScreen extends StatelessWidget { | ||||
|   const NewChatScreen({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return EditChatScreen(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @RoutePage() | ||||
| class EditChatScreen extends HookConsumerWidget { | ||||
|   final int? id; | ||||
|   const EditChatScreen({super.key, @PathParam("id") this.id}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final formKey = useMemoized(() => GlobalKey<FormState>(), []); | ||||
|  | ||||
|     final submitting = useState(false); | ||||
|  | ||||
|     final nameController = useTextEditingController(); | ||||
|     final descriptionController = useTextEditingController(); | ||||
|     final picture = useState<SnCloudFile?>(null); | ||||
|     final background = useState<SnCloudFile?>(null); | ||||
|  | ||||
|     final chat = ref.watch(chatroomProvider(id)); | ||||
|  | ||||
|     useEffect(() { | ||||
|       if (chat.value != null) { | ||||
|         nameController.text = chat.value!.name; | ||||
|         descriptionController.text = chat.value!.description; | ||||
|         picture.value = chat.value!.picture; | ||||
|         background.value = chat.value!.background; | ||||
|       } | ||||
|       return; | ||||
|     }, [chat]); | ||||
|  | ||||
|     void setPicture(String position) async { | ||||
|       final result = await ref | ||||
|           .read(imagePickerProvider) | ||||
|           .pickImage(source: ImageSource.gallery); | ||||
|       if (result == null) return; | ||||
|  | ||||
|       submitting.value = true; | ||||
|       try { | ||||
|         final baseUrl = ref.watch(serverUrlProvider); | ||||
|         final atk = await getFreshAtk( | ||||
|           ref.watch(tokenPairProvider), | ||||
|           baseUrl, | ||||
|           onRefreshed: (atk, rtk) { | ||||
|             setTokenPair(ref.watch(sharedPreferencesProvider), atk, rtk); | ||||
|             ref.invalidate(tokenPairProvider); | ||||
|           }, | ||||
|         ); | ||||
|         if (atk == null) throw ArgumentError('Access token is null'); | ||||
|         final cloudFile = | ||||
|             await putMediaToCloud( | ||||
|               fileData: result, | ||||
|               atk: atk, | ||||
|               baseUrl: baseUrl, | ||||
|               filename: result.name, | ||||
|               mimetype: result.mimeType ?? 'image/jpeg', | ||||
|             ).future; | ||||
|         if (cloudFile == null) { | ||||
|           throw ArgumentError('Failed to upload the file...'); | ||||
|         } | ||||
|         switch (position) { | ||||
|           case 'picture': | ||||
|             picture.value = cloudFile; | ||||
|           case 'background': | ||||
|             background.value = cloudFile; | ||||
|         } | ||||
|       } catch (err) { | ||||
|         showErrorAlert(err); | ||||
|       } finally { | ||||
|         submitting.value = false; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     Future<void> performAction() async { | ||||
|       if (!formKey.currentState!.validate()) return; | ||||
|  | ||||
|       submitting.value = true; | ||||
|       try { | ||||
|         final client = ref.watch(apiClientProvider); | ||||
|         final resp = await client.request( | ||||
|           id == null ? '/chat' : '/chat/$id', | ||||
|           data: { | ||||
|             'name': nameController.text, | ||||
|             'description': descriptionController.text, | ||||
|             'background_id': background.value?.id, | ||||
|             'picture_id': picture.value?.id, | ||||
|           }, | ||||
|           options: Options(method: id == null ? 'POST' : 'PATCH'), | ||||
|         ); | ||||
|         if (context.mounted) { | ||||
|           context.maybePop(SnChat.fromJson(resp.data)); | ||||
|         } | ||||
|       } catch (err) { | ||||
|         showErrorAlert(err); | ||||
|       } finally { | ||||
|         submitting.value = false; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     return AppScaffold( | ||||
|       appBar: AppBar( | ||||
|         title: Text(id == null ? 'createChatRoom' : 'editChatRoom').tr(), | ||||
|         leading: const PageBackButton(), | ||||
|       ), | ||||
|       body: Column( | ||||
|         children: [ | ||||
|           AspectRatio( | ||||
|             aspectRatio: 16 / 7, | ||||
|             child: Stack( | ||||
|               clipBehavior: Clip.none, | ||||
|               fit: StackFit.expand, | ||||
|               children: [ | ||||
|                 GestureDetector( | ||||
|                   child: Container( | ||||
|                     color: Theme.of(context).colorScheme.surfaceContainerHigh, | ||||
|                     child: | ||||
|                         background.value != null | ||||
|                             ? CloudFileWidget( | ||||
|                               item: background.value!, | ||||
|                               fit: BoxFit.cover, | ||||
|                             ) | ||||
|                             : const SizedBox.shrink(), | ||||
|                   ), | ||||
|                   onTap: () { | ||||
|                     setPicture('background'); | ||||
|                   }, | ||||
|                 ), | ||||
|                 Positioned( | ||||
|                   left: 20, | ||||
|                   bottom: -32, | ||||
|                   child: GestureDetector( | ||||
|                     child: ProfilePictureWidget( | ||||
|                       item: picture.value, | ||||
|                       radius: 40, | ||||
|                       fallbackIcon: Symbols.group, | ||||
|                     ), | ||||
|                     onTap: () { | ||||
|                       setPicture('picture'); | ||||
|                     }, | ||||
|                   ), | ||||
|                 ), | ||||
|               ], | ||||
|             ), | ||||
|           ).padding(bottom: 32), | ||||
|           Form( | ||||
|             key: formKey, | ||||
|             child: Column( | ||||
|               crossAxisAlignment: CrossAxisAlignment.start, | ||||
|               children: [ | ||||
|                 TextFormField( | ||||
|                   controller: nameController, | ||||
|                   decoration: const InputDecoration(labelText: 'Name'), | ||||
|                   onTapOutside: | ||||
|                       (_) => FocusManager.instance.primaryFocus?.unfocus(), | ||||
|                 ), | ||||
|                 const SizedBox(height: 16), | ||||
|                 TextFormField( | ||||
|                   controller: descriptionController, | ||||
|                   decoration: const InputDecoration(labelText: 'Description'), | ||||
|                   minLines: 3, | ||||
|                   maxLines: null, | ||||
|                   onTapOutside: | ||||
|                       (_) => FocusManager.instance.primaryFocus?.unfocus(), | ||||
|                 ), | ||||
|                 const SizedBox(height: 16), | ||||
|                 Align( | ||||
|                   alignment: Alignment.centerRight, | ||||
|                   child: TextButton.icon( | ||||
|                     onPressed: submitting.value ? null : performAction, | ||||
|                     label: const Text('Save'), | ||||
|                     icon: const Icon(Symbols.save), | ||||
|                   ), | ||||
|                 ), | ||||
|               ], | ||||
|             ).padding(all: 24), | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										167
									
								
								lib/screens/chat/chat.g.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								lib/screens/chat/chat.g.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,167 @@ | ||||
| // GENERATED CODE - DO NOT MODIFY BY HAND | ||||
|  | ||||
| part of 'chat.dart'; | ||||
|  | ||||
| // ************************************************************************** | ||||
| // RiverpodGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| String _$chatroomsJoinedHash() => r'3a2db4159663c54dfd7bc40519e2faa6df69b41f'; | ||||
|  | ||||
| /// See also [chatroomsJoined]. | ||||
| @ProviderFor(chatroomsJoined) | ||||
| final chatroomsJoinedProvider = | ||||
|     AutoDisposeFutureProvider<List<SnChat>>.internal( | ||||
|       chatroomsJoined, | ||||
|       name: r'chatroomsJoinedProvider', | ||||
|       debugGetCreateSourceHash: | ||||
|           const bool.fromEnvironment('dart.vm.product') | ||||
|               ? null | ||||
|               : _$chatroomsJoinedHash, | ||||
|       dependencies: null, | ||||
|       allTransitiveDependencies: null, | ||||
|     ); | ||||
|  | ||||
| @Deprecated('Will be removed in 3.0. Use Ref instead') | ||||
| // ignore: unused_element | ||||
| typedef ChatroomsJoinedRef = AutoDisposeFutureProviderRef<List<SnChat>>; | ||||
| String _$chatroomHash() => r'27bd4cb49326bb2f2eac7d7db9db7f610e21afb2'; | ||||
|  | ||||
| /// Copied from Dart SDK | ||||
| class _SystemHash { | ||||
|   _SystemHash._(); | ||||
|  | ||||
|   static int combine(int hash, int value) { | ||||
|     // ignore: parameter_assignments | ||||
|     hash = 0x1fffffff & (hash + value); | ||||
|     // ignore: parameter_assignments | ||||
|     hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); | ||||
|     return hash ^ (hash >> 6); | ||||
|   } | ||||
|  | ||||
|   static int finish(int hash) { | ||||
|     // ignore: parameter_assignments | ||||
|     hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); | ||||
|     // ignore: parameter_assignments | ||||
|     hash = hash ^ (hash >> 11); | ||||
|     return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// See also [chatroom]. | ||||
| @ProviderFor(chatroom) | ||||
| const chatroomProvider = ChatroomFamily(); | ||||
|  | ||||
| /// See also [chatroom]. | ||||
| class ChatroomFamily extends Family<AsyncValue<SnChat?>> { | ||||
|   /// See also [chatroom]. | ||||
|   const ChatroomFamily(); | ||||
|  | ||||
|   /// See also [chatroom]. | ||||
|   ChatroomProvider call(int? identifier) { | ||||
|     return ChatroomProvider(identifier); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   ChatroomProvider getProviderOverride(covariant ChatroomProvider provider) { | ||||
|     return call(provider.identifier); | ||||
|   } | ||||
|  | ||||
|   static const Iterable<ProviderOrFamily>? _dependencies = null; | ||||
|  | ||||
|   @override | ||||
|   Iterable<ProviderOrFamily>? get dependencies => _dependencies; | ||||
|  | ||||
|   static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null; | ||||
|  | ||||
|   @override | ||||
|   Iterable<ProviderOrFamily>? get allTransitiveDependencies => | ||||
|       _allTransitiveDependencies; | ||||
|  | ||||
|   @override | ||||
|   String? get name => r'chatroomProvider'; | ||||
| } | ||||
|  | ||||
| /// See also [chatroom]. | ||||
| class ChatroomProvider extends AutoDisposeFutureProvider<SnChat?> { | ||||
|   /// See also [chatroom]. | ||||
|   ChatroomProvider(int? identifier) | ||||
|     : this._internal( | ||||
|         (ref) => chatroom(ref as ChatroomRef, identifier), | ||||
|         from: chatroomProvider, | ||||
|         name: r'chatroomProvider', | ||||
|         debugGetCreateSourceHash: | ||||
|             const bool.fromEnvironment('dart.vm.product') | ||||
|                 ? null | ||||
|                 : _$chatroomHash, | ||||
|         dependencies: ChatroomFamily._dependencies, | ||||
|         allTransitiveDependencies: ChatroomFamily._allTransitiveDependencies, | ||||
|         identifier: identifier, | ||||
|       ); | ||||
|  | ||||
|   ChatroomProvider._internal( | ||||
|     super._createNotifier, { | ||||
|     required super.name, | ||||
|     required super.dependencies, | ||||
|     required super.allTransitiveDependencies, | ||||
|     required super.debugGetCreateSourceHash, | ||||
|     required super.from, | ||||
|     required this.identifier, | ||||
|   }) : super.internal(); | ||||
|  | ||||
|   final int? identifier; | ||||
|  | ||||
|   @override | ||||
|   Override overrideWith( | ||||
|     FutureOr<SnChat?> Function(ChatroomRef provider) create, | ||||
|   ) { | ||||
|     return ProviderOverride( | ||||
|       origin: this, | ||||
|       override: ChatroomProvider._internal( | ||||
|         (ref) => create(ref as ChatroomRef), | ||||
|         from: from, | ||||
|         name: null, | ||||
|         dependencies: null, | ||||
|         allTransitiveDependencies: null, | ||||
|         debugGetCreateSourceHash: null, | ||||
|         identifier: identifier, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   AutoDisposeFutureProviderElement<SnChat?> createElement() { | ||||
|     return _ChatroomProviderElement(this); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   bool operator ==(Object other) { | ||||
|     return other is ChatroomProvider && other.identifier == identifier; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   int get hashCode { | ||||
|     var hash = _SystemHash.combine(0, runtimeType.hashCode); | ||||
|     hash = _SystemHash.combine(hash, identifier.hashCode); | ||||
|  | ||||
|     return _SystemHash.finish(hash); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @Deprecated('Will be removed in 3.0. Use Ref instead') | ||||
| // ignore: unused_element | ||||
| mixin ChatroomRef on AutoDisposeFutureProviderRef<SnChat?> { | ||||
|   /// The parameter `identifier` of this provider. | ||||
|   int? get identifier; | ||||
| } | ||||
|  | ||||
| class _ChatroomProviderElement extends AutoDisposeFutureProviderElement<SnChat?> | ||||
|     with ChatroomRef { | ||||
|   _ChatroomProviderElement(super.provider); | ||||
|  | ||||
|   @override | ||||
|   int? get identifier => (origin as ChatroomProvider).identifier; | ||||
| } | ||||
|  | ||||
| // ignore_for_file: type=lint | ||||
| // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package | ||||
							
								
								
									
										0
									
								
								lib/screens/chat/new_chat.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								lib/screens/chat/new_chat.dart
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										118
									
								
								lib/screens/chat/room.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								lib/screens/chat/room.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | ||||
| import 'package:auto_route/annotations.dart'; | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_hooks/flutter_hooks.dart'; | ||||
| import 'package:gap/gap.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/widgets/content/cloud_files.dart'; | ||||
| import 'package:material_symbols_icons/material_symbols_icons.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
| import 'chat.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class ChatRoomScreen extends HookConsumerWidget { | ||||
|   final int id; | ||||
|   const ChatRoomScreen({super.key, @PathParam("id") required this.id}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final chatRoom = ref.watch(chatroomProvider(id)); | ||||
|  | ||||
|     final messageController = useTextEditingController(); | ||||
|  | ||||
|     return Scaffold( | ||||
|       appBar: AppBar( | ||||
|         title: chatRoom.when( | ||||
|           data: | ||||
|               (room) => Row( | ||||
|                 spacing: 8, | ||||
|                 mainAxisAlignment: MainAxisAlignment.center, | ||||
|                 crossAxisAlignment: CrossAxisAlignment.center, | ||||
|                 children: [ | ||||
|                   SizedBox( | ||||
|                     height: 26, | ||||
|                     width: 26, | ||||
|                     child: | ||||
|                         room?.picture != null | ||||
|                             ? ProfilePictureWidget( | ||||
|                               item: room?.picture, | ||||
|                               fallbackIcon: Symbols.chat, | ||||
|                             ) | ||||
|                             : CircleAvatar( | ||||
|                               child: Text( | ||||
|                                 room?.name[0].toUpperCase() ?? '', | ||||
|                                 style: const TextStyle(fontSize: 12), | ||||
|                               ), | ||||
|                             ), | ||||
|                   ), | ||||
|                   Text(room?.name ?? 'unknown').fontSize(19).tr(), | ||||
|                 ], | ||||
|               ), | ||||
|           loading: () => const Text('Loading...'), | ||||
|           error: (_, __) => const Text('Error'), | ||||
|         ), | ||||
|         actions: [ | ||||
|           IconButton(icon: const Icon(Icons.more_vert), onPressed: () {}), | ||||
|           const Gap(8), | ||||
|         ], | ||||
|       ), | ||||
|       body: Column( | ||||
|         children: [ | ||||
|           Expanded( | ||||
|             child: chatRoom.when( | ||||
|               data: (room) => SizedBox.expand(), | ||||
|               loading: () => const Center(child: CircularProgressIndicator()), | ||||
|               error: (error, stack) => Center(child: Text('Error: $error')), | ||||
|             ), | ||||
|           ), | ||||
|           Material( | ||||
|             elevation: 2, | ||||
|             child: Container( | ||||
|               padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8), | ||||
|               decoration: BoxDecoration( | ||||
|                 color: Colors.white, | ||||
|                 boxShadow: [ | ||||
|                   BoxShadow( | ||||
|                     color: Colors.grey.withOpacity(0.2), | ||||
|                     spreadRadius: 1, | ||||
|                     blurRadius: 3, | ||||
|                   ), | ||||
|                 ], | ||||
|               ), | ||||
|               child: Row( | ||||
|                 children: [ | ||||
|                   IconButton(icon: const Icon(Icons.add), onPressed: () {}), | ||||
|                   Expanded( | ||||
|                     child: TextField( | ||||
|                       controller: messageController, | ||||
|                       decoration: InputDecoration( | ||||
|                         hintText: 'chatMessageHint'.tr( | ||||
|                           args: [chatRoom.value?.name ?? 'unknown'.tr()], | ||||
|                         ), | ||||
|                         border: OutlineInputBorder(), | ||||
|                         isDense: true, | ||||
|                         contentPadding: const EdgeInsets.symmetric( | ||||
|                           horizontal: 12, | ||||
|                           vertical: 8, | ||||
|                         ), | ||||
|                       ), | ||||
|                       maxLines: null, | ||||
|                       onTapOutside: | ||||
|                           (_) => FocusManager.instance.primaryFocus?.unfocus(), | ||||
|                     ), | ||||
|                   ), | ||||
|                   const Gap(8), | ||||
|                   IconButton( | ||||
|                     icon: const Icon(Icons.send), | ||||
|                     color: Theme.of(context).colorScheme.primary, | ||||
|                     onPressed: () {}, | ||||
|                   ), | ||||
|                 ], | ||||
|               ).padding(bottom: MediaQuery.of(context).padding.bottom), | ||||
|             ), | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user