✨ Chat room layout
This commit is contained in:
		| @@ -70,5 +70,10 @@ | |||||||
|   "name": "Name", |   "name": "Name", | ||||||
|   "description": "Description", |   "description": "Description", | ||||||
|   "slug": "Slug", |   "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: ExploreRoute.page, path: 'explore'), | ||||||
|         AutoRoute(page: AccountRoute.page, path: 'account'), |         AutoRoute(page: AccountRoute.page, path: 'account'), | ||||||
|         AutoRoute(page: RealmListRoute.page, path: 'realms'), |         AutoRoute(page: RealmListRoute.page, path: 'realms'), | ||||||
|  |         AutoRoute(page: ChatListRoute.page, path: 'chat'), | ||||||
|       ], |       ], | ||||||
|     ), |     ), | ||||||
|     AutoRoute(page: LoginRoute.page, path: '/auth/login'), |     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: PostEditRoute.page, path: '/posts/:id/edit'), | ||||||
|     AutoRoute(page: NewRealmRoute.page, path: '/realms/new'), |     AutoRoute(page: NewRealmRoute.page, path: '/realms/new'), | ||||||
|     AutoRoute(page: EditRealmRoute.page, path: '/realms/:slug/edit'), |     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 | // coverage:ignore-file | ||||||
|  |  | ||||||
| // ignore_for_file: no_leading_underscores_for_library_prefixes | // ignore_for_file: no_leading_underscores_for_library_prefixes | ||||||
| import 'package:auto_route/auto_route.dart' as _i12; | import 'package:auto_route/auto_route.dart' as _i14; | ||||||
| import 'package:flutter/material.dart' as _i13; | import 'package:flutter/material.dart' as _i15; | ||||||
| import 'package:island/models/post.dart' as _i14; | import 'package:island/models/post.dart' as _i16; | ||||||
| import 'package:island/screens/account.dart' as _i1; | import 'package:island/screens/account.dart' as _i1; | ||||||
| import 'package:island/screens/account/me.dart' as _i7; | import 'package:island/screens/account/me.dart' as _i9; | ||||||
| import 'package:island/screens/account/me/publishers.dart' as _i3; | import 'package:island/screens/account/me/publishers.dart' as _i5; | ||||||
| import 'package:island/screens/account/me/update.dart' as _i11; | import 'package:island/screens/account/me/update.dart' as _i13; | ||||||
| import 'package:island/screens/auth/create_account.dart' as _i2; | import 'package:island/screens/auth/create_account.dart' as _i4; | ||||||
| import 'package:island/screens/auth/login.dart' as _i6; | import 'package:island/screens/auth/login.dart' as _i8; | ||||||
| import 'package:island/screens/auth/tabs.dart' as _i10; | import 'package:island/screens/auth/tabs.dart' as _i12; | ||||||
| import 'package:island/screens/explore.dart' as _i5; | import 'package:island/screens/chat/chat.dart' as _i2; | ||||||
| import 'package:island/screens/posts/compose.dart' as _i8; | import 'package:island/screens/chat/room.dart' as _i3; | ||||||
| import 'package:island/screens/posts/detail.dart' as _i9; | import 'package:island/screens/explore.dart' as _i7; | ||||||
| import 'package:island/screens/realm/realms.dart' as _i4; | 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 | /// generated route for | ||||||
| /// [_i1.AccountScreen] | /// [_i1.AccountScreen] | ||||||
| class AccountRoute extends _i12.PageRouteInfo<void> { | class AccountRoute extends _i14.PageRouteInfo<void> { | ||||||
|   const AccountRoute({List<_i12.PageRouteInfo>? children}) |   const AccountRoute({List<_i14.PageRouteInfo>? children}) | ||||||
|     : super(AccountRoute.name, initialChildren: children); |     : super(AccountRoute.name, initialChildren: children); | ||||||
|  |  | ||||||
|   static const String name = 'AccountRoute'; |   static const String name = 'AccountRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       return const _i1.AccountScreen(); |       return const _i1.AccountScreen(); | ||||||
| @@ -41,28 +43,123 @@ class AccountRoute extends _i12.PageRouteInfo<void> { | |||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i2.CreateAccountScreen] | /// [_i2.ChatListScreen] | ||||||
| class CreateAccountRoute extends _i12.PageRouteInfo<void> { | class ChatListRoute extends _i14.PageRouteInfo<void> { | ||||||
|   const CreateAccountRoute({List<_i12.PageRouteInfo>? children}) |   const ChatListRoute({List<_i14.PageRouteInfo>? children}) | ||||||
|     : super(CreateAccountRoute.name, initialChildren: 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, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       return const _i2.CreateAccountScreen(); |       return const _i2.ChatListScreen(); | ||||||
|     }, |     }, | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i3.EditPublisherScreen] | /// [_i3.ChatRoomScreen] | ||||||
| class EditPublisherRoute extends _i12.PageRouteInfo<EditPublisherRouteArgs> { | 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({ |   EditPublisherRoute({ | ||||||
|     _i13.Key? key, |     _i15.Key? key, | ||||||
|     String? name, |     String? name, | ||||||
|     List<_i12.PageRouteInfo>? children, |     List<_i14.PageRouteInfo>? children, | ||||||
|   }) : super( |   }) : super( | ||||||
|          EditPublisherRoute.name, |          EditPublisherRoute.name, | ||||||
|          args: EditPublisherRouteArgs(key: key, name: name), |          args: EditPublisherRouteArgs(key: key, name: name), | ||||||
| @@ -72,14 +169,14 @@ class EditPublisherRoute extends _i12.PageRouteInfo<EditPublisherRouteArgs> { | |||||||
|  |  | ||||||
|   static const String name = 'EditPublisherRoute'; |   static const String name = 'EditPublisherRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       final pathParams = data.inheritedPathParams; |       final pathParams = data.inheritedPathParams; | ||||||
|       final args = data.argsAs<EditPublisherRouteArgs>( |       final args = data.argsAs<EditPublisherRouteArgs>( | ||||||
|         orElse: () => EditPublisherRouteArgs(name: pathParams.optString('id')), |         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 { | class EditPublisherRouteArgs { | ||||||
|   const EditPublisherRouteArgs({this.key, this.name}); |   const EditPublisherRouteArgs({this.key, this.name}); | ||||||
|  |  | ||||||
|   final _i13.Key? key; |   final _i15.Key? key; | ||||||
|  |  | ||||||
|   final String? name; |   final String? name; | ||||||
|  |  | ||||||
| @@ -98,12 +195,12 @@ class EditPublisherRouteArgs { | |||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i4.EditRealmScreen] | /// [_i6.EditRealmScreen] | ||||||
| class EditRealmRoute extends _i12.PageRouteInfo<EditRealmRouteArgs> { | class EditRealmRoute extends _i14.PageRouteInfo<EditRealmRouteArgs> { | ||||||
|   EditRealmRoute({ |   EditRealmRoute({ | ||||||
|     _i13.Key? key, |     _i15.Key? key, | ||||||
|     String? slug, |     String? slug, | ||||||
|     List<_i12.PageRouteInfo>? children, |     List<_i14.PageRouteInfo>? children, | ||||||
|   }) : super( |   }) : super( | ||||||
|          EditRealmRoute.name, |          EditRealmRoute.name, | ||||||
|          args: EditRealmRouteArgs(key: key, slug: slug), |          args: EditRealmRouteArgs(key: key, slug: slug), | ||||||
| @@ -113,14 +210,14 @@ class EditRealmRoute extends _i12.PageRouteInfo<EditRealmRouteArgs> { | |||||||
|  |  | ||||||
|   static const String name = 'EditRealmRoute'; |   static const String name = 'EditRealmRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       final pathParams = data.inheritedPathParams; |       final pathParams = data.inheritedPathParams; | ||||||
|       final args = data.argsAs<EditRealmRouteArgs>( |       final args = data.argsAs<EditRealmRouteArgs>( | ||||||
|         orElse: () => EditRealmRouteArgs(slug: pathParams.optString('slug')), |         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 { | class EditRealmRouteArgs { | ||||||
|   const EditRealmRouteArgs({this.key, this.slug}); |   const EditRealmRouteArgs({this.key, this.slug}); | ||||||
|  |  | ||||||
|   final _i13.Key? key; |   final _i15.Key? key; | ||||||
|  |  | ||||||
|   final String? slug; |   final String? slug; | ||||||
|  |  | ||||||
| @@ -139,108 +236,124 @@ class EditRealmRouteArgs { | |||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i5.ExploreScreen] | /// [_i7.ExploreScreen] | ||||||
| class ExploreRoute extends _i12.PageRouteInfo<void> { | class ExploreRoute extends _i14.PageRouteInfo<void> { | ||||||
|   const ExploreRoute({List<_i12.PageRouteInfo>? children}) |   const ExploreRoute({List<_i14.PageRouteInfo>? children}) | ||||||
|     : super(ExploreRoute.name, initialChildren: children); |     : super(ExploreRoute.name, initialChildren: children); | ||||||
|  |  | ||||||
|   static const String name = 'ExploreRoute'; |   static const String name = 'ExploreRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       return const _i5.ExploreScreen(); |       return const _i7.ExploreScreen(); | ||||||
|     }, |     }, | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i6.LoginScreen] | /// [_i8.LoginScreen] | ||||||
| class LoginRoute extends _i12.PageRouteInfo<void> { | class LoginRoute extends _i14.PageRouteInfo<void> { | ||||||
|   const LoginRoute({List<_i12.PageRouteInfo>? children}) |   const LoginRoute({List<_i14.PageRouteInfo>? children}) | ||||||
|     : super(LoginRoute.name, initialChildren: children); |     : super(LoginRoute.name, initialChildren: children); | ||||||
|  |  | ||||||
|   static const String name = 'LoginRoute'; |   static const String name = 'LoginRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       return const _i6.LoginScreen(); |       return const _i8.LoginScreen(); | ||||||
|     }, |     }, | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i3.ManagedPublisherScreen] | /// [_i5.ManagedPublisherScreen] | ||||||
| class ManagedPublisherRoute extends _i12.PageRouteInfo<void> { | class ManagedPublisherRoute extends _i14.PageRouteInfo<void> { | ||||||
|   const ManagedPublisherRoute({List<_i12.PageRouteInfo>? children}) |   const ManagedPublisherRoute({List<_i14.PageRouteInfo>? children}) | ||||||
|     : super(ManagedPublisherRoute.name, initialChildren: children); |     : super(ManagedPublisherRoute.name, initialChildren: children); | ||||||
|  |  | ||||||
|   static const String name = 'ManagedPublisherRoute'; |   static const String name = 'ManagedPublisherRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       return const _i3.ManagedPublisherScreen(); |       return const _i5.ManagedPublisherScreen(); | ||||||
|     }, |     }, | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i7.MyselfProfileScreen] | /// [_i9.MyselfProfileScreen] | ||||||
| class MyselfProfileRoute extends _i12.PageRouteInfo<void> { | class MyselfProfileRoute extends _i14.PageRouteInfo<void> { | ||||||
|   const MyselfProfileRoute({List<_i12.PageRouteInfo>? children}) |   const MyselfProfileRoute({List<_i14.PageRouteInfo>? children}) | ||||||
|     : super(MyselfProfileRoute.name, initialChildren: children); |     : super(MyselfProfileRoute.name, initialChildren: children); | ||||||
|  |  | ||||||
|   static const String name = 'MyselfProfileRoute'; |   static const String name = 'MyselfProfileRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       return const _i7.MyselfProfileScreen(); |       return const _i9.MyselfProfileScreen(); | ||||||
|     }, |     }, | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i3.NewPublisherScreen] | /// [_i2.NewChatScreen] | ||||||
| class NewPublisherRoute extends _i12.PageRouteInfo<void> { | class NewChatRoute extends _i14.PageRouteInfo<void> { | ||||||
|   const NewPublisherRoute({List<_i12.PageRouteInfo>? children}) |   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); |     : super(NewPublisherRoute.name, initialChildren: children); | ||||||
|  |  | ||||||
|   static const String name = 'NewPublisherRoute'; |   static const String name = 'NewPublisherRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       return const _i3.NewPublisherScreen(); |       return const _i5.NewPublisherScreen(); | ||||||
|     }, |     }, | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i4.NewRealmScreen] | /// [_i6.NewRealmScreen] | ||||||
| class NewRealmRoute extends _i12.PageRouteInfo<void> { | class NewRealmRoute extends _i14.PageRouteInfo<void> { | ||||||
|   const NewRealmRoute({List<_i12.PageRouteInfo>? children}) |   const NewRealmRoute({List<_i14.PageRouteInfo>? children}) | ||||||
|     : super(NewRealmRoute.name, initialChildren: children); |     : super(NewRealmRoute.name, initialChildren: children); | ||||||
|  |  | ||||||
|   static const String name = 'NewRealmRoute'; |   static const String name = 'NewRealmRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       return const _i4.NewRealmScreen(); |       return const _i6.NewRealmScreen(); | ||||||
|     }, |     }, | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i8.PostComposeScreen] | /// [_i10.PostComposeScreen] | ||||||
| class PostComposeRoute extends _i12.PageRouteInfo<PostComposeRouteArgs> { | class PostComposeRoute extends _i14.PageRouteInfo<PostComposeRouteArgs> { | ||||||
|   PostComposeRoute({ |   PostComposeRoute({ | ||||||
|     _i13.Key? key, |     _i15.Key? key, | ||||||
|     _i14.SnPost? originalPost, |     _i16.SnPost? originalPost, | ||||||
|     List<_i12.PageRouteInfo>? children, |     List<_i14.PageRouteInfo>? children, | ||||||
|   }) : super( |   }) : super( | ||||||
|          PostComposeRoute.name, |          PostComposeRoute.name, | ||||||
|          args: PostComposeRouteArgs(key: key, originalPost: originalPost), |          args: PostComposeRouteArgs(key: key, originalPost: originalPost), | ||||||
| @@ -249,13 +362,13 @@ class PostComposeRoute extends _i12.PageRouteInfo<PostComposeRouteArgs> { | |||||||
|  |  | ||||||
|   static const String name = 'PostComposeRoute'; |   static const String name = 'PostComposeRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       final args = data.argsAs<PostComposeRouteArgs>( |       final args = data.argsAs<PostComposeRouteArgs>( | ||||||
|         orElse: () => const PostComposeRouteArgs(), |         orElse: () => const PostComposeRouteArgs(), | ||||||
|       ); |       ); | ||||||
|       return _i8.PostComposeScreen( |       return _i10.PostComposeScreen( | ||||||
|         key: args.key, |         key: args.key, | ||||||
|         originalPost: args.originalPost, |         originalPost: args.originalPost, | ||||||
|       ); |       ); | ||||||
| @@ -266,9 +379,9 @@ class PostComposeRoute extends _i12.PageRouteInfo<PostComposeRouteArgs> { | |||||||
| class PostComposeRouteArgs { | class PostComposeRouteArgs { | ||||||
|   const PostComposeRouteArgs({this.key, this.originalPost}); |   const PostComposeRouteArgs({this.key, this.originalPost}); | ||||||
|  |  | ||||||
|   final _i13.Key? key; |   final _i15.Key? key; | ||||||
|  |  | ||||||
|   final _i14.SnPost? originalPost; |   final _i16.SnPost? originalPost; | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   String toString() { |   String toString() { | ||||||
| @@ -277,12 +390,12 @@ class PostComposeRouteArgs { | |||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i9.PostDetailScreen] | /// [_i11.PostDetailScreen] | ||||||
| class PostDetailRoute extends _i12.PageRouteInfo<PostDetailRouteArgs> { | class PostDetailRoute extends _i14.PageRouteInfo<PostDetailRouteArgs> { | ||||||
|   PostDetailRoute({ |   PostDetailRoute({ | ||||||
|     _i13.Key? key, |     _i15.Key? key, | ||||||
|     required int id, |     required int id, | ||||||
|     List<_i12.PageRouteInfo>? children, |     List<_i14.PageRouteInfo>? children, | ||||||
|   }) : super( |   }) : super( | ||||||
|          PostDetailRoute.name, |          PostDetailRoute.name, | ||||||
|          args: PostDetailRouteArgs(key: key, id: id), |          args: PostDetailRouteArgs(key: key, id: id), | ||||||
| @@ -292,14 +405,14 @@ class PostDetailRoute extends _i12.PageRouteInfo<PostDetailRouteArgs> { | |||||||
|  |  | ||||||
|   static const String name = 'PostDetailRoute'; |   static const String name = 'PostDetailRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       final pathParams = data.inheritedPathParams; |       final pathParams = data.inheritedPathParams; | ||||||
|       final args = data.argsAs<PostDetailRouteArgs>( |       final args = data.argsAs<PostDetailRouteArgs>( | ||||||
|         orElse: () => PostDetailRouteArgs(id: pathParams.getInt('id')), |         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 { | class PostDetailRouteArgs { | ||||||
|   const PostDetailRouteArgs({this.key, required this.id}); |   const PostDetailRouteArgs({this.key, required this.id}); | ||||||
|  |  | ||||||
|   final _i13.Key? key; |   final _i15.Key? key; | ||||||
|  |  | ||||||
|   final int id; |   final int id; | ||||||
|  |  | ||||||
| @@ -318,12 +431,12 @@ class PostDetailRouteArgs { | |||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i8.PostEditScreen] | /// [_i10.PostEditScreen] | ||||||
| class PostEditRoute extends _i12.PageRouteInfo<PostEditRouteArgs> { | class PostEditRoute extends _i14.PageRouteInfo<PostEditRouteArgs> { | ||||||
|   PostEditRoute({ |   PostEditRoute({ | ||||||
|     _i13.Key? key, |     _i15.Key? key, | ||||||
|     required int id, |     required int id, | ||||||
|     List<_i12.PageRouteInfo>? children, |     List<_i14.PageRouteInfo>? children, | ||||||
|   }) : super( |   }) : super( | ||||||
|          PostEditRoute.name, |          PostEditRoute.name, | ||||||
|          args: PostEditRouteArgs(key: key, id: id), |          args: PostEditRouteArgs(key: key, id: id), | ||||||
| @@ -333,14 +446,14 @@ class PostEditRoute extends _i12.PageRouteInfo<PostEditRouteArgs> { | |||||||
|  |  | ||||||
|   static const String name = 'PostEditRoute'; |   static const String name = 'PostEditRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       final pathParams = data.inheritedPathParams; |       final pathParams = data.inheritedPathParams; | ||||||
|       final args = data.argsAs<PostEditRouteArgs>( |       final args = data.argsAs<PostEditRouteArgs>( | ||||||
|         orElse: () => PostEditRouteArgs(id: pathParams.getInt('id')), |         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 { | class PostEditRouteArgs { | ||||||
|   const PostEditRouteArgs({this.key, required this.id}); |   const PostEditRouteArgs({this.key, required this.id}); | ||||||
|  |  | ||||||
|   final _i13.Key? key; |   final _i15.Key? key; | ||||||
|  |  | ||||||
|   final int id; |   final int id; | ||||||
|  |  | ||||||
| @@ -359,49 +472,49 @@ class PostEditRouteArgs { | |||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i4.RealmListScreen] | /// [_i6.RealmListScreen] | ||||||
| class RealmListRoute extends _i12.PageRouteInfo<void> { | class RealmListRoute extends _i14.PageRouteInfo<void> { | ||||||
|   const RealmListRoute({List<_i12.PageRouteInfo>? children}) |   const RealmListRoute({List<_i14.PageRouteInfo>? children}) | ||||||
|     : super(RealmListRoute.name, initialChildren: children); |     : super(RealmListRoute.name, initialChildren: children); | ||||||
|  |  | ||||||
|   static const String name = 'RealmListRoute'; |   static const String name = 'RealmListRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       return const _i4.RealmListScreen(); |       return const _i6.RealmListScreen(); | ||||||
|     }, |     }, | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i10.TabsScreen] | /// [_i12.TabsScreen] | ||||||
| class TabsRoute extends _i12.PageRouteInfo<void> { | class TabsRoute extends _i14.PageRouteInfo<void> { | ||||||
|   const TabsRoute({List<_i12.PageRouteInfo>? children}) |   const TabsRoute({List<_i14.PageRouteInfo>? children}) | ||||||
|     : super(TabsRoute.name, initialChildren: children); |     : super(TabsRoute.name, initialChildren: children); | ||||||
|  |  | ||||||
|   static const String name = 'TabsRoute'; |   static const String name = 'TabsRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       return const _i10.TabsScreen(); |       return const _i12.TabsScreen(); | ||||||
|     }, |     }, | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [_i11.UpdateProfileScreen] | /// [_i13.UpdateProfileScreen] | ||||||
| class UpdateProfileRoute extends _i12.PageRouteInfo<void> { | class UpdateProfileRoute extends _i14.PageRouteInfo<void> { | ||||||
|   const UpdateProfileRoute({List<_i12.PageRouteInfo>? children}) |   const UpdateProfileRoute({List<_i14.PageRouteInfo>? children}) | ||||||
|     : super(UpdateProfileRoute.name, initialChildren: children); |     : super(UpdateProfileRoute.name, initialChildren: children); | ||||||
|  |  | ||||||
|   static const String name = 'UpdateProfileRoute'; |   static const String name = 'UpdateProfileRoute'; | ||||||
|  |  | ||||||
|   static _i12.PageInfo page = _i12.PageInfo( |   static _i14.PageInfo page = _i14.PageInfo( | ||||||
|     name, |     name, | ||||||
|     builder: (data) { |     builder: (data) { | ||||||
|       return const _i11.UpdateProfileScreen(); |       return const _i13.UpdateProfileScreen(); | ||||||
|     }, |     }, | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,7 +11,12 @@ class TabsScreen extends StatelessWidget { | |||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return AutoTabsRouter.pageView( |     return AutoTabsRouter.pageView( | ||||||
|       routes: const [ExploreRoute(), RealmListRoute(), AccountRoute()], |       routes: const [ | ||||||
|  |         ExploreRoute(), | ||||||
|  |         ChatListRoute(), | ||||||
|  |         RealmListRoute(), | ||||||
|  |         AccountRoute(), | ||||||
|  |       ], | ||||||
|       builder: (context, child, _) { |       builder: (context, child, _) { | ||||||
|         final tabsRouter = AutoTabsRouter.of(context); |         final tabsRouter = AutoTabsRouter.of(context); | ||||||
|         return Scaffold( |         return Scaffold( | ||||||
| @@ -26,6 +31,10 @@ class TabsScreen extends StatelessWidget { | |||||||
|                 label: 'explore'.tr(), |                 label: 'explore'.tr(), | ||||||
|                 icon: const Icon(Symbols.explore), |                 icon: const Icon(Symbols.explore), | ||||||
|               ), |               ), | ||||||
|  |               NavigationDestination( | ||||||
|  |                 label: 'chat'.tr(), | ||||||
|  |                 icon: const Icon(Symbols.chat), | ||||||
|  |               ), | ||||||
|               NavigationDestination( |               NavigationDestination( | ||||||
|                 label: 'realms'.tr(), |                 label: 'realms'.tr(), | ||||||
|                 icon: const Icon(Symbols.workspaces), |                 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