Skip to content

Commit

Permalink
Merge pull request #21 from melton-foundation/beta_fixes
Browse files Browse the repository at this point in the history
Beta release fixes and features
  • Loading branch information
pranavsb authored Sep 17, 2020
2 parents b7f6df2 + 7111f34 commit 1fb5051
Show file tree
Hide file tree
Showing 19 changed files with 277 additions and 57 deletions.
Binary file added assets/errors/error_no_results.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/errors/error_unknown.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/errors/welcome_screen.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 11 additions & 2 deletions lib/api/userSearchService.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ import 'package:rxdart/rxdart.dart';
class UserSearchService {
UserSearchService() {
_results = _searchText
.debounce((_) => TimerStream(true, Duration(milliseconds: 250)))
.debounce((_) => TimerStream(true, Duration(milliseconds: 500)))
.switchMap((searchedName) async* {
print('searching: $searchedName');
yield await ApiService().getUserModelByName(searchedName.trim());
if (searchedName.trim().length == 0) {
List<UserModel> allUsers = await ApiService().getUsers();
allUsers.shuffle();
yield allUsers;
} else {
yield await ApiService().getUserModelByName(searchedName.trim());
}
_searchedString.add(searchedName);
});
}

Expand All @@ -20,6 +27,8 @@ class UserSearchService {
// Output stream
Stream<List<UserModel>> _results;
Stream<List<UserModel>> get results => _results;
StreamController<String> _searchedString = StreamController<String>();
Stream<String> get searchedString => _searchedString.stream;

void dispose() {
_searchText.close();
Expand Down
4 changes: 1 addition & 3 deletions lib/constants/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ class Constants {
static const Color meltonYellowAccent = Color.fromRGBO(230, 178, 90, 1.0);
static const Color meltonGreenAccent = Color.fromRGBO(106, 173, 137, 1.0);

static const Color userSearchFilters = Color.fromRGBO(57, 93, 115, 1.0);
static const Color directoryBackground = Color.fromRGBO(0, 40, 66, 1.0);
static const Color directoryBackground = Color.fromRGBO(0, 59, 98, 1.0);

static const List<Color> meltonRedYellowGreen = [
meltonRed,
Expand All @@ -37,7 +36,6 @@ class Constants {

static const placeholder_avatar = "assets/profile_avatar_placeholder_256px.png";

//todo alafia to get back on WU
static const List<String> campuses = [
"AU / Accra",
"BMS / Bangalore",
Expand Down
2 changes: 1 addition & 1 deletion lib/screens/DirectoryComponents/UserSearch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class _UserSearchState extends State<UserSearch> {
return Padding(
padding: EdgeInsets.fromLTRB(15, 15, 15, 15),
child: SizedBox(
height: 45,
height: 35,
child: TextField(
onChanged: (value) {
/*TODO : show loading or some indicator when user is typing */
Expand Down
25 changes: 20 additions & 5 deletions lib/screens/DirectoryComponents/UserSearchStreamBuilder.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:melton_app/api/userSearchService.dart';
import 'package:melton_app/models/UserModel.dart';
import 'package:melton_app/screens/errors/unknown_error.dart';
import 'package:melton_app/util/text_util.dart';

import 'UserTilesGrid.dart';

Expand All @@ -12,7 +14,7 @@ class UserSearchStreamBuilder extends StatelessWidget {
Widget build(BuildContext context) {
// bool isPageLoaded == false;
return Expanded(
child:buildStreamBuilder(),
child: buildStreamBuilder(),
);
}

Expand All @@ -21,24 +23,37 @@ class UserSearchStreamBuilder extends StatelessWidget {
stream: searchService.results,
builder: (context, AsyncSnapshot<List<UserModel>> snapshot) {
if (snapshot.hasError) {
return Text("${snapshot.error}"); //todo handle correctly
//todo test and add everywhere
return Column(
children: [
UnknownError(),
Text("${snapshot.error}"),
],
); //todo handle correctly
} else {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
case ConnectionState.none:
case ConnectionState.done:
searchService.searchUser(" ");
return Center(child: CircularProgressIndicator());
return Center(child: CircularProgressIndicator(backgroundColor: Colors.white,));
case ConnectionState.active:
if (snapshot.hasData) {
if (snapshot.data.length == 0) {
return Center(child: Text("No results found"));
return Center(child:
Column(
children: [
Image.asset("assets/errors/error_no_results.png"),
WhiteTitleText(content: "NO RESULTS FOUND!"),
],
)
);
} else {
return UserTilesGrid(context: context, snapshot: snapshot);
}
} else {
return Center(child: Text("ERROR: SOMETHING WENT WRONG"));
}
// case ConnectionState.done
}
}
return Center(child: Text("ERROR: SOMETHING WENT WRONG"));
Expand Down
24 changes: 24 additions & 0 deletions lib/screens/DirectoryComponents/UserSearchedString.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:flutter/material.dart';

import 'package:melton_app/api/userSearchService.dart';

import 'package:melton_app/util/text_util.dart';

class UserSearchedString extends StatelessWidget {
final UserSearchService searchService;

UserSearchedString({this.searchService});

@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: searchService.searchedString,
builder: (context, snapshot) {
if (snapshot.data == null || snapshot.data.trim().length <= 2) {
return Container();
}
return WhiteSubtitleText(content: "Showing Fellows with '${snapshot.data}'");
},
);
}
}
38 changes: 20 additions & 18 deletions lib/screens/components/UserProfileInformation.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import 'package:flutter/material.dart';

import 'package:melton_app/models/ProfileModel.dart';

import 'package:melton_app/screens/components/profile_line_item_selectable.dart';
import 'package:melton_app/screens/components/JF_badge.dart';
import 'package:melton_app/screens/components/profile_line_item.dart';
import 'package:melton_app/screens/components/profile_photo.dart';
Expand All @@ -16,17 +19,27 @@ Widget getProfileLineItemIfNotNull(String label, String content) {
return ProfileLineItem(label: label, content: content);
}

Widget getProfileLineItem(String label, String content) {
return ProfileLineItem(label: label, content: content);
}

Widget getProfileLineItemIfNotNullOrEmpty(String label, String content) {
if (content == null || content.length == 0) {
return empty;
}
return ProfileLineItem(label: label, content: content);
}


Widget getProfileLineItem(String label, String content) {
return ProfileLineItem(label: label, content: content);
}

Widget getTelephoneProfileLineItem(String phoneNumber, String countryCode) {
return !(phoneNumber.length > 0 && countryCode.length > 0)
? empty : ProfileLineItemSelectable(label: "PHONE", content: "+$countryCode $phoneNumber");
}

Widget getEmailProfileLineItem(String email) {
return ProfileLineItemSelectable(label: "EMAIL", content: email);
}

Widget getUsersSDGInfo(SDGList SDGs) {
return SDGProfile(
firstSDG: SDGs.firstSDG,
Expand All @@ -35,15 +48,6 @@ Widget getUsersSDGInfo(SDGList SDGs) {
);
}

Widget getUserPhoneNumberDetails(String phoneNumber, String countryCode) {
return !(phoneNumber.length > 0 && countryCode.length > 0)
? empty
: ProfileLineItem(
label: "PHONE",
content: "+" + countryCode + " " + phoneNumber,
);
}

Widget getUserSocialMediaDetails(SocialMediaAccounts socialMediaAccounts) {
return SocialMediaLineItem(
facebook: socialMediaAccounts.facebook,
Expand Down Expand Up @@ -74,16 +78,14 @@ List<Widget> getUserDetails({bool isProfileModel, String picture, String name,
ProfilePhoto(url: picture),
getProfileLineItemIfNotNull("", name.toUpperCase()),
Center(child: JFBadge(isJF: isJuniorFellow)),
(isProfileModel)? getUserImpactPoints(points):empty ,
getUserImpactPoints(points),
getUserSocialMediaDetails(socialMediaAccounts),
getProfileLineItemIfNotNullOrEmpty("WORK", work),
getUsersSDGInfo(SDGs),
//todo convert to tel:
getUserPhoneNumberDetails(phoneNumber, countryCode),
getTelephoneProfileLineItem(phoneNumber, countryCode),
getEmailProfileLineItem(email),
getProfileLineItem("CAMPUS", campus.toUpperCase()),
getProfileLineItem("BATCH", batch.toString()),
getProfileLineItemIfNotNullOrEmpty("CITY", city),
//todo convert to mailto:url
getProfileLineItem("EMAIL", email),
];
}
44 changes: 44 additions & 0 deletions lib/screens/components/profile_line_item_selectable.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import 'package:flutter/material.dart';

import 'package:melton_app/util/url_launch_util.dart';
import 'package:melton_app/constants/constants.dart';

class ProfileLineItemSelectable extends StatelessWidget {
final String label;
final String content;

ProfileLineItemSelectable({this.label, this.content});

@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Divider(),
Text(label,
textAlign: TextAlign.left,
style: TextStyle(letterSpacing: 2.0,
color: Constants.meltonBlue,
fontWeight: FontWeight.bold),
),
FlatButton(
onPressed: () {launchTelOrMailtoUrl(content, label == "PHONE");},
child: SelectableText(
content,
textAlign: TextAlign.center,
style: TextStyle(
color: Constants.meltonRed,
fontWeight: FontWeight.bold,
fontSize: 18.0,
),
),
),
],
),
);
}
}


27 changes: 7 additions & 20 deletions lib/screens/components/social_media_line_item.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:url_launcher/url_launcher.dart';

import 'package:melton_app/util/url_launch_util.dart';
import 'package:melton_app/constants/constants.dart';

class SocialMediaLineItem extends StatelessWidget {
Expand Down Expand Up @@ -40,13 +41,13 @@ class SocialMediaLineItem extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
facebook == null ? empty : IconButton(
icon: Icon(FontAwesomeIcons.facebook), onPressed:() {_launchURL(facebook);},
icon: Icon(FontAwesomeIcons.facebook), onPressed:() {launchSocialMediaUrl(facebook);},
iconSize: 36.0, color: Constants.meltonBlue,),
instagram == null ? empty : IconButton(
icon: Icon(FontAwesomeIcons.instagram), onPressed:() {_launchURL(instagram);},
icon: Icon(FontAwesomeIcons.instagram), onPressed:() {launchSocialMediaUrl(instagram);},
iconSize: 36.0, color: Constants.meltonRedAccent,),
twitter == null ? empty : IconButton(
icon: Icon(FontAwesomeIcons.twitter), onPressed:() {_launchURL(twitter);},
icon: Icon(FontAwesomeIcons.twitter), onPressed:() {launchSocialMediaUrl(twitter);},
iconSize: 36.0, color: Constants.meltonBlueAccent,),
wechat == null ? empty : IconButton(
icon: Icon(FontAwesomeIcons.weixin), onPressed:() {
Expand All @@ -56,7 +57,7 @@ class SocialMediaLineItem extends StatelessWidget {
},
iconSize: 36.0, color: Constants.meltonGreenAccent,),
linkedin == null ? empty : IconButton(
icon: Icon(FontAwesomeIcons.linkedin), onPressed:() {_launchURL(linkedin);},
icon: Icon(FontAwesomeIcons.linkedin), onPressed:() {launchSocialMediaUrl(linkedin);},
iconSize: 36.0, color: Constants.meltonBlueAccent,),
others.length == 0 ? empty : IconButton(
icon: Icon(FontAwesomeIcons.globeAmericas, color: Constants.meltonBlueAccent,),
Expand All @@ -83,7 +84,7 @@ class SocialMediaLineItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.stretch,
children: others.map((e) =>
RaisedButton(
onPressed: () {_launchURL(e);},
onPressed: () {launchSocialMediaUrl(e);},
child: Text(e.split("://")[1],
style: TextStyle(
color: Constants.meltonBlueAccent,
Expand All @@ -105,18 +106,4 @@ class SocialMediaLineItem extends StatelessWidget {
);
});
}

//todo test on android and ios
_launchURL(String url) async {
if (await canLaunch(url)) {
bool nativeLaunchSuccess = await launch(url, forceSafariVC: false, universalLinksOnly: true);
if (!nativeLaunchSuccess) {
await launch(url, forceSafariVC: false, forceWebView: false);
}
} else {
//todo handle correctly
// show toast notification/snackbar?
print("ERROR: Could not open $url");
}
}
}
2 changes: 2 additions & 0 deletions lib/screens/directory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:melton_app/api/userSearchService.dart';
import 'package:melton_app/constants/constants.dart';
import 'package:melton_app/screens/DirectoryComponents/UserSearch.dart';
import 'package:melton_app/screens/DirectoryComponents/UserSearchFilters.dart';
import 'package:melton_app/screens/DirectoryComponents/UserSearchedString.dart';
import 'package:melton_app/screens/DirectoryComponents/UserSearchStreamBuilder.dart';

class Directory extends StatefulWidget {
Expand All @@ -27,6 +28,7 @@ class _DirectoryState extends State<Directory> {
children: [
UserSearch(searchService: searchService),
UserSearchFilters(),
UserSearchedString(searchService: searchService),
UserSearchStreamBuilder(searchService: searchService),
],
));
Expand Down
8 changes: 5 additions & 3 deletions lib/screens/errors/no_internet.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'package:flutter/material.dart';

import 'package:melton_app/util/text_util.dart';

class NoInternet extends StatelessWidget {
Widget build(BuildContext context) {
return Material(
Expand All @@ -8,9 +10,9 @@ class NoInternet extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Image.asset("assets/errors/error_no_internet.png"),
Text("NO INTERNET", style: TextStyle(fontWeight: FontWeight.bold, color: Colors.black, fontSize: 22),),
Text(""),
Text("Or our server is down...", style: TextStyle(fontWeight: FontWeight.bold),),
BlackTitleText(content: "NO INTERNET"),
BlackSubtitleText(content: ""),
BlackSubtitleText(content: "Or our server is down..."),
],
),
),
Expand Down
16 changes: 16 additions & 0 deletions lib/screens/errors/unknown_error.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:flutter/material.dart';

import 'package:melton_app/util/text_util.dart';

class UnknownError extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
Image.asset("assets/errors/error_unknown.png"),
WhiteTitleText(content: "OOPS! SOMETHING WENT WRONG"),
WhiteSubtitleText(content: "Let us know if this error persists.")
],
);
}
}
1 change: 1 addition & 0 deletions lib/screens/login.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class _LoginScreenState extends State<LoginScreen> {
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Image.asset("assets/errors/welcome_screen.png"),
WelcomeText("WELCOME TO THE MELTON APP!"),
WelcomeText("Let's get started!"),
WelcomeText("Only Melton Fellows can use this app. "),
Expand Down
Loading

0 comments on commit 1fb5051

Please sign in to comment.