Recent Conversations Page, Conversations Page implemented'

This commit is contained in:
2025-02-16 18:37:42 +00:00
parent 7e33872886
commit 1a74d16d85
17 changed files with 707 additions and 150 deletions
+12 -8
View File
@@ -1,10 +1,14 @@
//const endPoint = 'http://10.15.45.11/v1';
//const endPoint = 'https://api.theonasanyas.com/v1';
const endPoint = 'https://cloud.appwrite.io/v1';
const projectId = '678bdc7c00203eff8af5';
const selfSigned = false;
const databaseId = '678c8659000a7d6b5bff';
const userCollectionId = '678c865e002fe1cddd06';
const chatsCollectionId = '678c866c0038822276ad';
const convCollectionId = '678c8667001944dee794';
const imageStorageBucket = '678d2162002a6770aaad';
class Constants {
static Constants instance = Constants();
var endPoint = 'https://cloud.appwrite.io/v1';
var projectId = '678bdc7c00203eff8af5';
var selfSigned = false;
var databaseId = '678c8659000a7d6b5bff';
var userCollectionId = '678c865e002fe1cddd06';
var chatsCollectionId = '678c866c0038822276ad';
var convCollectionId = '678c8667001944dee794';
var imageStorageBucket = '678d2162002a6770aaad';
}
+66 -15
View File
@@ -4,6 +4,7 @@ import 'package:appwrite/models.dart' as model;
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:messaging_app/components/constants.dart';
import 'package:messaging_app/models/chats.dart';
import 'package:messaging_app/models/conversations.dart';
import 'package:messaging_app/models/users.dart';
import 'package:messaging_app/service/navigation_service.dart';
@@ -25,9 +26,8 @@ class MessagingProviders extends ChangeNotifier {
late final Storage storage;
// Auth Status
late AuthStatus status;
AuthStatus? status;
late model.User? user;
late model.Session session;
static MessagingProviders instance = MessagingProviders();
@@ -37,7 +37,10 @@ class MessagingProviders extends ChangeNotifier {
}
_init() {
client.setEndpoint(endPoint).setProject(projectId).setSelfSigned();
client
.setEndpoint(Constants.instance.endPoint)
.setProject(Constants.instance.projectId)
.setSelfSigned();
account = Account(client);
database = Databases(client);
storage = Storage(client);
@@ -48,6 +51,7 @@ class MessagingProviders extends ChangeNotifier {
user = await account.get();
if (user != null) {
status = AuthStatus.authenticated;
await updateLastSeen();
_autoLogin();
}
} catch (e) {
@@ -69,13 +73,14 @@ class MessagingProviders extends ChangeNotifier {
try {
status = AuthStatus.authenticating;
session = await account.createEmailPasswordSession(
await account.createEmailPasswordSession(
email: _email, password: _password);
user = await account.get();
status = AuthStatus.authenticated;
SnackBarService.instance.showSnackBarSuccess("Welcome! ${user!.name}");
await updateLastSeen();
NavigationService.instance.navigateToReplacement("home");
} on AppwriteException catch (e) {
SnackBarService.instance.showSnackBarError(e.message!);
@@ -109,7 +114,7 @@ class MessagingProviders extends ChangeNotifier {
}
Future<void> createUser(String _email, String _password, String _name,
Future<void> onSuccess(String _uid)) async {
Future<void> Function(String _uid) onSuccess) async {
notifyListeners();
try {
user = await account.create(
@@ -118,6 +123,7 @@ class MessagingProviders extends ChangeNotifier {
status = AuthStatus.authenticated;
await onSuccess(user!.$id);
SnackBarService.instance.showSnackBarSuccess("Welcome! ${user!.name}");
await updateLastSeen();
NavigationService.instance.goBack();
NavigationService.instance.navigateToReplacement("home");
} on AppwriteException catch (e) {
@@ -136,8 +142,8 @@ class MessagingProviders extends ChangeNotifier {
notifyListeners();
try {
await database.createDocument(
databaseId: databaseId,
collectionId: userCollectionId,
databaseId: Constants.instance.databaseId,
collectionId: Constants.instance.userCollectionId,
documentId: _documentId,
data: {
"name": _name,
@@ -166,18 +172,51 @@ class MessagingProviders extends ChangeNotifier {
notifyListeners();
}
Future<void> updateLastSeen() async {
await database.updateDocument(
databaseId: Constants.instance.databaseId,
collectionId: Constants.instance.userCollectionId,
documentId: user!.$id,
data: {"lastSeen": DateTime.now().toUtc().toIso8601String()},
);
}
Stream<Users> getUser(String userId) {
var _userData = database.getDocument(
databaseId: databaseId,
collectionId: userCollectionId,
databaseId: Constants.instance.databaseId,
collectionId: Constants.instance.userCollectionId,
documentId: userId,
);
return _userData.asStream().map((_snapshot) {
return Users.fromData(_snapshot);
return _userData.asStream().map((_document) {
return Users.fromData(_document);
});
}
Stream<List<Users>> getAllUsers(String _searchText) {
List<Users> _returnValue = [];
if (_searchText.isNotEmpty) {
var _usersData = database.listDocuments(
databaseId: Constants.instance.databaseId,
collectionId: Constants.instance.userCollectionId,
queries: [
Query.contains("name", _searchText),
],
);
return _usersData.asStream().map(
(_documentList) {
for (var _document in _documentList.documents) {
_returnValue.add(Users.fromData(_document));
}
return _returnValue;
},
);
} else {
return Stream.empty();
}
}
Stream<List<Conversations>> getUserConversation(String userId) {
//
List<dynamic> _chatId = [];
@@ -185,8 +224,8 @@ class MessagingProviders extends ChangeNotifier {
List<Conversations> _returnValue = [];
var _conversationData = database.getDocument(
databaseId: databaseId,
collectionId: convCollectionId,
databaseId: Constants.instance.databaseId,
collectionId: Constants.instance.convCollectionId,
documentId: userId.trim(),
);
@@ -203,12 +242,24 @@ class MessagingProviders extends ChangeNotifier {
);
}
Stream<Chats> getChat(String _chatId) {
var _chat = database.getDocument(
databaseId: Constants.instance.databaseId,
collectionId: Constants.instance.chatsCollectionId,
documentId: _chatId,
);
return _chat.asStream().map((_document) {
return Chats.fromData(_document);
});
}
uploadUserImage(XFile? file, String _uid) async {
notifyListeners();
try {
File _file = File(file!.path);
var _message = await storage.createFile(
bucketId: imageStorageBucket,
bucketId: Constants.instance.imageStorageBucket,
fileId: ID.unique(),
file: InputFile.fromPath(path: _file.path, filename: file.name),
permissions: [
@@ -217,7 +268,7 @@ class MessagingProviders extends ChangeNotifier {
],
);
return "$endPoint/storage/buckets/${_message.bucketId}/files/${_message.$id}/view?project=$projectId";
return "${Constants.instance.endPoint}/storage/buckets/${_message.bucketId}/files/${_message.$id}/view?project=${Constants.instance.projectId}";
} on AppwriteException catch (e) {
SnackBarService.instance.showSnackBarError(e.message!);
//
+38
View File
@@ -0,0 +1,38 @@
import 'package:appwrite/models.dart';
import 'package:messaging_app/models/messages.dart';
class Chats {
String ownerId;
List<String> members;
String? type;
List<Messages>? messages;
Chats({
required this.ownerId,
required this.members,
required this.type,
required this.messages,
});
factory Chats.fromData(Document _document) {
List<Messages> _outMessages = [];
List<String> _outMembers = [];
List<dynamic> _messages = _document.data['messages'];
for (var _message in _messages) {
_outMessages.add(Messages.fromData(_message));
}
List<dynamic> _members = _document.data['members'];
for (var _member in _members) {
_outMembers.add(_member);
}
return Chats(
ownerId: _document.data['ownerId'],
members: _outMembers,
type: _document.data['type'],
messages: _outMessages,
);
}
}
+2 -2
View File
@@ -9,10 +9,10 @@ class Conversations {
required this.details,
});
factory Conversations.fromData(String _chatId, String details) {
factory Conversations.fromData(String _chatId, String _details) {
return Conversations(
chatId: _chatId,
details: Details.fromData(details),
details: Details.fromData(_details),
);
}
}
+8 -9
View File
@@ -3,8 +3,8 @@ import 'dart:convert';
class Details {
String name;
String image;
int? unseenCount;
String lastMessage;
int unseenCount;
String? lastMessage;
DateTime? timeStamp;
Details({
@@ -15,14 +15,13 @@ class Details {
required this.unseenCount,
});
factory Details.fromData(String _data) {
Map _decodedData = json.decode(_data);
factory Details.fromData(String _details) {
return Details(
name: _decodedData['name'],
image: _decodedData['image'],
lastMessage: _decodedData['lastMessage'],
timeStamp: DateTime.parse(_decodedData['timeStamp'] ?? ""),
unseenCount: _decodedData['unseenCount'],
name: json.decode(_details)['name'],
image: json.decode(_details)['image'],
lastMessage: json.decode(_details)['lastMessage'],
timeStamp: DateTime.parse(json.decode(_details)['timeStamp'] ?? ""),
unseenCount: json.decode(_details)['unseenCount'],
);
}
}
+33
View File
@@ -0,0 +1,33 @@
import 'dart:convert';
enum MessageType {
Text,
Image,
}
class Messages {
String message;
String senderId;
MessageType type;
DateTime timeStamp;
Messages({
required this.message,
required this.senderId,
required this.type,
required this.timeStamp,
});
factory Messages.fromData(String _message) {
var _messageType = json.decode(_message)['type'] == "text"
? MessageType.Text
: MessageType.Image;
return Messages(
message: json.decode(_message)['message'],
senderId: json.decode(_message)['senderId'],
type: _messageType,
timeStamp: DateTime.parse(json.decode(_message)['timeStamp'] ?? ""),
);
}
}
+8 -6
View File
@@ -1,25 +1,27 @@
import 'package:appwrite/models.dart';
class Users {
String id;
String name;
String email;
String image;
DateTime lastSeen;
Users({
required this.id,
required this.name,
required this.email,
required this.image,
required this.lastSeen,
});
factory Users.fromData(Document _snapshot) {
factory Users.fromData(Document _document) {
return Users(
name: _snapshot.data["name"],
email: _snapshot.data["email"],
image: _snapshot.data["image"],
lastSeen: DateTime.parse(_snapshot.data["lastSeen"]),
id: _document.data['\$id'],
name: _document.data['name'],
email: _document.data['email'],
image: _document.data['image'],
lastSeen: DateTime.parse(_document.data['lastSeen']),
);
}
}
+234
View File
@@ -0,0 +1,234 @@
import 'package:flutter/material.dart';
import 'package:messaging_app/components/messaging_provider.dart';
import 'package:messaging_app/models/chats.dart';
import 'package:messaging_app/models/messages.dart';
import 'package:provider/provider.dart';
import 'package:timeago/timeago.dart' as timeago;
class ConversationsPage extends StatefulWidget {
ConversationsPage({
super.key,
required this.conversationId,
// required this.receiverId,
required this.chatImage,
required this.chatName,
});
String conversationId;
// String receiverId;
String chatName;
String chatImage;
@override
State<StatefulWidget> createState() {
return _ConversationsPageState();
}
}
class _ConversationsPageState extends State<ConversationsPage> {
//
late double _deviceHeight;
late double _deviceWidth;
late MessagingProviders _auth;
@override
Widget build(BuildContext context) {
//
_deviceHeight = MediaQuery.of(context).size.height;
_deviceWidth = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
title: Text(widget.chatName),
titleTextStyle: TextStyle(fontSize: 16),
),
body: ChangeNotifierProvider<MessagingProviders>.value(
value: MessagingProviders.instance,
child: _conversationPageUI(),
),
);
}
Widget _conversationPageUI() {
return Builder(builder: (_context) {
_auth = Provider.of<MessagingProviders>(_context);
return Stack(
clipBehavior: Clip.none,
children: [
_messageListView(),
_messageInputField(_context),
],
);
});
}
Widget _messageListView() {
return Container(
height: _deviceHeight * 0.75,
width: _deviceWidth,
child: StreamBuilder<Chats>(
stream: MessagingProviders.instance.getChat(widget.conversationId),
builder: (_context, _snapshot) {
return _snapshot.hasData
? ListView.builder(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
itemCount: _snapshot.data!.messages!.length,
itemBuilder: (BuildContext _context, int _index) {
var _message = _snapshot.data!.messages![_index];
return _messageView(_message);
},
)
: Text("");
}),
);
}
Widget _messageView(Messages _message) {
bool _isOwnMessage = false;
if (_message.senderId == _auth.user!.$id) {
_isOwnMessage = true;
}
return Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment:
_isOwnMessage ? MainAxisAlignment.end : MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
_isOwnMessage ? Container() : _imageViewBubble(),
_textMessageBubble(_isOwnMessage, _message),
],
),
);
}
Widget _textMessageBubble(bool _isOwnMessage, Messages _message) {
List<Color> _colorScheme = _isOwnMessage
? [Colors.blue, Color.fromRGBO(42, 117, 188, 1)]
: [Color.fromRGBO(49, 69, 69, 1), Color.fromRGBO(43, 43, 43, 1)];
return Container(
height: _deviceHeight * 0.10,
width: _deviceWidth * 0.75,
padding: EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
gradient: LinearGradient(
colors: _colorScheme,
stops: [0.25, 0.85],
begin: Alignment.bottomLeft,
end: Alignment.bottomRight),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(_message.message),
Text(
timeago.format(_message.timeStamp),
style: TextStyle(
color: Colors.white70,
),
),
],
),
);
}
Widget _imageViewBubble() {
return Container(
height: _deviceHeight * 0.05,
width: _deviceHeight * 0.05,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(500),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
widget.chatImage,
),
),
),
);
}
Widget _messageInputField(BuildContext _context) {
return Align(
alignment: Alignment.bottomCenter,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.max,
children: [
_messageText(),
_imageUpload(),
_sendMessage(_context),
],
),
);
}
Widget _messageText() {
return Container(
padding: EdgeInsets.only(left: 10, right: 10),
decoration: BoxDecoration(
color: Color.fromRGBO(43, 43, 43, 1),
borderRadius: BorderRadius.circular(30)
),
margin: EdgeInsets.symmetric(
horizontal: _deviceWidth * 0.04,
vertical: _deviceHeight * 0.02
),
width: _deviceWidth * 0.70,
child: TextFormField(
validator: (_input) {
if (_input == null) {
return "";
}
},
onChanged: (_input) {
//
},
onSaved: (_input) {
//
},
cursorColor: Colors.white,
decoration: InputDecoration(
border: InputBorder.none,
hintText: "type a message",
),
autocorrect: false,
),
);
}
Widget _sendMessage(BuildContext context) {
return Container(
height: _deviceHeight * 0.045,
width: _deviceHeight * 0.045,
child: IconButton(
onPressed: () {},
icon: Icon(
Icons.send,
color: Colors.white,
),
),
);
}
Widget _imageUpload() {
return SizedBox(
height: _deviceHeight * 0.045,
width: _deviceHeight * 0.045,
child: FloatingActionButton(onPressed: () {},
backgroundColor: Colors.blue,
child: Icon(Icons.camera_enhance),),
);
}
}
+11 -9
View File
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:messaging_app/pages/profile_page.dart';
import 'package:messaging_app/pages/recent_converstations.dart';
import 'package:messaging_app/pages/recent_converstations_page.dart';
import 'package:messaging_app/pages/search_page.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@@ -14,10 +15,11 @@ class HomePage extends StatefulWidget {
class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
//TickerProviderStateMixin
// //
late double _deviceHeight;
late double _deviceWidth;
late TabController _tabController;
late final TabController _tabController;
@override
void initState() {
@@ -42,10 +44,10 @@ class _HomePageState extends State<HomePage>
_deviceWidth = MediaQuery.of(context).size.width;
return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
// backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: AppBar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
title: Text("Slick Messenger"),
// backgroundColor: Theme.of(context).scaffoldBackgroundColor,
title: Text("the messenger"),
titleTextStyle: TextStyle(fontSize: 16),
bottom: TabBar(
unselectedLabelColor: Colors.grey,
@@ -56,19 +58,19 @@ class _HomePageState extends State<HomePage>
Tab(
icon: Icon(
Icons.people_outline,
size: 25,
size: 30,
),
),
Tab(
icon: Icon(
Icons.chat_bubble_outline,
size: 25,
size: 30,
),
),
Tab(
icon: Icon(
Icons.person_outline,
size: 25,
size: 30,
),
),
],
@@ -82,7 +84,7 @@ class _HomePageState extends State<HomePage>
return TabBarView(
controller: _tabController,
children: [
Placeholder(),
SearchPage( deviceHeight: _deviceHeight , deviceWidth: _deviceWidth,),
RecentConverstationsPage(_deviceHeight, _deviceWidth),
ProfilePage(_deviceHeight, _deviceWidth),
],
+1 -1
View File
@@ -176,7 +176,7 @@ class _LoginPageState extends State<LoginPage> {
},
color: Colors.blue,
child: Text(
'Login'.toUpperCase(),
'LOGIN',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w700,
+3
View File
@@ -2,8 +2,10 @@ import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:messaging_app/components/messaging_provider.dart';
import 'package:messaging_app/models/users.dart';
import 'package:messaging_app/service/snackbar_service.dart';
import 'package:provider/provider.dart';
// ignore: must_be_immutable
class ProfilePage extends StatelessWidget {
//
@@ -27,6 +29,7 @@ class ProfilePage extends StatelessWidget {
Widget _profilePageUI() {
return Builder(builder: (BuildContext _context) {
SnackBarService.instance.buildContext = _context;
_auth = Provider.of<MessagingProviders>(_context);
return StreamBuilder<Users>(
stream: MessagingProviders.instance.getUser(_auth.user!.$id),
-95
View File
@@ -1,95 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:messaging_app/components/messaging_provider.dart';
import 'package:messaging_app/models/conversations.dart';
import 'package:provider/provider.dart';
import 'package:timeago/timeago.dart' as timeago;
class RecentConverstationsPage extends StatelessWidget {
//
final double _deviceHeight;
final double _deviceWidth;
late MessagingProviders _auth;
RecentConverstationsPage(this._deviceHeight, this._deviceWidth);
@override
Widget build(BuildContext context) {
return Container(
height: _deviceHeight,
width: _deviceWidth,
child: ChangeNotifierProvider<MessagingProviders>.value(
value: MessagingProviders.instance,
child: _conversationView(),
),
);
}
Widget _conversationView() {
return Builder(builder: (_context) {
_auth = Provider.of<MessagingProviders>(_context);
return Container(
height: _deviceHeight,
width: _deviceWidth,
child: StreamBuilder<List<Conversations>>(
stream: MessagingProviders.instance
.getUserConversation(_auth.user!.$id),
builder: (_, _snapshot) {
return _snapshot.hasData
? ListView.builder(
itemCount: _snapshot.data!.length,
itemBuilder: (_context, _index) {
var _details = _snapshot.data![_index].details;
return ListTile(
onTap: () {
//
},
title: Text(_details.name),
subtitle: Text(_details.lastMessage),
leading: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(_details.image),
),
),
),
trailing: _listTrailingWidget(_details.timeStamp),
);
},
)
: SpinKitWanderingCubes(
color: Colors.blue,
size: 50.0,
);
}),
);
});
}
Widget _listTrailingWidget(DateTime? _date) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
timeago.format(_date!),
style: TextStyle(fontSize: 15),
),
Container(
height: 12,
width: 12,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(100),
),
)
],
);
}
}
+120
View File
@@ -0,0 +1,120 @@
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:messaging_app/components/messaging_provider.dart';
import 'package:messaging_app/models/conversations.dart';
import 'package:messaging_app/pages/conversations_page.dart';
import 'package:messaging_app/service/navigation_service.dart';
import 'package:messaging_app/service/snackbar_service.dart';
import 'package:provider/provider.dart';
import 'package:timeago/timeago.dart' as timeago;
// ignore: must_be_immutable
class RecentConverstationsPage extends StatelessWidget {
//
final double _deviceHeight;
final double _deviceWidth;
late MessagingProviders _auth;
RecentConverstationsPage(this._deviceHeight, this._deviceWidth);
@override
Widget build(BuildContext context) {
return Container(
height: _deviceHeight,
width: _deviceWidth,
child: ChangeNotifierProvider<MessagingProviders>.value(
value: MessagingProviders.instance,
child: _conversationView(),
),
);
}
Widget _conversationView() {
return Builder(builder: (_context) {
SnackBarService.instance.buildContext = _context;
_auth = Provider.of<MessagingProviders>(_context);
return SizedBox(
height: _deviceHeight,
width: _deviceWidth,
child: StreamBuilder<List<Conversations>>(
stream: MessagingProviders.instance
.getUserConversation(_auth.user!.$id),
builder: (_, _snapshot) {
if (_snapshot.hasData) {
return ListView.builder(
itemCount: _snapshot.data!.length,
itemBuilder: (_context, _index) {
var _details = _snapshot.data![_index].details;
var _chatId = _snapshot.data![_index].chatId;
return ListTile(
onTap: () {
//
NavigationService.instance.navigateToRoute(
MaterialPageRoute(
builder: (BuildContext _context) {
return ConversationsPage(
conversationId: _chatId,
chatName: _details.name,
chatImage: _details.image,
);
},
),
);
},
title: Text(_details.name),
subtitle: Text(_details.lastMessage!),
leading: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(_details.image),
),
),
),
trailing: _listTrailingWidget(_details.timeStamp),
);
},
);
}
if (_snapshot.hasError) {
return Align(
child: Text(
"no active conversation",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
);
} else {
return SpinKitWanderingCubes(
color: Colors.blue,
size: 50.0,
);
}
}),
);
});
}
Widget _listTrailingWidget(DateTime? _date) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
"last message",
style: TextStyle(fontSize: 15),
),
Text(
timeago.format(_date!),
style: TextStyle(fontSize: 15),
)
],
);
}
}
+2 -2
View File
@@ -226,7 +226,7 @@ class _RegisterationPageState extends State<RegisterationPage> {
onPressed: () {
if (_image == null) {
SnackBarService.instance
.showSnackBarError("Please Select Image");
.showSnackBarError("Please Select an Image");
}
if (_formKey.currentState!.validate() && _image != null) {
//
@@ -247,7 +247,7 @@ class _RegisterationPageState extends State<RegisterationPage> {
},
color: Colors.blue,
child: Text(
'Register'.toUpperCase(),
"REGISTER",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w700,
+168
View File
@@ -0,0 +1,168 @@
import 'package:flutter/material.dart';
import 'package:messaging_app/components/messaging_provider.dart';
import 'package:messaging_app/models/users.dart';
import 'package:provider/provider.dart';
import 'package:timeago/timeago.dart' as timeago;
class SearchPage extends StatefulWidget {
SearchPage({
super.key,
required this.deviceHeight,
required this.deviceWidth,
});
double deviceHeight;
double deviceWidth;
late MessagingProviders _auth;
@override
State<SearchPage> createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
late String _searchText;
late List<Users> _usersData;
@override
void initState() {
super.initState();
_searchText = '';
_usersData = [];
}
@override
Widget build(BuildContext context) {
return SizedBox(
height: widget.deviceHeight,
width: widget.deviceWidth,
child: ChangeNotifierProvider.value(
value: MessagingProviders.instance,
child: _searchPaheUI(),
),
);
}
Widget _searchPaheUI() {
return Builder(builder: (_context) {
widget._auth = Provider.of<MessagingProviders>(_context);
return Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
_searchPageUIField(),
_searchPageUIList(),
],
);
});
}
Widget _searchPageUIField() {
return Container(
height: widget.deviceHeight * 0.08,
width: widget.deviceWidth,
padding: EdgeInsets.symmetric(vertical: widget.deviceHeight * 0.02),
child: TextField(
autocorrect: false,
style: TextStyle(
color: Colors.white,
),
onChanged: (_input) {
setState(() {
_searchText = _input;
});
},
decoration: InputDecoration(
prefixIcon: Icon(Icons.search),
labelText: "search",
labelStyle: TextStyle(color: Colors.white),
border: OutlineInputBorder(borderSide: BorderSide.none),
),
),
);
}
Widget _searchPageUIList() {
return StreamBuilder<List<Users>>(
stream: MessagingProviders.instance.getAllUsers(_searchText.trim()),
builder: (_, _snapshot) {
if (_snapshot.hasData) {
_usersData = _snapshot.data!
.where((_data) => _data.id != widget._auth.user!.$id)
.toList();
}
return _snapshot.hasData
? SizedBox(
height: widget.deviceHeight * 0.70,
child: ListView.builder(
itemCount: _usersData.length,
itemBuilder: (_, _index) {
var _userData = _usersData[_index];
var _isUserActive = _userData.lastSeen.isBefore(
DateTime.now().toUtc().subtract(
Duration(
minutes: 1,
),
),
);
return ListTile(
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:
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,
// );
;
});
}
}
-2
View File
@@ -6,8 +6,6 @@ class SnackBarService {
BuildContext? _buildContext;
static SnackBarService instance = SnackBarService();
SnackBarService() {}
set buildContext(BuildContext _context) {
_buildContext = _context;
}