From ea195a71c680af6e867e1eaa8dfcdb05003870a1 Mon Sep 17 00:00:00 2001 From: Jahid Date: Fri, 3 Mar 2023 15:35:50 +0600 Subject: [PATCH 01/10] Home Screen and Search Screen ui design --- lib/Screens/home_screen.dart | 90 ++++++++++++++++++++++++++++ lib/Screens/search_screen.dart | 68 +++++++++++++++++++++ lib/Widgets/my_search_textfield.dart | 39 ++++++++++++ lib/main.dart | 2 + 4 files changed, 199 insertions(+) create mode 100644 lib/Screens/home_screen.dart create mode 100644 lib/Screens/search_screen.dart create mode 100644 lib/Widgets/my_search_textfield.dart diff --git a/lib/Screens/home_screen.dart b/lib/Screens/home_screen.dart new file mode 100644 index 0000000..e7fd7db --- /dev/null +++ b/lib/Screens/home_screen.dart @@ -0,0 +1,90 @@ +import 'package:connector/Screens/search_screen.dart'; +import 'package:flutter/material.dart'; + + + +class HomeScreen extends StatefulWidget { + @override + _HomeScreenState createState() => _HomeScreenState(); +} + +class _HomeScreenState extends State { + int _currentIndex = 0; + + final List _pages = [ PageOne(), PageTwo(), PageThree(), ]; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.grey[300], + appBar: AppBar( + backgroundColor: Colors.blue, + title: Text('Connector'), + ), + body: _pages[_currentIndex], + bottomNavigationBar: BottomNavigationBar( + currentIndex: _currentIndex, + selectedItemColor: Colors.black87, + onTap: (int index) { + setState(() { + _currentIndex = index; + }); + }, + items: [ + BottomNavigationBarItem( + icon: Icon(Icons.home), + label: 'Home', + ), + BottomNavigationBarItem( + icon: Icon(Icons.dashboard), + label: 'Dashboard', + ), + BottomNavigationBarItem( + icon: Icon(Icons.person), + label: 'Profile', + ), + ], + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) =>SearchScreen(), + ), + ); + }, + child: Icon(Icons.search), + backgroundColor: Colors.blue, + ), + //floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, + ); + } +} + +class PageOne extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Center( + child: Text('Home Page'), + ); + } +} + +class PageTwo extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Center( + child: Text('Dashboard Page'), + ); + } +} + +class PageThree extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Center( + child: Text('Profile Page'), + ); + } +} diff --git a/lib/Screens/search_screen.dart b/lib/Screens/search_screen.dart new file mode 100644 index 0000000..6caf066 --- /dev/null +++ b/lib/Screens/search_screen.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; + +import '../Widgets/my_search_textfield.dart'; +import 'home_screen.dart'; +import 'my_text_field.dart'; + +class SearchScreen extends StatefulWidget{ + //UserModel user; + //SearchScreen(this.user); + @override + SearchScreenState createState() =>SearchScreenState(); +} + +class SearchScreenState extends State{ + + @override + Widget build(BuildContext context) { + TextEditingController SearchController= new TextEditingController(); + return Scaffold( + backgroundColor: Colors.grey[300], + appBar: AppBar( + leading: BackButton( + onPressed: (){ + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) =>HomeScreen(), + ), + ); + }, + ), + title:Text("Search your friend"), + backgroundColor: Colors.blue, + + ), + body:Column( + children:[ + Row( + children:[ + Expanded( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: MySearchTextField( + controller: SearchController, + hintText: "Type username......", + obscureText: false, + ), + ), + ), + Align( + alignment: Alignment.topLeft, + child: IconButton( + color: Colors.grey.shade800, + iconSize: 30, + onPressed: (){}, + icon:Icon(Icons.search), + ), + ), + const SizedBox(width:10), + + ], + ) + ] + ) + ); + } +} + diff --git a/lib/Widgets/my_search_textfield.dart b/lib/Widgets/my_search_textfield.dart new file mode 100644 index 0000000..7832a63 --- /dev/null +++ b/lib/Widgets/my_search_textfield.dart @@ -0,0 +1,39 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class MySearchTextField extends StatelessWidget { + final controller; + final String hintText; + final bool obscureText; + + const MySearchTextField({ + super.key, + required this.controller, + required this.hintText, + required this.obscureText, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 25.0), + child: TextField( + controller: controller, + obscureText: obscureText, + decoration: InputDecoration( + enabledBorder: const OutlineInputBorder( + //borderRadius:BorderRadius.all(2.0), + borderSide: BorderSide(color: Colors.white), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: BorderSide(color: Colors.grey.shade400), + ), + fillColor: Colors.grey.shade200, + filled: true, + hintText: hintText, + hintStyle: TextStyle(color: Colors.grey[500])), + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index 1ac2fcb..f55b400 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,8 @@ import 'package:flutter/material.dart'; import 'package:connector/Screens/sign_in_screen.dart'; import 'package:connector/Screens/splash_screen.dart'; +import 'Screens/home_screen.dart'; + void main() { runApp(const MyApp()); } From 2b2ca27bfade3e55772deca71db85d7d31d3d794 Mon Sep 17 00:00:00 2001 From: Jahid Date: Sun, 5 Mar 2023 16:16:37 +0600 Subject: [PATCH 02/10] Connected to Firebase --- android/app/build.gradle | 10 ++- android/build.gradle | 1 + lib/Screens/home_screen.dart | 6 +- lib/Screens/sign_in_screen.dart | 4 +- lib/Screens/sign_up_screen.dart | 6 +- lib/main.dart | 5 +- pubspec.lock | 111 ++++++++++++++++++++++++++++++++ pubspec.yaml | 3 + 8 files changed, 138 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 14f23ee..e76c7bc 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -22,6 +22,7 @@ if (flutterVersionName == null) { } apply plugin: 'com.android.application' +apply plugin: 'com.google.gms.google-services' apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" @@ -39,10 +40,11 @@ android { applicationId "com.example.connector" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. - minSdkVersion flutter.minSdkVersion + minSdkVersion 23 targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName + multiDexEnabled true } buildTypes { @@ -57,3 +59,9 @@ android { flutter { source '../..' } + +dependencies { + // Import the Firebase BoM + implementation platform('com.google.firebase:firebase-bom:31.2.3') + +} diff --git a/android/build.gradle b/android/build.gradle index 83ae220..716cf6a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,6 +8,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:7.1.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath 'com.google.gms:google-services:4.3.15' } } diff --git a/lib/Screens/home_screen.dart b/lib/Screens/home_screen.dart index e7fd7db..41abb78 100644 --- a/lib/Screens/home_screen.dart +++ b/lib/Screens/home_screen.dart @@ -32,12 +32,12 @@ class _HomeScreenState extends State { }, items: [ BottomNavigationBarItem( - icon: Icon(Icons.home), - label: 'Home', + icon: Icon(Icons.message), + label: 'Messsges', ), BottomNavigationBarItem( icon: Icon(Icons.dashboard), - label: 'Dashboard', + label: 'Stories', ), BottomNavigationBarItem( icon: Icon(Icons.person), diff --git a/lib/Screens/sign_in_screen.dart b/lib/Screens/sign_in_screen.dart index 825567e..c748526 100644 --- a/lib/Screens/sign_in_screen.dart +++ b/lib/Screens/sign_in_screen.dart @@ -12,7 +12,9 @@ class SignInScreen extends StatelessWidget { final passwordController = TextEditingController(); - void signUserIn() {} + void signUserIn() { + + } @override Widget build(BuildContext context) { diff --git a/lib/Screens/sign_up_screen.dart b/lib/Screens/sign_up_screen.dart index 749998b..45c1aed 100644 --- a/lib/Screens/sign_up_screen.dart +++ b/lib/Screens/sign_up_screen.dart @@ -15,7 +15,9 @@ class SignUpScreen extends StatelessWidget { final confirmPasswordController=TextEditingController(); - void signUserIn() {} + void signUserUp() { + + } @override Widget build(BuildContext context) { @@ -87,7 +89,7 @@ class SignUpScreen extends StatelessWidget { SignUpButton( - onTap: signUserIn, + onTap: signUserUp, ), const SizedBox(height: 30), diff --git a/lib/main.dart b/lib/main.dart index f55b400..0187686 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,11 +1,14 @@ //it is for test purpose +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:connector/Screens/sign_in_screen.dart'; import 'package:connector/Screens/splash_screen.dart'; import 'Screens/home_screen.dart'; -void main() { +void main()async{ + WidgetsFlutterBinding.ensureInitialized(); + await Firebase.initializeApp(); runApp(const MyApp()); } diff --git a/pubspec.lock b/pubspec.lock index e9b9197..653d7b8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,13 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.16" async: dependency: transitive description: @@ -29,6 +36,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.1" + cloud_firestore: + dependency: "direct main" + description: + name: cloud_firestore + url: "https://pub.dartlang.org" + source: hosted + version: "4.4.3" + cloud_firestore_platform_interface: + dependency: transitive + description: + name: cloud_firestore_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "5.11.3" + cloud_firestore_web: + dependency: transitive + description: + name: cloud_firestore_web + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.3" collection: dependency: transitive description: @@ -50,6 +78,48 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" + firebase_auth: + dependency: "direct main" + description: + name: firebase_auth + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.9" + firebase_auth_platform_interface: + dependency: transitive + description: + name: firebase_auth_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "6.11.11" + firebase_auth_web: + dependency: transitive + description: + name: firebase_auth_web + url: "https://pub.dartlang.org" + source: hosted + version: "5.2.8" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + url: "https://pub.dartlang.org" + source: hosted + version: "2.7.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "4.5.3" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" flutter: dependency: "direct main" description: flutter @@ -67,6 +137,32 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.2" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.17.0" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.4" lints: dependency: transitive description: @@ -102,6 +198,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.2" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.4" sky_engine: dependency: transitive description: flutter @@ -149,6 +252,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.12" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" vector_math: dependency: transitive description: @@ -158,3 +268,4 @@ packages: version: "2.1.2" sdks: dart: ">=2.18.2 <3.0.0" + flutter: ">=1.20.0" diff --git a/pubspec.yaml b/pubspec.yaml index 1b551f6..aa4c106 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -36,6 +36,9 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 + firebase_auth: ^4.2.9 + firebase_core: ^2.7.0 + cloud_firestore: ^4.4.3 dev_dependencies: flutter_test: From 71ef946d75d3d3890958058bf232167c79d361ca Mon Sep 17 00:00:00 2001 From: Jahid Date: Sun, 5 Mar 2023 16:17:41 +0600 Subject: [PATCH 03/10] Connected to Firebase --- android/app/google-services.json | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 android/app/google-services.json diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..a596b3d --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,47 @@ +{ + "project_info": { + "project_number": "161225848235", + "project_id": "connector-71f47", + "storage_bucket": "connector-71f47.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:161225848235:android:c8d4df7ae7c1e12e748eee", + "android_client_info": { + "package_name": "com.example.connector" + } + }, + "oauth_client": [ + { + "client_id": "161225848235-blfn2vatpgbjdi5q8rorft3cmgnobmg6.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.example.connector", + "certificate_hash": "a2267a3dcdf7bebeb0d5ffb54dea2e640e680994" + } + }, + { + "client_id": "161225848235-aq3s7thct6vohut7g1kvdb9s3t7u4k9t.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyB5SWT-ufPTXgxFQAIp7F0ndIPqMXHLB2E" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "161225848235-aq3s7thct6vohut7g1kvdb9s3t7u4k9t.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file From aef1373055d3f8f4145649d07304f6b26bf27715 Mon Sep 17 00:00:00 2001 From: Jahid Date: Tue, 7 Mar 2023 15:32:06 +0600 Subject: [PATCH 04/10] Sign Up And Sign In Feature implemented --- lib/Screens/sign_in_screen.dart | 12 +++- lib/Screens/sign_up_screen.dart | 9 ++- pubspec.lock | 111 ++++++++++++++++++++++++++++++++ pubspec.yaml | 4 +- 4 files changed, 130 insertions(+), 6 deletions(-) diff --git a/lib/Screens/sign_in_screen.dart b/lib/Screens/sign_in_screen.dart index 825567e..9399fc7 100644 --- a/lib/Screens/sign_in_screen.dart +++ b/lib/Screens/sign_in_screen.dart @@ -1,3 +1,4 @@ +import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:connector/Screens/sign_in_button.dart'; import 'package:connector/Screens/my_text_field.dart'; @@ -8,11 +9,16 @@ class SignInScreen extends StatelessWidget { SignInScreen({super.key}); - final usernameController = TextEditingController(); + final emailController = TextEditingController(); final passwordController = TextEditingController(); - void signUserIn() {} + void signUserIn() async{ + User? user=FirebaseAuth.instance.currentUser; + //if(user!=null) return HomeS + await FirebaseAuth.instance.signInWithEmailAndPassword(email: emailController.text.trim(), + password: passwordController.text.trim()); + } @override Widget build(BuildContext context) { @@ -36,7 +42,7 @@ class SignInScreen extends StatelessWidget { MyTextField( - controller: usernameController, + controller: emailController, hintText: 'Username or Email', obscureText: false, ), diff --git a/lib/Screens/sign_up_screen.dart b/lib/Screens/sign_up_screen.dart index 749998b..ffd5a3c 100644 --- a/lib/Screens/sign_up_screen.dart +++ b/lib/Screens/sign_up_screen.dart @@ -1,3 +1,4 @@ +import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:connector/Screens/sign_in_button.dart'; import 'package:connector/Screens/my_text_field.dart'; @@ -15,7 +16,11 @@ class SignUpScreen extends StatelessWidget { final confirmPasswordController=TextEditingController(); - void signUserIn() {} + Future signUserUp() async { + UserCredential userCredential=await FirebaseAuth.instance.createUserWithEmailAndPassword(email: emailController.text.trim(), + password: passwordController.text.trim()); + } + @override Widget build(BuildContext context) { @@ -87,7 +92,7 @@ class SignUpScreen extends StatelessWidget { SignUpButton( - onTap: signUserIn, + onTap: signUserUp, ), const SizedBox(height: 30), diff --git a/pubspec.lock b/pubspec.lock index e9b9197..653d7b8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,13 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.16" async: dependency: transitive description: @@ -29,6 +36,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.1" + cloud_firestore: + dependency: "direct main" + description: + name: cloud_firestore + url: "https://pub.dartlang.org" + source: hosted + version: "4.4.3" + cloud_firestore_platform_interface: + dependency: transitive + description: + name: cloud_firestore_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "5.11.3" + cloud_firestore_web: + dependency: transitive + description: + name: cloud_firestore_web + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.3" collection: dependency: transitive description: @@ -50,6 +78,48 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" + firebase_auth: + dependency: "direct main" + description: + name: firebase_auth + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.9" + firebase_auth_platform_interface: + dependency: transitive + description: + name: firebase_auth_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "6.11.11" + firebase_auth_web: + dependency: transitive + description: + name: firebase_auth_web + url: "https://pub.dartlang.org" + source: hosted + version: "5.2.8" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + url: "https://pub.dartlang.org" + source: hosted + version: "2.7.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "4.5.3" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" flutter: dependency: "direct main" description: flutter @@ -67,6 +137,32 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.2" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.17.0" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.4" lints: dependency: transitive description: @@ -102,6 +198,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.2" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.4" sky_engine: dependency: transitive description: flutter @@ -149,6 +252,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.12" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" vector_math: dependency: transitive description: @@ -158,3 +268,4 @@ packages: version: "2.1.2" sdks: dart: ">=2.18.2 <3.0.0" + flutter: ">=1.20.0" diff --git a/pubspec.yaml b/pubspec.yaml index 1b551f6..c9530e7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -36,7 +36,9 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 - + firebase_auth: ^4.2.9 + firebase_core: ^2.7.0 + cloud_firestore: ^4.4.3 dev_dependencies: flutter_test: sdk: flutter From f4ad747d61f76cdb9a18a3233d81b211d92fce8f Mon Sep 17 00:00:00 2001 From: Jahid Date: Thu, 9 Mar 2023 07:18:21 +0600 Subject: [PATCH 05/10] Sign Up And Sign In Feature Updated --- lib/Pages/profile_page.dart | 43 ++++++++++++++++++++++++++++++++ lib/Screens/home_screen.dart | 17 ++++++++++--- lib/Screens/sign_in_screen.dart | 28 +++++++++++++++++++-- lib/Screens/sign_out_button.dart | 32 ++++++++++++++++++++++++ lib/Screens/sign_up_screen.dart | 31 ++++++++++++++++++++--- lib/Screens/splash_screen.dart | 29 +++++++++++++++------ lib/main.dart | 2 ++ pubspec.lock | 18 ++++++------- 8 files changed, 174 insertions(+), 26 deletions(-) create mode 100644 lib/Pages/profile_page.dart create mode 100644 lib/Screens/sign_out_button.dart diff --git a/lib/Pages/profile_page.dart b/lib/Pages/profile_page.dart new file mode 100644 index 0000000..fed59b9 --- /dev/null +++ b/lib/Pages/profile_page.dart @@ -0,0 +1,43 @@ +import 'package:connector/Screens/sign_out_button.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter/material.dart'; + +import '../Screens/splash_screen.dart'; + +class ProfilePage extends StatefulWidget { + @override + State createState() => _ProfilePageState(); +} + +class _ProfilePageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body:SafeArea( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SignOutButton(onTap: signUserOut) + ], + ), + ), + ) + ); + } + + signUserOut() async{ + // Initialize Firebase Auth + final FirebaseAuth _auth = FirebaseAuth.instance; + + // Sign out the user + await _auth.signOut(); + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) =>SplashScreen(), + ), + ); + } +} diff --git a/lib/Screens/home_screen.dart b/lib/Screens/home_screen.dart index 41abb78..8d56d41 100644 --- a/lib/Screens/home_screen.dart +++ b/lib/Screens/home_screen.dart @@ -1,6 +1,8 @@ import 'package:connector/Screens/search_screen.dart'; import 'package:flutter/material.dart'; +import '../Pages/profile_page.dart'; + class HomeScreen extends StatefulWidget { @@ -10,6 +12,7 @@ class HomeScreen extends StatefulWidget { class _HomeScreenState extends State { int _currentIndex = 0; + bool is_message_page=true; final List _pages = [ PageOne(), PageTwo(), PageThree(), ]; @@ -28,6 +31,8 @@ class _HomeScreenState extends State { onTap: (int index) { setState(() { _currentIndex = index; + if(_currentIndex!=0) is_message_page=false; + else is_message_page=true; }); }, items: [ @@ -45,7 +50,9 @@ class _HomeScreenState extends State { ), ], ), - floatingActionButton: FloatingActionButton( + floatingActionButton:Visibility( + visible: is_message_page, + child: FloatingActionButton( onPressed: () { Navigator.pushReplacement( context, @@ -57,6 +64,8 @@ class _HomeScreenState extends State { child: Icon(Icons.search), backgroundColor: Colors.blue, ), + + ) //floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, ); } @@ -83,8 +92,8 @@ class PageTwo extends StatelessWidget { class PageThree extends StatelessWidget { @override Widget build(BuildContext context) { - return Center( - child: Text('Profile Page'), - ); + return ProfilePage(); } } + + diff --git a/lib/Screens/sign_in_screen.dart b/lib/Screens/sign_in_screen.dart index 9399fc7..a6a9d00 100644 --- a/lib/Screens/sign_in_screen.dart +++ b/lib/Screens/sign_in_screen.dart @@ -1,23 +1,47 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:connector/Screens/sign_in_button.dart'; import 'package:connector/Screens/my_text_field.dart'; import 'package:connector/Screens/sign_up_screen.dart'; +import 'home_screen.dart'; -class SignInScreen extends StatelessWidget { + +class SignInScreen extends StatefulWidget { SignInScreen({super.key}); + @override + State createState() => _SignInScreenState(); +} + +class _SignInScreenState extends State { final emailController = TextEditingController(); + final passwordController = TextEditingController(); + + void signUserIn() async{ User? user=FirebaseAuth.instance.currentUser; - //if(user!=null) return HomeS await FirebaseAuth.instance.signInWithEmailAndPassword(email: emailController.text.trim(), password: passwordController.text.trim()); + FirebaseAuth.instance + .authStateChanges() + .listen((User? user) async{ + if (user == null) { + print('User is currently signed out!'); + } else { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) =>HomeScreen(), + ), + ); + } + }); } @override diff --git a/lib/Screens/sign_out_button.dart b/lib/Screens/sign_out_button.dart new file mode 100644 index 0000000..accc20f --- /dev/null +++ b/lib/Screens/sign_out_button.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; + +class SignOutButton extends StatelessWidget { + final Function()? onTap; + + const SignOutButton({super.key, required this.onTap}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: Container( + padding: const EdgeInsets.all(25), + margin: const EdgeInsets.symmetric(horizontal: 25), + decoration: BoxDecoration( + color: Colors.black87, + borderRadius: BorderRadius.circular(8), + ), + child: const Center( + child: Text( + "Sign Out", + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + ), + ), + ); + } +} diff --git a/lib/Screens/sign_up_screen.dart b/lib/Screens/sign_up_screen.dart index ffd5a3c..41df96d 100644 --- a/lib/Screens/sign_up_screen.dart +++ b/lib/Screens/sign_up_screen.dart @@ -1,27 +1,50 @@ +import 'package:connector/Screens/sign_in_screen.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:connector/Screens/sign_in_button.dart'; import 'package:connector/Screens/my_text_field.dart'; -import 'package:connector/Screens/sign_in_screen.dart'; +import 'package:connector/Screens/sign_in_screen.dart' as globe; import 'package:connector/Screens/sign_up_button.dart'; -class SignUpScreen extends StatelessWidget { +import 'home_screen.dart'; + + +class SignUpScreen extends StatefulWidget { SignUpScreen({super.key}); + @override + State createState() => _SignUpScreenState(); +} +class _SignUpScreenState extends State { final usernameController = TextEditingController(); + final emailController=TextEditingController(); + final passwordController = TextEditingController(); - final confirmPasswordController=TextEditingController(); + final confirmPasswordController=TextEditingController(); Future signUserUp() async { UserCredential userCredential=await FirebaseAuth.instance.createUserWithEmailAndPassword(email: emailController.text.trim(), password: passwordController.text.trim()); + FirebaseAuth.instance + .authStateChanges() + .listen((User? user) async{ + if (user == null) { + print('User is currently signed out!'); + } else { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) =>HomeScreen(), + ), + ); + } + }); } - @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/Screens/splash_screen.dart b/lib/Screens/splash_screen.dart index f4efc53..75c908b 100644 --- a/lib/Screens/splash_screen.dart +++ b/lib/Screens/splash_screen.dart @@ -1,8 +1,12 @@ import 'dart:async'; +import 'package:connector/Screens/sign_in_screen.dart'; +import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; -import 'package:connector/Screens/sign_in_screen.dart'; +import 'package:connector/Screens/sign_in_screen.dart' as glob; + +import 'home_screen.dart'; class SplashScreen extends StatefulWidget{ @override @@ -14,13 +18,24 @@ class _SplashScreenState extends State { @override void initState(){ super.initState(); + Timer(Duration(seconds: 3),(){ - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (BuildContext context) =>SignInScreen(), - ), - ); + User? user = FirebaseAuth.instance.currentUser; + if(user != null){ + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) =>HomeScreen(), + ), + ); + }else{ + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) =>SignInScreen(), + ), + ); + } }); } diff --git a/lib/main.dart b/lib/main.dart index 0187686..e3095db 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,7 @@ import 'package:connector/Screens/splash_screen.dart'; import 'Screens/home_screen.dart'; void main()async{ + WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(const MyApp()); @@ -15,6 +16,7 @@ void main()async{ class MyApp extends StatelessWidget { const MyApp({super.key}); + // This widget is the root of your application. @override Widget build(BuildContext context) { diff --git a/pubspec.lock b/pubspec.lock index 653d7b8..e0e1f17 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,7 +7,7 @@ packages: name: _flutterfire_internals url: "https://pub.dartlang.org" source: hosted - version: "1.0.16" + version: "1.0.17" async: dependency: transitive description: @@ -42,21 +42,21 @@ packages: name: cloud_firestore url: "https://pub.dartlang.org" source: hosted - version: "4.4.3" + version: "4.4.4" cloud_firestore_platform_interface: dependency: transitive description: name: cloud_firestore_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "5.11.3" + version: "5.11.4" cloud_firestore_web: dependency: transitive description: name: cloud_firestore_web url: "https://pub.dartlang.org" source: hosted - version: "3.3.3" + version: "3.3.4" collection: dependency: transitive description: @@ -84,28 +84,28 @@ packages: name: firebase_auth url: "https://pub.dartlang.org" source: hosted - version: "4.2.9" + version: "4.2.10" firebase_auth_platform_interface: dependency: transitive description: name: firebase_auth_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "6.11.11" + version: "6.11.12" firebase_auth_web: dependency: transitive description: name: firebase_auth_web url: "https://pub.dartlang.org" source: hosted - version: "5.2.8" + version: "5.2.9" firebase_core: dependency: "direct main" description: name: firebase_core url: "https://pub.dartlang.org" source: hosted - version: "2.7.0" + version: "2.7.1" firebase_core_platform_interface: dependency: transitive description: @@ -119,7 +119,7 @@ packages: name: firebase_core_web url: "https://pub.dartlang.org" source: hosted - version: "2.2.1" + version: "2.2.2" flutter: dependency: "direct main" description: flutter From 1f68067bf0a6480dec3079cca4a856ed1091cc77 Mon Sep 17 00:00:00 2001 From: Jahid Date: Sat, 11 Mar 2023 14:27:02 +0600 Subject: [PATCH 06/10] Profile Page implemented --- android/app/build.gradle | 2 +- android/app/src/main/AndroidManifest.xml | 2 + lib/Pages/profile_page.dart | 37 +++++ lib/Screens/sign_up_screen.dart | 3 + lib/Screens/update_profile_screen.dart | 134 ++++++++++++++++++ lib/Widgets/save_button.dart | 32 +++++ lib/Widgets/update_profile_button.dart | 35 +++++ .../upload_profile_picture_button.dart | 35 +++++ pubspec.lock | 121 +++++++++++++++- pubspec.yaml | 5 + 10 files changed, 404 insertions(+), 2 deletions(-) create mode 100644 lib/Screens/update_profile_screen.dart create mode 100644 lib/Widgets/save_button.dart create mode 100644 lib/Widgets/update_profile_button.dart create mode 100644 lib/Widgets/upload_profile_picture_button.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index e76c7bc..f5a84cd 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -27,7 +27,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion flutter.compileSdkVersion + compileSdkVersion 33 ndkVersion flutter.ndkVersion compileOptions { diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 954f04a..b38323a 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,7 @@ + + { + User? user = FirebaseAuth.instance.currentUser; + @override Widget build(BuildContext context) { + final usernameController = TextEditingController(); + final emailController = TextEditingController(); + final passwordController1 = TextEditingController(); + final passwordController2 = TextEditingController(); + final passwordController3 = TextEditingController(); return Scaffold( body:SafeArea( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, + children: [ + + //const SizedBox(height: 60), + CircleAvatar( + radius: 60.0, + backgroundImage: AssetImage('${user?.photoURL}'), + ), + const SizedBox(height: 20), + Text('${user?.displayName}',style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + )), + const SizedBox(height: 30), + UpdateProfileButton(onTap: updateProfile), + const SizedBox(height: 20), SignOutButton(onTap: signUserOut) ], ), @@ -40,4 +66,15 @@ class _ProfilePageState extends State { ), ); } + + + + updateProfile() { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) =>UpdateProfileScreen(), + ), + ); + } } diff --git a/lib/Screens/sign_up_screen.dart b/lib/Screens/sign_up_screen.dart index 41df96d..346d062 100644 --- a/lib/Screens/sign_up_screen.dart +++ b/lib/Screens/sign_up_screen.dart @@ -29,6 +29,9 @@ class _SignUpScreenState extends State { Future signUserUp() async { UserCredential userCredential=await FirebaseAuth.instance.createUserWithEmailAndPassword(email: emailController.text.trim(), password: passwordController.text.trim()); + User? user =FirebaseAuth.instance.currentUser; + user?.updateDisplayName(usernameController.text.trim()); + user?.updatePhotoURL('https://www.google.com/url?sa=i&url=https%3A%2F%2Fwww.sony.co.uk%2Fpresscentre%2Fcontacts&psig=AOvVaw12QSig7O_cvnNRLQ4qQ4VL&ust=1678607500153000&source=images&cd=vfe&ved=0CBAQjRxqFwoTCNihlr2y0_0CFQAAAAAdAAAAABAI'); FirebaseAuth.instance .authStateChanges() .listen((User? user) async{ diff --git a/lib/Screens/update_profile_screen.dart b/lib/Screens/update_profile_screen.dart new file mode 100644 index 0000000..80599b2 --- /dev/null +++ b/lib/Screens/update_profile_screen.dart @@ -0,0 +1,134 @@ + + +import 'dart:io'; + +import 'package:connector/Widgets/save_button.dart'; +import 'package:connector/Widgets/update_profile_button.dart'; +import 'package:connector/Widgets/upload_profile_picture_button.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:firebase_storage/firebase_storage.dart'; +import 'package:permission_handler/permission_handler.dart'; + +import 'home_screen.dart'; +import 'my_text_field.dart'; + + +class UpdateProfileScreen extends StatelessWidget { + final usernameController = TextEditingController(); + final emailController = TextEditingController(); + final passwordController = TextEditingController(); + final passwordController2 = TextEditingController(); + final passwordController3 = TextEditingController(); + + @override + Widget build(BuildContext context) { + saveUserDetails() { + User? user = FirebaseAuth.instance.currentUser; + if (usernameController.text.toString() != null) { + user?.updateDisplayName(usernameController.text.toString()); + } + if (emailController.text.toString() != null) { + user?.updateEmail(emailController.text.toString()); + } + if (passwordController.text.toString() != null) { + user?.updatePassword(passwordController.text.toString()); + } + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) => HomeScreen(), + ), + ); + } + return Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar( + leading: BackButton( + onPressed: () { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) => HomeScreen(), + ), + ); + }, + ), + title: Text("Update Profile"), + backgroundColor: Colors.blue, + + ), + body: SafeArea( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + MyTextField( + controller: usernameController, + hintText: 'Update username', + obscureText: false, + ), + const SizedBox(height: 10), + MyTextField( + controller: emailController, + hintText: 'Change email', + obscureText: false, + ), + const SizedBox(height: 10), + MyTextField( + controller: passwordController, + hintText: 'Enter current password', + obscureText: true, + ), + const SizedBox(height: 10), + MyTextField( + controller: passwordController2, + hintText: 'Enter new password', + obscureText: true, + ), + const SizedBox(height: 10), + MyTextField( + controller: passwordController3, + hintText: 'Confirm new password', + obscureText: true, + ), + const SizedBox(height: 20), + UploadProfilePictureButton(onTap: uploadProfilePic), + const SizedBox(height: 20), + SaveButton(onTap: saveUserDetails), + + ], + ), + ), + ) + ); + } + + + uploadProfilePic() async { + final _firebaseStorage = FirebaseStorage.instance; + final _imagePicker = ImagePicker(); + PickedFile? image; + User? user = FirebaseAuth.instance.currentUser; + //Check Permissions + await Permission.photos.request(); + + var permissionStatus = await Permission.photos.status; + + if (permissionStatus.isGranted) { + //Select Image + image = await _imagePicker.getImage(source: ImageSource.gallery); + var file = File(image!.path); + + if (image != null) { + //Upload to Firebase + var snapshot = await _firebaseStorage.ref() + .child('images/imageName') + .putFile(file); + String downloadUrl = await snapshot.ref.getDownloadURL(); + user?.updatePhotoURL(downloadUrl); + } + } + } +} \ No newline at end of file diff --git a/lib/Widgets/save_button.dart b/lib/Widgets/save_button.dart new file mode 100644 index 0000000..90302d9 --- /dev/null +++ b/lib/Widgets/save_button.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; + +class SaveButton extends StatelessWidget { + final Function()? onTap; + + const SaveButton({super.key, required this.onTap}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: Container( + padding: const EdgeInsets.all(25), + margin: const EdgeInsets.symmetric(horizontal: 100), + decoration: BoxDecoration( + color: Colors.black87, + borderRadius: BorderRadius.circular(8), + ), + child: const Center( + child: Text( + "Save", + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + ), + ), + ); + } +} diff --git a/lib/Widgets/update_profile_button.dart b/lib/Widgets/update_profile_button.dart new file mode 100644 index 0000000..f330602 --- /dev/null +++ b/lib/Widgets/update_profile_button.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +class UpdateProfileButton extends StatelessWidget { + final Function()? onTap; + + const UpdateProfileButton({super.key, required this.onTap}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: Container( + padding: const EdgeInsets.all(25), + margin: const EdgeInsets.symmetric(horizontal: 25), + decoration: BoxDecoration( + border: Border.all( + color:Colors.black87, + ), + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + child: const Center( + child: Text( + "Update profile", + style: TextStyle( + color: Colors.black87, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + ), + ), + ); + } +} diff --git a/lib/Widgets/upload_profile_picture_button.dart b/lib/Widgets/upload_profile_picture_button.dart new file mode 100644 index 0000000..c3f612c --- /dev/null +++ b/lib/Widgets/upload_profile_picture_button.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +class UploadProfilePictureButton extends StatelessWidget { + final Function()? onTap; + + const UploadProfilePictureButton({super.key, required this.onTap}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: Container( + padding: const EdgeInsets.all(25), + margin: const EdgeInsets.symmetric(horizontal: 25), + decoration: BoxDecoration( + border: Border.all( + color:Colors.black87, + ), + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + child: const Center( + child: Text( + "Upload profile picture", + style: TextStyle( + color: Colors.black87, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + ), + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index e0e1f17..7d1e06b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -64,6 +64,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.16.0" + cross_file: + dependency: transitive + description: + name: cross_file + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.3+4" cupertino_icons: dependency: "direct main" description: @@ -78,6 +85,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" + file: + dependency: "direct main" + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.4" firebase_auth: dependency: "direct main" description: @@ -120,6 +134,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.2.2" + firebase_storage: + dependency: "direct main" + description: + name: firebase_storage + url: "https://pub.dartlang.org" + source: hosted + version: "11.0.15" + firebase_storage_platform_interface: + dependency: transitive + description: + name: firebase_storage_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.31" + firebase_storage_web: + dependency: transitive + description: + name: firebase_storage_web + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.24" flutter: dependency: "direct main" description: flutter @@ -132,6 +167,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.1" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" flutter_test: dependency: "direct dev" description: flutter @@ -142,6 +184,13 @@ packages: description: flutter source: sdk version: "0.0.0" + http: + dependency: transitive + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.5" http_parser: dependency: transitive description: @@ -149,6 +198,41 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.2" + image_picker: + dependency: "direct main" + description: + name: image_picker + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.7" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.6+1" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.12" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.7+1" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.6.3" intl: dependency: transitive description: @@ -198,6 +282,41 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.2" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + url: "https://pub.dartlang.org" + source: hosted + version: "10.2.0" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + url: "https://pub.dartlang.org" + source: hosted + version: "10.2.0" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + url: "https://pub.dartlang.org" + source: hosted + version: "9.0.7" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "3.9.0" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2" plugin_platform_interface: dependency: transitive description: @@ -268,4 +387,4 @@ packages: version: "2.1.2" sdks: dart: ">=2.18.2 <3.0.0" - flutter: ">=1.20.0" + flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index c9530e7..d6efdf5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,6 +39,11 @@ dependencies: firebase_auth: ^4.2.9 firebase_core: ^2.7.0 cloud_firestore: ^4.4.3 + firebase_storage: ^11.0.15 + image_picker: ^0.8.7 + file: ^6.1.4 + permission_handler: ^10.2.0 + dev_dependencies: flutter_test: sdk: flutter From 74fae9a520c28edd18a8ef5315f0decec788ba16 Mon Sep 17 00:00:00 2001 From: Jahid Date: Sat, 11 Mar 2023 19:05:23 +0600 Subject: [PATCH 07/10] Profile Page updated --- lib/Screens/home_screen.dart | 5 ++++- lib/Screens/sign_up_screen.dart | 2 +- lib/Screens/update_profile_screen.dart | 7 +------ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/Screens/home_screen.dart b/lib/Screens/home_screen.dart index 8d56d41..a691b27 100644 --- a/lib/Screens/home_screen.dart +++ b/lib/Screens/home_screen.dart @@ -18,6 +18,7 @@ class _HomeScreenState extends State { @override Widget build(BuildContext context) { + return Scaffold( backgroundColor: Colors.grey[300], appBar: AppBar( @@ -84,7 +85,9 @@ class PageTwo extends StatelessWidget { @override Widget build(BuildContext context) { return Center( - child: Text('Dashboard Page'), + child: Text('No stories available',style: TextStyle( + fontSize: 15, + )), ); } } diff --git a/lib/Screens/sign_up_screen.dart b/lib/Screens/sign_up_screen.dart index 346d062..10aaff2 100644 --- a/lib/Screens/sign_up_screen.dart +++ b/lib/Screens/sign_up_screen.dart @@ -31,7 +31,7 @@ class _SignUpScreenState extends State { password: passwordController.text.trim()); User? user =FirebaseAuth.instance.currentUser; user?.updateDisplayName(usernameController.text.trim()); - user?.updatePhotoURL('https://www.google.com/url?sa=i&url=https%3A%2F%2Fwww.sony.co.uk%2Fpresscentre%2Fcontacts&psig=AOvVaw12QSig7O_cvnNRLQ4qQ4VL&ust=1678607500153000&source=images&cd=vfe&ved=0CBAQjRxqFwoTCNihlr2y0_0CFQAAAAAdAAAAABAI'); + user?.updatePhotoURL('gs://connector-71f47.appspot.com/contact-dummy_landscape_964x656.jpg'); FirebaseAuth.instance .authStateChanges() .listen((User? user) async{ diff --git a/lib/Screens/update_profile_screen.dart b/lib/Screens/update_profile_screen.dart index 80599b2..643bb36 100644 --- a/lib/Screens/update_profile_screen.dart +++ b/lib/Screens/update_profile_screen.dart @@ -35,12 +35,7 @@ class UpdateProfileScreen extends StatelessWidget { if (passwordController.text.toString() != null) { user?.updatePassword(passwordController.text.toString()); } - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (BuildContext context) => HomeScreen(), - ), - ); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("User profile updated"))); } return Scaffold( resizeToAvoidBottomInset: false, From f65b2d87047ec03c84fc61b5ed1920416e47c28d Mon Sep 17 00:00:00 2001 From: Jahid Date: Sun, 12 Mar 2023 09:47:59 +0600 Subject: [PATCH 08/10] Search Screen Implemented --- android/app/src/main/AndroidManifest.xml | 1 + lib/Pages/profile_page.dart | 2 +- lib/Screens/search_screen.dart | 163 ++++++++++++++++------- lib/Screens/sign_up_screen.dart | 12 +- 4 files changed, 126 insertions(+), 52 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index b38323a..487ffdc 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -2,6 +2,7 @@ package="com.example.connector"> + { //const SizedBox(height: 60), CircleAvatar( radius: 60.0, - backgroundImage: AssetImage('${user?.photoURL}'), + backgroundImage: NetworkImage('${user?.photoURL}'), ), const SizedBox(height: 20), Text('${user?.displayName}',style: TextStyle( diff --git a/lib/Screens/search_screen.dart b/lib/Screens/search_screen.dart index 6caf066..4050bab 100644 --- a/lib/Screens/search_screen.dart +++ b/lib/Screens/search_screen.dart @@ -1,68 +1,131 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; -import '../Widgets/my_search_textfield.dart'; import 'home_screen.dart'; -import 'my_text_field.dart'; -class SearchScreen extends StatefulWidget{ - //UserModel user; - //SearchScreen(this.user); + +class SearchScreen extends StatefulWidget { + @override - SearchScreenState createState() =>SearchScreenState(); + _SearchScreenState createState() => _SearchScreenState(); } -class SearchScreenState extends State{ +class _SearchScreenState extends State { + TextEditingController searchController = TextEditingController(); + List searchResult =[]; + bool isLoading = false; + bool userFound=false; + + void onSearch()async{ + setState(() { + searchResult = []; + isLoading = true; + }); + final QuerySnapshot> result = await FirebaseFirestore.instance + .collection('users') + .where('username', isEqualTo: searchController.text) + .limit(1) + .get(); + + if (result.docs.length == 1) { + final DocumentSnapshot> userDoc = result.docs.first; + final userData = userDoc.data(); + userFound=true; + searchResult=[]; + searchResult.add(userData!); + print(searchResult); + // print other user data as needed + } else { + userFound=false; + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("No User Found"))); + print('User not found!'); + } + + setState(() { + isLoading = false; + }); + } + + + @override Widget build(BuildContext context) { - TextEditingController SearchController= new TextEditingController(); return Scaffold( - backgroundColor: Colors.grey[300], - appBar: AppBar( - leading: BackButton( - onPressed: (){ - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (BuildContext context) =>HomeScreen(), - ), - ); - }, - ), - title:Text("Search your friend"), - backgroundColor: Colors.blue, - + appBar: AppBar( + leading: BackButton( + onPressed: (){ + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (BuildContext context) =>HomeScreen(), + ), + ); + }, ), - body:Column( - children:[ - Row( - children:[ - Expanded( - child: Padding( - padding: const EdgeInsets.all(15.0), - child: MySearchTextField( - controller: SearchController, - hintText: "Type username......", - obscureText: false, - ), + backgroundColor: Colors.blue, + title: Text("Search your Friend"), + ), + body: Column( + children: [ + Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: TextField( + controller: searchController, + decoration: InputDecoration( + hintText: "type username....", + enabledBorder: const OutlineInputBorder( + borderSide: BorderSide(color: Colors.white), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: Colors.grey.shade400), + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + ), + fillColor: Colors.grey.shade200, + filled: true, ), ), - Align( - alignment: Alignment.topLeft, - child: IconButton( - color: Colors.grey.shade800, - iconSize: 30, - onPressed: (){}, - icon:Icon(Icons.search), + ), + ), + IconButton(onPressed: (){ + onSearch(); + }, icon: Icon(Icons.search)) + ], + ), + if(searchResult.length > 0) + Expanded(child: ListView.builder( + itemCount: searchResult.length, + shrinkWrap: true, + itemBuilder: (context,index){ + return ListTile( + leading: CircleAvatar( + radius: 20.0, + backgroundImage: NetworkImage(searchResult[index]['photourl']), ), - ), - const SizedBox(width:10), + title: Text(searchResult[index]['username']), + subtitle: Text(searchResult[index]['email']), + trailing: IconButton(onPressed: (){ + setState(() { + searchController.text = ""; + }); + /*Navigator.push(context, MaterialPageRoute(builder: (context)=>ChatScreen( + currentUser: widget.user, + friendId: searchResult[index]['uid'], + friendName: searchResult[index]['name'], + friendImage: searchResult[index]['image'])));*/ + }, icon: Icon(Icons.message)), + ); + })) + else if(isLoading == true) + Center(child: CircularProgressIndicator(valueColor: AlwaysStoppedAnimation(Colors.black))) + ], + ), - ], - ) - ] - ) ); } -} - +} \ No newline at end of file diff --git a/lib/Screens/sign_up_screen.dart b/lib/Screens/sign_up_screen.dart index 10aaff2..bcb8952 100644 --- a/lib/Screens/sign_up_screen.dart +++ b/lib/Screens/sign_up_screen.dart @@ -1,3 +1,4 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:connector/Screens/sign_in_screen.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; @@ -29,9 +30,18 @@ class _SignUpScreenState extends State { Future signUserUp() async { UserCredential userCredential=await FirebaseAuth.instance.createUserWithEmailAndPassword(email: emailController.text.trim(), password: passwordController.text.trim()); + User? user =FirebaseAuth.instance.currentUser; user?.updateDisplayName(usernameController.text.trim()); - user?.updatePhotoURL('gs://connector-71f47.appspot.com/contact-dummy_landscape_964x656.jpg'); + user?.updatePhotoURL('https://firebasestorage.googleapis.com/v0/b/connector-71f47.appspot.com/o/contact-dummy_landscape_964x656.jpg?alt=media&token=0559da6a-1aea-4858-a8a1-281f4b286da6'); + await FirebaseFirestore.instance.collection('users').doc(userCredential.user?.uid).set( + { + 'email':emailController.text, + 'username':usernameController.text, + 'photourl':'https://firebasestorage.googleapis.com/v0/b/connector-71f47.appspot.com/o/contact-dummy_landscape_964x656.jpg?alt=media&token=0559da6a-1aea-4858-a8a1-281f4b286da6', + }).then((value) => print("User data saved")) + .catchError((error) => print("Failed to save user data: $error")); + FirebaseAuth.instance .authStateChanges() .listen((User? user) async{ From c8eb1190f3fa09da815f9efae5cbbe9753be30bf Mon Sep 17 00:00:00 2001 From: Jahid Date: Tue, 14 Mar 2023 17:55:57 +0600 Subject: [PATCH 09/10] Chat screen and home page implemented --- android/app/src/main/AndroidManifest.xml | 6 +- lib/Pages/chat_page.dart | 83 +++++++++++ lib/Pages/home_page.dart | 85 ++++++++++++ lib/Pages/profile_page.dart | 2 + lib/Screens/home_screen.dart | 5 +- lib/Screens/search_screen.dart | 27 ++-- lib/Screens/sign_up_screen.dart | 1 + lib/Screens/update_profile_screen.dart | 3 +- lib/Widgets/message_text_field.dart | 81 +++++++++++ lib/Widgets/single_message.dart | 30 ++++ pubspec.lock | 168 +++++++++++++++++++++++ pubspec.yaml | 2 +- 12 files changed, 475 insertions(+), 18 deletions(-) create mode 100644 lib/Pages/chat_page.dart create mode 100644 lib/Pages/home_page.dart create mode 100644 lib/Widgets/message_text_field.dart create mode 100644 lib/Widgets/single_message.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 487ffdc..ddcee01 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,8 +1,8 @@ - - - + + + CircularProgressIndicator(), + errorWidget: (context,url,error)=>Icon(Icons.error,), + height: 40, + ), + ), + SizedBox(width: 5,), + Text(friendName,style: TextStyle(fontSize: 20),) + ], + ), + ), + + body: Column( + children: [ + Expanded(child: Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(25), + topRight: Radius.circular(25) + ) + ), + child: StreamBuilder( + stream: FirebaseFirestore.instance.collection("users").doc(currentUserId).collection('messages').doc(friendId).collection('chats').orderBy("date",descending: true).snapshots(), + builder: (context,AsyncSnapshot snapshot){ + if(snapshot.hasData){ + if(snapshot.data.docs.length < 1){ + return Center( + child: Text("Say Hi"), + ); + } + return ListView.builder( + itemCount: snapshot.data.docs.length, + reverse: true, + physics: BouncingScrollPhysics(), + itemBuilder: (context,index){ + bool isMe = snapshot.data.docs[index]['senderId'] == currentUserId; + return SingleMessage(message: snapshot.data.docs[index]['message'], isMe: isMe); + }); + } + return Center( + child: CircularProgressIndicator() + ); + }), + )), + MessageTextField(currentUserId, friendId), + ], + ), + + ); + } +} \ No newline at end of file diff --git a/lib/Pages/home_page.dart b/lib/Pages/home_page.dart new file mode 100644 index 0000000..a2802c6 --- /dev/null +++ b/lib/Pages/home_page.dart @@ -0,0 +1,85 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:connector/Pages/chat_page.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/material.dart'; + + +class HomePage extends StatefulWidget { + @override + _HomePageState createState() => _HomePageState(); +} + +class _HomePageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.grey[300], + body: StreamBuilder( + stream: FirebaseFirestore.instance.collection('users').doc('${FirebaseAuth.instance.currentUser?.uid}').collection('messages').snapshots(), + builder: (context,AsyncSnapshot snapshot){ + print("Hello world"); + if(snapshot.hasData){ + if(snapshot.data.docs.length < 1){ + return Center( + child: Text("No Chats Available !"), + ); + } + print("Hello world"); + return ListView.builder( + itemCount: snapshot.data.docs.length, + itemBuilder: (context,index){ + print("Hello Worlds"); + var friendId = snapshot.data.docs[index].id; + var lastMsg = snapshot.data.docs[index]['last_msg']; + return FutureBuilder( + future: FirebaseFirestore.instance.collection('users').doc(friendId).get(), + builder: (context,AsyncSnapshot asyncSnapshot){ + print("Hello Worlds"); + if(asyncSnapshot.hasData){ + print("He;;p world"); + var friend = asyncSnapshot.data.data(); + print("Help world"); + return Card( + child: ListTile( + leading: ClipRRect( + borderRadius: BorderRadius.circular(80), + child: CachedNetworkImage( + imageUrl:friend['photourl']??'', + placeholder: (conteext,url)=>CircularProgressIndicator(), + errorWidget: (context,url,error)=>Icon(Icons.error,), + height: 50, + ), + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + selectedTileColor: Colors.black87, + title: Text(friend['username'],style: TextStyle(fontWeight: FontWeight.bold)), + subtitle: Container( + child: Text("$lastMsg",style: TextStyle(color: Colors.grey),overflow: TextOverflow.ellipsis,), + ), + onTap: (){ + Navigator.push(context, MaterialPageRoute(builder: (context)=>ChatPage( + currentUserId: '${FirebaseAuth.instance.currentUser?.uid}'??'', + friendId: friend['uid']??'', + friendName: friend['username']??'', + friendImage: friend['photourl']??''))); + }, + ), + ); + } + return LinearProgressIndicator(valueColor: AlwaysStoppedAnimation(Colors.black)); + }, + + ); + }); + } + return Center(child: CircularProgressIndicator(valueColor: AlwaysStoppedAnimation(Colors.black)),); + }), + + + + ); + } +} \ No newline at end of file diff --git a/lib/Pages/profile_page.dart b/lib/Pages/profile_page.dart index 6ae10c8..b448415 100644 --- a/lib/Pages/profile_page.dart +++ b/lib/Pages/profile_page.dart @@ -25,6 +25,7 @@ class _ProfilePageState extends State { final passwordController2 = TextEditingController(); final passwordController3 = TextEditingController(); return Scaffold( + backgroundColor: Colors.grey[300], body:SafeArea( child: Center( child: Column( @@ -36,6 +37,7 @@ class _ProfilePageState extends State { CircleAvatar( radius: 60.0, backgroundImage: NetworkImage('${user?.photoURL}'), + ), const SizedBox(height: 20), Text('${user?.displayName}',style: TextStyle( diff --git a/lib/Screens/home_screen.dart b/lib/Screens/home_screen.dart index a691b27..c1467dd 100644 --- a/lib/Screens/home_screen.dart +++ b/lib/Screens/home_screen.dart @@ -1,6 +1,7 @@ import 'package:connector/Screens/search_screen.dart'; import 'package:flutter/material.dart'; +import '../Pages/home_page.dart'; import '../Pages/profile_page.dart'; @@ -75,9 +76,7 @@ class _HomeScreenState extends State { class PageOne extends StatelessWidget { @override Widget build(BuildContext context) { - return Center( - child: Text('Home Page'), - ); + return HomePage(); } } diff --git a/lib/Screens/search_screen.dart b/lib/Screens/search_screen.dart index 4050bab..c6aa0bb 100644 --- a/lib/Screens/search_screen.dart +++ b/lib/Screens/search_screen.dart @@ -1,6 +1,9 @@ +import 'package:cached_network_image/cached_network_image.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; +import '../Pages/chat_page.dart'; import 'home_screen.dart'; @@ -27,7 +30,7 @@ class _SearchScreenState extends State { .limit(1) .get(); - if (result.docs.length == 1) { + if (result.docs.length == 1 ) { final DocumentSnapshot> userDoc = result.docs.first; final userData = userDoc.data(); userFound=true; @@ -94,8 +97,10 @@ class _SearchScreenState extends State { ), IconButton(onPressed: (){ onSearch(); - }, icon: Icon(Icons.search)) + }, icon: Icon(Icons.search)), + const SizedBox(width: 10), ], + ), if(searchResult.length > 0) Expanded(child: ListView.builder( @@ -103,9 +108,11 @@ class _SearchScreenState extends State { shrinkWrap: true, itemBuilder: (context,index){ return ListTile( - leading: CircleAvatar( - radius: 20.0, - backgroundImage: NetworkImage(searchResult[index]['photourl']), + leading: CachedNetworkImage( + imageUrl:'${FirebaseAuth.instance.currentUser?.photoURL}', + placeholder: (conteext,url)=>CircularProgressIndicator(), + errorWidget: (context,url,error)=>Icon(Icons.error,), + height: 40, ), title: Text(searchResult[index]['username']), subtitle: Text(searchResult[index]['email']), @@ -113,11 +120,11 @@ class _SearchScreenState extends State { setState(() { searchController.text = ""; }); - /*Navigator.push(context, MaterialPageRoute(builder: (context)=>ChatScreen( - currentUser: widget.user, - friendId: searchResult[index]['uid'], - friendName: searchResult[index]['name'], - friendImage: searchResult[index]['image'])));*/ + Navigator.push(context, MaterialPageRoute(builder: (context)=>ChatPage( + currentUserId: '${FirebaseAuth.instance.currentUser?.uid}'??'', + friendId: searchResult[index]['uid']??'', + friendName: searchResult[index]['username']??'', + friendImage: searchResult[index]['photurl']??''))); }, icon: Icon(Icons.message)), ); })) diff --git a/lib/Screens/sign_up_screen.dart b/lib/Screens/sign_up_screen.dart index bcb8952..ee39ce6 100644 --- a/lib/Screens/sign_up_screen.dart +++ b/lib/Screens/sign_up_screen.dart @@ -36,6 +36,7 @@ class _SignUpScreenState extends State { user?.updatePhotoURL('https://firebasestorage.googleapis.com/v0/b/connector-71f47.appspot.com/o/contact-dummy_landscape_964x656.jpg?alt=media&token=0559da6a-1aea-4858-a8a1-281f4b286da6'); await FirebaseFirestore.instance.collection('users').doc(userCredential.user?.uid).set( { + 'uid':userCredential.user?.uid, 'email':emailController.text, 'username':usernameController.text, 'photourl':'https://firebasestorage.googleapis.com/v0/b/connector-71f47.appspot.com/o/contact-dummy_landscape_964x656.jpg?alt=media&token=0559da6a-1aea-4858-a8a1-281f4b286da6', diff --git a/lib/Screens/update_profile_screen.dart b/lib/Screens/update_profile_screen.dart index 643bb36..a94eb3a 100644 --- a/lib/Screens/update_profile_screen.dart +++ b/lib/Screens/update_profile_screen.dart @@ -107,7 +107,8 @@ class UpdateProfileScreen extends StatelessWidget { PickedFile? image; User? user = FirebaseAuth.instance.currentUser; //Check Permissions - await Permission.photos.request(); + var check=await Permission.photos.request(); + print(check); var permissionStatus = await Permission.photos.status; diff --git a/lib/Widgets/message_text_field.dart b/lib/Widgets/message_text_field.dart new file mode 100644 index 0000000..4f00e1b --- /dev/null +++ b/lib/Widgets/message_text_field.dart @@ -0,0 +1,81 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter/material.dart'; + + +class MessageTextField extends StatefulWidget { + final String currentId; + final String friendId; + + MessageTextField(this.currentId,this.friendId); + + @override + _MessageTextFieldState createState() => _MessageTextFieldState(); +} + +class _MessageTextFieldState extends State { + TextEditingController _controller = TextEditingController(); + @override + Widget build(BuildContext context) { + return Container( + color: Colors.white, + padding: EdgeInsetsDirectional.all(8), + child: Row( + children: [ + Expanded(child: TextField( + controller: _controller, + decoration: InputDecoration( + labelText:"Type your Message", + fillColor: Colors.grey[100], + filled: true, + border: OutlineInputBorder( + borderSide: BorderSide(width: 0), + gapPadding: 10, + borderRadius: BorderRadius.circular(25) + ) + ), + )), + SizedBox(width: 20,), + GestureDetector( + onTap: ()async{ + String message = _controller.text; + _controller.clear(); + await FirebaseFirestore.instance.collection('users').doc(widget.currentId).collection('messages').doc(widget.friendId).collection('chats').add({ + "senderId":widget.currentId, + "receiverId":widget.friendId, + "message":message, + "type":"text", + "date":DateTime.now(), + }).then((value) { + FirebaseFirestore.instance.collection('users').doc(widget.currentId).collection('messages').doc(widget.friendId).set({ + 'last_msg':message, + }); + }); + + await FirebaseFirestore.instance.collection('users').doc(widget.friendId).collection('messages').doc(widget.currentId).collection("chats").add({ + "senderId":widget.currentId, + "receiverId":widget.friendId, + "message":message, + "type":"text", + "date":DateTime.now(), + + }).then((value){ + FirebaseFirestore.instance.collection('users').doc(widget.friendId).collection('messages').doc(widget.currentId).set({ + "last_msg":message + }); + }); + }, + child: Container( + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.blue, + ), + child: Icon(Icons.send,color: Colors.white,), + ), + ) + ], + ), + + ); + } +} \ No newline at end of file diff --git a/lib/Widgets/single_message.dart b/lib/Widgets/single_message.dart new file mode 100644 index 0000000..dd3ca65 --- /dev/null +++ b/lib/Widgets/single_message.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + + +class SingleMessage extends StatelessWidget { + final String message; + final bool isMe; + SingleMessage({ + required this.message, + required this.isMe + }); + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: isMe ? MainAxisAlignment.end : MainAxisAlignment.start, + children: [ + Container( + padding: EdgeInsets.all(16), + margin: EdgeInsets.all(16), + constraints: BoxConstraints(maxWidth: 200), + decoration: BoxDecoration( + color: isMe ? Colors.black : Colors.orange, + borderRadius: BorderRadius.all(Radius.circular(12)) + ), + child: Text(message,style: TextStyle(color: Colors.white,),) + ), + ], + + ); + } +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 7d1e06b..d15136f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -22,6 +22,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + cached_network_image: + dependency: "direct main" + description: + name: cached_network_image + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.3" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" characters: dependency: transitive description: @@ -71,6 +92,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.3.3+4" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" cupertino_icons: dependency: "direct main" description: @@ -85,6 +113,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" file: dependency: "direct main" description: @@ -160,6 +195,20 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_blurhash: + dependency: transitive + description: + name: flutter_blurhash + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.0" flutter_lints: dependency: "direct dev" description: @@ -275,6 +324,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" + octo_image: + dependency: transitive + description: + name: octo_image + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" path: dependency: transitive description: @@ -282,6 +338,55 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.2" + path_provider: + dependency: transitive + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.13" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.24" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.10" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.6" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.5" + pedantic: + dependency: transitive + description: + name: pedantic + url: "https://pub.dartlang.org" + source: hosted + version: "1.11.1" permission_handler: dependency: "direct main" description: @@ -317,6 +422,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.2" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" plugin_platform_interface: dependency: transitive description: @@ -324,6 +436,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.4" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.4" + rxdart: + dependency: transitive + description: + name: rxdart + url: "https://pub.dartlang.org" + source: hosted + version: "0.27.7" sky_engine: dependency: transitive description: flutter @@ -336,6 +462,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.9.0" + sqflite: + dependency: transitive + description: + name: sqflite + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.6" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.3" stack_trace: dependency: transitive description: @@ -357,6 +497,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.1" + synchronized: + dependency: transitive + description: + name: synchronized + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" term_glyph: dependency: transitive description: @@ -378,6 +525,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" + uuid: + dependency: transitive + description: + name: uuid + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.7" vector_math: dependency: transitive description: @@ -385,6 +539,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.3" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" sdks: dart: ">=2.18.2 <3.0.0" flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index d6efdf5..3bb74b8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -43,7 +43,7 @@ dependencies: image_picker: ^0.8.7 file: ^6.1.4 permission_handler: ^10.2.0 - + cached_network_image: ^3.2.3 dev_dependencies: flutter_test: sdk: flutter From 7d2b69ad336b521e63c74d4280525bfbb436d33a Mon Sep 17 00:00:00 2001 From: Jahid Date: Wed, 15 Mar 2023 20:44:12 +0600 Subject: [PATCH 10/10] Design slightly modified --- lib/Pages/profile_page.dart | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/Pages/profile_page.dart b/lib/Pages/profile_page.dart index b448415..b31cebb 100644 --- a/lib/Pages/profile_page.dart +++ b/lib/Pages/profile_page.dart @@ -1,3 +1,4 @@ +import 'package:cached_network_image/cached_network_image.dart'; import 'package:connector/Screens/my_text_field.dart'; import 'package:connector/Screens/sign_out_button.dart'; import 'package:connector/Widgets/update_profile_button.dart'; @@ -34,10 +35,19 @@ class _ProfilePageState extends State { children: [ //const SizedBox(height: 60), - CircleAvatar( - radius: 60.0, - backgroundImage: NetworkImage('${user?.photoURL}'), - + CachedNetworkImage( + imageUrl:'${user?.photoURL}'??'', + placeholder: (conteext,url)=>CircularProgressIndicator(), + errorWidget: (context,url,error)=>Icon(Icons.error,), + imageBuilder: (context, imageProvider) => Container( + width: 130.0, + height: 130.0, + decoration: BoxDecoration( + shape: BoxShape.circle, + image: DecorationImage( + image: imageProvider, fit: BoxFit.cover), + ), + ), ), const SizedBox(height: 20), Text('${user?.displayName}',style: TextStyle(