mirror of
https://github.com/Iconica-Development/flutter_chat.git
synced 2025-05-18 18:33:49 +02:00
fix: feedback
This commit is contained in:
parent
5464766747
commit
1141aea83c
38 changed files with 702 additions and 625 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
## 3.0.0
|
||||||
|
|
||||||
|
- Add theming
|
||||||
|
- add validator for group name
|
||||||
|
- fix spamming buttons
|
||||||
|
- fix user list flickering on the group creation screen
|
||||||
|
|
||||||
## 2.0.0
|
## 2.0.0
|
||||||
|
|
||||||
- Add a serviceBuilder to the userstory configuration
|
- Add a serviceBuilder to the userstory configuration
|
||||||
|
|
|
@ -1,28 +1,9 @@
|
||||||
# This file configures the analyzer, which statically analyzes Dart code to
|
include: package:flutter_iconica_analysis/analysis_options.yaml
|
||||||
# check for errors, warnings, and lints.
|
|
||||||
#
|
|
||||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
|
||||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
|
||||||
# invoked from the command line by running `flutter analyze`.
|
|
||||||
|
|
||||||
# The following line activates a set of recommended lints for Flutter apps,
|
# Possible to overwrite the rules from the package
|
||||||
# packages, and plugins designed to encourage good coding practices.
|
|
||||||
include: package:flutter_lints/flutter.yaml
|
analyzer:
|
||||||
|
exclude:
|
||||||
|
|
||||||
linter:
|
linter:
|
||||||
# The lint rules applied to this project can be customized in the
|
|
||||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
|
||||||
# included above or to enable additional rules. A list of all available lints
|
|
||||||
# and their documentation is published at https://dart.dev/lints.
|
|
||||||
#
|
|
||||||
# Instead of disabling a lint rule for the entire project in the
|
|
||||||
# section below, it can also be suppressed for a single line of code
|
|
||||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
|
||||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
|
||||||
# producing the lint.
|
|
||||||
rules:
|
rules:
|
||||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
|
||||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
|
||||||
|
|
||||||
# Additional information about this file can be found at
|
|
||||||
# https://dart.dev/guides/language/analysis-options
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import "package:flutter/material.dart";
|
||||||
import 'package:flutter_chat/flutter_chat.dart';
|
import "package:flutter_chat/flutter_chat.dart";
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
@ -11,25 +11,22 @@ class App extends StatelessWidget {
|
||||||
const App({super.key});
|
const App({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => const MaterialApp(
|
||||||
return const MaterialApp(
|
|
||||||
home: Home(),
|
home: Home(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class Home extends StatelessWidget {
|
class Home extends StatelessWidget {
|
||||||
const Home({super.key});
|
const Home({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => Center(
|
||||||
return Center(
|
child: chatNavigatorUserStory(
|
||||||
child: chatNavigatorUserStory(context,
|
context,
|
||||||
configuration: ChatUserStoryConfiguration(
|
configuration: ChatUserStoryConfiguration(
|
||||||
chatService: LocalChatService(),
|
chatService: LocalChatService(),
|
||||||
chatOptionsBuilder: (ctx) => ChatOptions(
|
chatOptionsBuilder: (ctx) => const ChatOptions(),
|
||||||
noChatsPlaceholderBuilder: (translations) =>
|
),
|
||||||
Text(translations.noUsersFound),
|
),
|
||||||
))));
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,23 @@ dependencies:
|
||||||
path: ../
|
path: ../
|
||||||
flutter_chat_firebase:
|
flutter_chat_firebase:
|
||||||
path: ../../flutter_chat_firebase
|
path: ../../flutter_chat_firebase
|
||||||
|
dependency_overrides:
|
||||||
|
flutter_chat:
|
||||||
|
path: ../../flutter_chat
|
||||||
|
flutter_chat_interface:
|
||||||
|
path: ../../flutter_chat_interface
|
||||||
|
flutter_chat_local:
|
||||||
|
path: ../../flutter_chat_local
|
||||||
|
flutter_chat_view:
|
||||||
|
path: ../../flutter_chat_view
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^2.0.0
|
flutter_iconica_analysis:
|
||||||
|
git:
|
||||||
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
|
ref: 7.0.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||||
// tree, read text, and verify that the values of widget properties are correct.
|
// tree, read text, and verify that the values of widget properties are correct.
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import "package:flutter_test/flutter_test.dart";
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
testWidgets("Counter increments smoke test", (WidgetTester tester) async {
|
||||||
expect(true, true);
|
expect(true, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,7 +284,7 @@ Widget _newGroupChatOverviewScreenRoute(
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
await Navigator.of(context).push(
|
await Navigator.of(context).pushReplacement(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => _chatDetailScreenRoute(
|
builder: (context) => _chatDetailScreenRoute(
|
||||||
configuration,
|
configuration,
|
||||||
|
|
|
@ -14,6 +14,7 @@ List<GoRoute> getChatStoryRoutes(
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: ChatUserStoryRoutes.chatScreen,
|
path: ChatUserStoryRoutes.chatScreen,
|
||||||
pageBuilder: (context, state) {
|
pageBuilder: (context, state) {
|
||||||
|
var theme = Theme.of(context);
|
||||||
var service = configuration.chatServiceBuilder?.call(context) ??
|
var service = configuration.chatServiceBuilder?.call(context) ??
|
||||||
configuration.chatService;
|
configuration.chatService;
|
||||||
var chatScreen = ChatScreen(
|
var chatScreen = ChatScreen(
|
||||||
|
@ -47,6 +48,7 @@ List<GoRoute> getChatStoryRoutes(
|
||||||
chatScreen,
|
chatScreen,
|
||||||
) ??
|
) ??
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
backgroundColor: theme.colorScheme.surface,
|
||||||
body: chatScreen,
|
body: chatScreen,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -58,6 +60,8 @@ List<GoRoute> getChatStoryRoutes(
|
||||||
var chatId = state.pathParameters['id'];
|
var chatId = state.pathParameters['id'];
|
||||||
var service = configuration.chatServiceBuilder?.call(context) ??
|
var service = configuration.chatServiceBuilder?.call(context) ??
|
||||||
configuration.chatService;
|
configuration.chatService;
|
||||||
|
var theme = Theme.of(context);
|
||||||
|
|
||||||
var chatDetailScreen = ChatDetailScreen(
|
var chatDetailScreen = ChatDetailScreen(
|
||||||
chatTitleBuilder: configuration.chatTitleBuilder,
|
chatTitleBuilder: configuration.chatTitleBuilder,
|
||||||
usernameBuilder: configuration.usernameBuilder,
|
usernameBuilder: configuration.usernameBuilder,
|
||||||
|
@ -118,6 +122,7 @@ List<GoRoute> getChatStoryRoutes(
|
||||||
chatDetailScreen,
|
chatDetailScreen,
|
||||||
) ??
|
) ??
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
backgroundColor: theme.colorScheme.surface,
|
||||||
body: chatDetailScreen,
|
body: chatDetailScreen,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -128,6 +133,8 @@ List<GoRoute> getChatStoryRoutes(
|
||||||
pageBuilder: (context, state) {
|
pageBuilder: (context, state) {
|
||||||
var service = configuration.chatServiceBuilder?.call(context) ??
|
var service = configuration.chatServiceBuilder?.call(context) ??
|
||||||
configuration.chatService;
|
configuration.chatService;
|
||||||
|
var theme = Theme.of(context);
|
||||||
|
|
||||||
var newChatScreen = NewChatScreen(
|
var newChatScreen = NewChatScreen(
|
||||||
options: configuration.chatOptionsBuilder(context),
|
options: configuration.chatOptionsBuilder(context),
|
||||||
translations: configuration.translationsBuilder?.call(context) ??
|
translations: configuration.translationsBuilder?.call(context) ??
|
||||||
|
@ -165,6 +172,7 @@ List<GoRoute> getChatStoryRoutes(
|
||||||
newChatScreen,
|
newChatScreen,
|
||||||
) ??
|
) ??
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
backgroundColor: theme.colorScheme.surface,
|
||||||
body: newChatScreen,
|
body: newChatScreen,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -175,6 +183,8 @@ List<GoRoute> getChatStoryRoutes(
|
||||||
pageBuilder: (context, state) {
|
pageBuilder: (context, state) {
|
||||||
var service = configuration.chatServiceBuilder?.call(context) ??
|
var service = configuration.chatServiceBuilder?.call(context) ??
|
||||||
configuration.chatService;
|
configuration.chatService;
|
||||||
|
var theme = Theme.of(context);
|
||||||
|
|
||||||
var newGroupChatScreen = NewGroupChatScreen(
|
var newGroupChatScreen = NewGroupChatScreen(
|
||||||
options: configuration.chatOptionsBuilder(context),
|
options: configuration.chatOptionsBuilder(context),
|
||||||
translations: configuration.translationsBuilder?.call(context) ??
|
translations: configuration.translationsBuilder?.call(context) ??
|
||||||
|
@ -193,6 +203,7 @@ List<GoRoute> getChatStoryRoutes(
|
||||||
newGroupChatScreen,
|
newGroupChatScreen,
|
||||||
) ??
|
) ??
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
backgroundColor: theme.colorScheme.surface,
|
||||||
body: newGroupChatScreen,
|
body: newGroupChatScreen,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -204,6 +215,8 @@ List<GoRoute> getChatStoryRoutes(
|
||||||
var service = configuration.chatServiceBuilder?.call(context) ??
|
var service = configuration.chatServiceBuilder?.call(context) ??
|
||||||
configuration.chatService;
|
configuration.chatService;
|
||||||
var users = state.extra! as List<ChatUserModel>;
|
var users = state.extra! as List<ChatUserModel>;
|
||||||
|
var theme = Theme.of(context);
|
||||||
|
|
||||||
var newGroupChatOverviewScreen = NewGroupChatOverviewScreen(
|
var newGroupChatOverviewScreen = NewGroupChatOverviewScreen(
|
||||||
options: configuration.chatOptionsBuilder(context),
|
options: configuration.chatOptionsBuilder(context),
|
||||||
translations: configuration.translationsBuilder?.call(context) ??
|
translations: configuration.translationsBuilder?.call(context) ??
|
||||||
|
@ -223,7 +236,7 @@ List<GoRoute> getChatStoryRoutes(
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
await context.push(
|
context.go(
|
||||||
ChatUserStoryRoutes.chatDetailViewPath(chat.id ?? ''),
|
ChatUserStoryRoutes.chatDetailViewPath(chat.id ?? ''),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -237,6 +250,7 @@ List<GoRoute> getChatStoryRoutes(
|
||||||
newGroupChatOverviewScreen,
|
newGroupChatOverviewScreen,
|
||||||
) ??
|
) ??
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
backgroundColor: theme.colorScheme.surface,
|
||||||
body: newGroupChatOverviewScreen,
|
body: newGroupChatOverviewScreen,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -250,6 +264,8 @@ List<GoRoute> getChatStoryRoutes(
|
||||||
var id = userId == 'null' ? null : userId;
|
var id = userId == 'null' ? null : userId;
|
||||||
var service = configuration.chatServiceBuilder?.call(context) ??
|
var service = configuration.chatServiceBuilder?.call(context) ??
|
||||||
configuration.chatService;
|
configuration.chatService;
|
||||||
|
var theme = Theme.of(context);
|
||||||
|
|
||||||
var profileScreen = ChatProfileScreen(
|
var profileScreen = ChatProfileScreen(
|
||||||
translations: configuration.translationsBuilder?.call(context) ??
|
translations: configuration.translationsBuilder?.call(context) ??
|
||||||
configuration.translations,
|
configuration.translations,
|
||||||
|
@ -274,6 +290,7 @@ List<GoRoute> getChatStoryRoutes(
|
||||||
profileScreen,
|
profileScreen,
|
||||||
) ??
|
) ??
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
backgroundColor: theme.colorScheme.surface,
|
||||||
body: profileScreen,
|
body: profileScreen,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
name: flutter_chat
|
name: flutter_chat
|
||||||
description: A new Flutter package project.
|
description: A new Flutter package project.
|
||||||
version: 2.0.0
|
version: 3.0.0
|
||||||
|
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
|
@ -20,23 +20,23 @@ dependencies:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_chat
|
url: https://github.com/Iconica-Development/flutter_chat
|
||||||
path: packages/flutter_chat_view
|
path: packages/flutter_chat_view
|
||||||
ref: 2.0.0
|
ref: 3.0.0
|
||||||
flutter_chat_interface:
|
flutter_chat_interface:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_chat
|
url: https://github.com/Iconica-Development/flutter_chat
|
||||||
path: packages/flutter_chat_interface
|
path: packages/flutter_chat_interface
|
||||||
ref: 2.0.0
|
ref: 3.0.0
|
||||||
flutter_chat_local:
|
flutter_chat_local:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_chat
|
url: https://github.com/Iconica-Development/flutter_chat
|
||||||
path: packages/flutter_chat_local
|
path: packages/flutter_chat_local
|
||||||
ref: 2.0.0
|
ref: 3.0.0
|
||||||
uuid: ^4.3.3
|
uuid: ^4.3.3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_iconica_analysis:
|
flutter_iconica_analysis:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
ref: 6.0.0
|
ref: 7.0.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
name: flutter_chat_firebase
|
name: flutter_chat_firebase
|
||||||
description: A new Flutter package project.
|
description: A new Flutter package project.
|
||||||
version: 2.0.0
|
version: 3.0.0
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
@ -23,12 +23,12 @@ dependencies:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_chat
|
url: https://github.com/Iconica-Development/flutter_chat
|
||||||
path: packages/flutter_chat_interface
|
path: packages/flutter_chat_interface
|
||||||
ref: 2.0.0
|
ref: 3.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_iconica_analysis:
|
flutter_iconica_analysis:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
ref: 6.0.0
|
ref: 7.0.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
///
|
///
|
||||||
library flutter_chat_interface;
|
library flutter_chat_interface;
|
||||||
|
|
||||||
export 'package:flutter_chat_interface/src/chat_data_provider.dart';
|
export "package:flutter_chat_interface/src/chat_data_provider.dart";
|
||||||
export 'package:flutter_chat_interface/src/model/model.dart';
|
export "package:flutter_chat_interface/src/model/model.dart";
|
||||||
export 'package:flutter_chat_interface/src/service/service.dart';
|
export "package:flutter_chat_interface/src/service/service.dart";
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||||
import 'package:flutter_data_interface/flutter_data_interface.dart';
|
import "package:flutter_data_interface/flutter_data_interface.dart";
|
||||||
|
|
||||||
class ChatDataProvider extends DataInterface {
|
class ChatDataProvider extends DataInterface {
|
||||||
ChatDataProvider({
|
ChatDataProvider({
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||||
|
|
||||||
abstract class ChatModelInterface {
|
abstract class ChatModelInterface {
|
||||||
ChatModelInterface copyWith();
|
ChatModelInterface copyWith();
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||||
|
|
||||||
/// An abstract class defining the interface for an image message in a chat.
|
/// An abstract class defining the interface for an image message in a chat.
|
||||||
abstract class ChatImageMessageModelInterface extends ChatMessageModel {
|
abstract class ChatImageMessageModelInterface extends ChatMessageModel {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter_chat_interface/src/model/chat_user.dart';
|
import "package:flutter_chat_interface/src/model/chat_user.dart";
|
||||||
|
|
||||||
abstract class ChatMessageModelInterface {
|
abstract class ChatMessageModelInterface {
|
||||||
ChatUserModel get sender;
|
ChatUserModel get sender;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||||
|
|
||||||
abstract class ChatTextMessageModelInterface extends ChatMessageModel {
|
abstract class ChatTextMessageModelInterface extends ChatMessageModel {
|
||||||
ChatTextMessageModelInterface({
|
ChatTextMessageModelInterface({
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import "package:flutter/material.dart";
|
||||||
|
|
||||||
abstract class ChatUserModelInterface {
|
abstract class ChatUserModelInterface {
|
||||||
String? get id;
|
String? get id;
|
||||||
|
@ -49,17 +49,17 @@ class ChatUserModel implements ChatUserModelInterface {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? get fullName {
|
String? get fullName {
|
||||||
var fullName = '';
|
var fullName = "";
|
||||||
|
|
||||||
if (firstName != null && lastName != null) {
|
if (firstName != null && lastName != null) {
|
||||||
fullName += '$firstName $lastName';
|
fullName += "$firstName $lastName";
|
||||||
} else if (firstName != null) {
|
} else if (firstName != null) {
|
||||||
fullName += firstName!;
|
fullName += firstName!;
|
||||||
} else if (lastName != null) {
|
} else if (lastName != null) {
|
||||||
fullName += lastName!;
|
fullName += lastName!;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fullName == '' ? null : fullName;
|
return fullName == "" ? null : fullName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||||
|
|
||||||
abstract class GroupChatModelInterface extends ChatModel {
|
abstract class GroupChatModelInterface extends ChatModel {
|
||||||
GroupChatModelInterface({
|
GroupChatModelInterface({
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export 'chat.dart';
|
export "chat.dart";
|
||||||
export 'chat_image_message.dart';
|
export "chat_image_message.dart";
|
||||||
export 'chat_message.dart';
|
export "chat_message.dart";
|
||||||
export 'chat_text_message.dart';
|
export "chat_text_message.dart";
|
||||||
export 'chat_user.dart';
|
export "chat_user.dart";
|
||||||
export 'group_chat.dart';
|
export "group_chat.dart";
|
||||||
export 'personal_chat.dart';
|
export "personal_chat.dart";
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||||
|
|
||||||
abstract class PersonalChatModelInterface extends ChatModel {
|
abstract class PersonalChatModelInterface extends ChatModel {
|
||||||
PersonalChatModelInterface({
|
PersonalChatModelInterface({
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'dart:typed_data';
|
import "dart:typed_data";
|
||||||
import 'package:flutter/material.dart';
|
import "package:flutter/material.dart";
|
||||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||||
|
|
||||||
/// An abstract class defining the interface for a chat detail service.
|
/// An abstract class defining the interface for a chat detail service.
|
||||||
abstract class ChatDetailService with ChangeNotifier {
|
abstract class ChatDetailService with ChangeNotifier {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||||
|
|
||||||
abstract class ChatOverviewService {
|
abstract class ChatOverviewService {
|
||||||
/// Retrieves a stream of chats.
|
/// Retrieves a stream of chats.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||||
|
|
||||||
class ChatService {
|
class ChatService {
|
||||||
final ChatUserService chatUserService;
|
final ChatUserService chatUserService;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export 'chat_detail_service.dart';
|
export "chat_detail_service.dart";
|
||||||
export 'chat_overview_service.dart';
|
export "chat_overview_service.dart";
|
||||||
export 'chat_service.dart';
|
export "chat_service.dart";
|
||||||
export 'user_service.dart';
|
export "user_service.dart";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import 'package:flutter_chat_interface/flutter_chat_interface.dart';
|
import "package:flutter_chat_interface/flutter_chat_interface.dart";
|
||||||
|
|
||||||
abstract class ChatUserService {
|
abstract class ChatUserService {
|
||||||
/// Retrieves a user based on the ID.
|
/// Retrieves a user based on the ID.
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
name: flutter_chat_interface
|
name: flutter_chat_interface
|
||||||
description: A new Flutter package project.
|
description: A new Flutter package project.
|
||||||
version: 2.0.0
|
version: 3.0.0
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
@ -23,6 +23,6 @@ dev_dependencies:
|
||||||
flutter_iconica_analysis:
|
flutter_iconica_analysis:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
ref: 6.0.0
|
ref: 7.0.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: flutter_chat_local
|
name: flutter_chat_local
|
||||||
description: "A new Flutter package project."
|
description: "A new Flutter package project."
|
||||||
version: 2.0.0
|
version: 3.0.0
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
@ -14,7 +14,7 @@ dependencies:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_chat
|
url: https://github.com/Iconica-Development/flutter_chat
|
||||||
path: packages/flutter_chat_interface
|
path: packages/flutter_chat_interface
|
||||||
ref: 2.0.0
|
ref: 3.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -22,5 +22,5 @@ dev_dependencies:
|
||||||
flutter_iconica_analysis:
|
flutter_iconica_analysis:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
ref: 6.0.0
|
ref: 7.0.0
|
||||||
flutter:
|
flutter:
|
||||||
|
|
|
@ -73,7 +73,7 @@ class _ChatBottomState extends State<ChatBottom> {
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: widget.onPressSelectImage,
|
onPressed: widget.onPressSelectImage,
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.image,
|
Icons.image_outlined,
|
||||||
color: widget.iconColor,
|
color: widget.iconColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -105,6 +105,7 @@ class _ChatBottomState extends State<ChatBottom> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
widget.translations,
|
widget.translations,
|
||||||
|
context,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -54,7 +54,7 @@ class _ChatDetailRowState extends State<ChatDetailRow> {
|
||||||
widget.message.timestamp.minute ==
|
widget.message.timestamp.minute ==
|
||||||
widget.previousMessage?.timestamp.minute;
|
widget.previousMessage?.timestamp.minute;
|
||||||
var hasHeader = isNewDate || isSameSender;
|
var hasHeader = isNewDate || isSameSender;
|
||||||
|
var theme = Theme.of(context);
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
top: isNewDate || isSameSender ? 25.0 : 0,
|
top: isNewDate || isSameSender ? 25.0 : 0,
|
||||||
|
@ -160,10 +160,7 @@ class _ChatDetailRowState extends State<ChatDetailRow> {
|
||||||
)
|
)
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.last,
|
.last,
|
||||||
style: const TextStyle(
|
style: theme.textTheme.bodySmall,
|
||||||
fontSize: 12,
|
|
||||||
color: Color(0xFFBBBBBB),
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.end,
|
textAlign: TextAlign.end,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -30,7 +30,9 @@ class ChatRow extends StatelessWidget {
|
||||||
final Widget? avatar;
|
final Widget? avatar;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => Row(
|
Widget build(BuildContext context) {
|
||||||
|
var theme = Theme.of(context);
|
||||||
|
return Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
|
@ -47,29 +49,24 @@ class ChatRow extends StatelessWidget {
|
||||||
title,
|
title,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(
|
style: unreadMessages > 0
|
||||||
fontSize: 16,
|
? theme.textTheme.bodyLarge
|
||||||
fontWeight: unreadMessages > 0
|
: theme.textTheme.bodyMedium,
|
||||||
? FontWeight.w900
|
|
||||||
: FontWeight.w500,
|
|
||||||
),
|
),
|
||||||
),
|
if (subTitle != null) ...[
|
||||||
if (subTitle != null)
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 3.0),
|
padding: const EdgeInsets.only(top: 3.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
subTitle!,
|
subTitle!,
|
||||||
style: TextStyle(
|
style: unreadMessages > 0
|
||||||
fontSize: 16,
|
? theme.textTheme.bodyLarge
|
||||||
fontWeight: unreadMessages > 0
|
: theme.textTheme.bodyMedium,
|
||||||
? FontWeight.w500
|
|
||||||
: FontWeight.w300,
|
|
||||||
),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -77,7 +74,7 @@ class ChatRow extends StatelessWidget {
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
if (lastUsed != null) // Check if lastUsed is not null
|
if (lastUsed != null) ...[
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 4.0),
|
padding: const EdgeInsets.only(bottom: 4.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
@ -88,6 +85,7 @@ class ChatRow extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
if (unreadMessages > 0) ...[
|
if (unreadMessages > 0) ...[
|
||||||
Container(
|
Container(
|
||||||
width: 20,
|
width: 20,
|
||||||
|
@ -111,3 +109,4 @@ class ChatRow extends StatelessWidget {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -59,7 +59,10 @@ Widget _createNewChatButton(
|
||||||
ChatTranslations translations,
|
ChatTranslations translations,
|
||||||
) =>
|
) =>
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(5, 24, 5, 24),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 24,
|
||||||
|
horizontal: 5,
|
||||||
|
),
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Theme.of(context).primaryColor,
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
|
@ -74,7 +77,7 @@ Widget _createNewChatButton(
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontWeight: FontWeight.w800,
|
fontWeight: FontWeight.w800,
|
||||||
fontSize: 18,
|
fontSize: 20,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -84,19 +87,21 @@ Widget _createMessageInput(
|
||||||
TextEditingController textEditingController,
|
TextEditingController textEditingController,
|
||||||
Widget suffixIcon,
|
Widget suffixIcon,
|
||||||
ChatTranslations translations,
|
ChatTranslations translations,
|
||||||
) =>
|
BuildContext context,
|
||||||
TextField(
|
) {
|
||||||
|
var theme = Theme.of(context);
|
||||||
|
return TextField(
|
||||||
textCapitalization: TextCapitalization.sentences,
|
textCapitalization: TextCapitalization.sentences,
|
||||||
controller: textEditingController,
|
controller: textEditingController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(26.5),
|
borderRadius: BorderRadius.circular(25),
|
||||||
borderSide: const BorderSide(
|
borderSide: const BorderSide(
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(26.5),
|
borderRadius: BorderRadius.circular(25),
|
||||||
borderSide: const BorderSide(
|
borderSide: const BorderSide(
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
),
|
),
|
||||||
|
@ -106,21 +111,19 @@ Widget _createMessageInput(
|
||||||
horizontal: 30,
|
horizontal: 30,
|
||||||
),
|
),
|
||||||
hintText: translations.messagePlaceholder,
|
hintText: translations.messagePlaceholder,
|
||||||
hintStyle: const TextStyle(
|
hintStyle: theme.inputDecorationTheme.hintStyle,
|
||||||
fontWeight: FontWeight.normal,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
fillColor: Colors.white,
|
fillColor: Colors.white,
|
||||||
filled: true,
|
filled: true,
|
||||||
border: const OutlineInputBorder(
|
border: const OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.all(
|
borderRadius: BorderRadius.all(
|
||||||
Radius.circular(26.5),
|
Radius.circular(25),
|
||||||
),
|
),
|
||||||
borderSide: BorderSide.none,
|
borderSide: BorderSide.none,
|
||||||
),
|
),
|
||||||
suffixIcon: suffixIcon,
|
suffixIcon: suffixIcon,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _createChatRowContainer(
|
Widget _createChatRowContainer(
|
||||||
Widget chatRow,
|
Widget chatRow,
|
||||||
|
@ -130,7 +133,10 @@ Widget _createChatRowContainer(
|
||||||
vertical: 12.0,
|
vertical: 12.0,
|
||||||
horizontal: 10.0,
|
horizontal: 10.0,
|
||||||
),
|
),
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
child: chatRow,
|
child: chatRow,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _createImagePickerContainer(
|
Widget _createImagePickerContainer(
|
||||||
|
@ -166,6 +172,7 @@ Widget _createImagePickerContainer(
|
||||||
Scaffold _createScaffold(
|
Scaffold _createScaffold(
|
||||||
AppBar appbar,
|
AppBar appbar,
|
||||||
Widget body,
|
Widget body,
|
||||||
|
Color backgroundColor,
|
||||||
) =>
|
) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
appBar: appbar,
|
appBar: appbar,
|
||||||
|
@ -196,31 +203,32 @@ Widget _createGroupAvatar(
|
||||||
|
|
||||||
Widget _createNoChatsPlaceholder(
|
Widget _createNoChatsPlaceholder(
|
||||||
ChatTranslations translations,
|
ChatTranslations translations,
|
||||||
) =>
|
BuildContext context,
|
||||||
Center(
|
) {
|
||||||
|
var theme = Theme.of(context);
|
||||||
|
return Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
translations.noChatsFound,
|
translations.noChatsFound,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: const TextStyle(
|
style: theme.textTheme.bodySmall,
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 18,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _createNoUsersPlaceholder(
|
Widget _createNoUsersPlaceholder(
|
||||||
ChatTranslations translations,
|
ChatTranslations translations,
|
||||||
) =>
|
BuildContext context,
|
||||||
Center(
|
) {
|
||||||
|
var theme = Theme.of(context);
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 20),
|
||||||
child: Text(
|
child: Text(
|
||||||
translations.noUsersFound,
|
translations.noUsersFound,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: const TextStyle(
|
style: theme.textTheme.bodySmall,
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 18,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
typedef ButtonBuilder = Widget Function(
|
typedef ButtonBuilder = Widget Function(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
|
@ -232,6 +240,7 @@ typedef TextInputBuilder = Widget Function(
|
||||||
TextEditingController textEditingController,
|
TextEditingController textEditingController,
|
||||||
Widget suffixIcon,
|
Widget suffixIcon,
|
||||||
ChatTranslations translations,
|
ChatTranslations translations,
|
||||||
|
BuildContext context,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef ContainerBuilder = Widget Function(
|
typedef ContainerBuilder = Widget Function(
|
||||||
|
@ -247,6 +256,7 @@ typedef ImagePickerContainerBuilder = Widget Function(
|
||||||
typedef ScaffoldBuilder = Scaffold Function(
|
typedef ScaffoldBuilder = Scaffold Function(
|
||||||
AppBar appBar,
|
AppBar appBar,
|
||||||
Widget body,
|
Widget body,
|
||||||
|
Color backgroundColor,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef UserAvatarBuilder = Widget Function(
|
typedef UserAvatarBuilder = Widget Function(
|
||||||
|
@ -262,8 +272,10 @@ typedef GroupAvatarBuilder = Widget Function(
|
||||||
|
|
||||||
typedef NoChatsPlaceholderBuilder = Widget Function(
|
typedef NoChatsPlaceholderBuilder = Widget Function(
|
||||||
ChatTranslations translations,
|
ChatTranslations translations,
|
||||||
|
BuildContext context,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef NoUsersPlaceholderBuilder = Widget Function(
|
typedef NoUsersPlaceholderBuilder = Widget Function(
|
||||||
ChatTranslations translations,
|
ChatTranslations translations,
|
||||||
|
BuildContext context,
|
||||||
);
|
);
|
||||||
|
|
|
@ -36,13 +36,17 @@ class ChatTranslations {
|
||||||
required this.uploadFile,
|
required this.uploadFile,
|
||||||
required this.takePicture,
|
required this.takePicture,
|
||||||
required this.anonymousUser,
|
required this.anonymousUser,
|
||||||
|
required this.groupNameValidatorEmpty,
|
||||||
|
required this.groupNameValidatorTooLong,
|
||||||
|
required this.groupNameHintText,
|
||||||
|
required this.newGroupChatTitle,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Default translations for the chat component view
|
/// Default translations for the chat component view
|
||||||
const ChatTranslations.empty({
|
const ChatTranslations.empty({
|
||||||
this.chatsTitle = 'Chats',
|
this.chatsTitle = 'Chats',
|
||||||
this.chatsUnread = 'unread',
|
this.chatsUnread = 'unread',
|
||||||
this.newChatButton = 'Start a chat',
|
this.newChatButton = 'Start chat',
|
||||||
this.newGroupChatButton = 'Create a group chat',
|
this.newGroupChatButton = 'Create a group chat',
|
||||||
this.newChatTitle = 'Start a chat',
|
this.newChatTitle = 'Start a chat',
|
||||||
this.image = 'Image',
|
this.image = 'Image',
|
||||||
|
@ -68,6 +72,11 @@ class ChatTranslations {
|
||||||
this.imagePickerTitle = 'Do you want to upload a file or take a picture?',
|
this.imagePickerTitle = 'Do you want to upload a file or take a picture?',
|
||||||
this.uploadFile = 'UPLOAD FILE',
|
this.uploadFile = 'UPLOAD FILE',
|
||||||
this.takePicture = 'TAKE PICTURE',
|
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',
|
||||||
});
|
});
|
||||||
|
|
||||||
final String chatsTitle;
|
final String chatsTitle;
|
||||||
|
@ -98,6 +107,10 @@ class ChatTranslations {
|
||||||
|
|
||||||
/// Shown when the user has no name
|
/// Shown when the user has no name
|
||||||
final String anonymousUser;
|
final String anonymousUser;
|
||||||
|
final String groupNameValidatorEmpty;
|
||||||
|
final String groupNameValidatorTooLong;
|
||||||
|
final String groupNameHintText;
|
||||||
|
final String newGroupChatTitle;
|
||||||
|
|
||||||
// copyWith method to override the default values
|
// copyWith method to override the default values
|
||||||
ChatTranslations copyWith({
|
ChatTranslations copyWith({
|
||||||
|
@ -127,6 +140,10 @@ class ChatTranslations {
|
||||||
String? uploadFile,
|
String? uploadFile,
|
||||||
String? takePicture,
|
String? takePicture,
|
||||||
String? anonymousUser,
|
String? anonymousUser,
|
||||||
|
String? groupNameValidatorEmpty,
|
||||||
|
String? groupNameValidatorTooLong,
|
||||||
|
String? groupNameHintText,
|
||||||
|
String? newGroupChatTitle,
|
||||||
}) =>
|
}) =>
|
||||||
ChatTranslations(
|
ChatTranslations(
|
||||||
chatsTitle: chatsTitle ?? this.chatsTitle,
|
chatsTitle: chatsTitle ?? this.chatsTitle,
|
||||||
|
@ -160,5 +177,9 @@ class ChatTranslations {
|
||||||
uploadFile: uploadFile ?? this.uploadFile,
|
uploadFile: uploadFile ?? this.uploadFile,
|
||||||
takePicture: takePicture ?? this.takePicture,
|
takePicture: takePicture ?? this.takePicture,
|
||||||
anonymousUser: anonymousUser ?? this.anonymousUser,
|
anonymousUser: anonymousUser ?? this.anonymousUser,
|
||||||
|
groupNameValidatorEmpty: this.groupNameValidatorEmpty,
|
||||||
|
groupNameValidatorTooLong: this.groupNameValidatorTooLong,
|
||||||
|
groupNameHintText: this.groupNameHintText,
|
||||||
|
newGroupChatTitle: this.newGroupChatTitle,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,8 +168,9 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
|
||||||
builder: (context, AsyncSnapshot<ChatModel> snapshot) {
|
builder: (context, AsyncSnapshot<ChatModel> snapshot) {
|
||||||
var chatModel = snapshot.data;
|
var chatModel = snapshot.data;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
backgroundColor: theme.colorScheme.surface,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: theme.appBarTheme.backgroundColor ?? Colors.black,
|
backgroundColor: theme.appBarTheme.backgroundColor,
|
||||||
iconTheme: theme.appBarTheme.iconTheme ??
|
iconTheme: theme.appBarTheme.iconTheme ??
|
||||||
const IconThemeData(color: Colors.white),
|
const IconThemeData(color: Colors.white),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
|
@ -188,14 +189,6 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
|
||||||
children: chat == null
|
children: chat == null
|
||||||
? []
|
? []
|
||||||
: [
|
: [
|
||||||
if (chatModel is GroupChatModel) ...[
|
|
||||||
widget.options.groupAvatarBuilder(
|
|
||||||
chatModel.title,
|
|
||||||
chatModel.imageUrl,
|
|
||||||
36.0,
|
|
||||||
),
|
|
||||||
] else
|
|
||||||
...[],
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: (chatModel is GroupChatModel)
|
padding: (chatModel is GroupChatModel)
|
||||||
? const EdgeInsets.only(left: 15.5)
|
? const EdgeInsets.only(left: 15.5)
|
||||||
|
@ -216,12 +209,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
|
||||||
? chatModel.user.firstName ??
|
? chatModel.user.firstName ??
|
||||||
widget.translations.anonymousUser
|
widget.translations.anonymousUser
|
||||||
: '',
|
: '',
|
||||||
style: theme.appBarTheme.titleTextStyle ??
|
style: theme.appBarTheme.titleTextStyle,
|
||||||
TextStyle(
|
|
||||||
fontWeight: FontWeight.w800,
|
|
||||||
fontSize: 24,
|
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -271,11 +259,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
|
||||||
.writeFirstMessageInGroupChat
|
.writeFirstMessageInGroupChat
|
||||||
: widget
|
: widget
|
||||||
.translations.writeMessageToStartChat,
|
.translations.writeMessageToStartChat,
|
||||||
style: const TextStyle(
|
style: theme.textTheme.bodySmall,
|
||||||
fontSize: 14.0,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
color: Color.fromRGBO(33, 33, 33, 1),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
...detailRows,
|
...detailRows,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_chat_view/flutter_chat_view.dart';
|
import 'package:flutter_chat_view/flutter_chat_view.dart';
|
||||||
import 'package:flutter_chat_view/src/services/profile_service.dart';
|
|
||||||
import 'package:flutter_profile/flutter_profile.dart';
|
import 'package:flutter_profile/flutter_profile.dart';
|
||||||
|
|
||||||
class ChatProfileScreen extends StatefulWidget {
|
class ChatProfileScreen extends StatefulWidget {
|
||||||
|
@ -35,7 +34,6 @@ class ChatProfileScreen extends StatefulWidget {
|
||||||
class _ProfileScreenState extends State<ChatProfileScreen> {
|
class _ProfileScreenState extends State<ChatProfileScreen> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var size = MediaQuery.of(context).size;
|
|
||||||
var hasUser = widget.userId == null;
|
var hasUser = widget.userId == null;
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
return FutureBuilder<dynamic>(
|
return FutureBuilder<dynamic>(
|
||||||
|
@ -67,10 +65,10 @@ class _ProfileScreenState extends State<ChatProfileScreen> {
|
||||||
imageUrl: data.imageUrl,
|
imageUrl: data.imageUrl,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
backgroundColor: theme.colorScheme.surface,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: theme.appBarTheme.backgroundColor ?? Colors.black,
|
backgroundColor: theme.appBarTheme.backgroundColor,
|
||||||
iconTheme: theme.appBarTheme.iconTheme ??
|
iconTheme: theme.appBarTheme.iconTheme ??
|
||||||
const IconThemeData(color: Colors.white),
|
const IconThemeData(color: Colors.white),
|
||||||
title: Text(
|
title: Text(
|
||||||
|
@ -81,32 +79,28 @@ class _ProfileScreenState extends State<ChatProfileScreen> {
|
||||||
: (data is GroupChatModel)
|
: (data is GroupChatModel)
|
||||||
? data.title
|
? data.title
|
||||||
: '',
|
: '',
|
||||||
style: theme.appBarTheme.titleTextStyle ??
|
style: theme.appBarTheme.titleTextStyle,
|
||||||
const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: snapshot.hasData
|
body: snapshot.hasData
|
||||||
? ListView(
|
? ListView(
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(
|
Padding(
|
||||||
height: 10,
|
padding: const EdgeInsets.symmetric(vertical: 20),
|
||||||
|
child: Avatar(
|
||||||
|
user: user,
|
||||||
),
|
),
|
||||||
SizedBox(
|
|
||||||
height: 200,
|
|
||||||
width: size.width,
|
|
||||||
child: ProfilePage(
|
|
||||||
user: user!,
|
|
||||||
itemBuilderOptions: ItemBuilderOptions(
|
|
||||||
readOnly: true,
|
|
||||||
),
|
|
||||||
service: ChatProfileService(),
|
|
||||||
),
|
),
|
||||||
|
const Divider(
|
||||||
|
color: Colors.white,
|
||||||
|
thickness: 10,
|
||||||
),
|
),
|
||||||
if (data is GroupChatModel) ...[
|
if (data is GroupChatModel) ...[
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 100),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 100,
|
||||||
|
vertical: 20,
|
||||||
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
widget.translations.chatProfileUsers,
|
widget.translations.chatProfileUsers,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
|
|
|
@ -77,16 +77,10 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
return widget.options.scaffoldBuilder(
|
return widget.options.scaffoldBuilder(
|
||||||
AppBar(
|
AppBar(
|
||||||
backgroundColor:
|
backgroundColor: theme.appBarTheme.backgroundColor,
|
||||||
theme.appBarTheme.backgroundColor ?? const Color(0xff212121),
|
|
||||||
title: Text(
|
title: Text(
|
||||||
translations.chatsTitle,
|
translations.chatsTitle,
|
||||||
style: theme.appBarTheme.titleTextStyle ??
|
style: theme.appBarTheme.titleTextStyle,
|
||||||
TextStyle(
|
|
||||||
fontWeight: FontWeight.w800,
|
|
||||||
fontSize: 24,
|
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
actions: [
|
actions: [
|
||||||
|
@ -120,7 +114,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||||
controller: controller,
|
controller: controller,
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
padding: widget.options.paddingAroundChatList ??
|
padding: widget.options.paddingAroundChatList ??
|
||||||
const EdgeInsets.fromLTRB(28, 16, 28, 0),
|
const EdgeInsets.symmetric(vertical: 16, horizontal: 28),
|
||||||
children: [
|
children: [
|
||||||
StreamBuilder<List<ChatModel>>(
|
StreamBuilder<List<ChatModel>>(
|
||||||
stream: widget.service.chatOverviewService.getChatsStream(),
|
stream: widget.service.chatOverviewService.getChatsStream(),
|
||||||
|
@ -138,22 +132,30 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
translations.noChatsFound,
|
translations.noChatsFound,
|
||||||
style: const TextStyle(
|
style: theme.textTheme.bodySmall,
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
_hasCalledOnNoChats =
|
_hasCalledOnNoChats = false;
|
||||||
false; // Reset the flag if there are chats
|
|
||||||
}
|
}
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
for (ChatModel chat in (snapshot.data ?? []).where(
|
for (ChatModel chat in (snapshot.data ?? []).where(
|
||||||
(chat) => !deletedChats.contains(chat.id),
|
(chat) => !deletedChats.contains(chat.id),
|
||||||
)) ...[
|
)) ...[
|
||||||
Builder(
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.secondary
|
||||||
|
.withOpacity(0.3),
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Builder(
|
||||||
builder: (context) => !(widget
|
builder: (context) => !(widget
|
||||||
.disableDismissForPermanentChats &&
|
.disableDismissForPermanentChats &&
|
||||||
!chat.canBeDeleted)
|
!chat.canBeDeleted)
|
||||||
|
@ -165,7 +167,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) =>
|
builder: (BuildContext context) =>
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding:
|
||||||
|
const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment:
|
crossAxisAlignment:
|
||||||
|
@ -180,7 +183,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight:
|
||||||
|
FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
|
@ -205,7 +209,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment:
|
mainAxisAlignment:
|
||||||
MainAxisAlignment.center,
|
MainAxisAlignment
|
||||||
|
.center,
|
||||||
children: [
|
children: [
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
|
@ -215,7 +220,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||||
child: Text(
|
child: Text(
|
||||||
translations
|
translations
|
||||||
.deleteChatModalCancel,
|
.deleteChatModalCancel,
|
||||||
style: const TextStyle(
|
style:
|
||||||
|
const TextStyle(
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
),
|
),
|
||||||
|
@ -230,8 +236,9 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||||
style: ElevatedButton
|
style: ElevatedButton
|
||||||
.styleFrom(
|
.styleFrom(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
Theme.of(context)
|
Theme.of(
|
||||||
.primaryColor,
|
context,
|
||||||
|
).primaryColor,
|
||||||
),
|
),
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
Navigator.of(
|
Navigator.of(
|
||||||
|
@ -244,7 +251,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||||
.deleteChatModalConfirm,
|
.deleteChatModalConfirm,
|
||||||
style:
|
style:
|
||||||
const TextStyle(
|
const TextStyle(
|
||||||
color: Colors.white,
|
color:
|
||||||
|
Colors.white,
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -290,6 +298,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||||
dateFormatter: _dateFormatter,
|
dateFormatter: _dateFormatter,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -308,6 +317,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
theme.colorScheme.surface,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,12 +337,10 @@ class ChatListItem extends StatelessWidget {
|
||||||
final DateFormatter _dateFormatter;
|
final DateFormatter _dateFormatter;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => Column(
|
Widget build(BuildContext context) => GestureDetector(
|
||||||
children: [
|
onTap: () {
|
||||||
GestureDetector(
|
widget.onPressChat(chat);
|
||||||
onTap: () => widget.onPressChat(chat),
|
},
|
||||||
child: Container(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: widget.options.chatRowContainerBuilder(
|
child: widget.options.chatRowContainerBuilder(
|
||||||
(chat is PersonalChatModel)
|
(chat is PersonalChatModel)
|
||||||
? ChatRow(
|
? ChatRow(
|
||||||
|
@ -345,8 +353,7 @@ class ChatListItem extends StatelessWidget {
|
||||||
translations.anonymousUser,
|
translations.anonymousUser,
|
||||||
subTitle: chat.lastMessage != null
|
subTitle: chat.lastMessage != null
|
||||||
? chat.lastMessage is ChatTextMessageModel
|
? chat.lastMessage is ChatTextMessageModel
|
||||||
? (chat.lastMessage! as ChatTextMessageModel)
|
? (chat.lastMessage! as ChatTextMessageModel).text
|
||||||
.text
|
|
||||||
: '📷 '
|
: '📷 '
|
||||||
'${translations.image}'
|
'${translations.image}'
|
||||||
: '',
|
: '',
|
||||||
|
@ -361,8 +368,7 @@ class ChatListItem extends StatelessWidget {
|
||||||
unreadMessages: chat.unreadMessages ?? 0,
|
unreadMessages: chat.unreadMessages ?? 0,
|
||||||
subTitle: chat.lastMessage != null
|
subTitle: chat.lastMessage != null
|
||||||
? chat.lastMessage is ChatTextMessageModel
|
? chat.lastMessage is ChatTextMessageModel
|
||||||
? (chat.lastMessage! as ChatTextMessageModel)
|
? (chat.lastMessage! as ChatTextMessageModel).text
|
||||||
.text
|
|
||||||
: '📷 '
|
: '📷 '
|
||||||
'${translations.image}'
|
'${translations.image}'
|
||||||
: '',
|
: '',
|
||||||
|
@ -378,8 +384,5 @@ class ChatListItem extends StatelessWidget {
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,10 +47,11 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
backgroundColor: theme.colorScheme.surface,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
iconTheme: theme.appBarTheme.iconTheme ??
|
iconTheme: theme.appBarTheme.iconTheme ??
|
||||||
const IconThemeData(color: Colors.white),
|
const IconThemeData(color: Colors.white),
|
||||||
backgroundColor: theme.appBarTheme.backgroundColor ?? Colors.black,
|
backgroundColor: theme.appBarTheme.backgroundColor,
|
||||||
title: _buildSearchField(),
|
title: _buildSearchField(),
|
||||||
actions: [
|
actions: [
|
||||||
_buildSearchIcon(),
|
_buildSearchIcon(),
|
||||||
|
@ -114,7 +115,8 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||||
} else if (snapshot.hasData) {
|
} else if (snapshot.hasData) {
|
||||||
return _buildUserList(snapshot.data!);
|
return _buildUserList(snapshot.data!);
|
||||||
} else {
|
} else {
|
||||||
return Text(widget.translations.noUsersFound);
|
return widget.options
|
||||||
|
.noUsersPlaceholderBuilder(widget.translations, context);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -128,9 +130,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
|
|
||||||
return _isSearching
|
return _isSearching
|
||||||
? Padding(
|
? TextField(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
|
||||||
child: TextField(
|
|
||||||
focusNode: _textFieldFocusNode,
|
focusNode: _textFieldFocusNode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
@ -139,33 +139,19 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||||
},
|
},
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: widget.translations.searchPlaceholder,
|
hintText: widget.translations.searchPlaceholder,
|
||||||
hintStyle: theme.inputDecorationTheme.hintStyle ??
|
hintStyle: theme.inputDecorationTheme.hintStyle,
|
||||||
const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
focusedBorder: UnderlineInputBorder(
|
focusedBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: theme.inputDecorationTheme.focusedBorder?.borderSide
|
color: theme.colorScheme.primary,
|
||||||
.color ??
|
|
||||||
Colors.white,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
style: theme.inputDecorationTheme.hintStyle ??
|
style: theme.inputDecorationTheme.hintStyle,
|
||||||
const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
cursorColor: theme.textSelectionTheme.cursorColor ?? Colors.white,
|
cursorColor: theme.textSelectionTheme.cursorColor ?? Colors.white,
|
||||||
),
|
|
||||||
)
|
)
|
||||||
: Text(
|
: Text(
|
||||||
widget.translations.newChatTitle,
|
widget.translations.newChatTitle,
|
||||||
style: theme.appBarTheme.titleTextStyle ??
|
style: theme.appBarTheme.titleTextStyle,
|
||||||
TextStyle(
|
|
||||||
fontWeight: FontWeight.w800,
|
|
||||||
fontSize: 24,
|
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,6 +177,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildUserList(List<ChatUserModel> users) {
|
Widget _buildUserList(List<ChatUserModel> users) {
|
||||||
|
var theme = Theme.of(context);
|
||||||
var filteredUsers = users
|
var filteredUsers = users
|
||||||
.where(
|
.where(
|
||||||
(user) =>
|
(user) =>
|
||||||
|
@ -204,37 +191,44 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||||
if (_textFieldFocusNode.hasFocus && query.isEmpty) {
|
if (_textFieldFocusNode.hasFocus && query.isEmpty) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(top: 20.0),
|
padding: const EdgeInsets.only(top: 20.0),
|
||||||
child: Center(
|
|
||||||
child: Text(
|
child: Text(
|
||||||
widget.translations.startTyping,
|
widget.translations.startTyping,
|
||||||
style: const TextStyle(
|
style: theme.textTheme.bodySmall,
|
||||||
fontSize: 16.0,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.grey,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filteredUsers.isEmpty) {
|
if (filteredUsers.isEmpty) {
|
||||||
return widget.options.noChatsPlaceholderBuilder(widget.translations);
|
return widget.options
|
||||||
|
.noUsersPlaceholderBuilder(widget.translations, context);
|
||||||
}
|
}
|
||||||
|
var isPressed = false;
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
itemCount: filteredUsers.length,
|
itemCount: filteredUsers.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
var user = filteredUsers[index];
|
var user = filteredUsers[index];
|
||||||
return GestureDetector(
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: theme.colorScheme.secondary.withOpacity(0.3),
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: GestureDetector(
|
||||||
child: widget.options.chatRowContainerBuilder(
|
child: widget.options.chatRowContainerBuilder(
|
||||||
Container(
|
Padding(
|
||||||
|
padding: widget.options.paddingAroundChatList ??
|
||||||
|
const EdgeInsets.symmetric(vertical: 8, horizontal: 28),
|
||||||
|
child: Container(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 12.0, right: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
child: widget.options.userAvatarBuilder(user, 40.0),
|
child: widget.options.userAvatarBuilder(user, 40.0),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
|
@ -242,11 +236,9 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||||
height: 40.0,
|
height: 40.0,
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
user.fullName ?? widget.translations.anonymousUser,
|
user.fullName ??
|
||||||
style: const TextStyle(
|
widget.translations.anonymousUser,
|
||||||
fontSize: 18.0,
|
style: theme.textTheme.bodyLarge,
|
||||||
fontWeight: FontWeight.w800,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -255,9 +247,15 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
if (!isPressed) {
|
||||||
|
isPressed = true;
|
||||||
await widget.onPressCreateChat(user);
|
await widget.onPressCreateChat(user);
|
||||||
|
isPressed = false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -33,34 +33,57 @@ class _NewGroupChatOverviewScreenState
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
|
var formKey = GlobalKey<FormState>();
|
||||||
|
var isPressed = false;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
backgroundColor: theme.colorScheme.surface,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
iconTheme: theme.appBarTheme.iconTheme ??
|
iconTheme: theme.appBarTheme.iconTheme ??
|
||||||
const IconThemeData(color: Colors.white),
|
const IconThemeData(color: Colors.white),
|
||||||
backgroundColor: theme.appBarTheme.backgroundColor ?? Colors.black,
|
backgroundColor: theme.appBarTheme.backgroundColor,
|
||||||
title: const Text(
|
title: Text(
|
||||||
'New Group Chat',
|
widget.translations.newGroupChatTitle,
|
||||||
style: TextStyle(color: Colors.white),
|
style: theme.appBarTheme.titleTextStyle,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: TextField(
|
child: Form(
|
||||||
|
key: formKey,
|
||||||
|
child: TextFormField(
|
||||||
controller: _textEditingController,
|
controller: _textEditingController,
|
||||||
decoration: const InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: 'Group chat name',
|
hintText: widget.translations.groupNameHintText,
|
||||||
|
hintStyle: theme.inputDecorationTheme.hintStyle,
|
||||||
|
),
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return widget.translations.groupNameValidatorEmpty;
|
||||||
|
}
|
||||||
|
if (value.length > 15)
|
||||||
|
return widget.translations.groupNameValidatorTooLong;
|
||||||
|
return null;
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
backgroundColor: Theme.of(context).primaryColor,
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
|
if (!isPressed) {
|
||||||
|
isPressed = true;
|
||||||
|
if (formKey.currentState!.validate()) {
|
||||||
await widget.onPressCompleteGroupChatCreation(
|
await widget.onPressCompleteGroupChatCreation(
|
||||||
widget.users,
|
widget.users,
|
||||||
_textEditingController.text,
|
_textEditingController.text,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
isPressed = false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
child: const Icon(Icons.check_circle),
|
child: const Icon(
|
||||||
|
Icons.check_circle,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
|
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
|
||||||
);
|
);
|
||||||
|
|
|
@ -32,10 +32,11 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
backgroundColor: theme.colorScheme.surface,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
iconTheme: theme.appBarTheme.iconTheme ??
|
iconTheme: theme.appBarTheme.iconTheme ??
|
||||||
const IconThemeData(color: Colors.white),
|
const IconThemeData(color: Colors.white),
|
||||||
backgroundColor: theme.appBarTheme.backgroundColor ?? Colors.black,
|
backgroundColor: theme.appBarTheme.backgroundColor,
|
||||||
title: _buildSearchField(),
|
title: _buildSearchField(),
|
||||||
actions: [
|
actions: [
|
||||||
_buildSearchIcon(),
|
_buildSearchIcon(),
|
||||||
|
@ -51,10 +52,8 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||||
return Text('Error: ${snapshot.error}');
|
return Text('Error: ${snapshot.error}');
|
||||||
} else if (snapshot.hasData) {
|
} else if (snapshot.hasData) {
|
||||||
return _buildUserList(snapshot.data!);
|
return _buildUserList(snapshot.data!);
|
||||||
} else {
|
|
||||||
return widget.options
|
|
||||||
.noChatsPlaceholderBuilder(widget.translations);
|
|
||||||
}
|
}
|
||||||
|
return const SizedBox.shrink();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
|
@ -72,9 +71,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
|
|
||||||
return _isSearching
|
return _isSearching
|
||||||
? Padding(
|
? TextField(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
|
||||||
child: TextField(
|
|
||||||
focusNode: _textFieldFocusNode,
|
focusNode: _textFieldFocusNode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
@ -83,33 +80,19 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||||
},
|
},
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: widget.translations.searchPlaceholder,
|
hintText: widget.translations.searchPlaceholder,
|
||||||
hintStyle: theme.inputDecorationTheme.hintStyle ??
|
hintStyle: theme.inputDecorationTheme.hintStyle,
|
||||||
const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
focusedBorder: UnderlineInputBorder(
|
focusedBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: theme.inputDecorationTheme.focusedBorder?.borderSide
|
color: theme.colorScheme.primary,
|
||||||
.color ??
|
|
||||||
Colors.white,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
style: theme.inputDecorationTheme.hintStyle ??
|
style: theme.inputDecorationTheme.hintStyle,
|
||||||
const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
cursorColor: theme.textSelectionTheme.cursorColor ?? Colors.white,
|
cursorColor: theme.textSelectionTheme.cursorColor ?? Colors.white,
|
||||||
),
|
|
||||||
)
|
)
|
||||||
: Text(
|
: Text(
|
||||||
widget.translations.newGroupChatButton,
|
widget.translations.newGroupChatButton,
|
||||||
style: theme.appBarTheme.titleTextStyle ??
|
style: theme.appBarTheme.titleTextStyle,
|
||||||
TextStyle(
|
|
||||||
fontWeight: FontWeight.w800,
|
|
||||||
fontSize: 24,
|
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,60 +129,109 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
if (filteredUsers.isEmpty) {
|
if (filteredUsers.isEmpty) {
|
||||||
return widget.options.noChatsPlaceholderBuilder(widget.translations);
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
widget.options
|
||||||
|
.noUsersPlaceholderBuilder(widget.translations, context),
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ListView.separated(
|
return UserList(
|
||||||
itemCount: filteredUsers.length,
|
filteredUsers: filteredUsers,
|
||||||
separatorBuilder: (context, index) => const Padding(
|
selectedUserList: selectedUserList,
|
||||||
padding: EdgeInsets.symmetric(horizontal: 28.0),
|
options: widget.options,
|
||||||
child: Divider(),
|
translations: widget.translations,
|
||||||
), // Add Divider here
|
);
|
||||||
itemBuilder: (context, index) {
|
}
|
||||||
var user = filteredUsers[index];
|
}
|
||||||
var isSelected =
|
|
||||||
selectedUserList.any((selectedUser) => selectedUser == user);
|
|
||||||
|
|
||||||
return InkWell(
|
class UserList extends StatefulWidget {
|
||||||
|
const UserList({
|
||||||
|
required this.filteredUsers,
|
||||||
|
required this.selectedUserList,
|
||||||
|
required this.options,
|
||||||
|
required this.translations,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final List<ChatUserModel> filteredUsers;
|
||||||
|
final List<ChatUserModel> selectedUserList;
|
||||||
|
final ChatOptions options;
|
||||||
|
final ChatTranslations translations;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<UserList> createState() => _UserListState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UserListState extends State<UserList> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => ListView.builder(
|
||||||
|
itemCount: widget.filteredUsers.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
var user = widget.filteredUsers[index];
|
||||||
|
var isSelected = widget.selectedUserList
|
||||||
|
.any((selectedUser) => selectedUser == user);
|
||||||
|
var theme = Theme.of(context);
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: theme.colorScheme.secondary.withOpacity(0.3),
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (selectedUserList.contains(user)) {
|
if (widget.selectedUserList.contains(user)) {
|
||||||
selectedUserList.remove(user);
|
widget.selectedUserList.remove(user);
|
||||||
} else {
|
} else {
|
||||||
selectedUserList.add(user);
|
widget.selectedUserList.add(user);
|
||||||
}
|
}
|
||||||
debugPrint('The list of selected users is $selectedUserList');
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Container(
|
|
||||||
color: isSelected ? Colors.amber.shade200 : Colors.white,
|
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding:
|
padding: widget.options.paddingAroundChatList ??
|
||||||
const EdgeInsets.symmetric(vertical: 12.0, horizontal: 30),
|
const EdgeInsets.fromLTRB(28, 8, 28, 8),
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 12.0,
|
||||||
|
horizontal: 30,
|
||||||
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 12.0, right: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
child: widget.options.userAvatarBuilder(user, 40.0),
|
child: widget.options.userAvatarBuilder(user, 40.0),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 40.0, // Adjust the height as needed
|
height: 40,
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
user.fullName ?? widget.translations.anonymousUser,
|
user.fullName ??
|
||||||
style: const TextStyle(
|
widget.translations.anonymousUser,
|
||||||
fontWeight: FontWeight.w800,
|
style: theme.textTheme.bodyLarge,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (isSelected) ...[
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 16.0),
|
||||||
|
child: Icon(
|
||||||
|
Icons.check_circle,
|
||||||
|
color: theme.colorScheme.primary,
|
||||||
),
|
),
|
||||||
if (isSelected)
|
|
||||||
const Padding(
|
|
||||||
padding: EdgeInsets.only(right: 16.0),
|
|
||||||
child: Icon(Icons.check_circle, color: Colors.green),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -207,4 +239,3 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
name: flutter_chat_view
|
name: flutter_chat_view
|
||||||
description: A standard flutter package.
|
description: A standard flutter package.
|
||||||
version: 2.0.0
|
version: 3.0.0
|
||||||
|
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ dependencies:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_chat
|
url: https://github.com/Iconica-Development/flutter_chat
|
||||||
path: packages/flutter_chat_interface
|
path: packages/flutter_chat_interface
|
||||||
ref: 2.0.0
|
ref: 3.0.0
|
||||||
cached_network_image: ^3.2.2
|
cached_network_image: ^3.2.2
|
||||||
flutter_image_picker:
|
flutter_image_picker:
|
||||||
git:
|
git:
|
||||||
|
@ -37,6 +37,6 @@ dev_dependencies:
|
||||||
flutter_iconica_analysis:
|
flutter_iconica_analysis:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
ref: 6.0.0
|
ref: 7.0.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
|
|
Loading…
Reference in a new issue