Merge pull request 'dev' (#2) from dev into main
Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
@@ -25,14 +25,13 @@ class MessagingProviders extends ChangeNotifier {
|
|||||||
late final Account account;
|
late final Account account;
|
||||||
late final Databases database;
|
late final Databases database;
|
||||||
late final Storage storage;
|
late final Storage storage;
|
||||||
|
late model.User? user;
|
||||||
|
|
||||||
// Auth Status
|
// Auth Status
|
||||||
AuthStatus? status;
|
AuthStatus? status;
|
||||||
late model.User? user;
|
|
||||||
|
|
||||||
static MessagingProviders instance = MessagingProviders();
|
static MessagingProviders instance = MessagingProviders();
|
||||||
|
|
||||||
|
|
||||||
MessagingProviders() {
|
MessagingProviders() {
|
||||||
_init();
|
_init();
|
||||||
_loadUser();
|
_loadUser();
|
||||||
@@ -54,22 +53,15 @@ class MessagingProviders extends ChangeNotifier {
|
|||||||
if (user != null) {
|
if (user != null) {
|
||||||
status = AuthStatus.authenticated;
|
status = AuthStatus.authenticated;
|
||||||
await updateLastSeen();
|
await updateLastSeen();
|
||||||
_autoLogin();
|
NavigationService.instance.navigateToReplacement("home");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
status = AuthStatus.notAuthenticated;
|
status = AuthStatus.notAuthenticated;
|
||||||
} finally {
|
|
||||||
notifyListeners();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _autoLogin() {
|
|
||||||
NavigationService.instance.navigateToReplacement("home");
|
|
||||||
}
|
|
||||||
|
|
||||||
void login(String _email, String _password) async {
|
void login(String _email, String _password) async {
|
||||||
//
|
//
|
||||||
notifyListeners();
|
|
||||||
try {
|
try {
|
||||||
status != AuthStatus.error;
|
status != AuthStatus.error;
|
||||||
|
|
||||||
@@ -93,7 +85,6 @@ class MessagingProviders extends ChangeNotifier {
|
|||||||
SnackBarService.instance.showSnackBarError(e.toString());
|
SnackBarService.instance.showSnackBarError(e.toString());
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
notifyListeners();
|
|
||||||
} on Exception catch (e) {
|
} on Exception catch (e) {
|
||||||
SnackBarService.instance.showSnackBarError(e.toString());
|
SnackBarService.instance.showSnackBarError(e.toString());
|
||||||
}
|
}
|
||||||
@@ -103,22 +94,20 @@ class MessagingProviders extends ChangeNotifier {
|
|||||||
try {
|
try {
|
||||||
await updateLastSeen();
|
await updateLastSeen();
|
||||||
await account.deleteSession(sessionId: 'current');
|
await account.deleteSession(sessionId: 'current');
|
||||||
user = null;
|
// user = null;
|
||||||
status = AuthStatus.notAuthenticated;
|
status = AuthStatus.notAuthenticated;
|
||||||
// await onSuccess();
|
// await onSuccess();
|
||||||
await NavigationService.instance.navigateToReplacement("login");
|
|
||||||
SnackBarService.instance.showSnackBarError("logged out successfully");
|
SnackBarService.instance.showSnackBarError("logged out successfully");
|
||||||
|
await NavigationService.instance.navigateToReplacement("login");
|
||||||
} on AppwriteException catch (e) {
|
} on AppwriteException catch (e) {
|
||||||
SnackBarService.instance.showSnackBarError(e.message!);
|
SnackBarService.instance.showSnackBarError(e.message!);
|
||||||
} on Exception catch (e) {
|
} on Exception catch (e) {
|
||||||
SnackBarService.instance.showSnackBarError(e.toString());
|
SnackBarService.instance.showSnackBarError(e.toString());
|
||||||
}
|
}
|
||||||
notifyListeners();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> createUser(String _email, String _password, String _name,
|
Future<void> createUser(String _email, String _password, String _name,
|
||||||
Future<void> Function(String _uid) onSuccess) async {
|
Future<void> Function(String _uid) onSuccess) async {
|
||||||
notifyListeners();
|
|
||||||
try {
|
try {
|
||||||
user = await account.create(
|
user = await account.create(
|
||||||
userId: ID.unique(), email: _email, password: _password, name: _name);
|
userId: ID.unique(), email: _email, password: _password, name: _name);
|
||||||
@@ -137,12 +126,10 @@ class MessagingProviders extends ChangeNotifier {
|
|||||||
SnackBarService.instance.showSnackBarError(e.toString());
|
SnackBarService.instance.showSnackBarError(e.toString());
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
notifyListeners();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> createUserInDB(
|
Future<void> createUserInDB(
|
||||||
String _documentId, String _email, String _name, String _imageURL) async {
|
String _documentId, String _email, String _name, String _imageURL) async {
|
||||||
notifyListeners();
|
|
||||||
try {
|
try {
|
||||||
await database.createDocument(
|
await database.createDocument(
|
||||||
databaseId: Constants.instance.databaseId,
|
databaseId: Constants.instance.databaseId,
|
||||||
@@ -172,7 +159,6 @@ class MessagingProviders extends ChangeNotifier {
|
|||||||
user = null;
|
user = null;
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
notifyListeners();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateLastSeen() async {
|
Future<void> updateLastSeen() async {
|
||||||
@@ -184,7 +170,7 @@ class MessagingProviders extends ChangeNotifier {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<User> getUser(String userId) {
|
Stream<User> getUser(String userId) async* {
|
||||||
//
|
//
|
||||||
var _userData = database.getDocument(
|
var _userData = database.getDocument(
|
||||||
databaseId: Constants.instance.databaseId,
|
databaseId: Constants.instance.databaseId,
|
||||||
@@ -192,14 +178,14 @@ class MessagingProviders extends ChangeNotifier {
|
|||||||
documentId: userId,
|
documentId: userId,
|
||||||
);
|
);
|
||||||
|
|
||||||
return _userData.asStream().map((_document) {
|
updateLastSeen();
|
||||||
|
yield* _userData.asStream().map((_document) {
|
||||||
return User.fromData(_document);
|
return User.fromData(_document);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<List<User>> getAllUsers(String _searchText) async* {
|
Stream<List<User>> getAllUsers(String _searchText) async* {
|
||||||
//
|
//
|
||||||
// while (true) {
|
|
||||||
List<User> _returnValue = [];
|
List<User> _returnValue = [];
|
||||||
if (_searchText.isNotEmpty) {
|
if (_searchText.isNotEmpty) {
|
||||||
var _usersData = database.listDocuments(
|
var _usersData = database.listDocuments(
|
||||||
@@ -215,19 +201,17 @@ class MessagingProviders extends ChangeNotifier {
|
|||||||
for (var _document in _documentList.documents) {
|
for (var _document in _documentList.documents) {
|
||||||
_returnValue.add(User.fromData(_document));
|
_returnValue.add(User.fromData(_document));
|
||||||
}
|
}
|
||||||
_returnValue.sort((a,b) => b.lastSeen.compareTo(a.lastSeen));
|
_returnValue.sort((a, b) => b.lastSeen.compareTo(a.lastSeen));
|
||||||
return _returnValue;
|
return _returnValue;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
yield* Stream.empty();
|
yield* Stream.empty();
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<List<Conversations>> getUserConversation(String userId) async* {
|
Stream<List<Conversations>> getUserConversation(String userId) async* {
|
||||||
//
|
//
|
||||||
// while (true) {
|
|
||||||
List<dynamic> _chatId = [];
|
List<dynamic> _chatId = [];
|
||||||
List<dynamic> _details = [];
|
List<dynamic> _details = [];
|
||||||
List<dynamic> _lastModified = [];
|
List<dynamic> _lastModified = [];
|
||||||
@@ -253,98 +237,53 @@ class MessagingProviders extends ChangeNotifier {
|
|||||||
return _returnValue;
|
return _returnValue;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// }
|
|
||||||
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Stream<List<Conversations>> getUserConversations(String userId) async* {
|
|
||||||
// //
|
|
||||||
// // while (true) {
|
|
||||||
// List<dynamic> _chatId = [];
|
|
||||||
// List<dynamic> _details = [];
|
|
||||||
// List<dynamic> _lastModified = [];
|
|
||||||
// List<Conversations> _returnValue = [];
|
|
||||||
|
|
||||||
// var _conversationData = await database.getDocument(
|
|
||||||
// databaseId: Constants.instance.databaseId,
|
|
||||||
// collectionId: Constants.instance.convCollectionId,
|
|
||||||
// documentId: userId.trim(),
|
|
||||||
// );
|
|
||||||
|
|
||||||
// yield _conversationData.toMap map(
|
|
||||||
// (_snapshot) {
|
|
||||||
// _chatId = _snapshot.data['chatId'];
|
|
||||||
// _details = _snapshot.data['details'];
|
|
||||||
// _lastModified = _snapshot.data['lastModified'];
|
|
||||||
|
|
||||||
// for (int i = 0; i < _chatId.length; i++) {
|
|
||||||
// _returnValue.add(Conversations.fromData(
|
|
||||||
// _chatId[i], _details[i], _lastModified[i]));
|
|
||||||
// }
|
|
||||||
// _returnValue.sort((a, b) => b.lastModified!.compareTo(a.lastModified!));
|
|
||||||
// return _returnValue;
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
// // }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Stream<Chats> getMessage(String _chatId) async* {
|
Stream<Chats> getMessage(String _chatId) async* {
|
||||||
//
|
|
||||||
// while (true) {
|
|
||||||
var _chat = database.getDocument(
|
|
||||||
databaseId: Constants.instance.databaseId,
|
|
||||||
collectionId: Constants.instance.chatsCollectionId,
|
|
||||||
documentId: _chatId,
|
|
||||||
);
|
|
||||||
|
|
||||||
yield* _chat.asStream().map(
|
|
||||||
(_document) {
|
|
||||||
return Chats.fromDocument(_document);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String> getConversationLink(var _linkId) async {
|
|
||||||
//
|
//
|
||||||
try {
|
try {
|
||||||
var _conversationLinkDetail = await database.getDocument(
|
var _chat = database.getDocument(
|
||||||
databaseId: Constants.instance.databaseId,
|
databaseId: Constants.instance.databaseId,
|
||||||
collectionId: Constants.instance.conversationLinkId,
|
collectionId: Constants.instance.chatsCollectionId,
|
||||||
documentId: _linkId,
|
documentId: _chatId,
|
||||||
|
);
|
||||||
|
yield* _chat.asStream().map(
|
||||||
|
(_document) {
|
||||||
|
return Chats.fromDocument(_document);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
notifyListeners();
|
|
||||||
return _conversationLinkDetail.data['chatId'];
|
|
||||||
} on AppwriteException catch (e) {
|
} on AppwriteException catch (e) {
|
||||||
notifyListeners();
|
e.message!;
|
||||||
return '';
|
yield* Stream.empty();
|
||||||
|
} on Exception catch (e) {
|
||||||
|
e.toString();
|
||||||
|
yield* Stream.empty();
|
||||||
}
|
}
|
||||||
}
|
// else {}
|
||||||
|
|
||||||
Future<String> newMesaage(Map<String, dynamic> _chat) async {
|
|
||||||
//
|
|
||||||
var chatId = ID.unique();
|
|
||||||
await database.createDocument(
|
|
||||||
databaseId: Constants.instance.databaseId,
|
|
||||||
collectionId: Constants.instance.chatsCollectionId,
|
|
||||||
documentId: chatId,
|
|
||||||
data: _chat,
|
|
||||||
);
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return chatId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> sendMessage(
|
Future<void> sendMessage(String _chatId, Map<String, dynamic> _messages,
|
||||||
String chatId, Map<String, dynamic> _messages) async {
|
String _newOrUpdate) async {
|
||||||
//
|
//
|
||||||
await database.updateDocument(
|
if (_newOrUpdate == 'new') {
|
||||||
databaseId: Constants.instance.databaseId,
|
await database.createDocument(
|
||||||
collectionId: Constants.instance.chatsCollectionId,
|
databaseId: Constants.instance.databaseId,
|
||||||
documentId: chatId,
|
collectionId: Constants.instance.chatsCollectionId,
|
||||||
data: _messages,
|
documentId: _chatId,
|
||||||
);
|
data: _messages,
|
||||||
|
);
|
||||||
|
} else if (_newOrUpdate == 'update') {
|
||||||
|
await database.updateDocument(
|
||||||
|
databaseId: Constants.instance.databaseId,
|
||||||
|
collectionId: Constants.instance.chatsCollectionId,
|
||||||
|
documentId: _chatId,
|
||||||
|
data: _messages,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,7 +312,6 @@ class MessagingProviders extends ChangeNotifier {
|
|||||||
SnackBarService.instance.showSnackBarError(e.toString());
|
SnackBarService.instance.showSnackBarError(e.toString());
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
notifyListeners();
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-25
@@ -1,6 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:messaging_app/components/messaging_routes.dart';
|
import 'package:messaging_app/messaging_app.dart';
|
||||||
import 'package:messaging_app/service/navigation_service.dart';
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
@@ -10,26 +9,3 @@ void main() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessagingApp extends StatelessWidget {
|
|
||||||
|
|
||||||
const MessagingApp({super.key});
|
|
||||||
|
|
||||||
// This widget is the root of your application.
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return MaterialApp(
|
|
||||||
title: 'Messaging App',
|
|
||||||
navigatorKey: NavigationService.instance.navigatorKey,
|
|
||||||
theme: ThemeData(
|
|
||||||
brightness: Brightness.dark,
|
|
||||||
scaffoldBackgroundColor: Colors.black,
|
|
||||||
primaryColor: Color.fromRGBO(42, 117, 188, 1.0),
|
|
||||||
colorScheme: ColorScheme.dark(),
|
|
||||||
useMaterial3: true,
|
|
||||||
),
|
|
||||||
routes: MessagingRoutes.instance.messagingRoutes,
|
|
||||||
initialRoute: "login",
|
|
||||||
// home: RegisterationPage(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,167 +0,0 @@
|
|||||||
import 'package:appwrite/appwrite.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
runApp(const MyApp());
|
|
||||||
}
|
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
|
||||||
const MyApp({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return MaterialApp(
|
|
||||||
title: 'FlAppwrite Realtime Demo',
|
|
||||||
theme: ThemeData(
|
|
||||||
primarySwatch: Colors.blue,
|
|
||||||
),
|
|
||||||
home: const HomePage(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class HomePage extends StatefulWidget {
|
|
||||||
const HomePage({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<HomePage> createState() => _HomePageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _HomePageState extends State<HomePage> {
|
|
||||||
List<Map<String, dynamic>> items = [];
|
|
||||||
final TextEditingController _nameController = TextEditingController();
|
|
||||||
RealtimeSubscription? subscription;
|
|
||||||
late final Client client;
|
|
||||||
final database = '67db1d75002a1826f6f9'; // your database id
|
|
||||||
final itemsCollection = '67db1e36001ffd2719b7'; // your collection id
|
|
||||||
late final Databases databases;
|
|
||||||
|
|
||||||
@override
|
|
||||||
initState() {
|
|
||||||
super.initState();
|
|
||||||
|
|
||||||
client = Client()
|
|
||||||
.setEndpoint('https://api.theonasanyas.com/v1')
|
|
||||||
.setProject('67833160000cb0801fdb'); // your project id
|
|
||||||
databases = Databases(client);
|
|
||||||
loadItems();
|
|
||||||
subscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
loadItems() async {
|
|
||||||
try {
|
|
||||||
final res = await databases.listDocuments(
|
|
||||||
databaseId: database,
|
|
||||||
collectionId: itemsCollection,
|
|
||||||
);
|
|
||||||
setState(() {
|
|
||||||
items = List<Map<String, dynamic>>.from(res.documents.map(
|
|
||||||
(e) => e.data,
|
|
||||||
));
|
|
||||||
});
|
|
||||||
} on AppwriteException catch (e) {
|
|
||||||
print(e.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void subscribe() {
|
|
||||||
final realtime = Realtime(client);
|
|
||||||
|
|
||||||
subscription = realtime.subscribe([
|
|
||||||
'documents' // subscribe to all documents in every database and collection
|
|
||||||
]);
|
|
||||||
|
|
||||||
// listen to changes
|
|
||||||
subscription!.stream.listen((data) {
|
|
||||||
// data will consist of `events` and a `payload`
|
|
||||||
final event = data.events.first;
|
|
||||||
if (data.payload.isNotEmpty) {
|
|
||||||
if (event.endsWith('.create')) {
|
|
||||||
var item = data.payload;
|
|
||||||
items.add(item);
|
|
||||||
setState(() {});
|
|
||||||
} else if (event.endsWith('.delete')) {
|
|
||||||
var item = data.payload;
|
|
||||||
items.removeWhere((it) => it['\$id'] == item['\$id']);
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
dispose() {
|
|
||||||
subscription?.close();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: const Text('FlAppwrite Realtime Demo'),
|
|
||||||
),
|
|
||||||
body: ListView(children: [
|
|
||||||
...items.map((item) => ListTile(
|
|
||||||
title: Text(item['name']),
|
|
||||||
trailing: IconButton(
|
|
||||||
icon: const Icon(Icons.delete),
|
|
||||||
onPressed: () async {
|
|
||||||
await databases.deleteDocument(
|
|
||||||
databaseId: database,
|
|
||||||
collectionId: itemsCollection,
|
|
||||||
documentId: item['\$id'],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
]),
|
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
child: const Icon(Icons.add),
|
|
||||||
onPressed: () {
|
|
||||||
// dialog to add new item
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => AlertDialog(
|
|
||||||
title: const Text('Add new item'),
|
|
||||||
content: TextField(
|
|
||||||
controller: _nameController,
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
child: const Text('Cancel'),
|
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
child: const Text('Add'),
|
|
||||||
onPressed: () {
|
|
||||||
// add new item
|
|
||||||
final name = _nameController.text;
|
|
||||||
if (name.isNotEmpty) {
|
|
||||||
_nameController.clear();
|
|
||||||
_addItem(name);
|
|
||||||
}
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _addItem(String name) async {
|
|
||||||
try {
|
|
||||||
await databases.createDocument(
|
|
||||||
databaseId: database,
|
|
||||||
collectionId: itemsCollection,
|
|
||||||
documentId: ID.unique(),
|
|
||||||
data: {'name': name},
|
|
||||||
);
|
|
||||||
} on AppwriteException catch (e) {
|
|
||||||
print(e.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:messaging_app/components/messaging_routes.dart';
|
||||||
|
import 'package:messaging_app/service/navigation_service.dart';
|
||||||
|
|
||||||
|
class MessagingApp extends StatelessWidget {
|
||||||
|
|
||||||
|
const MessagingApp({super.key});
|
||||||
|
|
||||||
|
// This widget is the root of your application.
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
title: 'Messaging App',
|
||||||
|
navigatorKey: NavigationService.instance.navigatorKey,
|
||||||
|
theme: ThemeData(
|
||||||
|
brightness: Brightness.dark,
|
||||||
|
scaffoldBackgroundColor: Colors.black,
|
||||||
|
primaryColor: Color.fromRGBO(42, 117, 188, 1.0),
|
||||||
|
colorScheme: ColorScheme.dark(),
|
||||||
|
useMaterial3: true,
|
||||||
|
),
|
||||||
|
routes: MessagingRoutes.instance.messagingRoutes,
|
||||||
|
initialRoute: "login",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,28 @@
|
|||||||
import 'package:messaging_app/models/details.dart';
|
import 'package:messaging_app/models/details.dart';
|
||||||
|
|
||||||
class Conversations {
|
class Conversations {
|
||||||
|
String? id;
|
||||||
String chatId;
|
String chatId;
|
||||||
Details details;
|
Details details;
|
||||||
DateTime? lastModified;
|
DateTime? lastModified;
|
||||||
|
|
||||||
Conversations({
|
Conversations({
|
||||||
|
this.id,
|
||||||
required this.chatId,
|
required this.chatId,
|
||||||
required this.details,
|
required this.details,
|
||||||
this.lastModified,
|
this.lastModified,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Convert the details string to a Details object
|
||||||
|
// and parse the lastModified string to a DateTime object
|
||||||
|
// Note: You may need to adjust the parsing logic based on your data format
|
||||||
|
// For example, if _details is a JSON string, you can use json.decode to parse it
|
||||||
|
// and create a Details object from the parsed data.
|
||||||
|
// Assuming _details is a JSON string, you can use the Details.fromData method
|
||||||
|
// to create a Details object.
|
||||||
|
// Assuming _lastModified is a string in ISO 8601 format
|
||||||
|
|
||||||
|
|
||||||
factory Conversations.fromData(
|
factory Conversations.fromData(
|
||||||
String _chatId, String _details, String _lastModified) =>
|
String _chatId, String _details, String _lastModified) =>
|
||||||
Conversations(
|
Conversations(
|
||||||
|
|||||||
+18
-18
@@ -3,28 +3,28 @@ import 'dart:convert';
|
|||||||
class Details {
|
class Details {
|
||||||
String name;
|
String name;
|
||||||
String image;
|
String image;
|
||||||
|
String email;
|
||||||
int unseenCount;
|
int unseenCount;
|
||||||
String? lastMessage;
|
String? lastMessage;
|
||||||
DateTime? timeStamp;
|
DateTime? timeStamp;
|
||||||
String? type;
|
String? type;
|
||||||
|
|
||||||
Details({
|
Details(
|
||||||
required this.name,
|
{required this.name,
|
||||||
required this.image,
|
required this.image,
|
||||||
required this.lastMessage,
|
required this.email,
|
||||||
required this.timeStamp,
|
required this.lastMessage,
|
||||||
required this.unseenCount,
|
required this.timeStamp,
|
||||||
required this.type
|
required this.unseenCount,
|
||||||
});
|
required this.type});
|
||||||
|
|
||||||
factory Details.fromData(String _details) {
|
factory Details.fromData(String _details) => Details(
|
||||||
return Details(
|
email: json.decode(_details)['email'],
|
||||||
name: json.decode(_details)['name'],
|
name: json.decode(_details)['name'],
|
||||||
image: json.decode(_details)['image'],
|
image: json.decode(_details)['image'],
|
||||||
lastMessage: json.decode(_details)['lastMessage'],
|
lastMessage: json.decode(_details)['lastMessage'] ?? "",
|
||||||
timeStamp: DateTime.parse(json.decode(_details)['timeStamp'] ?? ""),
|
timeStamp: DateTime.parse(json.decode(_details)['timeStamp']),
|
||||||
unseenCount: json.decode(_details)['unseenCount'],
|
unseenCount: json.decode(_details)['unseenCount'],
|
||||||
type: json.decode(_details)['type'],
|
type: json.decode(_details)['type'] ?? "",
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ class Messages {
|
|||||||
timeStamp: _message['timeStamp'] ?? "",
|
timeStamp: _message['timeStamp'] ?? "",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
"message": message,
|
"message": message,
|
||||||
"senderId": senderId,
|
"senderId": senderId,
|
||||||
|
|||||||
@@ -15,13 +15,11 @@ class User {
|
|||||||
required this.lastSeen,
|
required this.lastSeen,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory User.fromData(Document _document) {
|
factory User.fromData(Document _document) => User(
|
||||||
return User(
|
id: _document.data['\$id'],
|
||||||
id: _document.data['\$id'],
|
name: _document.data['name'],
|
||||||
name: _document.data['name'],
|
email: _document.data['email'],
|
||||||
email: _document.data['email'],
|
image: _document.data['image'],
|
||||||
image: _document.data['image'],
|
lastSeen: DateTime.parse(_document.data['lastSeen']),
|
||||||
lastSeen: DateTime.parse(_document.data['lastSeen']),
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -11,19 +11,24 @@ import 'package:messaging_app/service/snackbar_service.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:timeago/timeago.dart' as timeago;
|
import 'package:timeago/timeago.dart' as timeago;
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
class ConversationsPage extends StatefulWidget {
|
class ConversationsPage extends StatefulWidget {
|
||||||
ConversationsPage({
|
ConversationsPage({
|
||||||
super.key,
|
super.key,
|
||||||
required this.chatId,
|
required this.chatId,
|
||||||
// required this.receiverId,
|
this.userId,
|
||||||
required this.chatImage,
|
required this.userName,
|
||||||
required this.chatName,
|
required this.userImage,
|
||||||
|
this.userEmail,
|
||||||
|
// this.chatMessage,
|
||||||
});
|
});
|
||||||
|
|
||||||
String chatId;
|
String chatId;
|
||||||
// String receiverId;
|
String? userId;
|
||||||
String chatName;
|
String userName;
|
||||||
String chatImage;
|
String userImage;
|
||||||
|
String? userEmail;
|
||||||
|
// Map? chatMessage;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() {
|
State<StatefulWidget> createState() {
|
||||||
@@ -33,13 +38,12 @@ class ConversationsPage extends StatefulWidget {
|
|||||||
|
|
||||||
class _ConversationsPageState extends State<ConversationsPage> {
|
class _ConversationsPageState extends State<ConversationsPage> {
|
||||||
//
|
//
|
||||||
|
MessagingProviders _auth = MessagingProviders.instance;
|
||||||
|
final ScrollController _scrollController = ScrollController();
|
||||||
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
late double _deviceHeight;
|
late double _deviceHeight;
|
||||||
late double _deviceWidth;
|
late double _deviceWidth;
|
||||||
|
|
||||||
final ScrollController _scrollController;
|
|
||||||
final GlobalKey<FormState> _formKey;
|
|
||||||
late MessagingProviders _auth;
|
|
||||||
List<List<Messages>> _messagesArray;
|
List<List<Messages>> _messagesArray;
|
||||||
List<Messages> _messages;
|
List<Messages> _messages;
|
||||||
List<String> _members;
|
List<String> _members;
|
||||||
@@ -48,8 +52,6 @@ class _ConversationsPageState extends State<ConversationsPage> {
|
|||||||
|
|
||||||
_ConversationsPageState()
|
_ConversationsPageState()
|
||||||
: _messageText = '',
|
: _messageText = '',
|
||||||
_formKey = GlobalKey<FormState>(),
|
|
||||||
_scrollController = ScrollController(),
|
|
||||||
_messagesArray = [],
|
_messagesArray = [],
|
||||||
_messages = [],
|
_messages = [],
|
||||||
_members = [],
|
_members = [],
|
||||||
@@ -63,12 +65,46 @@ class _ConversationsPageState extends State<ConversationsPage> {
|
|||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => Dialog(
|
||||||
|
child: SizedBox(
|
||||||
|
height: _deviceHeight * 0.25,
|
||||||
|
width: _deviceHeight * 0.25,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
// padding: EdgeInsets.all(20),
|
||||||
|
height: _deviceHeight * 0.20,
|
||||||
|
width: _deviceHeight * 0.20,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
image: DecorationImage(
|
||||||
|
image: NetworkImage(widget.userImage),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(widget.userName),
|
||||||
|
Text(widget.userEmail!)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.info_outline),
|
||||||
|
)
|
||||||
|
],
|
||||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
title: Text(widget.chatName),
|
title: Text(widget.userName),
|
||||||
titleTextStyle: TextStyle(fontSize: 16),
|
titleTextStyle: TextStyle(fontSize: 16),
|
||||||
),
|
),
|
||||||
body: ChangeNotifierProvider<MessagingProviders>.value(
|
body: ChangeNotifierProvider<MessagingProviders>.value(
|
||||||
value: MessagingProviders.instance,
|
value: _auth,
|
||||||
child: _conversationPageUI(),
|
child: _conversationPageUI(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -91,11 +127,11 @@ class _ConversationsPageState extends State<ConversationsPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _messageListView() {
|
Widget _messageListView() {
|
||||||
return Container(
|
return SizedBox(
|
||||||
height: _deviceHeight * 0.80,
|
height: _deviceHeight * 0.80,
|
||||||
width: _deviceWidth,
|
width: _deviceWidth,
|
||||||
child: StreamBuilder<Chats>(
|
child: StreamBuilder<Chats>(
|
||||||
stream: MessagingProviders.instance.getMessage(widget.chatId),
|
stream: _auth.getMessage(widget.chatId),
|
||||||
builder: (_context, _snapshot) {
|
builder: (_context, _snapshot) {
|
||||||
if (_snapshot.hasData) {
|
if (_snapshot.hasData) {
|
||||||
_members = _snapshot.data!.members;
|
_members = _snapshot.data!.members;
|
||||||
@@ -109,6 +145,15 @@ class _ConversationsPageState extends State<ConversationsPage> {
|
|||||||
child: Text("No Chat"),
|
child: Text("No Chat"),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
if (_scrollController.hasClients) {
|
||||||
|
_scrollController.animateTo(
|
||||||
|
_scrollController.position.maxScrollExtent,
|
||||||
|
duration: const Duration(microseconds: 500),
|
||||||
|
curve: Curves.fastOutSlowIn);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
@@ -192,6 +237,7 @@ class _ConversationsPageState extends State<ConversationsPage> {
|
|||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
timeago.format(DateTime.parse(_message.timeStamp)),
|
timeago.format(DateTime.parse(_message.timeStamp)),
|
||||||
|
// "${DateTime.parse(_message.timeStamp).}",
|
||||||
style: TextStyle(color: Colors.white70, fontSize: 10),
|
style: TextStyle(color: Colors.white70, fontSize: 10),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -252,7 +298,7 @@ class _ConversationsPageState extends State<ConversationsPage> {
|
|||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
image: NetworkImage(
|
image: NetworkImage(
|
||||||
widget.chatImage,
|
widget.userImage,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -317,7 +363,7 @@ class _ConversationsPageState extends State<ConversationsPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _sendText(BuildContext _context) {
|
Widget _sendText(BuildContext _context) {
|
||||||
return Container(
|
return SizedBox(
|
||||||
height: _deviceHeight * 0.045,
|
height: _deviceHeight * 0.045,
|
||||||
width: _deviceHeight * 0.045,
|
width: _deviceHeight * 0.045,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
@@ -348,8 +394,7 @@ class _ConversationsPageState extends State<ConversationsPage> {
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
XFile? _imageFile = await MediaService.instance.getImageFromLibrary();
|
XFile? _imageFile = await MediaService.instance.getImageFromLibrary();
|
||||||
if (_imageFile != null) {
|
if (_imageFile != null) {
|
||||||
var _url = await MessagingProviders.instance
|
var _url = await _auth.uploadUserImage(_imageFile, '_uid');
|
||||||
.uploadUserImage(_imageFile, '_uid');
|
|
||||||
|
|
||||||
await sendMessage('image', _url);
|
await sendMessage('image', _url);
|
||||||
}
|
}
|
||||||
@@ -386,9 +431,7 @@ class _ConversationsPageState extends State<ConversationsPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await _auth.sendMessage(
|
await _auth.sendMessage(
|
||||||
widget.chatId,
|
widget.chatId, {"messages": outMessages}, 'update');
|
||||||
{"messages": outMessages},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -396,7 +439,30 @@ class _ConversationsPageState extends State<ConversationsPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> sendMessage(var type, var _message) async {
|
Future<void> sendMessage(var type, var _message) async {
|
||||||
List outMessages = [];
|
List _outMessages = [];
|
||||||
|
|
||||||
|
if (_members.isEmpty) {
|
||||||
|
_members = [_auth.user!.$id, widget.userId!];
|
||||||
|
|
||||||
|
List<String> messagesTemp = [];
|
||||||
|
messagesTemp = [
|
||||||
|
json.encode({
|
||||||
|
_auth.user!.$id: [],
|
||||||
|
}),
|
||||||
|
json.encode({
|
||||||
|
widget.userId: [],
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
Map<String, dynamic> _chat = {
|
||||||
|
"ownerId": _auth.user!.$id,
|
||||||
|
"members": _members,
|
||||||
|
"messages": messagesTemp
|
||||||
|
};
|
||||||
|
|
||||||
|
await _auth.sendMessage(widget.chatId, _chat, 'new');
|
||||||
|
await Future.delayed(Duration(seconds: 1));
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _members.length; i++) {
|
for (var i = 0; i < _members.length; i++) {
|
||||||
_messagesArray[i].add(
|
_messagesArray[i].add(
|
||||||
@@ -408,7 +474,7 @@ class _ConversationsPageState extends State<ConversationsPage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
outMessages.add(
|
_outMessages.add(
|
||||||
json.encode(
|
json.encode(
|
||||||
{_members[i]: _messagesArray[i]},
|
{_members[i]: _messagesArray[i]},
|
||||||
),
|
),
|
||||||
@@ -417,7 +483,8 @@ class _ConversationsPageState extends State<ConversationsPage> {
|
|||||||
|
|
||||||
await _auth.sendMessage(
|
await _auth.sendMessage(
|
||||||
widget.chatId,
|
widget.chatId,
|
||||||
{"messages": outMessages},
|
{"messages": _outMessages},
|
||||||
|
'update',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-20
@@ -65,27 +65,28 @@ class _HomePageState extends State<HomePage>
|
|||||||
_deviceWidth = MediaQuery.of(context).size.width;
|
_deviceWidth = MediaQuery.of(context).size.width;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
// backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
// backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
automaticallyImplyLeading: false,
|
automaticallyImplyLeading: false,
|
||||||
// backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
// backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
title: Text("the messenger"),
|
title: Text("the messenger"),
|
||||||
titleTextStyle: TextStyle(fontSize: 16),
|
titleTextStyle: TextStyle(fontSize: 16),
|
||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
unselectedLabelColor: Colors.grey,
|
unselectedLabelColor: Colors.grey,
|
||||||
indicatorColor: Colors.blue,
|
indicatorColor: Colors.blue,
|
||||||
labelColor: Colors.blue,
|
labelColor: Colors.blue,
|
||||||
controller: _tabController,
|
controller: _tabController,
|
||||||
tabs: _iconTabs,
|
tabs: _iconTabs,
|
||||||
),
|
|
||||||
),
|
),
|
||||||
body: _tabBarPages(),
|
),
|
||||||
floatingActionButton: _tabController.index == 1
|
body: _tabBarPages(),
|
||||||
? Container()
|
// floatingActionButton: _tabController.index == 1
|
||||||
: FloatingActionButton(
|
// ? Container()
|
||||||
child: Icon(Icons.add),
|
// : FloatingActionButton(
|
||||||
onPressed: () {},
|
// child: Icon(Icons.add),
|
||||||
));
|
// onPressed: () {},
|
||||||
|
// ),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _tabBarPages() {
|
Widget _tabBarPages() {
|
||||||
|
|||||||
+13
-13
@@ -23,12 +23,8 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
String? _email;
|
String? _email;
|
||||||
String? _password;
|
String? _password;
|
||||||
|
|
||||||
late GlobalKey<FormState> _formKey;
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
late MessagingProviders _auth;
|
MessagingProviders _auth = MessagingProviders.instance;
|
||||||
|
|
||||||
_LoginPageState() {
|
|
||||||
_formKey = GlobalKey<FormState>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -40,7 +36,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
body: Align(
|
body: Align(
|
||||||
child: ChangeNotifierProvider<MessagingProviders>.value(
|
child: ChangeNotifierProvider<MessagingProviders>.value(
|
||||||
value: MessagingProviders.instance,
|
value: _auth,
|
||||||
child: _loginPageUI(),
|
child: _loginPageUI(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -133,9 +129,11 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
},
|
},
|
||||||
cursorColor: Colors.white,
|
cursorColor: Colors.white,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "email address",
|
hintText: "email address",
|
||||||
focusedBorder: UnderlineInputBorder(
|
focusedBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.white))),
|
borderSide: BorderSide(color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,9 +156,11 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
obscureText: true,
|
obscureText: true,
|
||||||
cursorColor: Colors.white,
|
cursorColor: Colors.white,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "password",
|
hintText: "password",
|
||||||
focusedBorder: UnderlineInputBorder(
|
focusedBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.white))),
|
borderSide: BorderSide(color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,17 +11,17 @@ class ProfilePage extends StatelessWidget {
|
|||||||
|
|
||||||
final double _deviceHeight;
|
final double _deviceHeight;
|
||||||
final double _deviceWidth;
|
final double _deviceWidth;
|
||||||
late MessagingProviders _auth;
|
MessagingProviders _auth = MessagingProviders.instance;
|
||||||
|
|
||||||
ProfilePage(this._deviceHeight, this._deviceWidth, {super.key});
|
ProfilePage(this._deviceHeight, this._deviceWidth, {super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return SizedBox(
|
||||||
height: _deviceHeight,
|
height: _deviceHeight,
|
||||||
width: _deviceWidth,
|
width: _deviceWidth,
|
||||||
child: ChangeNotifierProvider<MessagingProviders>.value(
|
child: ChangeNotifierProvider<MessagingProviders>.value(
|
||||||
value: MessagingProviders.instance,
|
value: _auth,
|
||||||
child: _profilePageUI(),
|
child: _profilePageUI(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -29,10 +29,11 @@ class ProfilePage extends StatelessWidget {
|
|||||||
|
|
||||||
Widget _profilePageUI() {
|
Widget _profilePageUI() {
|
||||||
return Builder(builder: (BuildContext _context) {
|
return Builder(builder: (BuildContext _context) {
|
||||||
|
// assert(_auth.user != null);
|
||||||
SnackBarService.instance.buildContext = _context;
|
SnackBarService.instance.buildContext = _context;
|
||||||
_auth = Provider.of<MessagingProviders>(_context);
|
_auth = Provider.of<MessagingProviders>(_context);
|
||||||
return StreamBuilder<User>(
|
return StreamBuilder<User>(
|
||||||
stream: MessagingProviders.instance.getUser(_auth.user!.$id),
|
stream: _auth.getUser(_auth.user!.$id),
|
||||||
builder: (_, _snapshot) {
|
builder: (_, _snapshot) {
|
||||||
var _userData = _snapshot.data;
|
var _userData = _snapshot.data;
|
||||||
return _snapshot.hasData
|
return _snapshot.hasData
|
||||||
@@ -76,7 +77,7 @@ class ProfilePage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _userNameWidget(String _name) {
|
Widget _userNameWidget(String _name) {
|
||||||
return Container(
|
return SizedBox(
|
||||||
height: _deviceHeight * 0.05,
|
height: _deviceHeight * 0.05,
|
||||||
width: _deviceWidth,
|
width: _deviceWidth,
|
||||||
child: Text(
|
child: Text(
|
||||||
@@ -91,7 +92,7 @@ class ProfilePage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _userEmailWidget(String _email) {
|
Widget _userEmailWidget(String _email) {
|
||||||
return Container(
|
return SizedBox(
|
||||||
height: _deviceHeight * 0.03,
|
height: _deviceHeight * 0.03,
|
||||||
width: _deviceWidth,
|
width: _deviceWidth,
|
||||||
child: Text(
|
child: Text(
|
||||||
@@ -106,7 +107,7 @@ class ProfilePage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _logoutButton() {
|
Widget _logoutButton() {
|
||||||
return Container(
|
return SizedBox(
|
||||||
height: _deviceHeight * 0.06,
|
height: _deviceHeight * 0.06,
|
||||||
width: _deviceWidth * 0.80,
|
width: _deviceWidth * 0.80,
|
||||||
child: MaterialButton(
|
child: MaterialButton(
|
||||||
@@ -115,7 +116,7 @@ class ProfilePage extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
color: Colors.red,
|
color: Colors.red,
|
||||||
child: Text(
|
child: Text(
|
||||||
"Logout".toUpperCase(),
|
"logout".toUpperCase(),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||||
import 'package:messaging_app/components/messaging_provider.dart';
|
import 'package:messaging_app/components/messaging_provider.dart';
|
||||||
@@ -25,18 +23,8 @@ class RecentConverstationsPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _RecentConverstationsPageState extends State<RecentConverstationsPage> {
|
class _RecentConverstationsPageState extends State<RecentConverstationsPage> {
|
||||||
late MessagingProviders _auth;
|
//
|
||||||
|
MessagingProviders _auth = MessagingProviders.instance;
|
||||||
final myController = StreamController<List<Conversations>>.broadcast();
|
|
||||||
Stream<List<Conversations>> get messageStream => myController.stream;
|
|
||||||
|
|
||||||
void messager() {
|
|
||||||
MessagingProviders.instance.getUserConversation(_auth.user!.$id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dispose() {
|
|
||||||
myController.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -44,7 +32,7 @@ class _RecentConverstationsPageState extends State<RecentConverstationsPage> {
|
|||||||
height: widget._deviceHeight,
|
height: widget._deviceHeight,
|
||||||
width: widget._deviceWidth,
|
width: widget._deviceWidth,
|
||||||
child: ChangeNotifierProvider<MessagingProviders>.value(
|
child: ChangeNotifierProvider<MessagingProviders>.value(
|
||||||
value: MessagingProviders.instance,
|
value: _auth,
|
||||||
child: _conversationView(context),
|
child: _conversationView(context),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -58,8 +46,7 @@ class _RecentConverstationsPageState extends State<RecentConverstationsPage> {
|
|||||||
height: widget._deviceHeight,
|
height: widget._deviceHeight,
|
||||||
width: widget._deviceWidth,
|
width: widget._deviceWidth,
|
||||||
child: StreamBuilder<List<Conversations>>(
|
child: StreamBuilder<List<Conversations>>(
|
||||||
stream: MessagingProviders.instance
|
stream: _auth.getUserConversation(_auth.user!.$id),
|
||||||
.getUserConversation(_auth.user!.$id),
|
|
||||||
builder: (_context, _snapshot) {
|
builder: (_context, _snapshot) {
|
||||||
if (_snapshot.hasData) {
|
if (_snapshot.hasData) {
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
@@ -75,8 +62,9 @@ class _RecentConverstationsPageState extends State<RecentConverstationsPage> {
|
|||||||
builder: (BuildContext _context) {
|
builder: (BuildContext _context) {
|
||||||
return ConversationsPage(
|
return ConversationsPage(
|
||||||
chatId: _chatId,
|
chatId: _chatId,
|
||||||
chatName: _details.name,
|
userName: _details.name,
|
||||||
chatImage: _details.image,
|
userImage : _details.image,
|
||||||
|
userEmail: _details.email,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -84,9 +72,11 @@ class _RecentConverstationsPageState extends State<RecentConverstationsPage> {
|
|||||||
},
|
},
|
||||||
title: Text(_details.name),
|
title: Text(_details.name),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
_details.type == 'text'
|
_details.type == ''
|
||||||
? _details.lastMessage!
|
? 'start chatting...'
|
||||||
: 'attachment: image',
|
: _details.type == 'text'
|
||||||
|
? _details.lastMessage!
|
||||||
|
: 'attachment: image',
|
||||||
),
|
),
|
||||||
leading: Container(
|
leading: Container(
|
||||||
width: 50,
|
width: 50,
|
||||||
|
|||||||
@@ -26,10 +26,8 @@ class _RegisterationPageState extends State<RegisterationPage> {
|
|||||||
String? _email;
|
String? _email;
|
||||||
String? _password;
|
String? _password;
|
||||||
|
|
||||||
GlobalKey<FormState> _formKey;
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
late MessagingProviders _auth;
|
MessagingProviders _auth = MessagingProviders.instance;
|
||||||
|
|
||||||
_RegisterationPageState() : _formKey = GlobalKey<FormState>();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -43,7 +41,7 @@ class _RegisterationPageState extends State<RegisterationPage> {
|
|||||||
// color: Colors.blue,
|
// color: Colors.blue,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: ChangeNotifierProvider<MessagingProviders>.value(
|
child: ChangeNotifierProvider<MessagingProviders>.value(
|
||||||
value: MessagingProviders.instance,
|
value: _auth,
|
||||||
child: _registerationPageUI(),
|
child: _registerationPageUI(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -163,9 +161,11 @@ class _RegisterationPageState extends State<RegisterationPage> {
|
|||||||
},
|
},
|
||||||
cursorColor: Colors.white,
|
cursorColor: Colors.white,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "name",
|
hintText: "name",
|
||||||
focusedBorder: UnderlineInputBorder(
|
focusedBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.white))),
|
borderSide: BorderSide(color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,9 +189,11 @@ class _RegisterationPageState extends State<RegisterationPage> {
|
|||||||
},
|
},
|
||||||
cursorColor: Colors.white,
|
cursorColor: Colors.white,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "email",
|
hintText: "email",
|
||||||
focusedBorder: UnderlineInputBorder(
|
focusedBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.white))),
|
borderSide: BorderSide(color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,9 +216,11 @@ class _RegisterationPageState extends State<RegisterationPage> {
|
|||||||
obscureText: true,
|
obscureText: true,
|
||||||
cursorColor: Colors.white,
|
cursorColor: Colors.white,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "password",
|
hintText: "password",
|
||||||
focusedBorder: UnderlineInputBorder(
|
focusedBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.white))),
|
borderSide: BorderSide(color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+97
-123
@@ -1,5 +1,3 @@
|
|||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:messaging_app/components/messaging_provider.dart';
|
import 'package:messaging_app/components/messaging_provider.dart';
|
||||||
import 'package:messaging_app/models/users.dart';
|
import 'package:messaging_app/models/users.dart';
|
||||||
@@ -8,6 +6,7 @@ import 'package:messaging_app/service/navigation_service.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:timeago/timeago.dart' as timeago;
|
import 'package:timeago/timeago.dart' as timeago;
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
class SearchPage extends StatefulWidget {
|
class SearchPage extends StatefulWidget {
|
||||||
SearchPage({
|
SearchPage({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -17,7 +16,6 @@ class SearchPage extends StatefulWidget {
|
|||||||
|
|
||||||
double deviceHeight;
|
double deviceHeight;
|
||||||
double deviceWidth;
|
double deviceWidth;
|
||||||
late MessagingProviders _auth;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<SearchPage> createState() => _SearchPageState();
|
State<SearchPage> createState() => _SearchPageState();
|
||||||
@@ -26,6 +24,7 @@ class SearchPage extends StatefulWidget {
|
|||||||
class _SearchPageState extends State<SearchPage> {
|
class _SearchPageState extends State<SearchPage> {
|
||||||
late String _searchText;
|
late String _searchText;
|
||||||
late List<User> _usersData;
|
late List<User> _usersData;
|
||||||
|
MessagingProviders _auth = MessagingProviders.instance;
|
||||||
//
|
//
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -41,7 +40,7 @@ class _SearchPageState extends State<SearchPage> {
|
|||||||
height: widget.deviceHeight,
|
height: widget.deviceHeight,
|
||||||
width: widget.deviceWidth,
|
width: widget.deviceWidth,
|
||||||
child: ChangeNotifierProvider.value(
|
child: ChangeNotifierProvider.value(
|
||||||
value: MessagingProviders.instance,
|
value: _auth,
|
||||||
child: _searchPaheUI(),
|
child: _searchPaheUI(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -50,7 +49,7 @@ class _SearchPageState extends State<SearchPage> {
|
|||||||
|
|
||||||
Widget _searchPaheUI() {
|
Widget _searchPaheUI() {
|
||||||
return Builder(builder: (_context) {
|
return Builder(builder: (_context) {
|
||||||
widget._auth = Provider.of<MessagingProviders>(_context);
|
_auth = Provider.of<MessagingProviders>(_context);
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
@@ -67,7 +66,9 @@ class _SearchPageState extends State<SearchPage> {
|
|||||||
return Container(
|
return Container(
|
||||||
height: widget.deviceHeight * 0.08,
|
height: widget.deviceHeight * 0.08,
|
||||||
width: widget.deviceWidth,
|
width: widget.deviceWidth,
|
||||||
padding: EdgeInsets.symmetric(vertical: widget.deviceHeight * 0.02),
|
padding: EdgeInsets.symmetric(
|
||||||
|
vertical: widget.deviceHeight * 0.02,
|
||||||
|
),
|
||||||
child: TextField(
|
child: TextField(
|
||||||
autocorrect: false,
|
autocorrect: false,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@@ -90,133 +91,106 @@ class _SearchPageState extends State<SearchPage> {
|
|||||||
|
|
||||||
Widget _searchPageUIList() {
|
Widget _searchPageUIList() {
|
||||||
return StreamBuilder<List<User>>(
|
return StreamBuilder<List<User>>(
|
||||||
stream: MessagingProviders.instance.getAllUsers(_searchText.trim()),
|
stream: _auth.getAllUsers(_searchText.trim()),
|
||||||
builder: (_, _snapshot) {
|
builder: (_, _snapshot) {
|
||||||
if (_snapshot.hasData) {
|
if (_snapshot.hasData) {
|
||||||
_usersData = _snapshot.data!
|
_usersData = _snapshot.data!
|
||||||
.where((_data) => _data.id != widget._auth.user!.$id)
|
.where((_data) => _data.id != _auth.user!.$id)
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
return _snapshot.hasData
|
return _snapshot.hasData
|
||||||
? SizedBox(
|
? SizedBox(
|
||||||
height: widget.deviceHeight * 0.70,
|
height: widget.deviceHeight * 0.70,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
itemCount: _usersData.length,
|
itemCount: _usersData.length,
|
||||||
itemBuilder: (_, _index) {
|
itemBuilder: (_, _index) {
|
||||||
var _userData = _usersData[_index];
|
var _userData = _usersData[_index];
|
||||||
var _isUserActive = _userData.lastSeen.isBefore(
|
var _isUserActive = _userData.lastSeen.isBefore(
|
||||||
DateTime.now().toUtc().subtract(
|
DateTime.now().toUtc().subtract(
|
||||||
Duration(
|
Duration(
|
||||||
minutes: 1,
|
minutes: 1,
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return ListTile(
|
|
||||||
enabled: true,
|
|
||||||
onTap: () async {
|
|
||||||
String _chatId;
|
|
||||||
String _linkId =
|
|
||||||
'${widget._auth.user!.$id}${_userData.id}';
|
|
||||||
|
|
||||||
_chatId = await MessagingProviders.instance
|
|
||||||
.getConversationLink(
|
|
||||||
_linkId.substring(0, 36));
|
|
||||||
|
|
||||||
if (_chatId.isEmpty) {
|
|
||||||
List<dynamic> _members = [
|
|
||||||
widget._auth.user!.$id,
|
|
||||||
_userData.id
|
|
||||||
];
|
|
||||||
|
|
||||||
List<String> messagesTemp = [];
|
|
||||||
messagesTemp = [
|
|
||||||
json.encode({
|
|
||||||
widget._auth.user!.$id: [],
|
|
||||||
}),
|
|
||||||
json.encode({
|
|
||||||
_userData.id: [],
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
Map<String, dynamic> _chat = {
|
|
||||||
"ownerId": widget._auth.user!.$id,
|
|
||||||
"members": _members,
|
|
||||||
"messages": messagesTemp
|
|
||||||
};
|
|
||||||
_chatId = await MessagingProviders.instance
|
|
||||||
.newMesaage(_chat);
|
|
||||||
}
|
|
||||||
|
|
||||||
NavigationService.instance.navigateToRoute(
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (BuildContext _context) {
|
|
||||||
return ConversationsPage(
|
|
||||||
chatId: _chatId,
|
|
||||||
chatName: _userData.name,
|
|
||||||
chatImage: _userData.image,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
title: Text(_userData.name),
|
|
||||||
leading: Container(
|
|
||||||
width: 50,
|
|
||||||
height: 50,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(100),
|
|
||||||
image: DecorationImage(
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
image: NetworkImage(_userData.image),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
trailing: Column(
|
);
|
||||||
mainAxisAlignment:
|
return ListTile(
|
||||||
MainAxisAlignment.spaceEvenly,
|
enabled: true,
|
||||||
mainAxisSize: MainAxisSize.max,
|
onTap: () async {
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
List _linkId = [
|
||||||
children: [
|
_auth.user!.$id.substring(0, 18),
|
||||||
_isUserActive
|
_userData.id.substring(0, 18)
|
||||||
? Text(
|
];
|
||||||
"last seen",
|
_linkId.sort();
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 15,
|
NavigationService.instance.navigateToRoute(
|
||||||
),
|
MaterialPageRoute(
|
||||||
)
|
builder: (BuildContext _context) {
|
||||||
: Text(
|
return ConversationsPage(
|
||||||
"active",
|
chatId: _linkId.join(),
|
||||||
style: TextStyle(
|
userId: _userData.id,
|
||||||
fontSize: 15,
|
userName: _userData.name,
|
||||||
),
|
userImage: _userData.image,
|
||||||
),
|
userEmail: _userData.email,
|
||||||
_isUserActive
|
);
|
||||||
? Text(
|
},
|
||||||
timeago.format(
|
|
||||||
_userData.lastSeen,
|
|
||||||
),
|
|
||||||
style: TextStyle(fontSize: 15),
|
|
||||||
)
|
|
||||||
: Container(
|
|
||||||
height: 10,
|
|
||||||
width: 10,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.blue,
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.circular(100),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
},
|
||||||
)
|
title: Text(_userData.name),
|
||||||
: Container()
|
leading: Container(
|
||||||
// : SpinKitWanderingCubes(
|
width: 50,
|
||||||
// color: Colors.blue,
|
height: 50,
|
||||||
// size: 50.0,
|
decoration: BoxDecoration(
|
||||||
// );
|
borderRadius: BorderRadius.circular(100),
|
||||||
;
|
image: DecorationImage(
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
image: NetworkImage(_userData.image),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
trailing: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
_isUserActive
|
||||||
|
? Text(
|
||||||
|
"last seen",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
|
"active",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_isUserActive
|
||||||
|
? Text(
|
||||||
|
timeago.format(
|
||||||
|
_userData.lastSeen,
|
||||||
|
),
|
||||||
|
style: TextStyle(fontSize: 15),
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
height: 10,
|
||||||
|
width: 10,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.blue,
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.circular(100),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
: Container();
|
||||||
|
// : SpinKitWanderingCubes(
|
||||||
|
// color: Colors.blue,
|
||||||
|
// size: 50.0,
|
||||||
|
// );
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user