mirror of
https://github.com/Iconica-Development/flutter_chat.git
synced 2025-05-18 18:33:49 +02:00
Merge pull request #93 from Iconica-Development/3.0.1
fix: routing issues
This commit is contained in:
commit
15f15748b6
45 changed files with 423 additions and 429 deletions
|
@ -1,3 +1,11 @@
|
|||
## 3.0.1
|
||||
|
||||
- fix bug where you could make multiple groups quickly by routing back to the previous screen
|
||||
- fix bug where you would route back to the user selection screen insterad of routing back to the chat overview screen
|
||||
- Add onPopInvoked callback to the userstory to add custom behaviour for the back button on the chatscreen
|
||||
- Handle overflows for users with a long name.
|
||||
- Remove the scaffold backgrounds because they should be inherited from the scaffold theme
|
||||
|
||||
## 3.0.0
|
||||
|
||||
- Add theming
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
///
|
||||
library flutter_chat;
|
||||
|
||||
export 'package:flutter_chat/src/chat_entry_widget.dart';
|
||||
export 'package:flutter_chat/src/flutter_chat_navigator_userstory.dart';
|
||||
export 'package:flutter_chat/src/flutter_chat_userstory.dart';
|
||||
export 'package:flutter_chat/src/models/chat_configuration.dart';
|
||||
export 'package:flutter_chat/src/routes.dart';
|
||||
export 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
||||
export 'package:flutter_chat_local/local_chat_service.dart';
|
||||
export 'package:flutter_chat_view/flutter_chat_view.dart';
|
||||
export "package:flutter_chat/src/chat_entry_widget.dart";
|
||||
export "package:flutter_chat/src/flutter_chat_navigator_userstory.dart";
|
||||
export "package:flutter_chat/src/flutter_chat_userstory.dart";
|
||||
export "package:flutter_chat/src/models/chat_configuration.dart";
|
||||
export "package:flutter_chat/src/routes.dart";
|
||||
export "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||
export "package:flutter_chat_local/local_chat_service.dart";
|
||||
export "package:flutter_chat_view/flutter_chat_view.dart";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'dart:async';
|
||||
import "dart:async";
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat/flutter_chat.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat/flutter_chat.dart";
|
||||
|
||||
/// A widget representing an entry point for a chat UI.
|
||||
class ChatEntryWidget extends StatefulWidget {
|
||||
|
@ -104,7 +104,7 @@ class _ChatEntryWidgetState extends State<ChatEntryWidget> {
|
|||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'${snapshot.data ?? 0}',
|
||||
"${snapshot.data ?? 0}",
|
||||
style: widget.textStyle,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat/flutter_chat.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat/flutter_chat.dart";
|
||||
|
||||
/// Navigates to the chat user story screen.
|
||||
///
|
||||
|
@ -30,48 +30,53 @@ Widget _chatScreenRoute(
|
|||
ChatUserStoryConfiguration configuration,
|
||||
BuildContext context,
|
||||
) =>
|
||||
ChatScreen(
|
||||
unreadMessageTextStyle: configuration.unreadMessageTextStyle,
|
||||
service: configuration.chatService,
|
||||
options: configuration.chatOptionsBuilder(context),
|
||||
onNoChats: () async => Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => _newChatScreenRoute(
|
||||
configuration,
|
||||
context,
|
||||
),
|
||||
),
|
||||
),
|
||||
onPressStartChat: () async {
|
||||
if (configuration.onPressStartChat != null) {
|
||||
return await configuration.onPressStartChat?.call();
|
||||
}
|
||||
|
||||
return Navigator.of(context).push(
|
||||
PopScope(
|
||||
canPop: configuration.onPopInvoked == null,
|
||||
onPopInvoked: (didPop) =>
|
||||
configuration.onPopInvoked?.call(didPop, context),
|
||||
child: ChatScreen(
|
||||
unreadMessageTextStyle: configuration.unreadMessageTextStyle,
|
||||
service: configuration.chatService,
|
||||
options: configuration.chatOptionsBuilder(context),
|
||||
onNoChats: () async => Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => _newChatScreenRoute(
|
||||
configuration,
|
||||
context,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
onPressChat: (chat) async =>
|
||||
configuration.onPressChat?.call(context, chat) ??
|
||||
await Navigator.of(context).push(
|
||||
),
|
||||
onPressStartChat: () async {
|
||||
if (configuration.onPressStartChat != null) {
|
||||
return await configuration.onPressStartChat?.call();
|
||||
}
|
||||
|
||||
return Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => _chatDetailScreenRoute(
|
||||
builder: (context) => _newChatScreenRoute(
|
||||
configuration,
|
||||
context,
|
||||
chat.id!,
|
||||
),
|
||||
),
|
||||
),
|
||||
onDeleteChat: (chat) async =>
|
||||
configuration.onDeleteChat?.call(context, chat) ??
|
||||
configuration.chatService.chatOverviewService.deleteChat(chat),
|
||||
deleteChatDialog: configuration.deleteChatDialog,
|
||||
translations: configuration.translations,
|
||||
);
|
||||
},
|
||||
onPressChat: (chat) async =>
|
||||
configuration.onPressChat?.call(context, chat) ??
|
||||
await Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => _chatDetailScreenRoute(
|
||||
configuration,
|
||||
context,
|
||||
chat.id!,
|
||||
),
|
||||
),
|
||||
),
|
||||
onDeleteChat: (chat) async =>
|
||||
configuration.onDeleteChat?.call(context, chat) ??
|
||||
configuration.chatService.chatOverviewService.deleteChat(chat),
|
||||
deleteChatDialog: configuration.deleteChatDialog,
|
||||
translations: configuration.translations,
|
||||
),
|
||||
);
|
||||
|
||||
/// Constructs the chat detail screen route widget.
|
||||
|
@ -218,7 +223,7 @@ Widget _newChatScreenRoute(
|
|||
if (configuration.onPressCreateChat != null) return;
|
||||
var chat = await configuration.chatService.chatOverviewService
|
||||
.getChatByUser(user);
|
||||
debugPrint('Chat is ${chat.id}');
|
||||
debugPrint("Chat is ${chat.id}");
|
||||
if (chat.id == null) {
|
||||
chat = await configuration.chatService.chatOverviewService
|
||||
.storeChatIfNot(
|
||||
|
@ -230,10 +235,13 @@ Widget _newChatScreenRoute(
|
|||
if (context.mounted) {
|
||||
await Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => _chatDetailScreenRoute(
|
||||
configuration,
|
||||
context,
|
||||
chat.id!,
|
||||
builder: (context) => PopScope(
|
||||
canPop: false,
|
||||
child: _chatDetailScreenRoute(
|
||||
configuration,
|
||||
context,
|
||||
chat.id!,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -279,17 +287,20 @@ Widget _newGroupChatOverviewScreenRoute(
|
|||
GroupChatModel(
|
||||
canBeDeleted: true,
|
||||
title: groupChatName,
|
||||
imageUrl: 'https://picsum.photos/200/300',
|
||||
imageUrl: "https://picsum.photos/200/300",
|
||||
users: users,
|
||||
),
|
||||
);
|
||||
if (context.mounted) {
|
||||
await Navigator.of(context).pushReplacement(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => _chatDetailScreenRoute(
|
||||
configuration,
|
||||
context,
|
||||
chat.id!,
|
||||
builder: (context) => PopScope(
|
||||
canPop: false,
|
||||
child: _chatDetailScreenRoute(
|
||||
configuration,
|
||||
context,
|
||||
chat.id!,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat/flutter_chat.dart';
|
||||
import 'package:flutter_chat/src/go_router.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat/flutter_chat.dart";
|
||||
import "package:flutter_chat/src/go_router.dart";
|
||||
import "package:go_router/go_router.dart";
|
||||
|
||||
List<GoRoute> getChatStoryRoutes(
|
||||
ChatUserStoryConfiguration configuration,
|
||||
|
@ -14,7 +14,6 @@ List<GoRoute> getChatStoryRoutes(
|
|||
GoRoute(
|
||||
path: ChatUserStoryRoutes.chatScreen,
|
||||
pageBuilder: (context, state) {
|
||||
var theme = Theme.of(context);
|
||||
var service = configuration.chatServiceBuilder?.call(context) ??
|
||||
configuration.chatService;
|
||||
var chatScreen = ChatScreen(
|
||||
|
@ -43,24 +42,27 @@ List<GoRoute> getChatStoryRoutes(
|
|||
return buildScreenWithoutTransition(
|
||||
context: context,
|
||||
state: state,
|
||||
child: configuration.chatPageBuilder?.call(
|
||||
context,
|
||||
chatScreen,
|
||||
) ??
|
||||
Scaffold(
|
||||
backgroundColor: theme.colorScheme.surface,
|
||||
body: chatScreen,
|
||||
),
|
||||
child: PopScope(
|
||||
canPop: configuration.onPopInvoked == null,
|
||||
onPopInvoked: (didPop) =>
|
||||
configuration.onPopInvoked?.call(didPop, context),
|
||||
child: configuration.chatPageBuilder?.call(
|
||||
context,
|
||||
chatScreen,
|
||||
) ??
|
||||
Scaffold(
|
||||
body: chatScreen,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: ChatUserStoryRoutes.chatDetailScreen,
|
||||
pageBuilder: (context, state) {
|
||||
var chatId = state.pathParameters['id'];
|
||||
var chatId = state.pathParameters["id"];
|
||||
var service = configuration.chatServiceBuilder?.call(context) ??
|
||||
configuration.chatService;
|
||||
var theme = Theme.of(context);
|
||||
|
||||
var chatDetailScreen = ChatDetailScreen(
|
||||
chatTitleBuilder: configuration.chatTitleBuilder,
|
||||
|
@ -122,7 +124,6 @@ List<GoRoute> getChatStoryRoutes(
|
|||
chatDetailScreen,
|
||||
) ??
|
||||
Scaffold(
|
||||
backgroundColor: theme.colorScheme.surface,
|
||||
body: chatDetailScreen,
|
||||
),
|
||||
);
|
||||
|
@ -133,7 +134,6 @@ List<GoRoute> getChatStoryRoutes(
|
|||
pageBuilder: (context, state) {
|
||||
var service = configuration.chatServiceBuilder?.call(context) ??
|
||||
configuration.chatService;
|
||||
var theme = Theme.of(context);
|
||||
|
||||
var newChatScreen = NewChatScreen(
|
||||
options: configuration.chatOptionsBuilder(context),
|
||||
|
@ -156,7 +156,7 @@ List<GoRoute> getChatStoryRoutes(
|
|||
}
|
||||
if (context.mounted) {
|
||||
await context.push(
|
||||
ChatUserStoryRoutes.chatDetailViewPath(chat.id ?? ''),
|
||||
ChatUserStoryRoutes.chatDetailViewPath(chat.id ?? ""),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
@ -172,7 +172,6 @@ List<GoRoute> getChatStoryRoutes(
|
|||
newChatScreen,
|
||||
) ??
|
||||
Scaffold(
|
||||
backgroundColor: theme.colorScheme.surface,
|
||||
body: newChatScreen,
|
||||
),
|
||||
);
|
||||
|
@ -183,7 +182,6 @@ List<GoRoute> getChatStoryRoutes(
|
|||
pageBuilder: (context, state) {
|
||||
var service = configuration.chatServiceBuilder?.call(context) ??
|
||||
configuration.chatService;
|
||||
var theme = Theme.of(context);
|
||||
|
||||
var newGroupChatScreen = NewGroupChatScreen(
|
||||
options: configuration.chatOptionsBuilder(context),
|
||||
|
@ -203,7 +201,6 @@ List<GoRoute> getChatStoryRoutes(
|
|||
newGroupChatScreen,
|
||||
) ??
|
||||
Scaffold(
|
||||
backgroundColor: theme.colorScheme.surface,
|
||||
body: newGroupChatScreen,
|
||||
),
|
||||
);
|
||||
|
@ -215,7 +212,6 @@ List<GoRoute> getChatStoryRoutes(
|
|||
var service = configuration.chatServiceBuilder?.call(context) ??
|
||||
configuration.chatService;
|
||||
var users = state.extra! as List<ChatUserModel>;
|
||||
var theme = Theme.of(context);
|
||||
|
||||
var newGroupChatOverviewScreen = NewGroupChatOverviewScreen(
|
||||
options: configuration.chatOptionsBuilder(context),
|
||||
|
@ -231,13 +227,13 @@ List<GoRoute> getChatStoryRoutes(
|
|||
GroupChatModel(
|
||||
canBeDeleted: true,
|
||||
title: groupChatName,
|
||||
imageUrl: 'https://picsum.photos/200/300',
|
||||
imageUrl: "https://picsum.photos/200/300",
|
||||
users: users,
|
||||
),
|
||||
);
|
||||
if (context.mounted) {
|
||||
context.go(
|
||||
ChatUserStoryRoutes.chatDetailViewPath(chat.id ?? ''),
|
||||
ChatUserStoryRoutes.chatDetailViewPath(chat.id ?? ""),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
@ -250,7 +246,6 @@ List<GoRoute> getChatStoryRoutes(
|
|||
newGroupChatOverviewScreen,
|
||||
) ??
|
||||
Scaffold(
|
||||
backgroundColor: theme.colorScheme.surface,
|
||||
body: newGroupChatOverviewScreen,
|
||||
),
|
||||
);
|
||||
|
@ -259,12 +254,11 @@ List<GoRoute> getChatStoryRoutes(
|
|||
GoRoute(
|
||||
path: ChatUserStoryRoutes.chatProfileScreen,
|
||||
pageBuilder: (context, state) {
|
||||
var chatId = state.pathParameters['id'];
|
||||
var userId = state.pathParameters['userId'];
|
||||
var id = userId == 'null' ? null : userId;
|
||||
var chatId = state.pathParameters["id"];
|
||||
var userId = state.pathParameters["userId"];
|
||||
var id = userId == "null" ? null : userId;
|
||||
var service = configuration.chatServiceBuilder?.call(context) ??
|
||||
configuration.chatService;
|
||||
var theme = Theme.of(context);
|
||||
|
||||
var profileScreen = ChatProfileScreen(
|
||||
translations: configuration.translationsBuilder?.call(context) ??
|
||||
|
@ -290,7 +284,6 @@ List<GoRoute> getChatStoryRoutes(
|
|||
profileScreen,
|
||||
) ??
|
||||
Scaffold(
|
||||
backgroundColor: theme.colorScheme.surface,
|
||||
body: profileScreen,
|
||||
),
|
||||
);
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:go_router/go_router.dart";
|
||||
|
||||
/// Builds a screen with a fade transition.
|
||||
///
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'dart:typed_data';
|
||||
import "dart:typed_data";
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat_view/flutter_chat_view.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat_view/flutter_chat_view.dart";
|
||||
|
||||
/// `ChatUserStoryConfiguration` is a class that configures the chat user story.
|
||||
@immutable
|
||||
|
@ -21,6 +21,7 @@ class ChatUserStoryConfiguration {
|
|||
this.onMessageSubmit,
|
||||
this.onReadChat,
|
||||
this.onUploadImage,
|
||||
this.onPopInvoked,
|
||||
this.onPressCreateChat,
|
||||
this.onPressCreateGroupChat,
|
||||
this.onPressCompleteGroupChatCreation,
|
||||
|
@ -118,6 +119,11 @@ class ChatUserStoryConfiguration {
|
|||
/// Callback function triggered when user profile is pressed.
|
||||
final Function(BuildContext context, ChatUserModel user)? onPressUserProfile;
|
||||
|
||||
/// Callback function triggered when the popscope on the chat
|
||||
/// homepage is triggered.
|
||||
// ignore: avoid_positional_boolean_parameters
|
||||
final Function(bool didPop, BuildContext context)? onPopInvoked;
|
||||
|
||||
final double? textfieldBottomPadding;
|
||||
|
||||
final Color? iconDisabledColor;
|
||||
|
|
|
@ -4,19 +4,19 @@
|
|||
|
||||
/// Provides route paths for the chat user story.
|
||||
mixin ChatUserStoryRoutes {
|
||||
static const String chatScreen = '/chat';
|
||||
static const String chatScreen = "/chat";
|
||||
|
||||
/// Constructs the path for the chat detail view.
|
||||
static String chatDetailViewPath(String chatId) => '/chat-detail/$chatId';
|
||||
static String chatDetailViewPath(String chatId) => "/chat-detail/$chatId";
|
||||
|
||||
static const String chatDetailScreen = '/chat-detail/:id';
|
||||
static const String newChatScreen = '/new-chat';
|
||||
static const String chatDetailScreen = "/chat-detail/:id";
|
||||
static const String newChatScreen = "/new-chat";
|
||||
|
||||
/// Constructs the path for the chat profile screen.
|
||||
static const String newGroupChatScreen = '/new-group-chat';
|
||||
static const String newGroupChatOverviewScreen = '/new-group-chat-overview';
|
||||
static const String newGroupChatScreen = "/new-group-chat";
|
||||
static const String newGroupChatOverviewScreen = "/new-group-chat-overview";
|
||||
static String chatProfileScreenPath(String chatId, String? userId) =>
|
||||
'/chat-profile/$chatId/$userId';
|
||||
"/chat-profile/$chatId/$userId";
|
||||
|
||||
static const String chatProfileScreen = '/chat-profile/:id/:userId';
|
||||
static const String chatProfileScreen = "/chat-profile/:id/:userId";
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
name: flutter_chat
|
||||
description: A new Flutter package project.
|
||||
version: 3.0.0
|
||||
version: 3.0.1
|
||||
|
||||
publish_to: none
|
||||
|
||||
|
@ -20,17 +20,17 @@ dependencies:
|
|||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_chat
|
||||
path: packages/flutter_chat_view
|
||||
ref: 3.0.0
|
||||
ref: 3.0.1
|
||||
flutter_chat_interface:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_chat
|
||||
path: packages/flutter_chat_interface
|
||||
ref: 3.0.0
|
||||
ref: 3.0.1
|
||||
flutter_chat_local:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_chat
|
||||
path: packages/flutter_chat_local
|
||||
ref: 3.0.0
|
||||
ref: 3.0.1
|
||||
uuid: ^4.3.3
|
||||
|
||||
dev_dependencies:
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
/// Options for Firebase chat configuration.
|
||||
@immutable
|
||||
class FirebaseChatOptions {
|
||||
/// Creates a new instance of `FirebaseChatOptions`.
|
||||
const FirebaseChatOptions({
|
||||
this.groupChatsCollectionName = 'group_chats',
|
||||
this.chatsCollectionName = 'chats',
|
||||
this.messagesCollectionName = 'messages',
|
||||
this.usersCollectionName = 'users',
|
||||
this.chatsMetaDataCollectionName = 'chat_metadata',
|
||||
this.userChatsCollectionName = 'chats',
|
||||
this.groupChatsCollectionName = "group_chats",
|
||||
this.chatsCollectionName = "chats",
|
||||
this.messagesCollectionName = "messages",
|
||||
this.usersCollectionName = "users",
|
||||
this.chatsMetaDataCollectionName = "chat_metadata",
|
||||
this.userChatsCollectionName = "chats",
|
||||
});
|
||||
|
||||
/// The collection name for group chats.
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat_firebase/dto/firebase_message_document.dart';
|
||||
import "package:cloud_firestore/cloud_firestore.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat_firebase/dto/firebase_message_document.dart";
|
||||
|
||||
/// Represents a chat document in Firebase.
|
||||
@immutable
|
||||
|
@ -23,16 +23,16 @@ class FirebaseChatDocument {
|
|||
|
||||
/// Constructs a FirebaseChatDocument from JSON.
|
||||
FirebaseChatDocument.fromJson(Map<String, dynamic> json, this.id)
|
||||
: title = json['title'],
|
||||
imageUrl = json['image_url'],
|
||||
personal = json['personal'],
|
||||
canBeDeleted = json['can_be_deleted'] ?? true,
|
||||
lastUsed = json['last_used'],
|
||||
users = json['users'] != null ? List<String>.from(json['users']) : [],
|
||||
lastMessage = json['last_message'] == null
|
||||
: title = json["title"],
|
||||
imageUrl = json["image_url"],
|
||||
personal = json["personal"],
|
||||
canBeDeleted = json["can_be_deleted"] ?? true,
|
||||
lastUsed = json["last_used"],
|
||||
users = json["users"] != null ? List<String>.from(json["users"]) : [],
|
||||
lastMessage = json["last_message"] == null
|
||||
? null
|
||||
: FirebaseMessageDocument.fromJson(
|
||||
json['last_message'],
|
||||
json["last_message"],
|
||||
null,
|
||||
);
|
||||
|
||||
|
@ -62,11 +62,11 @@ class FirebaseChatDocument {
|
|||
|
||||
/// Converts the FirebaseChatDocument to JSON format.
|
||||
Map<String, dynamic> toJson() => {
|
||||
'title': title,
|
||||
'image_url': imageUrl,
|
||||
'personal': personal,
|
||||
'last_used': lastUsed,
|
||||
'can_be_deleted': canBeDeleted,
|
||||
'users': users,
|
||||
"title": title,
|
||||
"image_url": imageUrl,
|
||||
"personal": personal,
|
||||
"last_used": lastUsed,
|
||||
"can_be_deleted": canBeDeleted,
|
||||
"users": users,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:cloud_firestore/cloud_firestore.dart";
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
/// Represents a message document in Firebase.
|
||||
@immutable
|
||||
|
@ -19,10 +19,10 @@ class FirebaseMessageDocument {
|
|||
|
||||
/// Constructs a FirebaseMessageDocument from JSON.
|
||||
FirebaseMessageDocument.fromJson(Map<String, dynamic> json, this.id)
|
||||
: sender = json['sender'],
|
||||
text = json['text'],
|
||||
imageUrl = json['image_url'],
|
||||
timestamp = json['timestamp'];
|
||||
: sender = json["sender"],
|
||||
text = json["text"],
|
||||
imageUrl = json["image_url"],
|
||||
timestamp = json["timestamp"];
|
||||
|
||||
/// The unique identifier of the message document.
|
||||
final String? id;
|
||||
|
@ -41,9 +41,9 @@ class FirebaseMessageDocument {
|
|||
|
||||
/// Converts the FirebaseMessageDocument to JSON format.
|
||||
Map<String, dynamic> toJson() => {
|
||||
'sender': sender,
|
||||
'text': text,
|
||||
'image_url': imageUrl,
|
||||
'timestamp': timestamp,
|
||||
"sender": sender,
|
||||
"text": text,
|
||||
"image_url": imageUrl,
|
||||
"timestamp": timestamp,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
/// Represents a user document in Firebase.
|
||||
@immutable
|
||||
|
@ -22,11 +22,11 @@ class FirebaseUserDocument {
|
|||
) : this(
|
||||
id: id,
|
||||
firstName:
|
||||
json['first_name'] == null ? '' : json['first_name']! as String,
|
||||
json["first_name"] == null ? "" : json["first_name"]! as String,
|
||||
lastName:
|
||||
json['last_name'] == null ? '' : json['last_name']! as String,
|
||||
json["last_name"] == null ? "" : json["last_name"]! as String,
|
||||
imageUrl:
|
||||
json['image_url'] == null ? null : json['image_url']! as String,
|
||||
json["image_url"] == null ? null : json["image_url"]! as String,
|
||||
);
|
||||
|
||||
/// The first name of the user.
|
||||
|
@ -43,8 +43,8 @@ class FirebaseUserDocument {
|
|||
|
||||
/// Converts the FirebaseUserDocument to JSON format.
|
||||
Map<String, Object?> toJson() => {
|
||||
'first_name': firstName,
|
||||
'last_name': lastName,
|
||||
'image_url': imageUrl,
|
||||
"first_name": firstName,
|
||||
"last_name": lastName,
|
||||
"image_url": imageUrl,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
///
|
||||
library flutter_chat_firebase;
|
||||
|
||||
export 'package:flutter_chat_firebase/service/service.dart';
|
||||
export "package:flutter_chat_firebase/service/service.dart";
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:firebase_storage/firebase_storage.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat_firebase/config/firebase_chat_options.dart';
|
||||
import 'package:flutter_chat_firebase/dto/firebase_message_document.dart';
|
||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
import "dart:async";
|
||||
import "dart:typed_data";
|
||||
import "package:cloud_firestore/cloud_firestore.dart";
|
||||
import "package:firebase_core/firebase_core.dart";
|
||||
import "package:firebase_storage/firebase_storage.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat_firebase/config/firebase_chat_options.dart";
|
||||
import "package:flutter_chat_firebase/dto/firebase_message_document.dart";
|
||||
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||
import "package:uuid/uuid.dart";
|
||||
|
||||
/// Service class for managing chat details using Firebase.
|
||||
class FirebaseChatDetailService
|
||||
|
@ -56,8 +56,8 @@ class FirebaseChatDetailService
|
|||
}
|
||||
|
||||
var message = {
|
||||
'sender': currentUser.id,
|
||||
'timestamp': DateTime.now(),
|
||||
"sender": currentUser.id,
|
||||
"timestamp": DateTime.now(),
|
||||
...data,
|
||||
};
|
||||
|
||||
|
@ -89,8 +89,8 @@ class FirebaseChatDetailService
|
|||
.doc(chatId);
|
||||
|
||||
await metadataReference.update({
|
||||
'last_used': DateTime.now(),
|
||||
'last_message': message,
|
||||
"last_used": DateTime.now(),
|
||||
"last_message": message,
|
||||
});
|
||||
|
||||
// update the chat counter for the other users
|
||||
|
@ -98,7 +98,7 @@ class FirebaseChatDetailService
|
|||
// there is a field in the chat document called users that has a
|
||||
// list of user ids
|
||||
var fetchedChat = await metadataReference.get();
|
||||
var chatUsers = fetchedChat.data()?['users'] as List<dynamic>;
|
||||
var chatUsers = fetchedChat.data()?["users"] as List<dynamic>;
|
||||
// for all users except the message sender update the unread counter
|
||||
for (var userId in chatUsers) {
|
||||
if (userId != currentUser.id) {
|
||||
|
@ -113,15 +113,15 @@ class FirebaseChatDetailService
|
|||
// it should be created when the chat is create
|
||||
if ((await userReference.get())
|
||||
.data()
|
||||
?.containsKey('amount_unread_messages') ??
|
||||
?.containsKey("amount_unread_messages") ??
|
||||
false) {
|
||||
await userReference.update({
|
||||
'amount_unread_messages': FieldValue.increment(1),
|
||||
"amount_unread_messages": FieldValue.increment(1),
|
||||
});
|
||||
} else {
|
||||
await userReference.set(
|
||||
{
|
||||
'amount_unread_messages': 1,
|
||||
"amount_unread_messages": 1,
|
||||
},
|
||||
SetOptions(merge: true),
|
||||
);
|
||||
|
@ -142,7 +142,7 @@ class FirebaseChatDetailService
|
|||
_sendMessage(
|
||||
chatId,
|
||||
{
|
||||
'text': text,
|
||||
"text": text,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -156,7 +156,7 @@ class FirebaseChatDetailService
|
|||
required Uint8List image,
|
||||
}) async {
|
||||
var ref = _storage
|
||||
.ref('${_options.chatsCollectionName}/$chatId/${const Uuid().v4()}');
|
||||
.ref("${_options.chatsCollectionName}/$chatId/${const Uuid().v4()}");
|
||||
|
||||
return ref.putData(image).then(
|
||||
(_) => ref.getDownloadURL().then(
|
||||
|
@ -164,7 +164,7 @@ class FirebaseChatDetailService
|
|||
_sendMessage(
|
||||
chatId,
|
||||
{
|
||||
'image_url': url,
|
||||
"image_url": url,
|
||||
},
|
||||
);
|
||||
},
|
||||
|
@ -186,7 +186,7 @@ class FirebaseChatDetailService
|
|||
.doc(chatId)
|
||||
.collection(_options.messagesCollectionName)
|
||||
.where(
|
||||
'timestamp',
|
||||
"timestamp",
|
||||
isGreaterThan: timestampToFilter,
|
||||
)
|
||||
.withConverter<FirebaseMessageDocument>(
|
||||
|
@ -241,7 +241,7 @@ class FirebaseChatDetailService
|
|||
_cumulativeMessages = [];
|
||||
lastChat = chatId;
|
||||
lastMessage = null;
|
||||
debugPrint('Canceling messages stream');
|
||||
debugPrint("Canceling messages stream");
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -280,7 +280,7 @@ class FirebaseChatDetailService
|
|||
.collection(_options.chatsCollectionName)
|
||||
.doc(chatId)
|
||||
.collection(_options.messagesCollectionName)
|
||||
.orderBy('timestamp', descending: true)
|
||||
.orderBy("timestamp", descending: true)
|
||||
.limit(pageSize);
|
||||
if (lastMessage == null) {
|
||||
messagesQuerySnapshot = await query
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'dart:async';
|
||||
import "dart:async";
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:firebase_storage/firebase_storage.dart';
|
||||
import 'package:flutter_chat_firebase/config/firebase_chat_options.dart';
|
||||
import 'package:flutter_chat_firebase/dto/firebase_chat_document.dart';
|
||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
||||
import "package:cloud_firestore/cloud_firestore.dart";
|
||||
import "package:firebase_core/firebase_core.dart";
|
||||
import "package:firebase_storage/firebase_storage.dart";
|
||||
import "package:flutter_chat_firebase/config/firebase_chat_options.dart";
|
||||
import "package:flutter_chat_firebase/dto/firebase_chat_document.dart";
|
||||
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||
|
||||
/// Service class for managing chat overviews using Firebase.
|
||||
class FirebaseChatOverviewService implements ChatOverviewService {
|
||||
|
@ -49,7 +49,7 @@ class FirebaseChatOverviewService implements ChatOverviewService {
|
|||
.doc(chatId)
|
||||
.get();
|
||||
|
||||
return snapshots.data()?['amount_unread_messages'];
|
||||
return snapshots.data()?["amount_unread_messages"];
|
||||
}
|
||||
|
||||
/// Retrieves a stream of chat overviews.
|
||||
|
@ -144,8 +144,8 @@ class FirebaseChatOverviewService implements ChatOverviewService {
|
|||
}
|
||||
chatModel = GroupChatModel(
|
||||
id: chat.id,
|
||||
title: chat.title ?? '',
|
||||
imageUrl: chat.imageUrl ?? '',
|
||||
title: chat.title ?? "",
|
||||
imageUrl: chat.imageUrl ?? "",
|
||||
unreadMessages: unread,
|
||||
users: users,
|
||||
lastMessage: chat.lastMessage != null && otherUser != null
|
||||
|
@ -226,7 +226,7 @@ class FirebaseChatOverviewService implements ChatOverviewService {
|
|||
.collection(_options.usersCollectionName)
|
||||
.doc(currentUser?.id)
|
||||
.collection(_options.userChatsCollectionName)
|
||||
.where('users', arrayContains: user.id)
|
||||
.where("users", arrayContains: user.id)
|
||||
.get();
|
||||
|
||||
var doc = collection.docs.isNotEmpty ? collection.docs.first : null;
|
||||
|
@ -250,16 +250,16 @@ class FirebaseChatOverviewService implements ChatOverviewService {
|
|||
.doc(chatId)
|
||||
.get();
|
||||
|
||||
if (chatCollection.exists && chatCollection.data()?['users'] != null) {
|
||||
if (chatCollection.exists && chatCollection.data()?["users"] != null) {
|
||||
// ignore: avoid_dynamic_calls
|
||||
var otherUser = chatCollection.data()?['users'].firstWhere(
|
||||
var otherUser = chatCollection.data()?["users"].firstWhere(
|
||||
(element) => element != currentUser?.id,
|
||||
);
|
||||
var user = await _userService.getUser(otherUser);
|
||||
return PersonalChatModel(
|
||||
id: chatId,
|
||||
user: user!,
|
||||
canBeDeleted: chatCollection.data()?['can_be_deleted'] ?? true,
|
||||
canBeDeleted: chatCollection.data()?["can_be_deleted"] ?? true,
|
||||
);
|
||||
} else {
|
||||
var groupChatCollection = await _db
|
||||
|
@ -281,8 +281,8 @@ class FirebaseChatOverviewService implements ChatOverviewService {
|
|||
}
|
||||
return GroupChatModel(
|
||||
id: chat?.id ?? chatId,
|
||||
title: chat?.title ?? '',
|
||||
imageUrl: chat?.imageUrl ?? '',
|
||||
title: chat?.title ?? "",
|
||||
imageUrl: chat?.imageUrl ?? "",
|
||||
users: users,
|
||||
canBeDeleted: chat?.canBeDeleted ?? true,
|
||||
);
|
||||
|
@ -373,7 +373,7 @@ class FirebaseChatOverviewService implements ChatOverviewService {
|
|||
.doc(userId)
|
||||
.collection(_options.userChatsCollectionName)
|
||||
.doc(reference.id)
|
||||
.set({'users': userIds}, SetOptions(merge: true));
|
||||
.set({"users": userIds}, SetOptions(merge: true));
|
||||
}
|
||||
|
||||
chat.id = reference.id;
|
||||
|
@ -411,11 +411,11 @@ class FirebaseChatOverviewService implements ChatOverviewService {
|
|||
.doc(userId)
|
||||
.collection(_options.groupChatsCollectionName)
|
||||
.doc(reference.id)
|
||||
.set({'users': userIds}, SetOptions(merge: true));
|
||||
.set({"users": userIds}, SetOptions(merge: true));
|
||||
}
|
||||
chat.id = reference.id;
|
||||
} else {
|
||||
throw Exception('Chat type not supported for firebase');
|
||||
throw Exception("Chat type not supported for firebase");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -443,7 +443,7 @@ class FirebaseChatOverviewService implements ChatOverviewService {
|
|||
// every chat has a field called amount_unread_messages, combine all
|
||||
// of these fields to get the total amount of unread messages
|
||||
var unreadChats = event.docs
|
||||
.map((chat) => chat.data()['amount_unread_messages'] ?? 0)
|
||||
.map((chat) => chat.data()["amount_unread_messages"] ?? 0)
|
||||
.toList();
|
||||
var totalUnreadChats = unreadChats.fold<int>(
|
||||
0,
|
||||
|
@ -476,6 +476,6 @@ class FirebaseChatOverviewService implements ChatOverviewService {
|
|||
.doc(currentUser!.id)
|
||||
.collection(_options.userChatsCollectionName)
|
||||
.doc(chat.id)
|
||||
.set({'amount_unread_messages': 0}, SetOptions(merge: true));
|
||||
.set({"amount_unread_messages": 0}, SetOptions(merge: true));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:flutter_chat_firebase/config/firebase_chat_options.dart';
|
||||
import 'package:flutter_chat_firebase/flutter_chat_firebase.dart';
|
||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
||||
import "package:firebase_core/firebase_core.dart";
|
||||
import "package:flutter_chat_firebase/config/firebase_chat_options.dart";
|
||||
import "package:flutter_chat_firebase/flutter_chat_firebase.dart";
|
||||
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||
|
||||
/// Service class for managing chat services using Firebase.
|
||||
class FirebaseChatService implements ChatService {
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:flutter_chat_firebase/config/firebase_chat_options.dart';
|
||||
import 'package:flutter_chat_firebase/dto/firebase_user_document.dart';
|
||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
||||
import "package:cloud_firestore/cloud_firestore.dart";
|
||||
import "package:firebase_auth/firebase_auth.dart";
|
||||
import "package:firebase_core/firebase_core.dart";
|
||||
import "package:flutter_chat_firebase/config/firebase_chat_options.dart";
|
||||
import "package:flutter_chat_firebase/dto/firebase_user_document.dart";
|
||||
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||
|
||||
/// Service class for managing chat users using Firebase.
|
||||
class FirebaseChatUserService implements ChatUserService {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export 'package:flutter_chat_firebase/service/firebase_chat_detail_service.dart';
|
||||
export 'package:flutter_chat_firebase/service/firebase_chat_overview_service.dart';
|
||||
export 'package:flutter_chat_firebase/service/firebase_chat_service.dart';
|
||||
export 'package:flutter_chat_firebase/service/firebase_chat_user_service.dart';
|
||||
export "package:flutter_chat_firebase/service/firebase_chat_detail_service.dart";
|
||||
export "package:flutter_chat_firebase/service/firebase_chat_overview_service.dart";
|
||||
export "package:flutter_chat_firebase/service/firebase_chat_service.dart";
|
||||
export "package:flutter_chat_firebase/service/firebase_chat_user_service.dart";
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
name: flutter_chat_firebase
|
||||
description: A new Flutter package project.
|
||||
version: 3.0.0
|
||||
version: 3.0.1
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
|
@ -23,7 +23,7 @@ dependencies:
|
|||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_chat
|
||||
path: packages/flutter_chat_interface
|
||||
ref: 3.0.0
|
||||
ref: 3.0.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_iconica_analysis:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
name: flutter_chat_interface
|
||||
description: A new Flutter package project.
|
||||
version: 3.0.0
|
||||
version: 3.0.1
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
///
|
||||
library local_chat_service;
|
||||
|
||||
export 'service/local_chat_detail_service.dart';
|
||||
export 'service/local_chat_overview_service.dart';
|
||||
export 'service/local_chat_service.dart';
|
||||
export 'service/local_chat_user_service.dart';
|
||||
export "service/local_chat_detail_service.dart";
|
||||
export "service/local_chat_overview_service.dart";
|
||||
export "service/local_chat_service.dart";
|
||||
export "service/local_chat_user_service.dart";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import 'dart:async';
|
||||
import "dart:async";
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
||||
import 'package:flutter_chat_local/local_chat_service.dart';
|
||||
import "package:flutter/foundation.dart";
|
||||
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||
import "package:flutter_chat_local/local_chat_service.dart";
|
||||
|
||||
/// A class providing local chat detail service implementation.
|
||||
class LocalChatDetailService with ChangeNotifier implements ChatDetailService {
|
||||
|
@ -69,13 +69,13 @@ class LocalChatDetailService with ChangeNotifier implements ChatDetailService {
|
|||
.firstWhere((element) => element.id == chatId);
|
||||
var message = ChatImageMessageModel(
|
||||
sender: const ChatUserModel(
|
||||
id: '3',
|
||||
firstName: 'ico',
|
||||
lastName: 'nica',
|
||||
imageUrl: 'https://picsum.photos/100/200',
|
||||
id: "3",
|
||||
firstName: "ico",
|
||||
lastName: "nica",
|
||||
imageUrl: "https://picsum.photos/100/200",
|
||||
),
|
||||
timestamp: DateTime.now(),
|
||||
imageUrl: 'https://picsum.photos/200/300',
|
||||
imageUrl: "https://picsum.photos/200/300",
|
||||
);
|
||||
|
||||
await (chatOverviewService as LocalChatOverviewService).updateChat(
|
||||
|
@ -102,10 +102,10 @@ class LocalChatDetailService with ChangeNotifier implements ChatDetailService {
|
|||
.firstWhere((element) => element.id == chatId);
|
||||
var message = ChatTextMessageModel(
|
||||
sender: const ChatUserModel(
|
||||
id: '3',
|
||||
firstName: 'ico',
|
||||
lastName: 'nica',
|
||||
imageUrl: 'https://picsum.photos/100/200',
|
||||
id: "3",
|
||||
firstName: "ico",
|
||||
lastName: "nica",
|
||||
imageUrl: "https://picsum.photos/100/200",
|
||||
),
|
||||
timestamp: DateTime.now(),
|
||||
text: text,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'dart:async';
|
||||
import "dart:async";
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
||||
import "package:flutter/foundation.dart";
|
||||
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||
|
||||
/// A class providing local chat overview service implementation.
|
||||
class LocalChatOverviewService
|
||||
|
@ -22,7 +22,7 @@ class LocalChatOverviewService
|
|||
_chats[index] = chat;
|
||||
_chatsController.addStream(Stream.value(_chats));
|
||||
notifyListeners();
|
||||
debugPrint('Chat updated: $chat');
|
||||
debugPrint("Chat updated: $chat");
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
|
@ -31,15 +31,15 @@ class LocalChatOverviewService
|
|||
_chats.removeWhere((element) => element.id == chat.id);
|
||||
_chatsController.add(_chats);
|
||||
notifyListeners();
|
||||
debugPrint('Chat deleted: $chat');
|
||||
debugPrint("Chat deleted: $chat");
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ChatModel> getChatById(String id) {
|
||||
var chat = _chats.firstWhere((element) => element.id == id);
|
||||
debugPrint('Retrieved chat by ID: $chat');
|
||||
debugPrint('Messages are: ${chat.messages?.length}');
|
||||
debugPrint("Retrieved chat by ID: $chat");
|
||||
debugPrint("Messages are: ${chat.messages?.length}");
|
||||
return Future.value(chat);
|
||||
}
|
||||
|
||||
|
@ -55,11 +55,11 @@ class LocalChatOverviewService
|
|||
chat = PersonalChatModel(
|
||||
user: user,
|
||||
messages: [],
|
||||
id: '',
|
||||
id: "",
|
||||
);
|
||||
chat.id = chat.hashCode.toString();
|
||||
_chats.add(chat);
|
||||
debugPrint('New chat created: $chat');
|
||||
debugPrint("New chat created: $chat");
|
||||
}
|
||||
|
||||
_chatsController.add([..._chats]);
|
||||
|
@ -85,9 +85,9 @@ class LocalChatOverviewService
|
|||
_chats.add(chat);
|
||||
_chatsController.add([..._chats]);
|
||||
notifyListeners();
|
||||
debugPrint('Chat stored: $chat');
|
||||
debugPrint("Chat stored: $chat");
|
||||
} else {
|
||||
debugPrint('Chat already exists: $chat');
|
||||
debugPrint("Chat already exists: $chat");
|
||||
}
|
||||
|
||||
return Future.value(chat);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
||||
import 'package:flutter_chat_local/service/local_chat_detail_service.dart';
|
||||
import 'package:flutter_chat_local/service/local_chat_overview_service.dart';
|
||||
import 'package:flutter_chat_local/service/local_chat_user_service.dart';
|
||||
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||
import "package:flutter_chat_local/service/local_chat_detail_service.dart";
|
||||
import "package:flutter_chat_local/service/local_chat_overview_service.dart";
|
||||
import "package:flutter_chat_local/service/local_chat_user_service.dart";
|
||||
|
||||
/// Service class for managing local chat services.
|
||||
class LocalChatService implements ChatService {
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
||||
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||
|
||||
/// Service class for managing local chat users.
|
||||
class LocalChatUserService implements ChatUserService {
|
||||
/// List of predefined chat users.
|
||||
List<ChatUserModel> users = [
|
||||
const ChatUserModel(
|
||||
id: '1',
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
imageUrl: 'https://picsum.photos/200/300',
|
||||
id: "1",
|
||||
firstName: "John",
|
||||
lastName: "Doe",
|
||||
imageUrl: "https://picsum.photos/200/300",
|
||||
),
|
||||
const ChatUserModel(
|
||||
id: '2',
|
||||
firstName: 'Jane',
|
||||
lastName: 'Doe',
|
||||
imageUrl: 'https://picsum.photos/200/300',
|
||||
id: "2",
|
||||
firstName: "Jane",
|
||||
lastName: "Doe",
|
||||
imageUrl: "https://picsum.photos/200/300",
|
||||
),
|
||||
const ChatUserModel(
|
||||
id: '3',
|
||||
firstName: 'ico',
|
||||
lastName: 'nica',
|
||||
imageUrl: 'https://picsum.photos/100/200',
|
||||
id: "3",
|
||||
firstName: "ico",
|
||||
lastName: "nica",
|
||||
imageUrl: "https://picsum.photos/100/200",
|
||||
),
|
||||
];
|
||||
|
||||
@override
|
||||
Future<List<ChatUserModel>> getAllUsers() =>
|
||||
Future.value(users.where((element) => element.id != '3').toList());
|
||||
Future.value(users.where((element) => element.id != "3").toList());
|
||||
|
||||
@override
|
||||
Future<ChatUserModel?> getCurrentUser() =>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: flutter_chat_local
|
||||
description: "A new Flutter package project."
|
||||
version: 3.0.0
|
||||
version: 3.0.1
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
|
@ -14,7 +14,7 @@ dependencies:
|
|||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_chat
|
||||
path: packages/flutter_chat_interface
|
||||
ref: 3.0.0
|
||||
ref: 3.0.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
///
|
||||
library flutter_chat_view;
|
||||
|
||||
export 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
||||
export "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||
|
||||
export 'src/components/chat_row.dart';
|
||||
export 'src/config/chat_options.dart';
|
||||
export 'src/config/chat_translations.dart';
|
||||
export 'src/screens/chat_detail_screen.dart';
|
||||
export 'src/screens/chat_profile_screen.dart';
|
||||
export 'src/screens/chat_screen.dart';
|
||||
export 'src/screens/new_chat_screen.dart';
|
||||
export 'src/screens/new_group_chat_overview_screen.dart';
|
||||
export 'src/screens/new_group_chat_screen.dart';
|
||||
export "src/components/chat_row.dart";
|
||||
export "src/config/chat_options.dart";
|
||||
export "src/config/chat_translations.dart";
|
||||
export "src/screens/chat_detail_screen.dart";
|
||||
export "src/screens/chat_profile_screen.dart";
|
||||
export "src/screens/chat_screen.dart";
|
||||
export "src/screens/new_chat_screen.dart";
|
||||
export "src/screens/new_group_chat_overview_screen.dart";
|
||||
export "src/screens/new_group_chat_screen.dart";
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat_view/flutter_chat_view.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat_view/flutter_chat_view.dart";
|
||||
|
||||
class ChatBottom extends StatefulWidget {
|
||||
const ChatBottom({
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat_view/flutter_chat_view.dart';
|
||||
import 'package:flutter_chat_view/src/components/chat_image.dart';
|
||||
import 'package:flutter_chat_view/src/services/date_formatter.dart';
|
||||
import "package:cached_network_image/cached_network_image.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat_view/flutter_chat_view.dart";
|
||||
import "package:flutter_chat_view/src/components/chat_image.dart";
|
||||
import "package:flutter_chat_view/src/services/date_formatter.dart";
|
||||
|
||||
class ChatDetailRow extends StatefulWidget {
|
||||
const ChatDetailRow({
|
||||
|
@ -46,6 +46,8 @@ class _ChatDetailRowState extends State<ChatDetailRow> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
|
||||
var isNewDate = widget.previousMessage != null &&
|
||||
widget.message.timestamp.day != widget.previousMessage?.timestamp.day;
|
||||
var isSameSender = widget.previousMessage == null ||
|
||||
|
@ -54,7 +56,6 @@ class _ChatDetailRowState extends State<ChatDetailRow> {
|
|||
widget.message.timestamp.minute ==
|
||||
widget.previousMessage?.timestamp.minute;
|
||||
var hasHeader = isNewDate || isSameSender;
|
||||
var theme = Theme.of(context);
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: isNewDate || isSameSender ? 25.0 : 0,
|
||||
|
@ -69,8 +70,7 @@ class _ChatDetailRowState extends State<ChatDetailRow> {
|
|||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 10.0),
|
||||
child: widget.message.sender.imageUrl != null &&
|
||||
widget.message.sender.imageUrl!.isNotEmpty
|
||||
child: widget.message.sender.imageUrl?.isNotEmpty ?? false
|
||||
? ChatImage(
|
||||
image: widget.message.sender.imageUrl!,
|
||||
)
|
||||
|
@ -92,27 +92,24 @@ class _ChatDetailRowState extends State<ChatDetailRow> {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
if (isNewDate || isSameSender)
|
||||
if (isNewDate || isSameSender) ...[
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (widget.usernameBuilder != null)
|
||||
widget.usernameBuilder!(
|
||||
widget.message.sender.fullName ?? '',
|
||||
)
|
||||
else
|
||||
Text(
|
||||
widget.message.sender.fullName ??
|
||||
widget.translations.anonymousUser,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w800,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium
|
||||
?.color,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: widget.usernameBuilder?.call(
|
||||
widget.message.sender.fullName ?? "",
|
||||
) ??
|
||||
Text(
|
||||
widget.message.sender.fullName ??
|
||||
widget.translations.anonymousUser,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w800,
|
||||
color: theme.textTheme.labelMedium?.color,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Text(
|
||||
|
@ -129,6 +126,7 @@ class _ChatDetailRowState extends State<ChatDetailRow> {
|
|||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 3.0),
|
||||
child: widget.message is ChatTextMessageModel
|
||||
|
@ -141,10 +139,7 @@ class _ChatDetailRowState extends State<ChatDetailRow> {
|
|||
(widget.message as ChatTextMessageModel).text,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium
|
||||
?.color,
|
||||
color: theme.textTheme.labelMedium?.color,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -158,7 +153,7 @@ class _ChatDetailRowState extends State<ChatDetailRow> {
|
|||
date: widget.message.timestamp,
|
||||
showFullDate: true,
|
||||
)
|
||||
.split(' ')
|
||||
.split(" ")
|
||||
.last,
|
||||
style: theme.textTheme.bodySmall,
|
||||
textAlign: TextAlign.end,
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:cached_network_image/cached_network_image.dart";
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
/// A stateless widget representing an image in the chat.
|
||||
class ChatImage extends StatelessWidget {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
class ChatRow extends StatelessWidget {
|
||||
const ChatRow({
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat_view/flutter_chat_view.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat_view/flutter_chat_view.dart";
|
||||
|
||||
SnackBar getImageLoadingSnackbar(ChatTranslations translations) => SnackBar(
|
||||
duration: const Duration(minutes: 1),
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat_view/flutter_chat_view.dart';
|
||||
import 'package:flutter_chat_view/src/components/chat_image.dart';
|
||||
import 'package:flutter_image_picker/flutter_image_picker.dart';
|
||||
import 'package:flutter_profile/flutter_profile.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat_view/flutter_chat_view.dart";
|
||||
import "package:flutter_chat_view/src/components/chat_image.dart";
|
||||
import "package:flutter_image_picker/flutter_image_picker.dart";
|
||||
import "package:flutter_profile/flutter_profile.dart";
|
||||
|
||||
class ChatOptions {
|
||||
const ChatOptions({
|
||||
|
@ -133,7 +133,7 @@ Widget _createChatRowContainer(
|
|||
vertical: 12.0,
|
||||
horizontal: 10.0,
|
||||
),
|
||||
child: Container(
|
||||
child: ColoredBox(
|
||||
color: Colors.transparent,
|
||||
child: chatRow,
|
||||
),
|
||||
|
@ -177,6 +177,7 @@ Scaffold _createScaffold(
|
|||
Scaffold(
|
||||
appBar: appbar,
|
||||
body: body,
|
||||
backgroundColor: backgroundColor,
|
||||
);
|
||||
|
||||
Widget _createUserAvatar(
|
||||
|
|
|
@ -44,39 +44,39 @@ class ChatTranslations {
|
|||
|
||||
/// Default translations for the chat component view
|
||||
const ChatTranslations.empty({
|
||||
this.chatsTitle = 'Chats',
|
||||
this.chatsUnread = 'unread',
|
||||
this.newChatButton = 'Start chat',
|
||||
this.newGroupChatButton = 'Create a group chat',
|
||||
this.newChatTitle = 'Start a chat',
|
||||
this.image = 'Image',
|
||||
this.searchPlaceholder = 'Search...',
|
||||
this.startTyping = 'Start typing to find a user to chat with',
|
||||
this.cancelImagePickerBtn = 'Cancel',
|
||||
this.messagePlaceholder = 'Write your message here...',
|
||||
this.writeMessageToStartChat = 'Write a message to start the chat',
|
||||
this.chatsTitle = "Chats",
|
||||
this.chatsUnread = "unread",
|
||||
this.newChatButton = "Start chat",
|
||||
this.newGroupChatButton = "Create a group chat",
|
||||
this.newChatTitle = "Start a chat",
|
||||
this.image = "Image",
|
||||
this.searchPlaceholder = "Search...",
|
||||
this.startTyping = "Start typing to find a user to chat with",
|
||||
this.cancelImagePickerBtn = "Cancel",
|
||||
this.messagePlaceholder = "Write your message here...",
|
||||
this.writeMessageToStartChat = "Write a message to start the chat",
|
||||
this.writeFirstMessageInGroupChat =
|
||||
'Write the first message in this group chat',
|
||||
this.imageUploading = 'Image is uploading...',
|
||||
this.deleteChatButton = 'Delete',
|
||||
this.deleteChatModalTitle = 'Delete chat',
|
||||
"Write the first message in this group chat",
|
||||
this.imageUploading = "Image is uploading...",
|
||||
this.deleteChatButton = "Delete",
|
||||
this.deleteChatModalTitle = "Delete chat",
|
||||
this.deleteChatModalDescription =
|
||||
'Are you sure you want to delete this chat?',
|
||||
this.deleteChatModalCancel = 'Cancel',
|
||||
this.deleteChatModalConfirm = 'Delete',
|
||||
this.noUsersFound = 'No users were found to start a chat with',
|
||||
this.noChatsFound = 'Click on \'Start a chat\' to create a new chat',
|
||||
this.anonymousUser = 'Anonymous user',
|
||||
this.chatCantBeDeleted = 'This chat can\'t be deleted',
|
||||
this.chatProfileUsers = 'Users:',
|
||||
this.imagePickerTitle = 'Do you want to upload a file or take a picture?',
|
||||
this.uploadFile = 'UPLOAD FILE',
|
||||
this.takePicture = 'TAKE PICTURE',
|
||||
this.groupNameHintText = 'Group chat name',
|
||||
this.groupNameValidatorEmpty = 'Please enter a group chat name',
|
||||
"Are you sure you want to delete this chat?",
|
||||
this.deleteChatModalCancel = "Cancel",
|
||||
this.deleteChatModalConfirm = "Delete",
|
||||
this.noUsersFound = "No users were found to start a chat with",
|
||||
this.noChatsFound = "Click on 'Start a chat' to create a new chat",
|
||||
this.anonymousUser = "Anonymous user",
|
||||
this.chatCantBeDeleted = "This chat can't be deleted",
|
||||
this.chatProfileUsers = "Users:",
|
||||
this.imagePickerTitle = "Do you want to upload a file or take a picture?",
|
||||
this.uploadFile = "UPLOAD FILE",
|
||||
this.takePicture = "TAKE PICTURE",
|
||||
this.groupNameHintText = "Group chat name",
|
||||
this.groupNameValidatorEmpty = "Please enter a group chat name",
|
||||
this.groupNameValidatorTooLong =
|
||||
'Group name is too long, max 15 characters',
|
||||
this.newGroupChatTitle = 'New Group Chat',
|
||||
"Group name is too long, max 15 characters",
|
||||
this.newGroupChatTitle = "New Group Chat",
|
||||
});
|
||||
|
||||
final String chatsTitle;
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
import "dart:async";
|
||||
import "dart:typed_data";
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat_view/flutter_chat_view.dart';
|
||||
import 'package:flutter_chat_view/src/components/chat_bottom.dart';
|
||||
import 'package:flutter_chat_view/src/components/chat_detail_row.dart';
|
||||
import 'package:flutter_chat_view/src/components/image_loading_snackbar.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat_view/flutter_chat_view.dart";
|
||||
import "package:flutter_chat_view/src/components/chat_bottom.dart";
|
||||
import "package:flutter_chat_view/src/components/chat_detail_row.dart";
|
||||
import "package:flutter_chat_view/src/components/image_loading_snackbar.dart";
|
||||
|
||||
class ChatDetailScreen extends StatefulWidget {
|
||||
const ChatDetailScreen({
|
||||
|
@ -167,8 +167,13 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
|
|||
future: widget.service.chatOverviewService.getChatById(widget.chatId),
|
||||
builder: (context, AsyncSnapshot<ChatModel> snapshot) {
|
||||
var chatModel = snapshot.data;
|
||||
var chatTitle = (chatModel is GroupChatModel)
|
||||
? chatModel.title
|
||||
: (chatModel is PersonalChatModel)
|
||||
? chatModel.user.firstName ?? widget.translations.anonymousUser
|
||||
: "";
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.colorScheme.surface,
|
||||
appBar: AppBar(
|
||||
backgroundColor: theme.appBarTheme.backgroundColor,
|
||||
iconTheme: theme.appBarTheme.iconTheme ??
|
||||
|
@ -184,36 +189,12 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
|
|||
),
|
||||
title: GestureDetector(
|
||||
onTap: () => widget.onPressChatTitle.call(context, chatModel!),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: chat == null
|
||||
? []
|
||||
: [
|
||||
Padding(
|
||||
padding: (chatModel is GroupChatModel)
|
||||
? const EdgeInsets.only(left: 15.5)
|
||||
: EdgeInsets.zero,
|
||||
child: widget.chatTitleBuilder != null
|
||||
? widget.chatTitleBuilder!.call(
|
||||
(chatModel is GroupChatModel)
|
||||
? chatModel.title
|
||||
: (chatModel is PersonalChatModel)
|
||||
? chatModel.user.firstName ??
|
||||
widget.translations.anonymousUser
|
||||
: '',
|
||||
)
|
||||
: Text(
|
||||
(chatModel is GroupChatModel)
|
||||
? chatModel.title
|
||||
: (chatModel is PersonalChatModel)
|
||||
? chatModel.user.firstName ??
|
||||
widget.translations.anonymousUser
|
||||
: '',
|
||||
style: theme.appBarTheme.titleTextStyle,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: widget.chatTitleBuilder?.call(chatTitle) ??
|
||||
Text(
|
||||
chatTitle,
|
||||
style: theme.appBarTheme.titleTextStyle,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
body: Stack(
|
||||
|
@ -251,7 +232,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
|
|||
reverse: detailRows.isNotEmpty,
|
||||
padding: const EdgeInsets.only(top: 24.0),
|
||||
children: [
|
||||
if (detailRows.isEmpty)
|
||||
if (detailRows.isEmpty && !showIndicator) ...[
|
||||
Center(
|
||||
child: Text(
|
||||
(chatModel is GroupChatModel)
|
||||
|
@ -262,12 +243,13 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
|
|||
style: theme.textTheme.bodySmall,
|
||||
),
|
||||
),
|
||||
],
|
||||
...detailRows,
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (chatModel != null)
|
||||
if (chatModel != null) ...[
|
||||
ChatBottom(
|
||||
chat: chatModel,
|
||||
messageInputBuilder: widget.options.messageInputBuilder,
|
||||
|
@ -277,12 +259,13 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
|
|||
iconColor: widget.iconColor,
|
||||
iconDisabledColor: widget.iconDisabledColor,
|
||||
),
|
||||
],
|
||||
SizedBox(
|
||||
height: widget.textfieldBottomPadding,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (showIndicator)
|
||||
if (showIndicator) ...[
|
||||
widget.loadingWidgetBuilder?.call(context) ??
|
||||
const Column(
|
||||
children: [
|
||||
|
@ -295,6 +278,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
|
|||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat_view/flutter_chat_view.dart';
|
||||
import 'package:flutter_profile/flutter_profile.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat_view/flutter_chat_view.dart";
|
||||
import "package:flutter_profile/flutter_profile.dart";
|
||||
|
||||
class ChatProfileScreen extends StatefulWidget {
|
||||
const ChatProfileScreen({
|
||||
|
@ -66,7 +66,6 @@ class _ProfileScreenState extends State<ChatProfileScreen> {
|
|||
);
|
||||
}
|
||||
return Scaffold(
|
||||
backgroundColor: theme.colorScheme.surface,
|
||||
appBar: AppBar(
|
||||
backgroundColor: theme.appBarTheme.backgroundColor,
|
||||
iconTheme: theme.appBarTheme.iconTheme ??
|
||||
|
@ -75,10 +74,10 @@ class _ProfileScreenState extends State<ChatProfileScreen> {
|
|||
(data is ChatUserModel)
|
||||
? '${data.firstName ?? ''} ${data.lastName ?? ''}'
|
||||
: (data is PersonalChatModel)
|
||||
? data.user.fullName ?? ''
|
||||
? data.user.fullName ?? ""
|
||||
: (data is GroupChatModel)
|
||||
? data.title
|
||||
: '',
|
||||
: "",
|
||||
style: theme.appBarTheme.titleTextStyle,
|
||||
),
|
||||
),
|
||||
|
@ -111,8 +110,8 @@ class _ProfileScreenState extends State<ChatProfileScreen> {
|
|||
),
|
||||
...data.users.map((e) {
|
||||
var user = User(
|
||||
firstName: e.firstName ?? '',
|
||||
lastName: e.lastName ?? '',
|
||||
firstName: e.firstName ?? "",
|
||||
lastName: e.lastName ?? "",
|
||||
imageUrl: e.imageUrl,
|
||||
);
|
||||
return Padding(
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'dart:async';
|
||||
import "dart:async";
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat_view/flutter_chat_view.dart';
|
||||
import 'package:flutter_chat_view/src/services/date_formatter.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat_view/flutter_chat_view.dart";
|
||||
import "package:flutter_chat_view/src/services/date_formatter.dart";
|
||||
|
||||
class ChatScreen extends StatefulWidget {
|
||||
const ChatScreen({
|
||||
|
@ -94,7 +94,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 22.0),
|
||||
child: Text(
|
||||
'${snapshot.data ?? 0} ${translations.chatsUnread}',
|
||||
"${snapshot.data ?? 0} ${translations.chatsUnread}",
|
||||
style: widget.unreadMessageTextStyle ??
|
||||
const TextStyle(
|
||||
color: Colors.white,
|
||||
|
@ -143,13 +143,11 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||
for (ChatModel chat in (snapshot.data ?? []).where(
|
||||
(chat) => !deletedChats.contains(chat.id),
|
||||
)) ...[
|
||||
Container(
|
||||
DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary
|
||||
color: theme.colorScheme.secondary
|
||||
.withOpacity(0.3),
|
||||
width: 0.5,
|
||||
),
|
||||
|
@ -269,7 +267,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||
});
|
||||
widget.onDeleteChat(chat);
|
||||
},
|
||||
background: Container(
|
||||
background: ColoredBox(
|
||||
color: Colors.red,
|
||||
child: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
|
@ -354,9 +352,9 @@ class ChatListItem extends StatelessWidget {
|
|||
subTitle: chat.lastMessage != null
|
||||
? chat.lastMessage is ChatTextMessageModel
|
||||
? (chat.lastMessage! as ChatTextMessageModel).text
|
||||
: '📷 '
|
||||
'${translations.image}'
|
||||
: '',
|
||||
: "📷 "
|
||||
"${translations.image}"
|
||||
: "",
|
||||
lastUsed: chat.lastUsed != null
|
||||
? _dateFormatter.format(
|
||||
date: chat.lastUsed!,
|
||||
|
@ -369,9 +367,9 @@ class ChatListItem extends StatelessWidget {
|
|||
subTitle: chat.lastMessage != null
|
||||
? chat.lastMessage is ChatTextMessageModel
|
||||
? (chat.lastMessage! as ChatTextMessageModel).text
|
||||
: '📷 '
|
||||
'${translations.image}'
|
||||
: '',
|
||||
: "📷 "
|
||||
"${translations.image}"
|
||||
: "",
|
||||
avatar: widget.options.groupAvatarBuilder(
|
||||
(chat as GroupChatModel).title,
|
||||
(chat as GroupChatModel).imageUrl,
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat_view/flutter_chat_view.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat_view/flutter_chat_view.dart";
|
||||
|
||||
class NewChatScreen extends StatefulWidget {
|
||||
const NewChatScreen({
|
||||
|
@ -41,13 +41,12 @@ class NewChatScreen extends StatefulWidget {
|
|||
class _NewChatScreenState extends State<NewChatScreen> {
|
||||
final FocusNode _textFieldFocusNode = FocusNode();
|
||||
bool _isSearching = false;
|
||||
String query = '';
|
||||
String query = "";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
backgroundColor: theme.colorScheme.surface,
|
||||
appBar: AppBar(
|
||||
iconTheme: theme.appBarTheme.iconTheme ??
|
||||
const IconThemeData(color: Colors.white),
|
||||
|
@ -111,7 +110,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
|||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (snapshot.hasError) {
|
||||
return Text('Error: ${snapshot.error}');
|
||||
return Text("Error: ${snapshot.error}");
|
||||
} else if (snapshot.hasData) {
|
||||
return _buildUserList(snapshot.data!);
|
||||
} else {
|
||||
|
@ -162,7 +161,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
|||
onPressed: () {
|
||||
setState(() {
|
||||
_isSearching = !_isSearching;
|
||||
query = '';
|
||||
query = "";
|
||||
});
|
||||
|
||||
if (_isSearching) {
|
||||
|
@ -207,7 +206,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
|||
itemCount: filteredUsers.length,
|
||||
itemBuilder: (context, index) {
|
||||
var user = filteredUsers[index];
|
||||
return Container(
|
||||
return DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
|
@ -221,7 +220,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
|||
Padding(
|
||||
padding: widget.options.paddingAroundChatList ??
|
||||
const EdgeInsets.symmetric(vertical: 8, horizontal: 28),
|
||||
child: Container(
|
||||
child: ColoredBox(
|
||||
color: Colors.transparent,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat_view/flutter_chat_view.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat_view/flutter_chat_view.dart";
|
||||
|
||||
class NewGroupChatOverviewScreen extends StatefulWidget {
|
||||
const NewGroupChatOverviewScreen({
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_chat_view/flutter_chat_view.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat_view/flutter_chat_view.dart";
|
||||
|
||||
class NewGroupChatScreen extends StatefulWidget {
|
||||
const NewGroupChatScreen({
|
||||
|
@ -26,7 +26,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
|||
List<ChatUserModel> selectedUserList = [];
|
||||
|
||||
bool _isSearching = false;
|
||||
String query = '';
|
||||
String query = "";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -49,7 +49,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
|||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (snapshot.hasError) {
|
||||
return Text('Error: ${snapshot.error}');
|
||||
return Text("Error: ${snapshot.error}");
|
||||
} else if (snapshot.hasData) {
|
||||
return _buildUserList(snapshot.data!);
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
|||
onPressed: () {
|
||||
setState(() {
|
||||
_isSearching = !_isSearching;
|
||||
query = '';
|
||||
query = "";
|
||||
});
|
||||
|
||||
if (_isSearching) {
|
||||
|
@ -174,7 +174,7 @@ class _UserListState extends State<UserList> {
|
|||
var isSelected = widget.selectedUserList
|
||||
.any((selectedUser) => selectedUser == user);
|
||||
var theme = Theme.of(context);
|
||||
return Container(
|
||||
return DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
|
@ -196,7 +196,7 @@ class _UserListState extends State<UserList> {
|
|||
child: Padding(
|
||||
padding: widget.options.paddingAroundChatList ??
|
||||
const EdgeInsets.fromLTRB(28, 8, 28, 8),
|
||||
child: Container(
|
||||
child: ColoredBox(
|
||||
color: Colors.transparent,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:intl/intl.dart';
|
||||
import "package:intl/intl.dart";
|
||||
|
||||
class DateFormatter {
|
||||
final _now = DateTime.now();
|
||||
|
@ -28,6 +28,6 @@ class DateFormatter {
|
|||
bool showFullDate = false,
|
||||
}) =>
|
||||
DateFormat(
|
||||
_isToday(date) ? 'HH:mm' : 'dd-MM-yyyy${showFullDate ? ' HH:mm' : ''}',
|
||||
_isToday(date) ? "HH:mm" : 'dd-MM-yyyy${showFullDate ? ' HH:mm' : ''}',
|
||||
).format(date);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'dart:async';
|
||||
import "dart:async";
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_profile/flutter_profile.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_profile/flutter_profile.dart";
|
||||
|
||||
class ChatProfileService extends ProfileService {
|
||||
@override
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
name: flutter_chat_view
|
||||
description: A standard flutter package.
|
||||
version: 3.0.0
|
||||
version: 3.0.1
|
||||
|
||||
publish_to: none
|
||||
|
||||
|
@ -20,7 +20,7 @@ dependencies:
|
|||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_chat
|
||||
path: packages/flutter_chat_interface
|
||||
ref: 3.0.0
|
||||
ref: 3.0.1
|
||||
cached_network_image: ^3.2.2
|
||||
flutter_image_picker:
|
||||
git:
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import "package:flutter_test/flutter_test.dart";
|
||||
|
||||
void main() {
|
||||
test('test', () {
|
||||
test("test", () {
|
||||
expect(true, true);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue