diff --git a/assets/Loading.flr b/assets/Loading.flr new file mode 100644 index 0000000..997b028 Binary files /dev/null and b/assets/Loading.flr differ diff --git a/fonts/Raleway-Black.ttf b/fonts/Raleway-Black.ttf new file mode 100644 index 0000000..fa0be3b Binary files /dev/null and b/fonts/Raleway-Black.ttf differ diff --git a/fonts/Raleway-Regular.ttf b/fonts/Raleway-Regular.ttf new file mode 100644 index 0000000..746c242 Binary files /dev/null and b/fonts/Raleway-Regular.ttf differ diff --git a/fonts/Raleway-SemiBold.ttf b/fonts/Raleway-SemiBold.ttf new file mode 100644 index 0000000..34db420 Binary files /dev/null and b/fonts/Raleway-SemiBold.ttf differ diff --git a/fonts/Raleway-Thin.ttf b/fonts/Raleway-Thin.ttf new file mode 100644 index 0000000..f623aba Binary files /dev/null and b/fonts/Raleway-Thin.ttf differ diff --git a/lib/Common_Resources/Constants.dart b/lib/Common_Resources/Constants.dart index 371d3f0..ff50779 100644 --- a/lib/Common_Resources/Constants.dart +++ b/lib/Common_Resources/Constants.dart @@ -21,8 +21,11 @@ Color kInsideHeadingColor = kNeon; Color kHomeHeadingFont = kNeon; Color kHomeTextFont = Colors.white; -TextStyle kGitooTheme = - TextStyle(color: kNeon, fontSize: 50, fontWeight: FontWeight.w900); +TextStyle kGitooTheme = TextStyle( + color: kNeon, + fontSize: 50, + fontWeight: FontWeight.w700, + fontFamily: 'Raleway'); TextStyle kInsideText = TextStyle( color: kInsideFontColor, @@ -42,7 +45,10 @@ TextStyle kHomeText = TextStyle( fontWeight: FontWeight.bold, fontFamily: 'Balsamiq'); TextStyle kHomeHeading = TextStyle( - color: kHomeHeadingFont, fontWeight: FontWeight.bold, fontSize: 20); + color: kHomeHeadingFont, + fontWeight: FontWeight.w700, + fontSize: 20, + fontFamily: 'Raleway'); TextStyle kUserNameStyle = TextStyle( fontSize: 30, fontWeight: FontWeight.bold, diff --git a/lib/Common_Resources/GoodBox.dart b/lib/Common_Resources/GoodBox.dart new file mode 100644 index 0000000..33252b7 --- /dev/null +++ b/lib/Common_Resources/GoodBox.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; + +import 'Constants.dart'; + +class GoodBox extends StatelessWidget { + final Widget child; + final bool isPressed; + GoodBox({this.child, this.isPressed = false}); + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: kPrimary, + borderRadius: BorderRadius.circular(20), + boxShadow: isPressed == true + ? [ + BoxShadow( + color: kDPrimary, + offset: Offset(-4, -4), + blurRadius: 6, + ), + BoxShadow( + color: kLPrimary, + offset: Offset(1, 1), + blurRadius: 10, + ), + ] + : [ + BoxShadow( + color: kDPrimary, + offset: Offset(4, 4), + blurRadius: 10, + ), + BoxShadow( + color: kLPrimary, + offset: Offset(-2, -2), + blurRadius: 6, + ), + ]), + child: Padding( + child: child, + padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5), + ), + ); + } +} diff --git a/lib/Common_Resources/NavBarButton.dart b/lib/Common_Resources/NavBarButton.dart new file mode 100644 index 0000000..7cceeaf --- /dev/null +++ b/lib/Common_Resources/NavBarButton.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'Constants.dart'; + +class NavBarButton extends StatelessWidget { + final IconData icon; + final bool isPressed; + NavBarButton({this.icon, this.isPressed}); + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.only(top: 5), + width: 80, + height: 80, + decoration: BoxDecoration( + color: kPrimary, + boxShadow: isPressed == true + ? [ + BoxShadow( + color: kLPrimary, offset: Offset(1, 1), blurRadius: 6), + BoxShadow( + color: kDPrimary, offset: Offset(-4, -4), blurRadius: 10) + ] + : [ + BoxShadow( + color: kLPrimary, offset: Offset(-4, -4), blurRadius: 10), + BoxShadow( + color: kDPrimary, offset: Offset(2, 2), blurRadius: 10) + ], + borderRadius: BorderRadius.circular(20), + ), + child: Icon( + icon, + color: isPressed == true ? kNeon : kTinder, + size: 40, + ), + ); + } +} diff --git a/lib/Common_Resources/Shared_Widgets.dart b/lib/Common_Resources/Shared_Widgets.dart deleted file mode 100644 index 7a74da7..0000000 --- a/lib/Common_Resources/Shared_Widgets.dart +++ /dev/null @@ -1,116 +0,0 @@ -import 'package:flutter/material.dart'; -import 'Constants.dart'; -import 'package:gitoo/Screens/HomePage.dart'; - -class BottomBarButton extends StatelessWidget { - final IconData icon; - BottomBarButton({this.icon}); - @override - Widget build(BuildContext context) { - return Container( - margin: EdgeInsets.only(top: 5), - width: 80, - height: 80, - decoration: BoxDecoration( - color: kPrimary, - boxShadow: [ - BoxShadow(color: kLPrimary, offset: Offset(-2, -2), blurRadius: 8), - BoxShadow(color: kDPrimary, offset: Offset(4, 4), blurRadius: 10) - ], - borderRadius: BorderRadius.circular(20), - ), - child: Icon( - icon, - color: kNeon, - size: 40, - ), - ); - } -} - -class GoodBox extends StatelessWidget { - final Widget child; - GoodBox({this.child}); - @override - Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - color: kPrimary, - borderRadius: BorderRadius.circular(20), - boxShadow: [ - BoxShadow( - color: kDPrimary, - offset: Offset(4, 4), - blurRadius: 10, - ), - BoxShadow( - color: kLPrimary, - offset: Offset(-2, -2), - blurRadius: 6, - ), - ]), - child: Padding( - child: child, - padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5), - ), - ); - } -} - -class SweetBox extends StatelessWidget { - final String title; - final IconData icon; - final Color iconColor; - final Function function; - final int flex; - final int count; - SweetBox( - {this.count, - this.title, - this.icon, - this.iconColor, - this.function, - this.flex = 1}); - @override - Widget build(BuildContext context) { - return Expanded( - flex: flex, - child: GestureDetector( - onTap: function, - child: GoodBox( - child: Column( - children: [ - Expanded( - flex: 3, - child: FittedBox( - fit: BoxFit.contain, - child: Icon( - icon, - color: iconColor, - ), - ), - ), - Expanded( - child: FittedBox( - child: Text( - '$title', - style: kHomeHeading, - ), - ), - ), - Expanded( - child: FittedBox( - fit: BoxFit.scaleDown, - child: Text( - '$count', - style: kHomeText, - ), - ), - ) - ], - ), - ), - ), - ); - } -} diff --git a/lib/Common_Resources/SweetBox.dart b/lib/Common_Resources/SweetBox.dart new file mode 100644 index 0000000..2f71f6e --- /dev/null +++ b/lib/Common_Resources/SweetBox.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import 'Constants.dart'; +import 'GoodBox.dart'; + +class SweetBox extends StatelessWidget { + final String title; + final IconData icon; + final Color iconColor; + final Function function; + final int count; + final bool isPressed; + SweetBox( + {this.count, + this.title, + this.icon, + this.iconColor, + this.function, + this.isPressed}); + @override + Widget build(BuildContext context) { + return Expanded( + child: GestureDetector( + onTap: function, + child: GoodBox( + isPressed: isPressed, + child: Column( + children: [ + Expanded( + flex: 3, + child: FittedBox( + fit: BoxFit.contain, + child: Icon( + icon, + color: iconColor, + ), + ), + ), + Expanded( + child: FittedBox( + child: Text( + '$title', + style: kHomeHeading, + ), + ), + ), + Expanded( + child: FittedBox( + fit: BoxFit.scaleDown, + child: Text( + '$count', + style: kHomeText, + ), + ), + ) + ], + ), + ), + ), + ); + } +} diff --git a/lib/DataBundle/DataBundle.dart b/lib/DataBundle/DataBundle.dart new file mode 100644 index 0000000..f3763a8 --- /dev/null +++ b/lib/DataBundle/DataBundle.dart @@ -0,0 +1,61 @@ +import 'package:flutter/cupertino.dart'; +import 'package:gitoo/Network/Network.dart'; +import 'package:gitoo/Network/URI.dart'; + +class DataBundle { + static final api = API(); + final networkLoader = NetworkLoader(api); + Future getUserData(String userId) async { + Map map = {}; + final Map data = await networkLoader.getData(userId); + if (data != null) { + for (int i = 0; i < endpoints.length; i++) { + if (data.containsKey(endpoints[i])) { + map[endpoints[i]] = data[endpoints[i]]; + } + } + } + return User(map: map); + } + + Future getUserBigData(String userId) async { + final List repoData = await networkLoader.getRepos(userId); + final List starredData = await networkLoader.getStarred(userId); + final List followersData = + await networkLoader.getFollowers(userId); + final List followingData = + await networkLoader.getFollowing(userId); + final List organisationsData = + await networkLoader.getOrganisations(userId); + final Map map = {}; + map['repos'] = repoData; + map['starred'] = starredData; + map['followers'] = followersData; + map['following'] = followingData; + map['organisations'] = organisationsData; + return UserBigData(map: map); + } + + List endpoints = [ + 'login', + 'avatar_url', + 'name', + 'blog', + 'location', + 'email', + 'bio', + 'public_repos', + 'followers', + 'following', + ]; +} + +class User { + final Map map; + User({@required this.map}); +} + +class UserBigData { + final Map map; + UserBigData({@required this.map}); +} diff --git a/lib/DataNotifier/DataNotifier.dart b/lib/DataNotifier/DataNotifier.dart new file mode 100644 index 0000000..db5d263 --- /dev/null +++ b/lib/DataNotifier/DataNotifier.dart @@ -0,0 +1,253 @@ +import 'package:flutter/material.dart'; +import 'package:gitoo/Common_Resources/Constants.dart'; +import 'package:gitoo/DataBundle/DataBundle.dart'; +import 'package:provider/provider.dart'; + +class DataNotifier extends ChangeNotifier { + User user; + UserBigData userBigData; + DataNotifier(BuildContext context) { + this.user = Provider.of(context, listen: false); + this.userBigData = Provider.of(context, listen: false); + } + Widget showFollowers() { + List followersList = userBigData.map['followers']; + if (followersList.isNotEmpty) { + return ListView.separated( + itemBuilder: (BuildContext context, index) { + return Row( + children: [ + Padding( + padding: EdgeInsets.only(left: 15, right: 10), + child: CircleAvatar( + backgroundImage: + NetworkImage('${followersList[index]['avatar_url']}'), + radius: 20, + ), + ), + Expanded( + child: Container( + alignment: Alignment.centerLeft, + child: FittedBox( + fit: BoxFit.scaleDown, + child: Text( + '${followersList[index]['login']}', + style: + kInsideText.copyWith(fontWeight: FontWeight.normal), + ), + ), + ), + ), + ], + ); + }, + separatorBuilder: (BuildContext context, index) { + return Divider( + color: kLPrimary, + ); + }, + itemCount: followersList.length); + } else { + return Center( + child: Text( + 'Nothing to Show here', + style: kInsideText, + ), + ); + } + } + Widget showFollowing() { + List followingList = userBigData.map['following']; + if (followingList.isNotEmpty) { + return ListView.separated( + itemBuilder: (BuildContext context, index) { + return Row( + children: [ + Padding( + padding: EdgeInsets.only(left: 15, right: 10), + child: CircleAvatar( + backgroundImage: + NetworkImage('${followingList[index]['avatar_url']}'), + radius: 20, + ), + ), + Expanded( + child: Container( + alignment: Alignment.centerLeft, + child: FittedBox( + fit: BoxFit.scaleDown, + child: Text( + '${followingList[index]['login']}', + style: + kInsideText.copyWith(fontWeight: FontWeight.normal), + ), + ), + ), + ), + ], + ); + }, + separatorBuilder: (BuildContext context, index) { + return Divider( + color: kLPrimary, + ); + }, + itemCount: followingList.length); + } else { + return Center( + child: Text( + 'Nothing to Show here', + style: kInsideText, + ), + ); + } + } + Widget showOrgs() { + List organisationsList = userBigData.map['organisations']; + if (organisationsList.isNotEmpty) { + return ListView.separated( + itemBuilder: (BuildContext context, index) { + return Row( + children: [ + Padding( + padding: EdgeInsets.only(left: 15, right: 10), + child: CircleAvatar( + backgroundImage: NetworkImage( + '${organisationsList[index]['avatar_url']}'), + radius: 20, + ), + ), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + FittedBox( + fit: BoxFit.scaleDown, + child: Align( + alignment: Alignment.centerLeft, + child: Text( + '${organisationsList[index]['login']}', + style: kInsideText.copyWith( + fontWeight: FontWeight.normal), + ), + ), + ), + Text( + '${organisationsList[index]['description'] ?? 'I don\'t know'}', + style: kInsideText.copyWith(color: kNeon), + ), + ], + ), + ) + ], + ); + }, + separatorBuilder: (BuildContext context, index) { + return Divider( + color: kLPrimary, + ); + }, + itemCount: organisationsList.length); + } else { + return Center( + child: Text( + 'Nothing to Show here', + style: kInsideText, + ), + ); + } + } + Widget showRepos() { + List reposList = userBigData.map['repos']; + if (reposList.isNotEmpty) { + return ListView.separated( + itemBuilder: (BuildContext context, index) { + return Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only(left: 15), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + FittedBox( + fit: BoxFit.scaleDown, + child: Align( + alignment: Alignment.centerLeft, + child: Text( + '${reposList[index]['name']}', + style: + kInsideText.copyWith(fontWeight: FontWeight.normal), + ), + ), + ), + Text( + '${reposList[index]['language'] ?? 'I don\'t know'}', + style: kInsideText.copyWith(color: kNeon), + ), + ], + ), + ); + }, + separatorBuilder: (BuildContext context, index) { + return Divider( + color: kLPrimary, + ); + }, + itemCount: reposList.length); + } else { + return Center( + child: Text( + 'Nothing to Show here', + style: kInsideText, + ), + ); + } + } + Widget showStarred() { + List starredList = userBigData.map['starred']; + if (starredList.isNotEmpty) { + return ListView.separated( + itemBuilder: (BuildContext context, index) { + return Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only(left: 15), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + FittedBox( + fit: BoxFit.scaleDown, + child: Align( + alignment: Alignment.centerLeft, + child: Text( + '${starredList[index]['full_name']}', + style: + kInsideText.copyWith(fontWeight: FontWeight.normal), + ), + ), + ), + Text( + '${starredList[index]['language'] ?? 'I don\'t know'}', + style: kInsideText.copyWith(color: kNeon), + ), + ], + ), + ); + }, + separatorBuilder: (BuildContext context, index) { + return Divider( + color: kLPrimary, + ); + }, + itemCount: starredList.length); + } else { + return Center( + child: Text( + 'Nothing to show here', + style: kInsideText, + ), + ); + } + } +} diff --git a/lib/InsidePages/List.dart b/lib/InsidePages/List.dart deleted file mode 100644 index 98e9812..0000000 --- a/lib/InsidePages/List.dart +++ /dev/null @@ -1,251 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:gitoo/Common_Resources/Constants.dart'; - -List followers = []; -List followersAvatar = []; -Widget getFollowers() { - if (followers.isNotEmpty) { - return ListView.separated( - itemBuilder: (BuildContext context, index) { - return Row( - children: [ - Padding( - padding: EdgeInsets.only(left: 15, right: 10), - child: CircleAvatar( - backgroundImage: NetworkImage('${followersAvatar[index]}'), - radius: 20, - ), - ), - Expanded( - child: Container( - alignment: Alignment.centerLeft, - child: FittedBox( - fit: BoxFit.scaleDown, - child: Text( - '${followers[index]}', - style: - kInsideText.copyWith(fontWeight: FontWeight.normal), - ), - ), - ), - ), - ], - ); - }, - separatorBuilder: (BuildContext context, index) { - return Divider( - color: kLPrimary, - ); - }, - itemCount: followers.length); - } else { - return Center( - child: Text( - 'Nothing to Show here', - style: kInsideText, - ), - ); - } -} - -List following = []; -List followingAvatar = []; -Widget getFollowing() { - if (following.isNotEmpty) { - return ListView.separated( - itemBuilder: (BuildContext context, index) { - return Row( - children: [ - Padding( - padding: EdgeInsets.only(left: 15, right: 10), - child: CircleAvatar( - backgroundImage: NetworkImage('${followingAvatar[index]}'), - radius: 20, - ), - ), - Expanded( - child: Container( - alignment: Alignment.centerLeft, - child: FittedBox( - fit: BoxFit.scaleDown, - child: Text( - '${following[index]}', - style: - kInsideText.copyWith(fontWeight: FontWeight.normal), - ), - ), - ), - ), - ], - ); - }, - separatorBuilder: (BuildContext context, index) { - return Divider( - color: kLPrimary, - ); - }, - itemCount: following.length); - } else { - return Center( - child: Text( - 'Nothing to Show here', - style: kInsideText, - ), - ); - } -} - -List organizations = []; -List organizationsAvatar = []; -List organizationsDesc = []; -Widget getOrgs() { - if (organizations.isNotEmpty) { - return ListView.separated( - itemBuilder: (BuildContext context, index) { - return Row( - children: [ - Padding( - padding: EdgeInsets.only(left: 15, right: 10), - child: CircleAvatar( - backgroundImage: - NetworkImage('${organizationsAvatar[index]}'), - radius: 20, - ), - ), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - FittedBox( - fit: BoxFit.scaleDown, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - '${organizations[index]}', - style: kInsideText.copyWith( - fontWeight: FontWeight.normal), - ), - ), - ), - Text( - '${organizationsDesc[index] ?? 'I don\'t know'}', - style: kInsideText.copyWith(color: kNeon), - ), - ], - ), - ) - ], - ); - }, - separatorBuilder: (BuildContext context, index) { - return Divider( - color: kLPrimary, - ); - }, - itemCount: organizations.length); - } else { - return Center( - child: Text( - 'Nothing to Show here', - style: kInsideText, - ), - ); - } -} - -List repos = []; -List reposLanguage = []; -Widget getRepos() { - if (repos.isNotEmpty) { - return ListView.separated( - itemBuilder: (BuildContext context, index) { - return Container( - alignment: Alignment.centerLeft, - padding: EdgeInsets.only(left: 15), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - FittedBox( - fit: BoxFit.scaleDown, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - '${repos[index]}', - style: - kInsideText.copyWith(fontWeight: FontWeight.normal), - ), - ), - ), - Text( - '${reposLanguage[index] ?? 'I don\'t know'}', - style: kInsideText.copyWith(color: kNeon), - ), - ], - ), - ); - }, - separatorBuilder: (BuildContext context, index) { - return Divider( - color: kLPrimary, - ); - }, - itemCount: repos.length); - } else { - return Center( - child: Text( - 'Nothing to Show here', - style: kInsideText, - ), - ); - } -} - -List starred = []; -List starredLanguage = []; -Widget getStarred() { - if (starred.isNotEmpty) { - return ListView.separated( - itemBuilder: (BuildContext context, index) { - return Container( - alignment: Alignment.centerLeft, - padding: EdgeInsets.only(left: 15), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - FittedBox( - fit: BoxFit.scaleDown, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - '${starred[index]}', - style: - kInsideText.copyWith(fontWeight: FontWeight.normal), - ), - ), - ), - Text( - '${starredLanguage[index] ?? 'I don\'t know'}', - style: kInsideText.copyWith(color: kNeon), - ), - ], - ), - ); - }, - separatorBuilder: (BuildContext context, index) { - return Divider( - color: kLPrimary, - ); - }, - itemCount: starred.length); - } else { - return Center( - child: Text( - 'Nothing to show here', - style: kInsideText, - ), - ); - } -} diff --git a/lib/Network/Network.dart b/lib/Network/Network.dart index 4152075..fddf2ea 100644 --- a/lib/Network/Network.dart +++ b/lib/Network/Network.dart @@ -1,120 +1,95 @@ import 'dart:convert'; -import 'package:gitoo/InsidePages/List.dart'; import 'package:http/http.dart'; -String name; -String email; -String avatar; -String info; -int noOfRepos; -int noOfFollowers; -int noOfFollowing; -String location; -String userId; -String twitter; -String blogger; -Map headers = {'Authorization': 'Apna khud se daalo'}; +import 'URI.dart'; class NetworkLoader { - String username; - NetworkLoader({this.username}); - String git = 'https://api.github.com/users/'; - Future checkUsername() async { - Response response = await get('$git$username', headers: headers); - print(response.statusCode); + final API api; + NetworkLoader(this.api); + Future checkUsername(String userId) async { + final uri = api.userURI().toString() + '/$userId'; + Response response = await get(uri, headers: api.headers); if (response.statusCode == 200) { return true; } else return false; } - Future getData() async { - Response response = await get('$git$username', headers: headers); + Future> getData(String userId) async { + final uri = api.userURI().toString() + '/$userId'; + Response response = await get(uri, headers: api.headers); Map data = jsonDecode(response.body); - name = data['name']; - avatar = data['avatar_url']; - email = data['email']; - info = data['bio']; - noOfRepos = data['public_repos']; - noOfFollowers = data['followers']; - noOfFollowing = data['following']; - location = data['location']; - twitter = data['twitter_username']; - blogger = data['blog']; - print(response.headers); - await getOrganisations(); - await getFollowers(); - await getFollowing(); - await getStarred(); - await getRepos(); - return; + return data; } - Future getFollowers() async { - int page = 1; - Response response = await get( - '$git$username/followers?page=$page&per_page=100', - headers: headers); - followers.clear(); - followersAvatar.clear(); - List data = jsonDecode(response.body); - for (int i = 0; i < data.length; i++) { - followers.add(data[i]['login']); - followersAvatar.add(data[i]['avatar_url']); + Future> getFollowers(String userId) async { + List temp = []; + for (int page = 1;; page++) { + final uri = api.userURI().toString() + + '/$userId' + + '/followers?page=$page&per_page=100'; + Response response = await get(uri, headers: api.headers); + List data = jsonDecode(response.body); + temp.addAll(data); + if (data.length < 100) break; } - - return; + return temp; } - Future getFollowing() async { - Response response = - await get('$git$username/following?per_page=100', headers: headers); - List data = jsonDecode(response.body); - following.clear(); - followingAvatar.clear(); - for (int i = 0; i < data.length; i++) { - following.add(data[i]['login']); - followingAvatar.add(data[i]['avatar_url']); + Future> getFollowing(String userId) async { + List temp = []; + for (int page = 1;; page++) { + final uri = api.userURI().toString() + + '/$userId' + + '/following?page=$page&per_page=100'; + Response response = await get(uri, headers: api.headers); + List data = jsonDecode(response.body); + temp.addAll(data); + if (data.length < 100) break; } - return; + return temp; } - Future getStarred() async { - Response response = - await get('$git$username/starred?per_page=100', headers: headers); - List data = jsonDecode(response.body); - starred.clear(); - starredLanguage.clear(); - for (int i = 0; i < data.length; i++) { - starred.add(data[i]['full_name']); - starredLanguage.add(data[i]['language']); + Future> getStarred(String userId) async { + List temp = []; + for (int page = 1;; page++) { + final uri = api.userURI().toString() + + '/$userId' + + '/starred?page=$page&per_page=100'; + Response response = await get(uri, headers: api.headers); + List data = jsonDecode(response.body); + temp.addAll(data); + if (data.length < 100) break; } - return; + + return temp; } - Future getOrganisations() async { - Response response = - await get('$git$username/orgs?per_page=100', headers: headers); - List data = jsonDecode(response.body); - organizations.clear(); - for (int i = 0; i < data.length; i++) { - organizations.add(data[i]['login']); - organizationsAvatar.add(data[i]['avatar_url']); - organizationsDesc.add(data[i]['description']); + Future> getOrganisations(String userId) async { + List temp = []; + for (int page = 0;; page++) { + final uri = api.userURI().toString() + + '/$userId' + + '/orgs?page=$page&per_page=100'; + Response response = await get(uri, headers: api.headers); + List data = jsonDecode(response.body); + temp.addAll(data); + if (data.length < 100) break; } - return; + return temp; } - Future getRepos() async { - Response response = - await get('$git$username/repos?per_page=100', headers: headers); - List data = jsonDecode(response.body); - repos.clear(); - reposLanguage.clear(); - for (int i = 0; i < data.length; i++) { - repos.add(data[i]['name']); - reposLanguage.add(data[i]['language']); + Future> getRepos(String userId) async { + List temp = []; + for (int page = 0;; page++) { + final uri = api.userURI().toString() + + '/$userId' + + '/repos?page=$page&per_page=100'; + Response response = await get(uri, headers: api.headers); + List data = jsonDecode(response.body); + temp.addAll(data); + if (data.length < 100) break; } - return; + return temp; } } diff --git a/lib/Network/URI.dart b/lib/Network/URI.dart new file mode 100644 index 0000000..f30de33 --- /dev/null +++ b/lib/Network/URI.dart @@ -0,0 +1,10 @@ +class API { + static final authToken = 'befd0ae5a9eeb9fad4da5813648d4842d1f568df'; + static final host = 'api.github.com'; + Map headers = {'Authorization': 'Token $authToken'}; + Uri userURI() => Uri( + scheme: 'https', + host: host, + path: '/users', + ); +} diff --git a/lib/Screens/About.dart b/lib/Screens/About.dart index 54ca551..2efe424 100644 --- a/lib/Screens/About.dart +++ b/lib/Screens/About.dart @@ -1,15 +1,17 @@ +import 'package:flare_flutter/flare_actor.dart'; import 'package:flutter/material.dart'; import 'package:flutter/painting.dart'; import 'package:fluttericon/brandico_icons.dart'; -import 'package:fluttericon/rpg_awesome_icons.dart'; import 'package:gitoo/Common_Resources/Constants.dart'; -import 'package:gitoo/Network/Network.dart'; +import 'package:gitoo/DataBundle/DataBundle.dart'; +import 'package:provider/provider.dart'; import 'package:share/share.dart'; import 'package:url_launcher/url_launcher.dart'; class About extends StatelessWidget { @override Widget build(BuildContext context) { + User user = Provider.of(context); return SafeArea( child: Scaffold( backgroundColor: kPrimary, @@ -17,17 +19,33 @@ class About extends StatelessWidget { children: [ Expanded( flex: 2, - child: Container( - padding: EdgeInsets.symmetric(vertical: 10), - decoration: BoxDecoration(shape: BoxShape.circle, boxShadow: [ - BoxShadow(color: kNeon, spreadRadius: 5, blurRadius: 3), - ]), - child: FittedBox( - fit: BoxFit.contain, - child: CircleAvatar( - backgroundImage: NetworkImage(avatar), + child: Stack( + children: [ + Positioned( + left: (MediaQuery.of(context).size.width) / 2 - 95, + child: CircleAvatar( + radius: 95, + backgroundColor: Colors.transparent, + child: FlareActor( + 'assets/Loading.flr', + animation: "Alarm", + alignment: Alignment.center, + ), + ), ), - ), + Positioned( + top: 35, + left: MediaQuery.of(context).size.width / 2 - 60, + child: FittedBox( + fit: BoxFit.contain, + child: CircleAvatar( + radius: 60, + backgroundColor: kPrimary, + backgroundImage: NetworkImage(user.map['avatar_url']), + ), + ), + ), + ], ), ), Expanded( @@ -39,17 +57,25 @@ class About extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( - '$name', + '${user.map['name']}', style: kUserNameStyle, ), Text( - '${email ?? 'Email Not Available'}', + '${user.map['email'] ?? 'Email Not Available'}', style: kEmailStyle, ), - Text( - '${info ?? 'Bio Not Available'}', - textAlign: TextAlign.center, - style: kHomeText.copyWith(fontSize: 15), + Expanded( + child: Container( + margin: EdgeInsets.symmetric(horizontal: 50), + child: FittedBox( + fit: BoxFit.contain, + child: Text( + '${user.map['bio'] ?? 'Bio Not Available'}', + textAlign: TextAlign.center, + style: kHomeText.copyWith(fontSize: 15), + ), + ), + ), ), SizedBox( height: 5, @@ -64,7 +90,7 @@ class About extends StatelessWidget { size: 23, ), Text( - '${location ?? 'Location Not Found'}', + '${user.map['location'] ?? 'Location Not Found'}', style: kHomeText, ), ], @@ -83,7 +109,8 @@ class About extends StatelessWidget { Expanded( child: GestureDetector( onTap: () { - _launchURL('https://www.twitter.com/$twitter'); + _launchURL( + 'https://www.twitter.com/${user.map['twitter']}'); }, child: Icon( Brandico.twitter_bird, @@ -95,7 +122,8 @@ class About extends StatelessWidget { Expanded( child: GestureDetector( onTap: () { - _launchURL('https://www.github.com/$userId'); + _launchURL( + 'https://www.github.com/${user.map['login_id']}'); }, child: Icon( Brandico.github_1, @@ -107,8 +135,7 @@ class About extends StatelessWidget { Expanded( child: GestureDetector( onTap: () { - print('$blogger'); - _launchURL('$blogger'); + _launchURL('https://${user.map['blog']}'); }, child: Icon( Brandico.blogger_rect, @@ -123,7 +150,7 @@ class About extends StatelessWidget { Expanded( child: GestureDetector( onTap: () { - Share.share('http://www.github.com/$userId'); + Share.share('http://www.github.com/${user.map['login_id']}'); }, child: Container( margin: EdgeInsets.symmetric(horizontal: 100, vertical: 25), diff --git a/lib/Screens/HomePage.dart b/lib/Screens/DashBoard.dart similarity index 70% rename from lib/Screens/HomePage.dart rename to lib/Screens/DashBoard.dart index 059a42d..6551029 100644 --- a/lib/Screens/HomePage.dart +++ b/lib/Screens/DashBoard.dart @@ -1,86 +1,41 @@ +import 'package:flare_flutter/flare_actor.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/painting.dart'; -import 'package:flutter/rendering.dart'; -import 'package:fluttericon/brandico_icons.dart'; import 'package:fluttericon/elusive_icons.dart'; import 'package:fluttericon/mfg_labs_icons.dart'; import 'package:fluttericon/modern_pictograms_icons.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:gitoo/Common_Resources/Shared_Widgets.dart'; -import 'package:gitoo/InsidePages/List.dart'; -import 'package:gitoo/Network/Network.dart'; -import 'package:gitoo/Screens/SplashScreen.dart'; +import 'package:gitoo/Common_Resources/Constants.dart'; +import 'package:gitoo/Common_Resources/GoodBox.dart'; +import 'package:gitoo/Common_Resources/SweetBox.dart'; +import 'package:gitoo/DataNotifier/DataNotifier.dart'; import 'package:marquee/marquee.dart'; -import '../Common_Resources/Constants.dart'; -import 'About.dart'; -Widget selectedList = getFollowers(); - -class HomePage extends StatefulWidget { +class DashBoard extends StatefulWidget { @override - _HomePageState createState() => _HomePageState(); + _DashBoardState createState() => _DashBoardState(); } -class _HomePageState extends State - with SingleTickerProviderStateMixin { - int currentIndex = 0; - final List screens = [ - Menu(), - SplashScreen(), - About(), - ]; - @override - Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () async => false, - child: SafeArea( - child: Scaffold( - resizeToAvoidBottomInset: false, - bottomNavigationBar: BottomNavigationBar( - onTap: (index) { - currentIndex = index; - setState(() {}); - }, - backgroundColor: kPrimary, - items: [ - BottomNavigationBarItem( - icon: BottomBarButton( - icon: Icons.home, - ), - title: Visibility( - visible: false, - child: Text(' '), - ), - ), - BottomNavigationBarItem( - icon: BottomBarButton( - icon: Icons.graphic_eq, - ), - title: Visibility(visible: false, child: Text('')), - ), - BottomNavigationBarItem( - icon: BottomBarButton( - icon: Icons.info, - ), - title: Visibility(visible: false, child: Text('')), - ), - ], - ), - body: screens[currentIndex], - ), - ), - ); +class _DashBoardState extends State { + int selectedList = 0; + String bio; + checkBio() { + if (bio.contains('\n')) { + bio = bio.replaceAll('\n', ' '); + } } -} - -class Menu extends StatefulWidget { - @override - _MenuState createState() => _MenuState(); -} -class _MenuState extends State { @override Widget build(BuildContext context) { + DataNotifier dataNotifier = DataNotifier(context); + bio = dataNotifier.user.map['bio'] ?? 'Bio Not Available'; + checkBio(); + List dataLists = [ + dataNotifier.showFollowers(), + dataNotifier.showFollowing(), + dataNotifier.showStarred(), + dataNotifier.showRepos(), + dataNotifier.showOrgs(), + ]; + return Stack( children: [ Column( @@ -97,7 +52,7 @@ class _MenuState extends State { child: FittedBox( fit: BoxFit.scaleDown, child: Text( - '${name ?? 'Not Available'}', + '${dataNotifier.user.map['name'] ?? 'Not Available'}', style: kUserNameStyle, ), ), @@ -119,7 +74,7 @@ class _MenuState extends State { child: FittedBox( fit: BoxFit.scaleDown, child: Text( - '${email ?? 'Not Available'}', + '${dataNotifier.user.map['email'] ?? 'Not Available'}', style: kEmailStyle, ), ), @@ -132,43 +87,47 @@ class _MenuState extends State { child: Row( children: [ SweetBox( - count: noOfFollowers, + count: dataNotifier.user.map['followers'], title: 'Followers', icon: MfgLabs.users, iconColor: kGreen, function: () { setState(() { - selectedList = getFollowers(); + selectedList = 0; }); }, + isPressed: selectedList == 0 ? true : false, ), SizedBox( width: 20, ), SweetBox( title: 'Following', - count: noOfFollowing, + count: dataNotifier.user.map['following'], icon: Elusive.group, iconColor: kGreen, function: () { setState(() { - selectedList = getFollowing(); + selectedList = 1; }); }, + isPressed: selectedList == 1 ? true : false, ), SizedBox( width: 20, ), SweetBox( title: 'Starred', - count: starred.length, + count: dataNotifier + .userBigData.map['starred'].length, icon: Icons.star, iconColor: kYellow, function: () { setState(() { - selectedList = getStarred(); + selectedList = 2; }); }, + isPressed: selectedList == 2 ? true : false, ), ], ), @@ -185,7 +144,8 @@ class _MenuState extends State { Expanded( flex: 20, child: GoodBox( - child: selectedList, + isPressed: false, + child: dataLists[selectedList], ), ), SizedBox( @@ -199,29 +159,35 @@ class _MenuState extends State { CrossAxisAlignment.stretch, children: [ SweetBox( - count: noOfRepos, + count: + dataNotifier.user.map['public_repos'], title: 'Repos', iconColor: kOrange, icon: Elusive.github, function: () { setState(() { - selectedList = getRepos(); + selectedList = 3; }); }, + isPressed: + selectedList == 3 ? true : false, ), SizedBox( height: 20, ), SweetBox( - count: organizations.length, + count: dataNotifier.userBigData + .map['organisations'].length, iconColor: kOrange, icon: ModernPictograms.money, + title: 'Orgs', function: () { setState(() { - selectedList = getOrgs(); + selectedList = 4; }); }, - title: 'Orgs', + isPressed: + selectedList == 4 ? true : false, ), ], ), @@ -239,7 +205,7 @@ class _MenuState extends State { child: Container( alignment: Alignment.center, child: Marquee( - text: '${info ?? 'Bio Not Available'}', + text: '$bio', style: kInfoStyle, scrollAxis: Axis.horizontal, crossAxisAlignment: CrossAxisAlignment.start, @@ -261,8 +227,21 @@ class _MenuState extends State { ], ), Positioned( - top: (MediaQuery.of(context).size.height) / 10, - left: 20, + top: (MediaQuery.of(context).size.height) / 20, + left: 10, + child: CircleAvatar( + radius: 75, + backgroundColor: Colors.transparent, + child: FlareActor( + 'assets/Loading.flr', + animation: "Alarm", + alignment: Alignment.center, + ), + ), + ), + Positioned( + top: (MediaQuery.of(context).size.height) / 11, + left: 40, child: Container( decoration: BoxDecoration( boxShadow: [ @@ -271,9 +250,10 @@ class _MenuState extends State { shape: BoxShape.circle, ), child: CircleAvatar( - radius: 60, + radius: 45, backgroundColor: kSecondary, - backgroundImage: NetworkImage('$avatar'), + backgroundImage: + NetworkImage(dataNotifier.user.map['avatar_url']), ), ), ), diff --git a/lib/Screens/NavBar.dart b/lib/Screens/NavBar.dart new file mode 100644 index 0000000..57371b7 --- /dev/null +++ b/lib/Screens/NavBar.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import 'package:gitoo/Common_Resources/NavBarButton.dart'; +import 'package:gitoo/Screens/About.dart'; +import 'package:gitoo/Screens/DashBoard.dart'; +import 'package:gitoo/Screens/SearchScreen.dart'; +import '../Common_Resources/Constants.dart'; + +class NavBar extends StatefulWidget { + @override + _NavBarState createState() => _NavBarState(); +} + +class _NavBarState extends State with SingleTickerProviderStateMixin { + int selectedIndex = 0; + @override + Widget build(BuildContext context) { + List screens = [DashBoard(), SearchScreen(), About()]; + return WillPopScope( + onWillPop: () async => false, + child: SafeArea( + child: Scaffold( + resizeToAvoidBottomInset: false, + bottomNavigationBar: BottomNavigationBar( + showSelectedLabels: false, + showUnselectedLabels: false, + onTap: (index) { + setState(() { + selectedIndex = index; + }); + }, + backgroundColor: kPrimary, + items: [ + BottomNavigationBarItem( + icon: NavBarButton( + icon: Icons.home, + isPressed: selectedIndex == 0 ? true : false, + ), + title: Text(''), + ), + BottomNavigationBarItem( + icon: NavBarButton( + icon: Icons.graphic_eq, + isPressed: selectedIndex == 1 ? true : false, + ), + title: Text(''), + ), + BottomNavigationBarItem( + icon: NavBarButton( + icon: Icons.info, + isPressed: selectedIndex == 2 ? true : false, + ), + title: Text(''), + ), + ], + ), + body: screens[selectedIndex], + ), + ), + ); + } +} diff --git a/lib/Screens/SplashScreen.dart b/lib/Screens/SearchScreen.dart similarity index 78% rename from lib/Screens/SplashScreen.dart rename to lib/Screens/SearchScreen.dart index cafa25a..79b7232 100644 --- a/lib/Screens/SplashScreen.dart +++ b/lib/Screens/SearchScreen.dart @@ -5,21 +5,24 @@ import 'package:flutter/painting.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:gitoo/Common_Resources/Constants.dart'; -import 'package:gitoo/Network/Network.dart'; -import 'HomePage.dart'; +import 'package:gitoo/DataBundle/DataBundle.dart'; +import 'package:gitoo/DataNotifier/DataNotifier.dart'; +import 'package:provider/provider.dart'; +import 'NavBar.dart'; -class SplashScreen extends StatefulWidget { +class SearchScreen extends StatefulWidget { @override - _SplashScreenState createState() => _SplashScreenState(); + _SearchScreenState createState() => _SearchScreenState(); } -class _SplashScreenState extends State { +class _SearchScreenState extends State { bool loading = false; bool isFocus = false; final audioCache = AudioCache(); String animationType = 'idle'; FocusNode userFocusNode = FocusNode(); TextEditingController userController = TextEditingController(); + @override void initState() { super.initState(); @@ -40,6 +43,7 @@ class _SplashScreenState extends State { @override Widget build(BuildContext context) { + final dataBundle = Provider.of(context, listen: false); return Scaffold( resizeToAvoidBottomInset: false, backgroundColor: kPrimary, @@ -118,23 +122,35 @@ class _SplashScreenState extends State { setState(() { loading = true; }); - NetworkLoader networkLoader = - NetworkLoader(username: userController.text); - bool isValid = await networkLoader.checkUsername(); - userId = userController.text; + bool isValid = await dataBundle.networkLoader + .checkUsername(userController.text); if (isValid) { audioCache.play('happy1.mp3'); setState(() { animationType = "success"; }); - await networkLoader.getData(); + final user = + await dataBundle.getUserData(userController.text); + final userBigData = + await dataBundle.getUserBigData(user.map['login']); Navigator.push( - context, - PageRouteBuilder( - transitionDuration: Duration(milliseconds: 10), - pageBuilder: (_, __, context) { - return HomePage(); - })); + context, + PageRouteBuilder( + transitionDuration: Duration(seconds: 3), + pageBuilder: (_, __, context) { + return Provider.value( + value: user, + child: Provider.value( + value: userBigData, + child: ChangeNotifierProvider( + create: (context) => DataNotifier(context), + child: NavBar(), + ), + ), + ); + }, + ), + ); } else { Fluttertoast.showToast( msg: "I don't think that Username exists", @@ -165,7 +181,8 @@ class _SplashScreenState extends State { 'Search', style: TextStyle( color: kPrimary, - fontWeight: FontWeight.w900, + fontWeight: FontWeight.w400, + fontFamily: 'Raleway', fontSize: 30), ), ), @@ -195,7 +212,8 @@ class _SplashScreenState extends State { style: TextStyle( color: kNeon, fontSize: 50, - fontWeight: FontWeight.w900), + fontFamily: 'Raleway', + fontWeight: FontWeight.w700), ), ), ), diff --git a/lib/main.dart b/lib/main.dart index ebfdaba..a73e628 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,16 +1,32 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:gitoo/Screens/SplashScreen.dart'; +import 'package:gitoo/Common_Resources/Constants.dart'; +import 'package:gitoo/DataNotifier/DataNotifier.dart'; +import 'package:gitoo/Screens/SearchScreen.dart'; +import 'package:provider/provider.dart'; + +import 'DataBundle/DataBundle.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - return MaterialApp( - title: 'Gitoo', - home: SafeArea(child: SplashScreen()), - debugShowCheckedModeBanner: false, + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + var myNavBar = SystemUiOverlayStyle.light.copyWith( + systemNavigationBarColor: kPrimary, statusBarColor: kDPrimary); + SystemChrome.setSystemUIOverlayStyle(myNavBar); + return Provider( + create: (BuildContext context) => DataBundle(), + child: MaterialApp( + title: 'Gitoo', + home: SafeArea(child: SearchScreen()), + debugShowCheckedModeBanner: false, + ), ); } } diff --git a/pubspec.yaml b/pubspec.yaml index 9c8184f..3c7dc14 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -77,6 +77,15 @@ flutter: - asset: fonts/BalsamiqSans-Regular.ttf - asset: fonts/BalsamiqSans-Bold.ttf weight: 700 + - family: Raleway + fonts: + - asset: fonts/Raleway-Regular.ttf + - asset: fonts/Raleway-SemiBold.ttf + weight: 700 + - asset: fonts/Raleway-Black.ttf + weight: 900 + - asset: fonts/Raleway-Thin.ttf + weight: 400 # - family: Trajan Pro # - asset: fonts/TrajanPro_Bold.ttf # weight: 700