diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 1af2befef7..7805d4c420 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -8,6 +8,8 @@
diff --git a/android/settings_aar.gradle b/android/settings_aar.gradle
new file mode 100644
index 0000000000..e7b4def49c
--- /dev/null
+++ b/android/settings_aar.gradle
@@ -0,0 +1 @@
+include ':app'
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index a508656d4a..ee2ba91b95 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -2,6 +2,10 @@
+
+ NSPhotoLibraryUsageDescription
+ Access gallery to pick image
+
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleExecutable
diff --git a/lib/screens/profile_screen.dart b/lib/screens/profile_screen.dart
index 84f911654b..f51f0190c4 100644
--- a/lib/screens/profile_screen.dart
+++ b/lib/screens/profile_screen.dart
@@ -1,3 +1,5 @@
+import 'dart:io';
+
import 'package:class_manager/constants.dart';
import 'package:class_manager/models/users.dart';
import 'package:class_manager/screens/onboarding_page.dart';
@@ -6,8 +8,11 @@ import 'package:class_manager/services/facebookAuthentication.dart';
import 'package:class_manager/services/googleAuthentication.dart';
import 'package:class_manager/services/user_info_services.dart';
import 'package:firebase_auth/firebase_auth.dart';
+import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
+import 'package:image_picker/image_picker.dart';
+import 'package:path/path.dart' as Path;
class ProfileScreen extends StatefulWidget {
@override
@@ -15,16 +20,51 @@ class ProfileScreen extends StatefulWidget {
}
class _ProfileScreenState extends State {
+ ImagePicker _imagePicker = ImagePicker();
+ StorageReference _storageReference = FirebaseStorage.instance.ref();
+
+ void getImage() async {
+ PickedFile image = await _imagePicker.getImage(source: ImageSource.gallery);
+
+ if (image == null) {
+ return;
+ }
+
+ String imagePath = image.path;
+
+ File file = File(imagePath);
+
+ uploadPictures(file);
+ }
+
+ uploadPictures(File image) async {
+ // uploads picture(s) to storage and return it's URL
+ final StorageReference ref =
+ _storageReference.child('${Path.basename(image.path)}}');
+
+ final StorageUploadTask uploadTask = ref.putFile(image);
+
+ UploadTaskSnapshot uploadTaskSnapshot = await uploadTask.future;
+ String pictureUrl = uploadTaskSnapshot.downloadUrl.toString();
+
+ final userInfoProvider =
+ Provider.of(context, listen: false);
+
+ Users currentUser = userInfoProvider.user;
+ currentUser.profilePictureUrl = pictureUrl;
+
+ userInfoProvider.setUser(currentUser);
+
+ userInfoProvider.upateProfilePictureUrl();
+ }
+
@override
Widget build(BuildContext context) {
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
final User userData = firebaseAuth.currentUser;
return Scaffold(
- backgroundColor: Theme
- .of(context)
- .backgroundColor
- .withOpacity(0.8),
+ backgroundColor: Theme.of(context).backgroundColor.withOpacity(0.8),
body: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(parent: BouncingScrollPhysics()),
child: Consumer(
@@ -36,17 +76,12 @@ class _ProfileScreenState extends State {
children: [
Column(
children: [
- SizedBox(height: 0.15 * MediaQuery
- .of(context)
- .size
- .height),
+ SizedBox(height: 0.15 * MediaQuery.of(context).size.height),
Container(
margin: EdgeInsets.fromLTRB(15, 15, 15, 60),
padding: EdgeInsets.all(30),
decoration: BoxDecoration(
- color: Theme
- .of(context)
- .primaryColor,
+ color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40),
topRight: Radius.circular(40),
@@ -139,8 +174,9 @@ class _ProfileScreenState extends State {
// For Sign Out from Google Auth or Facebook Auth, Back to the On Boarding Page
Navigator.pushAndRemoveUntil(
context,
- MaterialPageRoute(builder: (_) => OnboardingPage()),
- (Route route) => false,
+ MaterialPageRoute(
+ builder: (_) => OnboardingPage()),
+ (Route route) => false,
);
}
}
@@ -151,18 +187,10 @@ class _ProfileScreenState extends State {
horizontal: 20, vertical: 10),
shape: StadiumBorder(),
color: Colors.transparent,
- hoverColor: Theme
- .of(context)
- .primaryColor,
- splashColor: Theme
- .of(context)
- .primaryColor,
- focusColor: Theme
- .of(context)
- .primaryColor,
- highlightColor: Theme
- .of(context)
- .primaryColor,
+ hoverColor: Theme.of(context).primaryColor,
+ splashColor: Theme.of(context).primaryColor,
+ focusColor: Theme.of(context).primaryColor,
+ highlightColor: Theme.of(context).primaryColor,
child: Text(
"Log out",
style: TextStyle(
@@ -178,35 +206,28 @@ class _ProfileScreenState extends State {
],
),
Positioned(
- top: 0.1 * MediaQuery
- .of(context)
- .size
- .height,
+ top: 0.1 * MediaQuery.of(context).size.height,
child: CircleAvatar(
radius: profilePictureDiameter / 2,
- backgroundImage:
- AssetImage("assets/images/profile_pic.jpg"),
+ backgroundImage: _user.profilePictureUrl.isEmpty
+ ? AssetImage("assets/images/profile_pic.jpg")
+ : NetworkImage(_user.profilePictureUrl),
backgroundColor: Colors.transparent,
- foregroundColor: Theme
- .of(context)
- .backgroundColor,
+ foregroundColor: Theme.of(context).backgroundColor,
),
),
Positioned(
- top: 0.1 * MediaQuery
- .of(context)
- .size
- .height +
+ top: 0.1 * MediaQuery.of(context).size.height +
profilePictureDiameter -
35,
- left: (MediaQuery
- .of(context)
- .size
- .width / 2) + 25,
- child: Icon(
- Icons.camera_alt,
- size: profilePictureDiameter * 0.25,
- color: Colors.white,
+ left: (MediaQuery.of(context).size.width / 2) + 25,
+ child: IconButton(
+ icon: Icon(
+ Icons.camera_alt,
+ size: profilePictureDiameter * 0.25,
+ color: Colors.white,
+ ),
+ onPressed: getImage,
),
),
],
diff --git a/lib/services/user_db_services.dart b/lib/services/user_db_services.dart
index e238803775..55d05f24c0 100644
--- a/lib/services/user_db_services.dart
+++ b/lib/services/user_db_services.dart
@@ -23,6 +23,17 @@ class UserDBServices {
.set(_user.toJson(), SetOptions(merge: true));
}
+ static Future updateProfilePictureUrl(
+ String uid, String profilePictureUrl) async {
+ FirebaseFirestore firestoreDB = FirebaseFirestore.instance;
+
+ await firestoreDB.collection(usersCollection).doc(uid).update(
+ {
+ 'profilePictureUrl': profilePictureUrl,
+ },
+ );
+ }
+
// Fetches User Data from Collection
static Future fetchUserData(BuildContext context) async {
FirebaseFirestore firestoreDB = FirebaseFirestore.instance;
diff --git a/lib/services/user_info_services.dart b/lib/services/user_info_services.dart
index c2969e125b..6680da83f6 100644
--- a/lib/services/user_info_services.dart
+++ b/lib/services/user_info_services.dart
@@ -22,6 +22,12 @@ class UserInfoServices extends ChangeNotifier {
notifyListeners();
}
+ Future upateProfilePictureUrl() async {
+ await UserDBServices.updateProfilePictureUrl(
+ _user.uid, _user.profilePictureUrl);
+ // notifyListeners();
+ }
+
void setUser(Users _usr) {
this._user = _usr;
this.hasData = true;
diff --git a/lib/widgets/header.dart b/lib/widgets/header.dart
index 6b60379aa9..722ee916a5 100644
--- a/lib/widgets/header.dart
+++ b/lib/widgets/header.dart
@@ -8,37 +8,40 @@ class Header extends StatelessWidget {
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.fromLTRB(30.0, 50.0, 30.0, 30.0),
-
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Flexible(
- child:SvgPicture.asset(
- "assets/icons/grad_cap.svg",
- height: 70.0,
- ),
- ),
- Flexible(
- child:Consumer(
- builder: (ctx, _userInfo, _) => FittedBox(
- fit: BoxFit.fitWidth,
- child: Text(
- "Hello, " +
- (_userInfo.hasData
- ? _userInfo.user.name.split(" ")[0]
- : "Sir"),
- style: TextStyle(
- color: Colors.white,
- fontSize: 25.0,
- fontWeight: FontWeight.bold,
- ),
- ),
+ child: SvgPicture.asset(
+ "assets/icons/grad_cap.svg",
+ height: 70.0,
),
),
+ Consumer(
+ builder: (ctx, _userInfo, _) => Row(
+ children: [
+ FittedBox(
+ fit: BoxFit.fitWidth,
+ child: Text(
+ "Hello, " +
+ (_userInfo.hasData
+ ? _userInfo.user.name.split(" ")[0]
+ : "Sir"),
+ style: TextStyle(
+ color: Colors.white,
+ fontSize: 25.0,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ),
+ CircleAvatar(
+ radius: 25.0,
+ backgroundImage: _userInfo.user.profilePictureUrl.isEmpty
+ ? AssetImage("assets/images/profile_pic.jpg")
+ : NetworkImage(_userInfo.user.profilePictureUrl),
+ ),
+ ],
),
- CircleAvatar(
- radius: 25.0,
- backgroundImage: AssetImage("assets/images/profile_pic.jpg"),
),
],
),
diff --git a/pubspec.lock b/pubspec.lock
index 6bf4d16ed9..0c77c3e1b0 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -106,6 +106,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
+ ffi:
+ dependency: transitive
+ description:
+ name: ffi
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.0"
+ file:
+ dependency: transitive
+ description:
+ name: file
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "6.1.0"
firebase_auth:
dependency: "direct main"
description:
@@ -148,6 +162,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.1+3"
+ firebase_storage:
+ dependency: "direct main"
+ description:
+ name: firebase_storage
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.3.2"
flutter:
dependency: "direct main"
description: flutter
@@ -174,6 +195,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0"
+ flutter_plugin_android_lifecycle:
+ dependency: transitive
+ description:
+ name: flutter_plugin_android_lifecycle
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.11"
flutter_svg:
dependency: "direct main"
description:
@@ -219,6 +247,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.2"
+ http:
+ dependency: transitive
+ description:
+ name: http
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.12.2"
http_parser:
dependency: transitive
description:
@@ -233,6 +268,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
+ image_picker:
+ dependency: "direct main"
+ description:
+ name: image_picker
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.6.7+22"
+ image_picker_platform_interface:
+ dependency: transitive
+ description:
+ name: image_picker_platform_interface
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.6"
intl:
dependency: "direct main"
description:
@@ -289,6 +338,48 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0-nullsafety.0"
+ path_provider:
+ dependency: "direct main"
+ description:
+ name: path_provider
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.1"
+ path_provider_linux:
+ dependency: transitive
+ description:
+ name: path_provider_linux
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.0"
+ path_provider_macos:
+ dependency: transitive
+ description:
+ name: path_provider_macos
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.0"
+ path_provider_platform_interface:
+ dependency: transitive
+ description:
+ name: path_provider_platform_interface
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.0"
+ path_provider_windows:
+ dependency: transitive
+ description:
+ name: path_provider_windows
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.0"
+ pedantic:
+ dependency: transitive
+ description:
+ name: pedantic
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.11.0"
petitparser:
dependency: transitive
description:
@@ -296,6 +387,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.2"
+ platform:
+ dependency: transitive
+ description:
+ name: platform
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.0.0"
plugin_platform_interface:
dependency: transitive
description:
@@ -303,6 +401,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
+ process:
+ dependency: transitive
+ description:
+ name: process
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "4.1.0"
provider:
dependency: "direct main"
description:
@@ -385,6 +490,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
+ win32:
+ dependency: transitive
+ description:
+ name: win32
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.4"
+ xdg_directories:
+ dependency: transitive
+ description:
+ name: xdg_directories
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.2.0"
xml:
dependency: transitive
description:
@@ -400,5 +519,5 @@ packages:
source: hosted
version: "3.1.0"
sdks:
- dart: ">=2.12.0-0.0 <3.0.0"
+ dart: ">=2.12.0 <3.0.0"
flutter: ">=1.24.0-7.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 63889c971c..6148d3d2cc 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -24,6 +24,9 @@ dependencies:
google_sign_in:
uuid: ^3.0.1
flutter_facebook_login:
+ image_picker:
+ firebase_storage:
+ path_provider:
dev_dependencies:
flutter_test: