mirror of
https://github.com/Iconica-Development/flutter_chat.git
synced 2025-05-18 18:33:49 +02:00
feat: rework the existing navigator userstory to look more like flutter_availability userstory
This commit is contained in:
parent
5414ab237f
commit
a26e5d92f0
4 changed files with 137 additions and 110 deletions
|
@ -3,7 +3,7 @@ export "package:chat_repository_interface/chat_repository_interface.dart";
|
|||
|
||||
// User story
|
||||
export "package:flutter_chat/src/flutter_chat_entry_widget.dart";
|
||||
export "package:flutter_chat/src/flutter_chat_navigator_userstory.dart";
|
||||
export "package:flutter_chat/src/flutter_chat_navigator_userstories.dart";
|
||||
|
||||
// Options
|
||||
export "src/config/chat_builders.dart";
|
||||
|
|
|
@ -81,7 +81,7 @@ class _FlutterChatEntryWidgetState extends State<FlutterChatEntryWidget> {
|
|||
Widget build(BuildContext context) => InkWell(
|
||||
onTap: () async =>
|
||||
widget.onTap?.call() ??
|
||||
Navigator.of(context).pushReplacement(
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => FlutterChatNavigatorUserstory(
|
||||
userId: widget.userId,
|
||||
|
@ -122,7 +122,7 @@ class _FlutterChatEntryWidgetState extends State<FlutterChatEntryWidget> {
|
|||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
"${snapshot.data ?? 0}",
|
||||
snapshot.data?.toString() ?? "0",
|
||||
style: widget.textStyle,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
// SPDX-FileCopyrightText: 2023 Iconica
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
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/routes.dart";
|
||||
import "package:flutter_chat/src/services/pop_handler.dart";
|
||||
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 {
|
||||
/// Constructs a [FlutterChatNavigatorUserstory].
|
||||
const FlutterChatNavigatorUserstory({
|
||||
required this.userId,
|
||||
required this.options,
|
||||
super.key,
|
||||
});
|
||||
|
||||
/// The user ID of the person currently looking at the chat
|
||||
final String userId;
|
||||
|
||||
/// The chat options
|
||||
final ChatOptions options;
|
||||
|
||||
@override
|
||||
State<FlutterChatNavigatorUserstory> createState() =>
|
||||
_FlutterChatNavigatorUserstoryState();
|
||||
}
|
||||
|
||||
class _FlutterChatNavigatorUserstoryState
|
||||
extends State<FlutterChatNavigatorUserstory> {
|
||||
late ChatService _service = ChatService(
|
||||
userId: widget.userId,
|
||||
chatRepository: widget.options.chatRepository,
|
||||
userRepository: widget.options.userRepository,
|
||||
);
|
||||
|
||||
late final PopHandler _popHandler = PopHandler();
|
||||
|
||||
final GlobalKey<NavigatorState> _nestedNavigatorKey =
|
||||
GlobalKey<NavigatorState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => ChatScope(
|
||||
userId: widget.userId,
|
||||
options: widget.options,
|
||||
service: _service,
|
||||
popHandler: _popHandler,
|
||||
child: NavigatorPopHandler(
|
||||
// ignore: deprecated_member_use
|
||||
onPop: () => _popHandler.handlePop(),
|
||||
child: Navigator(
|
||||
key: _nestedNavigatorKey,
|
||||
onGenerateRoute: (settings) => MaterialPageRoute(
|
||||
builder: (context) => NavigatorWrapper(
|
||||
userId: widget.userId,
|
||||
chatService: _service,
|
||||
chatOptions: widget.options,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant FlutterChatNavigatorUserstory oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
|
||||
if (oldWidget.userId != widget.userId ||
|
||||
oldWidget.options != widget.options) {
|
||||
setState(() {
|
||||
_service = ChatService(
|
||||
userId: widget.userId,
|
||||
chatRepository: widget.options.chatRepository,
|
||||
userRepository: widget.options.userRepository,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2023 Iconica
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import "dart:async";
|
||||
|
||||
import "package:chat_repository_interface/chat_repository_interface.dart";
|
||||
|
@ -13,125 +9,66 @@ import "package:flutter_chat/src/screens/chat_screen.dart";
|
|||
import "package:flutter_chat/src/screens/creation/new_chat_screen.dart";
|
||||
import "package:flutter_chat/src/screens/creation/new_group_chat_overview.dart";
|
||||
import "package:flutter_chat/src/screens/creation/new_group_chat_screen.dart";
|
||||
import "package:flutter_chat/src/services/pop_handler.dart";
|
||||
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 {
|
||||
/// Constructs a [FlutterChatNavigatorUserstory].
|
||||
const FlutterChatNavigatorUserstory({
|
||||
required this.userId,
|
||||
required this.options,
|
||||
super.key,
|
||||
});
|
||||
|
||||
/// The user ID of the person currently looking at the chat
|
||||
final String userId;
|
||||
|
||||
/// The chat options
|
||||
final ChatOptions options;
|
||||
|
||||
@override
|
||||
State<FlutterChatNavigatorUserstory> createState() =>
|
||||
_FlutterChatNavigatorUserstoryState();
|
||||
}
|
||||
|
||||
class _FlutterChatNavigatorUserstoryState
|
||||
extends State<FlutterChatNavigatorUserstory> {
|
||||
late ChatService _service = ChatService(
|
||||
userId: widget.userId,
|
||||
chatRepository: widget.options.chatRepository,
|
||||
userRepository: widget.options.userRepository,
|
||||
);
|
||||
|
||||
late final PopHandler _popHandler = PopHandler();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => ChatScope(
|
||||
userId: widget.userId,
|
||||
options: widget.options,
|
||||
service: _service,
|
||||
popHandler: _popHandler,
|
||||
child: NavigatorPopHandler(
|
||||
// ignore: deprecated_member_use
|
||||
onPop: _popHandler.handlePop,
|
||||
child: Navigator(
|
||||
key: const ValueKey(
|
||||
"chat_navigator",
|
||||
),
|
||||
onGenerateRoute: (settings) => MaterialPageRoute(
|
||||
builder: (context) => _NavigatorWrapper(
|
||||
userId: widget.userId,
|
||||
chatService: _service,
|
||||
chatOptions: widget.options,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant FlutterChatNavigatorUserstory oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
|
||||
if (oldWidget.userId != widget.userId ||
|
||||
oldWidget.options != widget.options) {
|
||||
setState(() {
|
||||
_service = ChatService(
|
||||
userId: widget.userId,
|
||||
chatRepository: widget.options.chatRepository,
|
||||
userRepository: widget.options.userRepository,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _NavigatorWrapper extends StatelessWidget {
|
||||
const _NavigatorWrapper({
|
||||
/// The navigator wrapper
|
||||
class NavigatorWrapper extends StatelessWidget {
|
||||
/// Constructs a [NavigatorWrapper].
|
||||
const NavigatorWrapper({
|
||||
required this.userId,
|
||||
required this.chatService,
|
||||
required this.chatOptions,
|
||||
super.key,
|
||||
});
|
||||
|
||||
/// The user ID of the person starting the chat userstory
|
||||
final String userId;
|
||||
|
||||
/// The chat service containing the chat repository and user repository
|
||||
final ChatService chatService;
|
||||
|
||||
/// The chat userstory configuration
|
||||
final ChatOptions chatOptions;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => chatScreen(context);
|
||||
|
||||
/// The chat overview screen
|
||||
Widget chatScreen(BuildContext context) => ChatScreen(
|
||||
chatService: chatService,
|
||||
chatOptions: chatOptions,
|
||||
onPressChat: (chat) => route(context, chatDetailScreen(context, chat)),
|
||||
onPressChat: (chat) async =>
|
||||
_routeToScreen(context, chatDetailScreen(context, chat)),
|
||||
onDeleteChat: (chat) async {
|
||||
await chatService.deleteChat(chatId: chat.id);
|
||||
},
|
||||
onPressStartChat: () => route(context, newChatScreen(context)),
|
||||
onPressStartChat: () async =>
|
||||
_routeToScreen(context, newChatScreen(context)),
|
||||
);
|
||||
|
||||
/// The chat screen
|
||||
Widget chatDetailScreen(BuildContext context, ChatModel chat) =>
|
||||
ChatDetailScreen(
|
||||
chat: chat,
|
||||
onReadChat: (chat) async => chatService.markAsRead(chatId: chat.id),
|
||||
onPressChatTitle: (chat) async {
|
||||
if (chat.isGroupChat) {
|
||||
return route(context, chatProfileScreen(context, null, chat));
|
||||
return _routeToScreen(
|
||||
context,
|
||||
chatProfileScreen(context, null, chat),
|
||||
);
|
||||
}
|
||||
|
||||
var otherUserId = chat.getOtherUser(userId);
|
||||
var otherUser = await chatService.getUser(userId: otherUserId).first;
|
||||
|
||||
if (!context.mounted) return;
|
||||
return route(context, chatProfileScreen(context, otherUser, null));
|
||||
return _routeToScreen(
|
||||
context,
|
||||
chatProfileScreen(context, otherUser, null),
|
||||
);
|
||||
},
|
||||
onPressUserProfile: (user) =>
|
||||
route(context, chatProfileScreen(context, user, null)),
|
||||
onPressUserProfile: (user) async =>
|
||||
_routeToScreen(context, chatProfileScreen(context, user, null)),
|
||||
onUploadImage: (data) async {
|
||||
var path = await chatService.uploadImage(
|
||||
path: "chats/${chat.id}-$userId-${DateTime.now()}",
|
||||
|
@ -155,6 +92,7 @@ class _NavigatorWrapper extends StatelessWidget {
|
|||
},
|
||||
);
|
||||
|
||||
/// The chat profile screen
|
||||
Widget chatProfileScreen(
|
||||
BuildContext context,
|
||||
UserModel? user,
|
||||
|
@ -170,38 +108,41 @@ class _NavigatorWrapper extends StatelessWidget {
|
|||
var user = await chatService.getUser(userId: userId).first;
|
||||
|
||||
if (!context.mounted) return;
|
||||
route(context, chatProfileScreen(context, user, null));
|
||||
await _routeToScreen(context, chatProfileScreen(context, user, null));
|
||||
},
|
||||
onPressStartChat: (userId) async {
|
||||
var chat = await createChat(userId);
|
||||
var chat = await _createChat(userId);
|
||||
|
||||
if (!context.mounted) return;
|
||||
return route(context, chatDetailScreen(context, chat));
|
||||
return _routeToScreen(context, chatDetailScreen(context, chat));
|
||||
},
|
||||
);
|
||||
|
||||
/// The new chat screen
|
||||
Widget newChatScreen(BuildContext context) => NewChatScreen(
|
||||
userId: userId,
|
||||
chatService: chatService,
|
||||
chatOptions: chatOptions,
|
||||
onPressCreateGroupChat: () =>
|
||||
route(context, newGroupChatScreen(context)),
|
||||
onPressCreateGroupChat: () async =>
|
||||
_routeToScreen(context, newGroupChatScreen(context)),
|
||||
onPressCreateChat: (user) async {
|
||||
var chat = await createChat(user.id);
|
||||
var chat = await _createChat(user.id);
|
||||
|
||||
if (!context.mounted) return;
|
||||
return route(context, chatDetailScreen(context, chat));
|
||||
return _routeToScreen(context, chatDetailScreen(context, chat));
|
||||
},
|
||||
);
|
||||
|
||||
/// The new group chat screen
|
||||
Widget newGroupChatScreen(BuildContext context) => NewGroupChatScreen(
|
||||
userId: userId,
|
||||
chatService: chatService,
|
||||
chatOptions: chatOptions,
|
||||
onContinue: (users) =>
|
||||
route(context, newGroupChatOverview(context, users)),
|
||||
onContinue: (users) async =>
|
||||
_routeToScreen(context, newGroupChatOverview(context, users)),
|
||||
);
|
||||
|
||||
/// The new group chat overview screen
|
||||
Widget newGroupChatOverview(BuildContext context, List<UserModel> users) =>
|
||||
NewGroupChatOverview(
|
||||
options: chatOptions,
|
||||
|
@ -214,7 +155,7 @@ class _NavigatorWrapper extends StatelessWidget {
|
|||
image: image,
|
||||
);
|
||||
}
|
||||
var chat = await createGroupChat(
|
||||
var chat = await _createGroupChat(
|
||||
users,
|
||||
title,
|
||||
description,
|
||||
|
@ -222,11 +163,12 @@ class _NavigatorWrapper extends StatelessWidget {
|
|||
);
|
||||
|
||||
if (!context.mounted) return;
|
||||
return route(context, chatDetailScreen(context, chat));
|
||||
return _routeToScreen(context, chatDetailScreen(context, chat));
|
||||
},
|
||||
);
|
||||
|
||||
Future<ChatModel> createGroupChat(
|
||||
/// Creates a group chat
|
||||
Future<ChatModel> _createGroupChat(
|
||||
List<UserModel> userModels,
|
||||
String title,
|
||||
String description,
|
||||
|
@ -275,7 +217,8 @@ class _NavigatorWrapper extends StatelessWidget {
|
|||
return chat;
|
||||
}
|
||||
|
||||
Future<ChatModel> createChat(String otherUserId) async {
|
||||
/// Creates a chat
|
||||
Future<ChatModel> _createChat(String otherUserId) async {
|
||||
ChatModel? chat;
|
||||
|
||||
try {
|
||||
|
@ -311,11 +254,9 @@ class _NavigatorWrapper extends StatelessWidget {
|
|||
return chat;
|
||||
}
|
||||
|
||||
void route(BuildContext context, Widget screen) {
|
||||
unawaited(
|
||||
/// Routes to a new screen for the userstory
|
||||
Future _routeToScreen(BuildContext context, Widget screen) async =>
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (context) => screen),
|
||||
),
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
Loading…
Reference in a new issue