mirror of
https://github.com/Iconica-Development/flutter_chat.git
synced 2025-05-18 18:33:49 +02:00
feat: add onback behavior for each userstory screen so it pops correctly with the android backarrow
This commit is contained in:
parent
a26e5d92f0
commit
d610a0bb7d
8 changed files with 115 additions and 12 deletions
|
@ -11,7 +11,6 @@ import "package:flutter_chat/src/util/scope.dart";
|
|||
|
||||
/// The flutter chat navigator userstory
|
||||
/// [userId] is the id of the user
|
||||
/// [chatService] is the chat service
|
||||
/// [chatOptions] are the chat options
|
||||
/// This widget is the entry point for the chat UI
|
||||
class FlutterChatNavigatorUserstory extends StatefulWidget {
|
||||
|
@ -19,6 +18,7 @@ class FlutterChatNavigatorUserstory extends StatefulWidget {
|
|||
const FlutterChatNavigatorUserstory({
|
||||
required this.userId,
|
||||
required this.options,
|
||||
this.onExit,
|
||||
super.key,
|
||||
});
|
||||
|
||||
|
@ -28,6 +28,9 @@ class FlutterChatNavigatorUserstory extends StatefulWidget {
|
|||
/// The chat options
|
||||
final ChatOptions options;
|
||||
|
||||
/// Callback for when the user wants to navigate back to a previous screen
|
||||
final VoidCallback? onExit;
|
||||
|
||||
@override
|
||||
State<FlutterChatNavigatorUserstory> createState() =>
|
||||
_FlutterChatNavigatorUserstoryState();
|
||||
|
@ -62,6 +65,7 @@ class _FlutterChatNavigatorUserstoryState
|
|||
userId: widget.userId,
|
||||
chatService: _service,
|
||||
chatOptions: widget.options,
|
||||
onExit: widget.onExit,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -17,6 +17,7 @@ class NavigatorWrapper extends StatelessWidget {
|
|||
required this.userId,
|
||||
required this.chatService,
|
||||
required this.chatOptions,
|
||||
this.onExit,
|
||||
super.key,
|
||||
});
|
||||
|
||||
|
@ -29,6 +30,9 @@ class NavigatorWrapper extends StatelessWidget {
|
|||
/// The chat userstory configuration
|
||||
final ChatOptions chatOptions;
|
||||
|
||||
/// Callback for when the user wants to navigate back
|
||||
final VoidCallback? onExit;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => chatScreen(context);
|
||||
|
||||
|
@ -36,6 +40,7 @@ class NavigatorWrapper extends StatelessWidget {
|
|||
Widget chatScreen(BuildContext context) => ChatScreen(
|
||||
chatService: chatService,
|
||||
chatOptions: chatOptions,
|
||||
onExit: onExit,
|
||||
onPressChat: (chat) async =>
|
||||
_routeToScreen(context, chatDetailScreen(context, chat)),
|
||||
onDeleteChat: (chat) async {
|
||||
|
@ -49,6 +54,7 @@ class NavigatorWrapper extends StatelessWidget {
|
|||
Widget chatDetailScreen(BuildContext context, ChatModel chat) =>
|
||||
ChatDetailScreen(
|
||||
chat: chat,
|
||||
onExit: () => Navigator.of(context).pop(),
|
||||
onReadChat: (chat) async => chatService.markAsRead(chatId: chat.id),
|
||||
onPressChatTitle: (chat) async {
|
||||
if (chat.isGroupChat) {
|
||||
|
@ -104,6 +110,7 @@ class NavigatorWrapper extends StatelessWidget {
|
|||
userId: userId,
|
||||
userModel: user,
|
||||
chatModel: chat,
|
||||
onExit: () => Navigator.of(context).pop(),
|
||||
onTapUser: (userId) async {
|
||||
var user = await chatService.getUser(userId: userId).first;
|
||||
|
||||
|
@ -123,13 +130,17 @@ class NavigatorWrapper extends StatelessWidget {
|
|||
userId: userId,
|
||||
chatService: chatService,
|
||||
chatOptions: chatOptions,
|
||||
onExit: () => Navigator.of(context).pop(),
|
||||
onPressCreateGroupChat: () async =>
|
||||
_routeToScreen(context, newGroupChatScreen(context)),
|
||||
onPressCreateChat: (user) async {
|
||||
var chat = await _createChat(user.id);
|
||||
|
||||
if (!context.mounted) return;
|
||||
return _routeToScreen(context, chatDetailScreen(context, chat));
|
||||
return _replaceCurrentScreen(
|
||||
context,
|
||||
chatDetailScreen(context, chat),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -138,8 +149,11 @@ class NavigatorWrapper extends StatelessWidget {
|
|||
userId: userId,
|
||||
chatService: chatService,
|
||||
chatOptions: chatOptions,
|
||||
onContinue: (users) async =>
|
||||
_routeToScreen(context, newGroupChatOverview(context, users)),
|
||||
onExit: () => Navigator.of(context).pop(),
|
||||
onContinue: (users) async => _replaceCurrentScreen(
|
||||
context,
|
||||
newGroupChatOverview(context, users),
|
||||
),
|
||||
);
|
||||
|
||||
/// The new group chat overview screen
|
||||
|
@ -147,6 +161,7 @@ class NavigatorWrapper extends StatelessWidget {
|
|||
NewGroupChatOverview(
|
||||
options: chatOptions,
|
||||
users: users,
|
||||
onExit: () => Navigator.of(context).pop(),
|
||||
onComplete: (users, title, description, image) async {
|
||||
String? path;
|
||||
if (image != null) {
|
||||
|
@ -163,7 +178,10 @@ class NavigatorWrapper extends StatelessWidget {
|
|||
);
|
||||
|
||||
if (!context.mounted) return;
|
||||
return _routeToScreen(context, chatDetailScreen(context, chat));
|
||||
return _replaceCurrentScreen(
|
||||
context,
|
||||
chatDetailScreen(context, chat),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -259,4 +277,10 @@ class NavigatorWrapper extends StatelessWidget {
|
|||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (context) => screen),
|
||||
);
|
||||
|
||||
/// Replaces the current screen with a new screen for the userstory
|
||||
Future _replaceCurrentScreen(BuildContext context, Widget screen) async =>
|
||||
Navigator.of(context).pushReplacement(
|
||||
MaterialPageRoute(builder: (context) => screen),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,13 +8,15 @@ import "package:flutter_chat/src/config/screen_types.dart";
|
|||
import "package:flutter_chat/src/screens/chat_detail/widgets/default_message_builder.dart";
|
||||
import "package:flutter_chat/src/screens/creation/widgets/image_picker.dart";
|
||||
import "package:flutter_chat/src/util/scope.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
|
||||
/// Chat detail screen
|
||||
/// Seen when a user clicks on a chat
|
||||
class ChatDetailScreen extends StatefulWidget {
|
||||
class ChatDetailScreen extends StatefulHookWidget {
|
||||
/// Constructs a [ChatDetailScreen].
|
||||
const ChatDetailScreen({
|
||||
required this.chat,
|
||||
required this.onExit,
|
||||
required this.onPressChatTitle,
|
||||
required this.onPressUserProfile,
|
||||
required this.onUploadImage,
|
||||
|
@ -45,6 +47,9 @@ class ChatDetailScreen extends StatefulWidget {
|
|||
/// Callback function to get the chat title
|
||||
final String Function(ChatModel chat)? getChatTitle;
|
||||
|
||||
/// Callback for when the user wants to navigate back
|
||||
final VoidCallback onExit;
|
||||
|
||||
@override
|
||||
State<ChatDetailScreen> createState() => _ChatDetailScreenState();
|
||||
}
|
||||
|
@ -85,7 +90,8 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var chatOptions = ChatScope.of(context).options;
|
||||
var chatScope = ChatScope.of(context);
|
||||
var chatOptions = chatScope.options;
|
||||
var appBar = _AppBar(
|
||||
chatTitle: chatTitle,
|
||||
onPressChatTitle: widget.onPressChatTitle,
|
||||
|
@ -100,6 +106,11 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
|
|||
onReadChat: widget.onReadChat,
|
||||
);
|
||||
|
||||
useEffect(() {
|
||||
chatScope.popHandler.add(widget.onExit);
|
||||
return () => chatScope.popHandler.remove(widget.onExit);
|
||||
});
|
||||
|
||||
if (chatOptions.builders.baseScreenBuilder == null) {
|
||||
return Scaffold(
|
||||
appBar: appBar,
|
||||
|
|
|
@ -2,15 +2,18 @@ import "package:chat_repository_interface/chat_repository_interface.dart";
|
|||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat/src/config/chat_options.dart";
|
||||
import "package:flutter_chat/src/config/screen_types.dart";
|
||||
import "package:flutter_chat/src/util/scope.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
import "package:flutter_profile/flutter_profile.dart";
|
||||
|
||||
/// The chat profile screen
|
||||
/// Seen when a user taps on a chat profile
|
||||
/// Also used for group chats
|
||||
class ChatProfileScreen extends StatelessWidget {
|
||||
class ChatProfileScreen extends HookWidget {
|
||||
/// Constructs a [ChatProfileScreen]
|
||||
const ChatProfileScreen({
|
||||
required this.options,
|
||||
required this.onExit,
|
||||
required this.userId,
|
||||
required this.userModel,
|
||||
required this.service,
|
||||
|
@ -41,8 +44,18 @@ class ChatProfileScreen extends StatelessWidget {
|
|||
/// Callback function triggered when the start chat button is pressed
|
||||
final Function(String)? onPressStartChat;
|
||||
|
||||
/// Callback for when the user wants to navigate back
|
||||
final VoidCallback onExit;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var chatScope = ChatScope.of(context);
|
||||
|
||||
useEffect(() {
|
||||
chatScope.popHandler.add(onExit);
|
||||
return () => chatScope.popHandler.remove(onExit);
|
||||
});
|
||||
|
||||
if (options.builders.baseScreenBuilder == null) {
|
||||
return Scaffold(
|
||||
appBar: _AppBar(
|
||||
|
|
|
@ -5,17 +5,19 @@ import "package:flutter_chat/src/config/chat_translations.dart";
|
|||
import "package:flutter_chat/src/config/screen_types.dart";
|
||||
import "package:flutter_chat/src/services/date_formatter.dart";
|
||||
import "package:flutter_chat/src/util/scope.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
import "package:flutter_profile/flutter_profile.dart";
|
||||
|
||||
/// The chat screen
|
||||
/// Seen when a user is chatting
|
||||
class ChatScreen extends StatelessWidget {
|
||||
class ChatScreen extends HookWidget {
|
||||
/// Constructs a [ChatScreen]
|
||||
const ChatScreen({
|
||||
required this.chatService,
|
||||
required this.chatOptions,
|
||||
required this.onPressChat,
|
||||
required this.onDeleteChat,
|
||||
required this.onExit,
|
||||
this.onPressStartChat,
|
||||
super.key,
|
||||
});
|
||||
|
@ -35,8 +37,19 @@ class ChatScreen extends StatelessWidget {
|
|||
/// Callback function for deleting a chat.
|
||||
final void Function(ChatModel chat) onDeleteChat;
|
||||
|
||||
/// Callback for when the user wants to navigate back
|
||||
final VoidCallback? onExit;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var chatScope = ChatScope.of(context);
|
||||
|
||||
useEffect(() {
|
||||
if (onExit == null) return null;
|
||||
chatScope.popHandler.add(onExit!);
|
||||
return () => chatScope.popHandler.remove(onExit!);
|
||||
});
|
||||
|
||||
if (chatOptions.builders.baseScreenBuilder == null) {
|
||||
return Scaffold(
|
||||
appBar: _AppBar(
|
||||
|
|
|
@ -5,13 +5,16 @@ import "package:flutter_chat/src/config/screen_types.dart";
|
|||
import "package:flutter_chat/src/screens/creation/widgets/search_field.dart";
|
||||
import "package:flutter_chat/src/screens/creation/widgets/search_icon.dart";
|
||||
import "package:flutter_chat/src/screens/creation/widgets/user_list.dart";
|
||||
import "package:flutter_chat/src/util/scope.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
|
||||
/// New chat screen
|
||||
/// This screen is used to create a new chat
|
||||
class NewChatScreen extends StatefulWidget {
|
||||
class NewChatScreen extends StatefulHookWidget {
|
||||
/// Constructs a [NewChatScreen]
|
||||
const NewChatScreen({
|
||||
required this.userId,
|
||||
required this.onExit,
|
||||
required this.chatService,
|
||||
required this.chatOptions,
|
||||
required this.onPressCreateGroupChat,
|
||||
|
@ -34,6 +37,9 @@ class NewChatScreen extends StatefulWidget {
|
|||
/// Callback function triggered when a user is tapped
|
||||
final Function(UserModel) onPressCreateChat;
|
||||
|
||||
/// Callback for when the user wants to navigate back
|
||||
final VoidCallback onExit;
|
||||
|
||||
@override
|
||||
State<NewChatScreen> createState() => _NewChatScreenState();
|
||||
}
|
||||
|
@ -45,6 +51,13 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var chatScope = ChatScope.of(context);
|
||||
|
||||
useEffect(() {
|
||||
chatScope.popHandler.add(widget.onExit);
|
||||
return () => chatScope.popHandler.remove(widget.onExit);
|
||||
});
|
||||
|
||||
if (widget.chatOptions.builders.baseScreenBuilder == null) {
|
||||
return Scaffold(
|
||||
appBar: _AppBar(
|
||||
|
|
|
@ -5,15 +5,18 @@ import "package:flutter/material.dart";
|
|||
import "package:flutter_chat/src/config/chat_options.dart";
|
||||
import "package:flutter_chat/src/config/screen_types.dart";
|
||||
import "package:flutter_chat/src/screens/creation/widgets/image_picker.dart";
|
||||
import "package:flutter_chat/src/util/scope.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
import "package:flutter_profile/flutter_profile.dart";
|
||||
|
||||
/// New group chat overview
|
||||
/// Seen after the user has selected the users they
|
||||
/// want to add to the group chat
|
||||
class NewGroupChatOverview extends StatelessWidget {
|
||||
class NewGroupChatOverview extends HookWidget {
|
||||
/// Constructs a [NewGroupChatOverview]
|
||||
const NewGroupChatOverview({
|
||||
required this.options,
|
||||
required this.onExit,
|
||||
required this.users,
|
||||
required this.onComplete,
|
||||
super.key,
|
||||
|
@ -25,6 +28,9 @@ class NewGroupChatOverview extends StatelessWidget {
|
|||
/// The users to be added to the group chat
|
||||
final List<UserModel> users;
|
||||
|
||||
/// Callback for when the user wants to navigate back
|
||||
final VoidCallback onExit;
|
||||
|
||||
/// Callback function triggered when the group chat is created
|
||||
final Function(
|
||||
List<UserModel> users,
|
||||
|
@ -35,6 +41,13 @@ class NewGroupChatOverview extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var chatScope = ChatScope.of(context);
|
||||
|
||||
useEffect(() {
|
||||
chatScope.popHandler.add(onExit);
|
||||
return () => chatScope.popHandler.remove(onExit);
|
||||
});
|
||||
|
||||
if (options.builders.baseScreenBuilder == null) {
|
||||
return Scaffold(
|
||||
appBar: _AppBar(
|
||||
|
|
|
@ -5,13 +5,16 @@ import "package:flutter_chat/src/config/screen_types.dart";
|
|||
import "package:flutter_chat/src/screens/creation/widgets/search_field.dart";
|
||||
import "package:flutter_chat/src/screens/creation/widgets/search_icon.dart";
|
||||
import "package:flutter_chat/src/screens/creation/widgets/user_list.dart";
|
||||
import "package:flutter_chat/src/util/scope.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
|
||||
/// New group chat screen
|
||||
/// This screen is used to create a new group chat
|
||||
class NewGroupChatScreen extends StatefulWidget {
|
||||
class NewGroupChatScreen extends StatefulHookWidget {
|
||||
/// Constructs a [NewGroupChatScreen]
|
||||
const NewGroupChatScreen({
|
||||
required this.userId,
|
||||
required this.onExit,
|
||||
required this.chatService,
|
||||
required this.chatOptions,
|
||||
required this.onContinue,
|
||||
|
@ -27,6 +30,9 @@ class NewGroupChatScreen extends StatefulWidget {
|
|||
/// The chat options
|
||||
final ChatOptions chatOptions;
|
||||
|
||||
/// Callback for when the user wants to navigate back
|
||||
final VoidCallback onExit;
|
||||
|
||||
/// Callback function triggered when the continue button is pressed
|
||||
final Function(List<UserModel>) onContinue;
|
||||
|
||||
|
@ -43,6 +49,12 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var chatScope = ChatScope.of(context);
|
||||
|
||||
useEffect(() {
|
||||
chatScope.popHandler.add(widget.onExit);
|
||||
return () => chatScope.popHandler.remove(widget.onExit);
|
||||
});
|
||||
if (widget.chatOptions.builders.baseScreenBuilder == null) {
|
||||
return Scaffold(
|
||||
appBar: _AppBar(
|
||||
|
|
Loading…
Reference in a new issue