Skip to content
This repository has been archived by the owner on Jan 26, 2021. It is now read-only.

Commit

Permalink
Merge branch 'develop' into actions-update
Browse files Browse the repository at this point in the history
  • Loading branch information
bartekpacia authored Jul 9, 2020
2 parents 3d72130 + fc1d19e commit 25976c6
Show file tree
Hide file tree
Showing 26 changed files with 966 additions and 498 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

- You can join us on [AnitaB.org Open Source Zulip](https://anitab-org.zulipchat.com/). Each active repo has its own stream to direct questions to (for example #powerup or #portal). Mentorship System stream is [#mentorship-system](https://anitab-org.zulipchat.com/#narrow/stream/222534-mentorship-system).
- Remember that this is an inclusive community, committed to creating a safe, positive environment. See the full [Code of Conduct](code_of_conduct.md).
- Follow our [Commit Message Style Guide](https://github.com/anitab-org/mentorship-android/wiki/Commit-Message-Style-Guide) when you commit your changes.
- Follow our [Commit Message Style Guide](https://github.com/anitab-org/mentorship-flutter/wiki/Commit-Message-Style-Guide) when you commit your changes.
- Please consider raising an issue before submitting a pull request (PR) to solve a problem that is not present in our [issue tracker](https://github.com/anitab-org/mentorship-flutter/issues). This allows maintainers to first validate the issue you are trying to solve and also reference the PR to a specific issue.
- When developing a new feature, include at least one test when applicable.
- When submitting a PR, please follow [this template](.github/PULL_REQUEST_TEMPLATE.md) (which will probably be already filled up once you create the PR).
Expand Down
47 changes: 37 additions & 10 deletions lib/screens/home/home_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,33 @@ import 'package:mentorship_client/screens/home/pages/stats/stats_page.dart';
import 'package:mentorship_client/screens/settings/settings_screen.dart';
import 'package:toast/toast.dart';

import 'pages/members/bloc/members_page_bloc.dart';
import 'pages/members/bloc/members_page_event.dart';
import 'pages/stats/bloc/stats_page_bloc.dart';
import 'pages/stats/bloc/stats_page_event.dart';

/// [HomeScreen] is the main screen in the app. It's what user sees after successfully logging in.
/// HomeScreen's main task is to have scaffold with AppBar and BottomNavBar. Content (i.e body)
/// is provided by one of 5 Pages - [StatsPage], [ProfilePage], [RelationPage], [MembersPage] and [RequestsPage].
/// HomeScreen manages displaying of these pages using BottomNavBar and PageView.
class HomeScreen extends StatelessWidget {
final pageController = PageController();
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
final pageController = PageController();
int _currentIndex = 0;
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
// I think its too high in the widget tree, but I couldn't find a better solution

BlocProvider<ProfilePageBloc>(
create: (context) => ProfilePageBloc(userRepository: UserRepository.instance),
create: (context) =>
ProfilePageBloc(userRepository: UserRepository.instance)..add(ProfilePageShowed()),
child: ProfilePage(),
),
BlocProvider<HomeBloc>(
create: (context) => HomeBloc(),
Expand All @@ -38,12 +51,26 @@ class HomeScreen extends StatelessWidget {
create: (context) => RelationPageBloc(
relationRepository: RelationRepository.instance,
taskRepository: TaskRepository.instance,
),
)..add(RelationPageShowed()),
child: RelationPage(),
),
BlocProvider<RequestsPageBloc>(
create: (context) => RequestsPageBloc(
relationRepository: RelationRepository.instance,
),
)..add(RequestsPageShowed()),
child: RequestsPage(),
),

BlocProvider<StatsPageBloc>(
create: (context) => StatsPageBloc(userRepository: UserRepository.instance)
..add(
StatsPageShowed(),
),
),
BlocProvider<MembersPageBloc>(
create: (context) =>
MembersPageBloc(userRepository: UserRepository.instance)..add(MembersPageShowed()),
child: MembersPage(),
),
],
child: BlocListener<HomeBloc, HomeState>(
Expand Down Expand Up @@ -84,11 +111,11 @@ class HomeScreen extends StatelessWidget {
],
),
bottomNavigationBar: BottomNavyBar(
showElevation: false,
onItemSelected:
(index) => // This triggers when the user clicks item on BottomNavyBar
BlocProvider.of<HomeBloc>(context).add(HomeEvent.fromIndex(index)),
selectedIndex: state.index,
selectedIndex: _currentIndex,
onItemSelected: (index) {
setState(() => _currentIndex = index);
pageController.jumpToPage(index);
},
items: [
BottomNavyBarItem(
icon: Icon(Icons.home),
Expand Down
26 changes: 24 additions & 2 deletions lib/screens/home/pages/members/bloc/members_page_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,19 @@ class MembersPageBloc extends Bloc<MembersPageEvent, MembersPageState> {
final UserRepository userRepository;
int pageNumber = 1;
MembersPageBloc({@required this.userRepository}) : assert(userRepository != null);
//TODO: debounce the Events in order to prevent spamming our API
@override
MembersPageState get initialState => MembersPageInitial();

@override
Stream<MembersPageState> mapEventToState(MembersPageEvent event) async* {
if (event is MembersPageShowed) {
yield* _mapEventToMembersShowed(event);
} else if (event is MembersPageRefresh) {
yield* _mapEventToMembersRefresh(event);
}
}

Stream<MembersPageState> _mapEventToMembersShowed(MembersPageEvent event) async* {
final currentState = state;

if (event is MembersPageShowed && !_hasReachedMax(currentState)) {
Expand All @@ -39,11 +46,26 @@ class MembersPageBloc extends Bloc<MembersPageEvent, MembersPageState> {
);
}
} on Failure catch (failure) {
Logger.root.severe(failure.message);
Logger.root.severe("MembersPageBloc: Failure catched: $failure.message");
yield MembersPageFailure(failure.message);
}
}
}

Stream<MembersPageState> _mapEventToMembersRefresh(MembersPageEvent event) async* {
final currentState = state;

if (event is MembersPageRefresh && !_hasReachedMax(currentState)) {
try {
yield MembersPageLoading();
final List<User> users = await userRepository.getVerifiedUsers(pageNumber);
yield MembersPageSuccess(users: users, hasReachedMax: false);
} on Failure catch (failure) {
Logger.root.severe("MembersPageBloc: Failure catched: $failure.message");
yield state;
}
}
}
}

bool _hasReachedMax(MembersPageState state) => state is MembersPageSuccess && state.hasReachedMax;
2 changes: 2 additions & 0 deletions lib/screens/home/pages/members/bloc/members_page_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ abstract class MembersPageEvent extends Equatable {
}

class MembersPageShowed extends MembersPageEvent {}

class MembersPageRefresh extends MembersPageEvent {}
92 changes: 50 additions & 42 deletions lib/screens/home/pages/members/members_page.dart
Original file line number Diff line number Diff line change
@@ -1,74 +1,82 @@
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:mentorship_client/remote/models/user.dart';
import 'package:mentorship_client/remote/repositories/user_repository.dart';
import 'package:mentorship_client/screens/home/pages/members/bloc/bloc.dart';
import 'package:mentorship_client/screens/home/pages/members/widgets/member_list_tile.dart';
import 'package:mentorship_client/screens/member_profile/member_profile.dart';

class MembersPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider<MembersPageBloc>(
create: (context) =>
MembersPageBloc(userRepository: UserRepository.instance)..add(MembersPageShowed()),
child: _MembersPage());
}
}

class _MembersPage extends StatefulWidget {
class MembersPage extends StatefulWidget {
@override
_MembersPageState createState() => _MembersPageState();
}

class _MembersPageState extends State<_MembersPage> {
class _MembersPageState extends State<MembersPage> {
final _scrollController = ScrollController();
// ignore: dart.core.Sink
MembersPageBloc _membersPageBloc;
final _scrollThreshold = 10.0;
Completer<void> _refreshCompleter;

@override
void initState() {
super.initState();
_scrollController.addListener(_onScroll);
_membersPageBloc = BlocProvider.of<MembersPageBloc>(context);
_refreshCompleter = Completer<void>();
}

@override
Widget build(BuildContext context) {
return BlocBuilder<MembersPageBloc, MembersPageState>(
builder: (context, state) {
if (state is MembersPageFailure) {
return Center(
child: Text('failed to get users'),
);
}
if (state is MembersPageSuccess) {
if (state.users.isEmpty) {
return BlocConsumer<MembersPageBloc, MembersPageState>(listener: (context, state) {
if (state is MembersPageShowed) {
_refreshCompleter?.complete();
_refreshCompleter = Completer();
}
}, builder: (context, state) {
return BlocBuilder<MembersPageBloc, MembersPageState>(
builder: (context, state) {
if (state is MembersPageFailure) {
return Center(
child: Text('no users'),
child: Text('Failed to get users'),
);
}
if (state is MembersPageSuccess) {
if (state.users.isEmpty) {
return Center(
child: Text('No users'),
);
}
return RefreshIndicator(
onRefresh: () {
BlocProvider.of<MembersPageBloc>(context).add(
MembersPageRefresh(),
);
return _refreshCompleter.future;
},
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
bool _reachedEnd = index > state.users.length - 1;
User user = (!_reachedEnd) ? state.users[index] : null;
return _reachedEnd
? BottomLoader()
: InkWell(
onTap: () => _openMemberProfileScreen(context, user),
child: MemberListTile(user: user),
);
},
itemCount: state.hasReachedMax ? (state.users.length) : (state.users.length + 1),
controller: _scrollController,
),
);
}
return ListView.builder(
itemBuilder: (BuildContext context, int index) {
bool _reachedEnd = index > state.users.length - 1;
User user = (!_reachedEnd) ? state.users[index] : null;
return _reachedEnd
? BottomLoader()
: InkWell(
onTap: () => _openMemberProfileScreen(context, user),
child: MemberListTile(user: user),
);
},
itemCount: state.hasReachedMax ? (state.users.length) : (state.users.length + 1),
controller: _scrollController,
return Center(
child: CircularProgressIndicator(),
);
}
return Center(
child: CircularProgressIndicator(),
);
},
);
},
);
});
}

void _openMemberProfileScreen(BuildContext context, User user) {
Expand Down
30 changes: 28 additions & 2 deletions lib/screens/home/pages/profile/bloc/profile_page_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,42 @@ class ProfilePageBloc extends Bloc<ProfilePageEvent, ProfilePageState> {

@override
Stream<ProfilePageState> mapEventToState(ProfilePageEvent event) async* {
if (event is ProfilePageShowed) {
yield* mapEventToProfileShowed(event);
} else if (event is ProfilePageRefresh) {
yield* mapEventToRefreshRequested(event);
} else {
yield* mapEventToProfileEditing(event);
}
}

Stream<ProfilePageState> mapEventToProfileShowed(ProfilePageEvent event) async* {
if (event is ProfilePageShowed) {
yield ProfilePageLoading();
try {
_user = await userRepository.getCurrentUser();
yield ProfilePageSuccess(_user, message: event.message);
} on Failure catch (failure) {
Logger.root.severe(failure.message);
Logger.root.severe("ProfilePageBloc: Failure catched: $failure.message");
yield ProfilePageFailure(message: failure.message);
}
}
}

Stream<ProfilePageState> mapEventToRefreshRequested(ProfilePageEvent event) async* {
if (event is ProfilePageRefresh) {
yield ProfilePageLoading();
try {
_user = await userRepository.getCurrentUser();
yield ProfilePageSuccess(_user, message: event.message);
} on Failure catch (failure) {
Logger.root.severe("ProfilePageBloc: Failure catched: $failure.message");
yield state;
}
}
}

Stream<ProfilePageState> mapEventToProfileEditing(ProfilePageEvent event) async* {
if (event is ProfilePageEditStarted) {
yield ProfilePageEditing(_user);
}
Expand All @@ -54,7 +80,7 @@ class ProfilePageBloc extends Bloc<ProfilePageEvent, ProfilePageState> {
CustomResponse response = await userRepository.updateUser(updatedUser);
add(ProfilePageShowed(message: response.message));
} on Failure catch (failure) {
Logger.root.severe(failure.message);
Logger.root.severe("ProfilePageBloc: Failure catched: $failure.message");
add(ProfilePageShowed(message: failure.message));
}
}
Expand Down
6 changes: 6 additions & 0 deletions lib/screens/home/pages/profile/bloc/profile_page_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ class ProfilePageShowed extends ProfilePageEvent {
ProfilePageShowed({this.message});
}

class ProfilePageRefresh extends ProfilePageEvent {
final String message;

ProfilePageRefresh({this.message});
}

class ProfilePageEditStarted extends ProfilePageEvent {}

class ProfilePageEditSubmitted extends ProfilePageEvent {
Expand Down
Loading

0 comments on commit 25976c6

Please sign in to comment.