From 4c51f581c75920cabc220fcf0aa6d25c54efbb54 Mon Sep 17 00:00:00 2001 From: linhngo Date: Fri, 6 Dec 2019 16:32:17 +0700 Subject: [PATCH 1/6] Refactor user setting --- lib/common/auth0/auth.dart | 5 + lib/core/domain/base_entity.dart | 15 +++ lib/core/error/exception.dart | 1 + lib/core/usecase/usecase.dart | 10 ++ lib/features/app/app.dart | 11 +- lib/features/main/main_screen.dart | 2 +- .../user_setting/data/models/user_model.dart | 55 +++++++++ .../data/models/user_model.g.dart | 89 +++++++++++++++ .../user_setting_repository_impl.dart | 15 +++ .../data/user_setting_data_source.dart | 45 ++++++++ .../user_setting/domain/entities/user.dart | 63 +++++++++++ .../repositories/user_setting_repository.dart | 7 ++ .../domain/usecases/get_current_user.dart | 18 +++ .../domain/usecases/update_user.dart | 12 ++ lib/features/user_setting/more/bloc/bloc.dart | 3 - .../user_setting/more/bloc/more_bloc.dart | 53 --------- .../user_setting/more/bloc/more_event.dart | 33 ------ .../user_setting/more/bloc/more_state.dart | 10 -- lib/features/user_setting/more/more_tab.dart | 105 ------------------ .../user_setting/nickname/bloc/bloc.dart | 3 - .../nickname/bloc/nickname_bloc.dart | 28 ----- .../nickname/bloc/nickname_event.dart | 18 --- .../nickname/bloc/nickname_state.dart | 12 -- .../user_setting/presentations/bloc/bloc.dart | 3 + .../presentations/bloc/user_setting_bloc.dart | 56 ++++++++++ .../bloc/user_setting_event.dart | 54 +++++++++ .../bloc/user_setting_state.dart | 10 ++ .../presentations/pages/more_tab.dart | 101 +++++++++++++++++ .../pages}/nickname_screen.dart | 31 ++---- .../pages}/user_needs_screen.dart | 6 +- .../widgets}/needs_button.dart | 0 .../widgets}/setting_option_button.dart | 0 lib/injection_container.dart | 65 +++++++++++ lib/main.dart | 40 ++++--- pubspec.lock | 19 +++- pubspec.yaml | 11 +- 36 files changed, 683 insertions(+), 326 deletions(-) create mode 100644 lib/core/domain/base_entity.dart create mode 100644 lib/core/error/exception.dart create mode 100644 lib/core/usecase/usecase.dart create mode 100644 lib/features/user_setting/data/models/user_model.dart create mode 100644 lib/features/user_setting/data/models/user_model.g.dart create mode 100644 lib/features/user_setting/data/repositories/user_setting_repository_impl.dart create mode 100644 lib/features/user_setting/data/user_setting_data_source.dart create mode 100644 lib/features/user_setting/domain/entities/user.dart create mode 100644 lib/features/user_setting/domain/repositories/user_setting_repository.dart create mode 100644 lib/features/user_setting/domain/usecases/get_current_user.dart create mode 100644 lib/features/user_setting/domain/usecases/update_user.dart delete mode 100644 lib/features/user_setting/more/bloc/bloc.dart delete mode 100644 lib/features/user_setting/more/bloc/more_bloc.dart delete mode 100644 lib/features/user_setting/more/bloc/more_event.dart delete mode 100644 lib/features/user_setting/more/bloc/more_state.dart delete mode 100644 lib/features/user_setting/more/more_tab.dart delete mode 100644 lib/features/user_setting/nickname/bloc/bloc.dart delete mode 100644 lib/features/user_setting/nickname/bloc/nickname_bloc.dart delete mode 100644 lib/features/user_setting/nickname/bloc/nickname_event.dart delete mode 100644 lib/features/user_setting/nickname/bloc/nickname_state.dart create mode 100644 lib/features/user_setting/presentations/bloc/bloc.dart create mode 100644 lib/features/user_setting/presentations/bloc/user_setting_bloc.dart create mode 100644 lib/features/user_setting/presentations/bloc/user_setting_event.dart create mode 100644 lib/features/user_setting/presentations/bloc/user_setting_state.dart create mode 100644 lib/features/user_setting/presentations/pages/more_tab.dart rename lib/features/user_setting/{nickname => presentations/pages}/nickname_screen.dart (74%) rename lib/features/user_setting/{user_needs => presentations/pages}/user_needs_screen.dart (97%) rename lib/features/user_setting/{user_needs/components => presentations/widgets}/needs_button.dart (100%) rename lib/features/user_setting/{more => presentations/widgets}/setting_option_button.dart (100%) create mode 100644 lib/injection_container.dart diff --git a/lib/common/auth0/auth.dart b/lib/common/auth0/auth.dart index fe8ba47..267f45e 100644 --- a/lib/common/auth0/auth.dart +++ b/lib/common/auth0/auth.dart @@ -123,4 +123,9 @@ class Auth { static Future messageBackground(Map message) async { log(message.toString(), name: 'Backgroud Message'); } + + static Future> currentUserStream() async { + final user = await currentUser(); + return UserDao.userStream(user.id); + } } diff --git a/lib/core/domain/base_entity.dart b/lib/core/domain/base_entity.dart new file mode 100644 index 0000000..04e5814 --- /dev/null +++ b/lib/core/domain/base_entity.dart @@ -0,0 +1,15 @@ +import 'package:equatable/equatable.dart'; +import 'package:meta/meta.dart'; + +class BaseEntity extends Equatable { + final String id; + final DateTime created; + final DateTime updated; + + BaseEntity( + {@required this.id, @required this.created, @required this.updated}) + : assert(id != null && created != null && updated != null); + + @override + List get props => [id, created, updated]; +} diff --git a/lib/core/error/exception.dart b/lib/core/error/exception.dart new file mode 100644 index 0000000..b333f57 --- /dev/null +++ b/lib/core/error/exception.dart @@ -0,0 +1 @@ +class DatabaseException implements Exception {} diff --git a/lib/core/usecase/usecase.dart b/lib/core/usecase/usecase.dart new file mode 100644 index 0000000..efd37d4 --- /dev/null +++ b/lib/core/usecase/usecase.dart @@ -0,0 +1,10 @@ +import 'package:equatable/equatable.dart'; + +abstract class UseCase { + Future call(Params param); +} + +class NoParams extends Equatable { + @override + List get props => []; +} diff --git a/lib/features/app/app.dart b/lib/features/app/app.dart index 9ee7401..2ac8aca 100644 --- a/lib/features/app/app.dart +++ b/lib/features/app/app.dart @@ -5,8 +5,8 @@ import 'package:better_help/common/auth0/auth.dart'; import 'package:better_help/common/screens.dart'; import 'package:better_help/features/auth0/ui/welcome_screen.dart'; import 'package:better_help/features/main/main_screen.dart'; -import 'package:better_help/features/user_setting/nickname/nickname_screen.dart'; -import 'package:better_help/features/user_setting/user_needs/user_needs_screen.dart'; +import 'package:better_help/features/user_setting/presentations/pages/nickname_screen.dart'; +import 'package:better_help/features/user_setting/presentations/pages/user_needs_screen.dart'; import 'package:better_help/generated/i18n.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -53,19 +53,12 @@ class _AppState extends State with WidgetsBindingObserver { @override void dispose() { WidgetsBinding.instance.removeObserver(this); - appBloc.close(); super.dispose(); } @override Widget build(BuildContext context) { return CupertinoApp( - theme: CupertinoThemeData( - primaryColor: Color(0xff54bd98), - brightness: Brightness.light, - primaryContrastingColor: Colors.white, - scaffoldBackgroundColor: Colors.white, - ), debugShowCheckedModeBanner: false, onGenerateTitle: (BuildContext context) => S.of(context).app_name, localizationsDelegates: const [ diff --git a/lib/features/main/main_screen.dart b/lib/features/main/main_screen.dart index 7be240b..10c9e6d 100644 --- a/lib/features/main/main_screen.dart +++ b/lib/features/main/main_screen.dart @@ -8,7 +8,7 @@ import 'package:better_help/features/app/components/notification.dart'; import 'package:better_help/features/main/sharing_tab.dart'; import 'package:better_help/features/message/message_group_list/message_tab.dart'; import 'package:better_help/features/need_help/need_help_tab.dart'; -import 'package:better_help/features/user_setting/more/more_tab.dart'; +import 'package:better_help/features/user_setting/presentations/pages/more_tab.dart'; import 'package:better_help/generated/i18n.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; diff --git a/lib/features/user_setting/data/models/user_model.dart b/lib/features/user_setting/data/models/user_model.dart new file mode 100644 index 0000000..5c6c223 --- /dev/null +++ b/lib/features/user_setting/data/models/user_model.dart @@ -0,0 +1,55 @@ +import 'package:better_help/features/user_setting/domain/entities/user.dart'; +import 'package:better_help/generated/i18n.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter/widgets.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:meta/meta.dart'; +import 'package:uuid/uuid.dart'; + +part 'user_model.g.dart'; + +@JsonSerializable() +class UserModel extends User { + UserModel( + {String id, + DateTime created, + DateTime updated, + @required String displayName, + @required String email, + String phoneNumber, + @required String photoUrl, + List types = const [UserType.NORMAL], + List friendIds = const [], + List tokens = const [], + UserNeeds needs, + bool online = false}) + : super( + id: id ?? Uuid().v1(), + created: created ?? DateTime.now(), + updated: updated ?? DateTime.now(), + displayName: displayName, + email: email, + phoneNumber: phoneNumber, + photoUrl: photoUrl, + tokens: tokens, + types: types, + needs: needs, + friendIds: friendIds, + online: online); + + factory UserModel.fromJson(Map json) => + _$UserModelFromJson(json); + + Map toJson() => _$UserModelToJson(this); +} + +Map userNeedsOptionMapString(BuildContext context) => { + UserNeeds.TEENAGE: S.of(context).option_family, + UserNeeds.FAMILY: S.of(context).option_family, + UserNeeds.LOVE: S.of(context).option_love, + UserNeeds.GO_AHEAD: S.of(context).option_go_a_head, + }; + +String userNeedsDescription(BuildContext context, UserNeeds needs) => + S.of(context).need_help_description( + userNeedsOptionMapString(context)[needs].toLowerCase()); diff --git a/lib/features/user_setting/data/models/user_model.g.dart b/lib/features/user_setting/data/models/user_model.g.dart new file mode 100644 index 0000000..d701d32 --- /dev/null +++ b/lib/features/user_setting/data/models/user_model.g.dart @@ -0,0 +1,89 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UserModel _$UserModelFromJson(Map json) { + return UserModel( + id: json['id'] as String, + created: json['created'] == null + ? null + : (json['created'] as Timestamp).toDate(), + updated: json['updated'] == null + ? null + : (json['updated'] as Timestamp).toDate(), + displayName: json['displayName'] as String, + email: json['email'] as String, + phoneNumber: json['phoneNumber'] as String, + photoUrl: json['photoUrl'] as String, + types: (json['types'] as List) + ?.map((e) => _$enumDecodeNullable(_$UserTypeEnumMap, e)) + ?.toList(), + friendIds: (json['friendIds'] as List)?.map((e) => e as String)?.toList(), + tokens: (json['tokens'] as List)?.map((e) => e as String)?.toList(), + needs: _$enumDecodeNullable(_$UserNeedsEnumMap, json['needs']), + online: json['online'] as bool, + ); +} + +Map _$UserModelToJson(UserModel instance) => { + 'id': instance.id, + 'created': instance.created?.toUtc(), + 'updated': instance.updated?.toUtc(), + 'displayName': instance.displayName, + 'email': instance.email, + 'phoneNumber': instance.phoneNumber, + 'photoUrl': instance.photoUrl, + 'types': instance.types?.map((e) => _$UserTypeEnumMap[e])?.toList(), + 'friendIds': instance.friendIds, + 'tokens': instance.tokens, + 'needs': _$UserNeedsEnumMap[instance.needs], + 'online': instance.online, + }; + +T _$enumDecode( + Map enumValues, + dynamic source, { + T unknownValue, +}) { + if (source == null) { + throw ArgumentError('A value must be provided. Supported values: ' + '${enumValues.values.join(', ')}'); + } + + final value = enumValues.entries + .singleWhere((e) => e.value == source, orElse: () => null) + ?.key; + + if (value == null && unknownValue == null) { + throw ArgumentError('`$source` is not one of the supported values: ' + '${enumValues.values.join(', ')}'); + } + return value ?? unknownValue; +} + +T _$enumDecodeNullable( + Map enumValues, + dynamic source, { + T unknownValue, +}) { + if (source == null) { + return null; + } + return _$enumDecode(enumValues, source, unknownValue: unknownValue); +} + +const _$UserTypeEnumMap = { + UserType.NORMAL: 'NORMAL', + UserType.VOLUNTEER: 'VOLUNTEER', +}; + +const _$UserNeedsEnumMap = { + UserNeeds.TEENAGE: 'TEENAGE', + UserNeeds.FAMILY: 'FAMILY', + UserNeeds.LOVE: 'LOVE', + UserNeeds.GO_AHEAD: 'GO_AHEAD', +}; diff --git a/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart b/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart new file mode 100644 index 0000000..80b5221 --- /dev/null +++ b/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart @@ -0,0 +1,15 @@ +import 'package:better_help/features/user_setting/data/user_setting_data_source.dart'; +import 'package:better_help/features/user_setting/domain/entities/user.dart'; +import 'package:better_help/features/user_setting/domain/repositories/user_setting_repository.dart'; + +class UserSettingRepositoryImpl implements UserSettingRepository { + final UserSettingDataSource _dataSource; + + UserSettingRepositoryImpl(this._dataSource); + + @override + Future updateUser(User user) => _dataSource.updateUser(user); + + @override + Future getUser(String id) => _dataSource.getUser(id); +} diff --git a/lib/features/user_setting/data/user_setting_data_source.dart b/lib/features/user_setting/data/user_setting_data_source.dart new file mode 100644 index 0000000..047d93b --- /dev/null +++ b/lib/features/user_setting/data/user_setting_data_source.dart @@ -0,0 +1,45 @@ +import 'dart:async'; + +import 'package:better_help/core/error/exception.dart'; +import 'package:better_help/features/user_setting/data/models/user_model.dart'; +import 'package:better_help/features/user_setting/domain/entities/user.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; + +abstract class UserSettingDataSource { + Stream getUserStream(String id); + + Future updateUser(User user); + + Future getUser(String id); +} + +class UserSettingDataSourceImpl implements UserSettingDataSource { + final Firestore _firestore; + + UserSettingDataSourceImpl(this._firestore); + + CollectionReference get _userCollection => _firestore.collection('users'); + + StreamTransformer get toUser => + StreamTransformer.fromHandlers( + handleData: (data, sink) => sink.add(UserModel.fromJson(data.data)), + ); + + @override + Future updateUser(User user) => + _userCollection.document(user.id).setData((user as UserModel).toJson()); + + @override + Stream getUserStream(String id) => + _userCollection.document(id).snapshots().transform(toUser); + + @override + Future getUser(String id) async { + final doc = await _userCollection.document(id).get(); + if (doc.exists) { + return UserModel.fromJson(doc.data); + } else { + throw DatabaseException(); + } + } +} diff --git a/lib/features/user_setting/domain/entities/user.dart b/lib/features/user_setting/domain/entities/user.dart new file mode 100644 index 0000000..c34dd3b --- /dev/null +++ b/lib/features/user_setting/domain/entities/user.dart @@ -0,0 +1,63 @@ +import 'package:better_help/core/domain/base_entity.dart'; +import 'package:flutter/cupertino.dart'; + +enum UserType { NORMAL, VOLUNTEER } + +enum UserNeeds { TEENAGE, FAMILY, LOVE, GO_AHEAD } + +class User extends BaseEntity { + final String displayName; + final String email; + final String phoneNumber; + final String photoUrl; + final List types; + final List friendIds; + final List tokens; + final UserNeeds needs; + final bool online; + + User( + {@required String id, + @required DateTime created, + @required DateTime updated, + @required this.displayName, + @required this.email, + this.phoneNumber, + @required this.photoUrl, + @required this.types, + @required this.friendIds, + @required this.tokens, + this.needs, + @required this.online}) + : super(id: id, created: created, updated: updated); + + User copyWith({ + String id, + DateTime created, + DateTime updated, + String displayName, + String email, + String phoneNumber, + String photoUrl, + List types, + List friendIds, + List tokens, + UserNeeds needs, + bool online, + }) { + return User( + id: id ?? this.id, + created: created ?? this.created, + updated: updated ?? this.updated, + displayName: displayName ?? this.displayName, + email: email ?? this.email, + phoneNumber: phoneNumber ?? this.phoneNumber, + photoUrl: photoUrl ?? this.photoUrl, + types: types ?? this.types, + tokens: tokens ?? this.tokens, + needs: needs ?? this.needs, + online: online ?? this.online, + friendIds: friendIds ?? this.friendIds, + ); + } +} diff --git a/lib/features/user_setting/domain/repositories/user_setting_repository.dart b/lib/features/user_setting/domain/repositories/user_setting_repository.dart new file mode 100644 index 0000000..78a1415 --- /dev/null +++ b/lib/features/user_setting/domain/repositories/user_setting_repository.dart @@ -0,0 +1,7 @@ +import 'package:better_help/features/user_setting/domain/entities/user.dart'; + +abstract class UserSettingRepository { + Future getUser(String id); + + Future updateUser(User user); +} diff --git a/lib/features/user_setting/domain/usecases/get_current_user.dart b/lib/features/user_setting/domain/usecases/get_current_user.dart new file mode 100644 index 0000000..de578b9 --- /dev/null +++ b/lib/features/user_setting/domain/usecases/get_current_user.dart @@ -0,0 +1,18 @@ +import 'package:better_help/core/usecase/usecase.dart'; +import 'package:better_help/features/user_setting/domain/entities/user.dart'; +import 'package:better_help/features/user_setting/domain/repositories/user_setting_repository.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:meta/meta.dart'; + +class GetCurrentUser implements UseCase { + final UserSettingRepository repository; + final FirebaseAuth firebaseAuth; + + GetCurrentUser({@required this.firebaseAuth, @required this.repository}); + + @override + Future call(NoParams param) async { + final fUser = await firebaseAuth.currentUser(); + return repository.getUser(fUser.uid); + } +} diff --git a/lib/features/user_setting/domain/usecases/update_user.dart b/lib/features/user_setting/domain/usecases/update_user.dart new file mode 100644 index 0000000..fbbf092 --- /dev/null +++ b/lib/features/user_setting/domain/usecases/update_user.dart @@ -0,0 +1,12 @@ +import 'package:better_help/core/usecase/usecase.dart'; +import 'package:better_help/features/user_setting/domain/entities/user.dart'; +import 'package:better_help/features/user_setting/domain/repositories/user_setting_repository.dart'; + +class UpdateUser implements UseCase { + final UserSettingRepository repository; + + UpdateUser(this.repository); + + @override + Future call(User user) => repository.updateUser(user); +} diff --git a/lib/features/user_setting/more/bloc/bloc.dart b/lib/features/user_setting/more/bloc/bloc.dart deleted file mode 100644 index fb53efe..0000000 --- a/lib/features/user_setting/more/bloc/bloc.dart +++ /dev/null @@ -1,3 +0,0 @@ -export 'more_bloc.dart'; -export 'more_event.dart'; -export 'more_state.dart'; diff --git a/lib/features/user_setting/more/bloc/more_bloc.dart b/lib/features/user_setting/more/bloc/more_bloc.dart deleted file mode 100644 index cfbf5ee..0000000 --- a/lib/features/user_setting/more/bloc/more_bloc.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'dart:async'; - -import 'package:better_help/common/auth0/auth.dart'; -import 'package:better_help/common/data/dao/user_dao.dart'; -import 'package:better_help/common/data/models/user.dart'; -import 'package:better_help/common/route/route.dart'; -import 'package:bloc/bloc.dart'; -import 'package:rxdart/rxdart.dart'; - -import './bloc.dart'; - -class MoreBloc extends Bloc { - - final _userController = BehaviorSubject(); - - User get user => _userController.value; - - Stream get userStream => _userController.stream; - - Function get changeUser => _userController.add; - - StreamSubscription _firebaseUserSubscription; - - MoreBloc() { - Auth.currentUser().then((user) { - if (user != null) { - UserDao.userStream(user.id).pipe(_userController); - } - }); - } - - @override - Future close() async { - super.close(); - _userController.close(); - _firebaseUserSubscription.cancel(); - } - - @override - MoreState get initialState => InitialMoreState(); - - @override - Stream mapEventToState(MoreEvent event,) async* { - if (event is SignOutEvent) { - Auth.signOut(); - goToWelcomeScreen(event.context); - } else if (event is ChangeNicknameEvent) { - goToNicknameScreen(event.context); - } else if (event is ChangeUserNeedsEvent) { - goToUserNeedsScreen(event.context); - } - } -} diff --git a/lib/features/user_setting/more/bloc/more_event.dart b/lib/features/user_setting/more/bloc/more_event.dart deleted file mode 100644 index 9cadd11..0000000 --- a/lib/features/user_setting/more/bloc/more_event.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:equatable/equatable.dart'; -import 'package:flutter/widgets.dart'; - -abstract class MoreEvent extends Equatable { - const MoreEvent(); -} - -class SignOutEvent extends MoreEvent { - final BuildContext context; - - SignOutEvent(this.context); - - @override - List get props => null; -} - -class ChangeUserNeedsEvent extends MoreEvent { - final BuildContext context; - - ChangeUserNeedsEvent(this.context); - - @override - List get props => null; -} - -class ChangeNicknameEvent extends MoreEvent { - final BuildContext context; - - ChangeNicknameEvent(this.context); - - @override - List get props => null; -} diff --git a/lib/features/user_setting/more/bloc/more_state.dart b/lib/features/user_setting/more/bloc/more_state.dart deleted file mode 100644 index 8784e4d..0000000 --- a/lib/features/user_setting/more/bloc/more_state.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'package:equatable/equatable.dart'; - -abstract class MoreState extends Equatable { - const MoreState(); -} - -class InitialMoreState extends MoreState { - @override - List get props => []; -} diff --git a/lib/features/user_setting/more/more_tab.dart b/lib/features/user_setting/more/more_tab.dart deleted file mode 100644 index 42a7fcb..0000000 --- a/lib/features/user_setting/more/more_tab.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'package:better_help/common/data/models/user.dart'; -import 'package:better_help/common/dimens.dart'; -import 'package:better_help/common/ui/screen_title.dart'; -import 'package:better_help/common/utils/time_utils.dart'; -import 'package:better_help/features/user_setting/more/bloc/bloc.dart'; -import 'package:better_help/features/user_setting/more/setting_option_button.dart'; -import 'package:better_help/generated/i18n.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; - -class MoreTab extends StatefulWidget { - @override - _MoreTabState createState() => _MoreTabState(); -} - -class _MoreTabState extends State { - final moreBloc = MoreBloc(); - - @override - void initState() { - super.initState(); - } - - @override - void dispose() { - super.dispose(); - moreBloc.close(); - } - - @override - Widget build(BuildContext context) { - final screenUtil = ScreenUtil.getInstance(); - - return SafeArea( - child: Container( - child: StreamBuilder( - stream: moreBloc.userStream, - builder: (context, snapshot) { - if (snapshot.hasError) { - return Center( - child: Text('Something went wrong. ${snapshot.error}'), - ); - } - - return SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: screenUtil.setHeight(Dimens.top_space), - ), - Center( - child: ScreenTitle( - title: S.of(context).more_greeting( - getAHaftDayName(context), - snapshot.hasData - ? snapshot.data.displayName - : S.of(context).you), - ), - ), - SizedBox( - height: screenUtil.setHeight(Dimens.large_space), - ), - _optionList(), - ], - ), - ); - }), - ), - ); - } - - Widget _optionList() { - final screenUtil = ScreenUtil.getInstance(); - - return Container( - child: Column( - children: [ - SettingOptionButton( - name: S.of(context).more_change_nickname, - onPress: () => moreBloc.add(ChangeNicknameEvent(context)), - ), - SettingOptionButton( - name: S.of(context).more_change_status, - onPress: () => moreBloc.add(ChangeUserNeedsEvent(context)), - ), - SizedBox( - height: screenUtil.setHeight(Dimens.xlarge_space), - ), - SettingOptionButton( - name: S.of(context).more_share_app, - ), - SizedBox( - height: screenUtil.setHeight(Dimens.xlarge_space), - ), - SettingOptionButton( - name: S.of(context).more_sign_out, - onPress: () => moreBloc.add(SignOutEvent(context)), - ), - ], - ), - ); - } -} diff --git a/lib/features/user_setting/nickname/bloc/bloc.dart b/lib/features/user_setting/nickname/bloc/bloc.dart deleted file mode 100644 index c7957db..0000000 --- a/lib/features/user_setting/nickname/bloc/bloc.dart +++ /dev/null @@ -1,3 +0,0 @@ -export 'nickname_bloc.dart'; -export 'nickname_event.dart'; -export 'nickname_state.dart'; diff --git a/lib/features/user_setting/nickname/bloc/nickname_bloc.dart b/lib/features/user_setting/nickname/bloc/nickname_bloc.dart deleted file mode 100644 index 020addb..0000000 --- a/lib/features/user_setting/nickname/bloc/nickname_bloc.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'dart:async'; - -import 'package:better_help/common/auth0/auth.dart'; -import 'package:better_help/common/data/dao/user_dao.dart'; -import 'package:better_help/common/data/models/user.dart'; -import 'package:better_help/common/route/route.dart'; -import 'package:bloc/bloc.dart'; - -import './bloc.dart'; - -class NicknameBloc extends Bloc { - @override - NicknameState get initialState => InitialNicknameState(); - - @override - Stream mapEventToState(NicknameEvent event,) async* { - if (event is SaveNewNickname) { - final user = await Auth.currentUser(); - final json = user.toJson(); - json['displayName'] = event.nickname; - UserDao.updateUser(user: User.fromJson(json)); - final result = backToLastScreen(event.context); - if (!result) { - goToUserNeedsScreen(event.context, deleteAllLastScreen: true); - } - } - } -} diff --git a/lib/features/user_setting/nickname/bloc/nickname_event.dart b/lib/features/user_setting/nickname/bloc/nickname_event.dart deleted file mode 100644 index ec9cb2d..0000000 --- a/lib/features/user_setting/nickname/bloc/nickname_event.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:equatable/equatable.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:meta/meta.dart'; - -@immutable -abstract class NicknameEvent extends Equatable { - const NicknameEvent(); -} - -class SaveNewNickname extends NicknameEvent { - final BuildContext context; - final String nickname; - - SaveNewNickname({@required this.context, @required this.nickname}); - - @override - List get props => [nickname]; -} diff --git a/lib/features/user_setting/nickname/bloc/nickname_state.dart b/lib/features/user_setting/nickname/bloc/nickname_state.dart deleted file mode 100644 index cae09aa..0000000 --- a/lib/features/user_setting/nickname/bloc/nickname_state.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:equatable/equatable.dart'; -import 'package:meta/meta.dart'; - -@immutable -abstract class NicknameState extends Equatable { - const NicknameState(); -} - -class InitialNicknameState extends NicknameState { - @override - List get props => null; -} diff --git a/lib/features/user_setting/presentations/bloc/bloc.dart b/lib/features/user_setting/presentations/bloc/bloc.dart new file mode 100644 index 0000000..963aec3 --- /dev/null +++ b/lib/features/user_setting/presentations/bloc/bloc.dart @@ -0,0 +1,3 @@ +export 'user_setting_bloc.dart'; +export 'user_setting_event.dart'; +export 'user_setting_state.dart'; diff --git a/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart b/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart new file mode 100644 index 0000000..80c910b --- /dev/null +++ b/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart @@ -0,0 +1,56 @@ +import 'dart:async'; + +import 'package:better_help/common/auth0/auth.dart'; +import 'package:better_help/common/route/route.dart'; +import 'package:better_help/core/usecase/usecase.dart'; +import 'package:better_help/features/user_setting/domain/usecases/get_current_user.dart'; +import 'package:better_help/features/user_setting/domain/usecases/update_user.dart'; +import 'package:bloc/bloc.dart'; +import 'package:meta/meta.dart'; + +import './bloc.dart'; + +class UserSettingBloc extends Bloc { + final UpdateUser updateUser; + final GetCurrentUser getCurrentUser; + + UserSettingBloc({ + @required this.getCurrentUser, + @required this.updateUser, + }); + + @override + UserSettingState get initialState => InitialUserSettingState(); + + @override + Stream mapEventToState( + UserSettingEvent event, + ) async* { + if (event is SignOut) { + Auth.signOut(); + goToWelcomeScreen(event.context); + } else if (event is PressOnChangeUserNeedsButton) { + goToUserNeedsScreen(event.context); + } else if (event is PressOnChangeNicknameButton) { + goToNicknameScreen(event.context); + } else if (event is SubmitNewNickname) { + final user = (await getCurrentUser(NoParams())) + .copyWith(updated: DateTime.now(), displayName: event.nickname); + updateUser(user); + + final result = backToLastScreen(event.context); + if (!result) { + goToUserNeedsScreen(event.context); + } + } else if (event is PressOnNeedOption) { + final user = (await getCurrentUser(NoParams())) + .copyWith(updated: DateTime.now(), needs: event.userNeeds); + updateUser(user); + + final result = backToLastScreen(event.context); + if (!result) { + goToMainScreen(event.context); + } + } + } +} diff --git a/lib/features/user_setting/presentations/bloc/user_setting_event.dart b/lib/features/user_setting/presentations/bloc/user_setting_event.dart new file mode 100644 index 0000000..6079ae6 --- /dev/null +++ b/lib/features/user_setting/presentations/bloc/user_setting_event.dart @@ -0,0 +1,54 @@ +import 'package:better_help/features/user_setting/domain/entities/user.dart'; +import 'package:equatable/equatable.dart'; +import 'package:flutter/widgets.dart'; + +abstract class UserSettingEvent extends Equatable { + const UserSettingEvent(); +} + +class SignOut extends UserSettingEvent { + final BuildContext context; + + SignOut({@required this.context}); + + @override + List get props => []; +} + +class PressOnChangeUserNeedsButton extends UserSettingEvent { + final BuildContext context; + + PressOnChangeUserNeedsButton({@required this.context}); + + @override + List get props => []; +} + +class PressOnChangeNicknameButton extends UserSettingEvent { + final BuildContext context; + + PressOnChangeNicknameButton({@required this.context}); + + @override + List get props => []; +} + +class SubmitNewNickname extends UserSettingEvent { + final BuildContext context; + final String nickname; + + SubmitNewNickname({@required this.context, @required this.nickname}); + + @override + List get props => [nickname]; +} + +class PressOnNeedOption extends UserSettingEvent { + final BuildContext context; + final UserNeeds userNeeds; + + PressOnNeedOption({@required this.context, @required this.userNeeds}); + + @override + List get props => []; +} diff --git a/lib/features/user_setting/presentations/bloc/user_setting_state.dart b/lib/features/user_setting/presentations/bloc/user_setting_state.dart new file mode 100644 index 0000000..e0b9e1c --- /dev/null +++ b/lib/features/user_setting/presentations/bloc/user_setting_state.dart @@ -0,0 +1,10 @@ +import 'package:equatable/equatable.dart'; + +abstract class UserSettingState extends Equatable { + const UserSettingState(); +} + +class InitialUserSettingState extends UserSettingState { + @override + List get props => []; +} diff --git a/lib/features/user_setting/presentations/pages/more_tab.dart b/lib/features/user_setting/presentations/pages/more_tab.dart new file mode 100644 index 0000000..e809361 --- /dev/null +++ b/lib/features/user_setting/presentations/pages/more_tab.dart @@ -0,0 +1,101 @@ +import 'package:better_help/common/dimens.dart'; +import 'package:better_help/common/ui/screen_title.dart'; +import 'package:better_help/common/utils/time_utils.dart'; +import 'package:better_help/core/usecase/usecase.dart'; +import 'package:better_help/features/user_setting/domain/entities/user.dart'; +import 'package:better_help/features/user_setting/presentations/bloc/bloc.dart'; +import 'package:better_help/features/user_setting/presentations/widgets/setting_option_button.dart'; +import 'package:better_help/generated/i18n.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class MoreTab extends StatelessWidget { + @override + Widget build(BuildContext context) { + return SafeArea( + child: Container( + child: _buildBody(context), + ), + ); + } + + FutureBuilder _buildBody(BuildContext context) { + final screenUtil = ScreenUtil.getInstance(); + final userSettingBloc = BlocProvider.of(context); + + return FutureBuilder( + future: userSettingBloc.getCurrentUser(NoParams()), + builder: (context, snapshot) { + if (snapshot.hasError) { + return Center( + child: Text('Something went wrong. ${snapshot.error}'), + ); + } + + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: screenUtil.setHeight(Dimens.top_space), + ), + Center( + child: ScreenTitle( + title: S.of(context).more_greeting( + getAHaftDayName(context), + snapshot.hasData + ? snapshot.data.displayName + : S + .of(context) + .you), + ), + ), + SizedBox( + height: screenUtil.setHeight(Dimens.large_space), + ), + _optionList(context), + ], + ), + ); + }); + } + + Widget _optionList(BuildContext context) { + final screenUtil = ScreenUtil.getInstance(); + final userSettingBloc = BlocProvider.of(context); + + return Container( + child: Column( + children: [ + SettingOptionButton( + name: S.of(context).more_change_nickname, + onPress: () => + userSettingBloc + .add(PressOnChangeNicknameButton(context: context)), + ), + SettingOptionButton( + name: S.of(context).more_change_status, + onPress: () => + userSettingBloc + .add(PressOnChangeUserNeedsButton(context: context)), + ), + SizedBox( + height: screenUtil.setHeight(Dimens.xlarge_space), + ), + SettingOptionButton( + name: S.of(context).more_share_app, + ), + SizedBox( + height: screenUtil.setHeight(Dimens.xlarge_space), + ), + SettingOptionButton( + name: S.of(context).more_sign_out, + onPress: () => userSettingBloc.add(SignOut(context: context)), + ), + ], + ), + ); + } +} diff --git a/lib/features/user_setting/nickname/nickname_screen.dart b/lib/features/user_setting/presentations/pages/nickname_screen.dart similarity index 74% rename from lib/features/user_setting/nickname/nickname_screen.dart rename to lib/features/user_setting/presentations/pages/nickname_screen.dart index 89ed81d..04c556a 100644 --- a/lib/features/user_setting/nickname/nickname_screen.dart +++ b/lib/features/user_setting/presentations/pages/nickname_screen.dart @@ -1,36 +1,21 @@ import 'package:better_help/common/dimens.dart'; import 'package:better_help/common/ui/screen_caption.dart'; import 'package:better_help/common/ui/screen_title.dart'; -import 'package:better_help/features/user_setting/nickname/bloc/bloc.dart'; +import 'package:better_help/features/user_setting/presentations/bloc/bloc.dart'; +import 'package:better_help/features/user_setting/presentations/bloc/user_setting_bloc.dart'; import 'package:better_help/generated/i18n.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -class NicknameScreen extends StatefulWidget { - @override - _NicknameScreenState createState() => _NicknameScreenState(); -} - -class _NicknameScreenState extends State { - final nicknameBloc = NicknameBloc(); - - @override - void initState() { - super.initState(); - } - - @override - void dispose() { - super.dispose(); - nicknameBloc.close(); - } - +class NicknameScreen extends StatelessWidget { @override Widget build(BuildContext context) { + final userSettingBloc = BlocProvider.of(context); final screenUtil = ScreenUtil.getInstance(); final textNicknameStyle = Theme.of(context).primaryTextTheme.body1; - + return CupertinoPageScaffold( child: Container( margin: EdgeInsets.symmetric( @@ -59,9 +44,9 @@ class _NicknameScreenState extends State { style: textNicknameStyle.copyWith( fontSize: screenUtil.setSp(Dimens.body1_size)), onSubmitted: (nickname) => - nicknameBloc + userSettingBloc .add( - SaveNewNickname(context: context, nickname: nickname)), + SubmitNewNickname(context: context, nickname: nickname)), ) ], ), diff --git a/lib/features/user_setting/user_needs/user_needs_screen.dart b/lib/features/user_setting/presentations/pages/user_needs_screen.dart similarity index 97% rename from lib/features/user_setting/user_needs/user_needs_screen.dart rename to lib/features/user_setting/presentations/pages/user_needs_screen.dart index 0b79e61..c94927f 100644 --- a/lib/features/user_setting/user_needs/user_needs_screen.dart +++ b/lib/features/user_setting/presentations/pages/user_needs_screen.dart @@ -8,9 +8,9 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'bloc/bloc.dart'; -import 'bloc/user_needs_event.dart'; -import 'components/needs_button.dart'; +import '../../user_needs/bloc/bloc.dart'; +import '../../user_needs/bloc/user_needs_event.dart'; +import '../widgets/needs_button.dart'; class UserNeedsScreen extends StatefulWidget { @override diff --git a/lib/features/user_setting/user_needs/components/needs_button.dart b/lib/features/user_setting/presentations/widgets/needs_button.dart similarity index 100% rename from lib/features/user_setting/user_needs/components/needs_button.dart rename to lib/features/user_setting/presentations/widgets/needs_button.dart diff --git a/lib/features/user_setting/more/setting_option_button.dart b/lib/features/user_setting/presentations/widgets/setting_option_button.dart similarity index 100% rename from lib/features/user_setting/more/setting_option_button.dart rename to lib/features/user_setting/presentations/widgets/setting_option_button.dart diff --git a/lib/injection_container.dart b/lib/injection_container.dart new file mode 100644 index 0000000..29d76b1 --- /dev/null +++ b/lib/injection_container.dart @@ -0,0 +1,65 @@ +import 'package:better_help/features/app/bloc/app_bloc.dart'; +import 'package:better_help/features/user_setting/data/repositories/user_setting_repository_impl.dart'; +import 'package:better_help/features/user_setting/data/user_setting_data_source.dart'; +import 'package:better_help/features/user_setting/domain/repositories/user_setting_repository.dart'; +import 'package:better_help/features/user_setting/domain/usecases/get_current_user.dart'; +import 'package:better_help/features/user_setting/domain/usecases/update_user.dart'; +import 'package:better_help/features/user_setting/presentations/bloc/bloc.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:get_it/get_it.dart'; + +final sl = GetIt.instance; + +Future init() async { + blocs(); + userCases(); + repositories(); + dataSources(); + externals(); +} + +void externals() { + sl.registerLazySingleton(() => Firestore.instance); + sl.registerLazySingleton(() => FirebaseAuth.instance); +} + +void dataSources() { + sl.registerLazySingleton( + () => UserSettingDataSourceImpl( + sl(), + ), + ); +} + +void repositories() { + sl.registerLazySingleton( + () => UserSettingRepositoryImpl( + sl(), + ), + ); +} + +void userCases() { + sl.registerLazySingleton( + () => GetCurrentUser( + firebaseAuth: sl(), + repository: sl(), + ), + ); + sl.registerLazySingleton( + () => UpdateUser( + sl(), + ), + ); +} + +void blocs() { + sl.registerFactory(() => AppBloc()); + sl.registerFactory( + () => UserSettingBloc( + updateUser: sl(), + getCurrentUser: sl(), + ), + ); +} diff --git a/lib/main.dart b/lib/main.dart index 3c0a974..d4cb249 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,24 +1,36 @@ import 'package:better_help/common/themes.dart'; import 'package:better_help/features/app/app.dart'; import 'package:better_help/features/app/bloc/app_bloc.dart'; +import 'package:better_help/features/user_setting/presentations/bloc/user_setting_bloc.dart'; +import 'package:better_help/injection_container.dart' as di; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:provider/provider.dart'; -void main() => {Provider.debugCheckInvalidValueType = null, runApp(MyApp())}; +void main() async { + await di.init(); + runApp(MyApp()); +} class MyApp extends StatelessWidget { - @override - Widget build(BuildContext context) { - return MultiProvider( - child: Theme( - data: theme, - child: App(), - ), - providers: [ - BlocProvider.value(value: AppBloc()), - ] - ); - } + @override + Widget build(BuildContext context) { + return MultiBlocProvider( + child: Theme( + data: theme, + child: App(), + ), + providers: [ + BlocProvider( + create: (_) => di.sl(), + ), + BlocProvider( + create: (context) => + UserSettingBloc( + updateUser: di.sl(), + getCurrentUser: di.sl(), + ), + ), + ]); + } } diff --git a/pubspec.lock b/pubspec.lock index 5db70a5..8692859 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -168,7 +168,7 @@ packages: name: cupertino_icons url: "https://pub.dartlang.org" source: hosted - version: "0.1.2" + version: "0.1.3" dart_style: dependency: transitive description: @@ -182,7 +182,7 @@ packages: name: equatable url: "https://pub.dartlang.org" source: hosted - version: "0.6.1" + version: "1.0.1" firebase_auth: dependency: "direct main" description: @@ -229,7 +229,7 @@ packages: name: flutter_bloc url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.1.1" flutter_cache_manager: dependency: transitive description: @@ -255,7 +255,7 @@ packages: name: flutter_screenutil url: "https://pub.dartlang.org" source: hosted - version: "0.6.0" + version: "0.7.0" flutter_test: dependency: "direct dev" description: flutter @@ -268,6 +268,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.27" + get_it: + dependency: "direct main" + description: + name: get_it + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.3" glob: dependency: transitive description: @@ -463,7 +470,7 @@ packages: name: provider url: "https://pub.dartlang.org" source: hosted - version: "3.1.0+1" + version: "3.2.0" pub_semver: dependency: transitive description: @@ -636,7 +643,7 @@ packages: name: webview_flutter url: "https://pub.dartlang.org" source: hosted - version: "0.3.15+1" + version: "0.3.17" yaml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 53559ce..56427e4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,12 +12,12 @@ dependencies: flutter_localizations: sdk: flutter flutter_cupertino_localizations: ^1.0.1 - flutter_screenutil: ^0.6.0 - flutter_bloc: ^2.0.1 - cupertino_icons: ^0.1.2 + flutter_screenutil: ^0.7.0 + flutter_bloc: ^2.1.1 + cupertino_icons: ^0.1.3 cached_network_image: ^1.1.3 - webview_flutter: ^0.3.15+1 - equatable: ^0.6.1 + webview_flutter: ^0.3.17 + equatable: ^1.0.1 firebase_auth: ^0.15.0 firebase_core: ^0.4.1+5 cloud_firestore: ^0.12.10 @@ -28,6 +28,7 @@ dependencies: uuid: ^2.0.4 bubble: ^1.1.9+1 flash: ^1.2.0 + get_it: ^3.0.3 dev_dependencies: flutter_test: From 8ac9dbcaeaba9423104a5323eec87dbca6474b9c Mon Sep 17 00:00:00 2001 From: linhngo Date: Fri, 6 Dec 2019 17:33:00 +0700 Subject: [PATCH 2/6] Fix app crash --- .../user_setting_repository_impl.dart | 11 +++--- .../data/user_setting_data_source.dart | 7 ++-- .../domain/usecases/get_current_user.dart | 5 ++- .../domain/usecases/update_user.dart | 3 +- lib/injection_container.dart | 34 ++++--------------- lib/main.dart | 10 +++--- 6 files changed, 24 insertions(+), 46 deletions(-) diff --git a/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart b/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart index 80b5221..f611820 100644 --- a/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart +++ b/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart @@ -1,15 +1,16 @@ import 'package:better_help/features/user_setting/data/user_setting_data_source.dart'; import 'package:better_help/features/user_setting/domain/entities/user.dart'; import 'package:better_help/features/user_setting/domain/repositories/user_setting_repository.dart'; +import 'package:meta/meta.dart'; class UserSettingRepositoryImpl implements UserSettingRepository { - final UserSettingDataSource _dataSource; - - UserSettingRepositoryImpl(this._dataSource); + final UserSettingDataSource dataSource; + + UserSettingRepositoryImpl({@required this.dataSource}); @override - Future updateUser(User user) => _dataSource.updateUser(user); + Future updateUser(User user) => dataSource.updateUser(user); @override - Future getUser(String id) => _dataSource.getUser(id); + Future getUser(String id) => dataSource.getUser(id); } diff --git a/lib/features/user_setting/data/user_setting_data_source.dart b/lib/features/user_setting/data/user_setting_data_source.dart index 047d93b..f86a446 100644 --- a/lib/features/user_setting/data/user_setting_data_source.dart +++ b/lib/features/user_setting/data/user_setting_data_source.dart @@ -14,11 +14,8 @@ abstract class UserSettingDataSource { } class UserSettingDataSourceImpl implements UserSettingDataSource { - final Firestore _firestore; - - UserSettingDataSourceImpl(this._firestore); - - CollectionReference get _userCollection => _firestore.collection('users'); + CollectionReference get _userCollection => + Firestore.instance.collection('users'); StreamTransformer get toUser => StreamTransformer.fromHandlers( diff --git a/lib/features/user_setting/domain/usecases/get_current_user.dart b/lib/features/user_setting/domain/usecases/get_current_user.dart index de578b9..f7e957e 100644 --- a/lib/features/user_setting/domain/usecases/get_current_user.dart +++ b/lib/features/user_setting/domain/usecases/get_current_user.dart @@ -6,13 +6,12 @@ import 'package:meta/meta.dart'; class GetCurrentUser implements UseCase { final UserSettingRepository repository; - final FirebaseAuth firebaseAuth; - GetCurrentUser({@required this.firebaseAuth, @required this.repository}); + GetCurrentUser({@required this.repository}); @override Future call(NoParams param) async { - final fUser = await firebaseAuth.currentUser(); + final fUser = await FirebaseAuth.instance.currentUser(); return repository.getUser(fUser.uid); } } diff --git a/lib/features/user_setting/domain/usecases/update_user.dart b/lib/features/user_setting/domain/usecases/update_user.dart index fbbf092..5c7db0a 100644 --- a/lib/features/user_setting/domain/usecases/update_user.dart +++ b/lib/features/user_setting/domain/usecases/update_user.dart @@ -1,11 +1,12 @@ import 'package:better_help/core/usecase/usecase.dart'; import 'package:better_help/features/user_setting/domain/entities/user.dart'; import 'package:better_help/features/user_setting/domain/repositories/user_setting_repository.dart'; +import 'package:meta/meta.dart'; class UpdateUser implements UseCase { final UserSettingRepository repository; - UpdateUser(this.repository); + UpdateUser({@required this.repository}); @override Future call(User user) => repository.updateUser(user); diff --git a/lib/injection_container.dart b/lib/injection_container.dart index 29d76b1..16a28c8 100644 --- a/lib/injection_container.dart +++ b/lib/injection_container.dart @@ -5,53 +5,33 @@ import 'package:better_help/features/user_setting/domain/repositories/user_setti import 'package:better_help/features/user_setting/domain/usecases/get_current_user.dart'; import 'package:better_help/features/user_setting/domain/usecases/update_user.dart'; import 'package:better_help/features/user_setting/presentations/bloc/bloc.dart'; -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:firebase_auth/firebase_auth.dart'; import 'package:get_it/get_it.dart'; final sl = GetIt.instance; -Future init() async { +void init() { blocs(); + externals(); userCases(); repositories(); dataSources(); - externals(); } -void externals() { - sl.registerLazySingleton(() => Firestore.instance); - sl.registerLazySingleton(() => FirebaseAuth.instance); -} +void externals() {} void dataSources() { sl.registerLazySingleton( - () => UserSettingDataSourceImpl( - sl(), - ), - ); + () => UserSettingDataSourceImpl()); } void repositories() { sl.registerLazySingleton( - () => UserSettingRepositoryImpl( - sl(), - ), - ); + () => UserSettingRepositoryImpl(dataSource: sl())); } void userCases() { - sl.registerLazySingleton( - () => GetCurrentUser( - firebaseAuth: sl(), - repository: sl(), - ), - ); - sl.registerLazySingleton( - () => UpdateUser( - sl(), - ), - ); + sl.registerLazySingleton(() => GetCurrentUser(repository: sl())); + sl.registerLazySingleton(() => UpdateUser(repository: sl())); } void blocs() { diff --git a/lib/main.dart b/lib/main.dart index d4cb249..4a8fd1a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,8 +7,8 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -void main() async { - await di.init(); +void main() { + di.init(); runApp(MyApp()); } @@ -21,11 +21,11 @@ class MyApp extends StatelessWidget { child: App(), ), providers: [ - BlocProvider( + BlocProvider( create: (_) => di.sl(), ), - BlocProvider( - create: (context) => + BlocProvider( + create: (_) => UserSettingBloc( updateUser: di.sl(), getCurrentUser: di.sl(), From 0133ad9f2f8de0378bac339836abb5cf18632014 Mon Sep 17 00:00:00 2001 From: linhngo Date: Fri, 6 Dec 2019 23:09:25 +0700 Subject: [PATCH 3/6] Fix bug update user needs (unresolve) --- .../user_setting_repository_impl.dart | 2 +- .../data/user_setting_data_source.dart | 25 ++---- .../presentations/bloc/user_setting_bloc.dart | 15 ++++ .../bloc/user_setting_event.dart | 9 +++ .../presentations/pages/more_tab.dart | 18 ++--- .../pages/user_needs_screen.dart | 76 +++++++------------ .../user_setting/user_needs/bloc/bloc.dart | 3 - .../user_needs/bloc/user_needs_bloc.dart | 54 ------------- .../user_needs/bloc/user_needs_event.dart | 53 ------------- .../user_needs/bloc/user_needs_state.dart | 10 --- 10 files changed, 68 insertions(+), 197 deletions(-) delete mode 100644 lib/features/user_setting/user_needs/bloc/bloc.dart delete mode 100644 lib/features/user_setting/user_needs/bloc/user_needs_bloc.dart delete mode 100644 lib/features/user_setting/user_needs/bloc/user_needs_event.dart delete mode 100644 lib/features/user_setting/user_needs/bloc/user_needs_state.dart diff --git a/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart b/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart index f611820..ac09ac1 100644 --- a/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart +++ b/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart @@ -5,7 +5,7 @@ import 'package:meta/meta.dart'; class UserSettingRepositoryImpl implements UserSettingRepository { final UserSettingDataSource dataSource; - + UserSettingRepositoryImpl({@required this.dataSource}); @override diff --git a/lib/features/user_setting/data/user_setting_data_source.dart b/lib/features/user_setting/data/user_setting_data_source.dart index f86a446..0a6c546 100644 --- a/lib/features/user_setting/data/user_setting_data_source.dart +++ b/lib/features/user_setting/data/user_setting_data_source.dart @@ -1,37 +1,28 @@ import 'dart:async'; +import 'dart:developer'; import 'package:better_help/core/error/exception.dart'; import 'package:better_help/features/user_setting/data/models/user_model.dart'; -import 'package:better_help/features/user_setting/domain/entities/user.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; abstract class UserSettingDataSource { - Stream getUserStream(String id); + Future updateUser(UserModel user); - Future updateUser(User user); - - Future getUser(String id); + Future getUser(String id); } class UserSettingDataSourceImpl implements UserSettingDataSource { CollectionReference get _userCollection => Firestore.instance.collection('users'); - StreamTransformer get toUser => - StreamTransformer.fromHandlers( - handleData: (data, sink) => sink.add(UserModel.fromJson(data.data)), - ); - @override - Future updateUser(User user) => - _userCollection.document(user.id).setData((user as UserModel).toJson()); - - @override - Stream getUserStream(String id) => - _userCollection.document(id).snapshots().transform(toUser); + Future updateUser(UserModel user) { + log(user.id); + return _userCollection.document(user.id).updateData(user.toJson()); + } @override - Future getUser(String id) async { + Future getUser(String id) async { final doc = await _userCollection.document(id).get(); if (doc.exists) { return UserModel.fromJson(doc.data); diff --git a/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart b/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart index 80c910b..8a7cd4b 100644 --- a/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart +++ b/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart @@ -1,8 +1,10 @@ import 'dart:async'; +import 'dart:developer'; import 'package:better_help/common/auth0/auth.dart'; import 'package:better_help/common/route/route.dart'; import 'package:better_help/core/usecase/usecase.dart'; +import 'package:better_help/features/user_setting/domain/entities/user.dart'; import 'package:better_help/features/user_setting/domain/usecases/get_current_user.dart'; import 'package:better_help/features/user_setting/domain/usecases/update_user.dart'; import 'package:bloc/bloc.dart'; @@ -26,6 +28,7 @@ class UserSettingBloc extends Bloc { Stream mapEventToState( UserSettingEvent event, ) async* { + log(event.toString()); if (event is SignOut) { Auth.signOut(); goToWelcomeScreen(event.context); @@ -47,6 +50,18 @@ class UserSettingBloc extends Bloc { .copyWith(updated: DateTime.now(), needs: event.userNeeds); updateUser(user); + log('aaa'); + final result = backToLastScreen(event.context); + log('bbb'); + if (!result) { + goToMainScreen(event.context); + } + } else if (event is JoinVolunteer) { + final user = (await getCurrentUser(NoParams())); + final newUser = user.copyWith( + updated: DateTime.now(), types: user.types..add(UserType.VOLUNTEER)); + updateUser(newUser); + final result = backToLastScreen(event.context); if (!result) { goToMainScreen(event.context); diff --git a/lib/features/user_setting/presentations/bloc/user_setting_event.dart b/lib/features/user_setting/presentations/bloc/user_setting_event.dart index 6079ae6..dab94ec 100644 --- a/lib/features/user_setting/presentations/bloc/user_setting_event.dart +++ b/lib/features/user_setting/presentations/bloc/user_setting_event.dart @@ -49,6 +49,15 @@ class PressOnNeedOption extends UserSettingEvent { PressOnNeedOption({@required this.context, @required this.userNeeds}); + @override + List get props => [userNeeds]; +} + +class JoinVolunteer extends UserSettingEvent { + final BuildContext context; + + JoinVolunteer({@required this.context}); + @override List get props => []; } diff --git a/lib/features/user_setting/presentations/pages/more_tab.dart b/lib/features/user_setting/presentations/pages/more_tab.dart index e809361..ea3ba10 100644 --- a/lib/features/user_setting/presentations/pages/more_tab.dart +++ b/lib/features/user_setting/presentations/pages/more_tab.dart @@ -24,7 +24,7 @@ class MoreTab extends StatelessWidget { FutureBuilder _buildBody(BuildContext context) { final screenUtil = ScreenUtil.getInstance(); final userSettingBloc = BlocProvider.of(context); - + return FutureBuilder( future: userSettingBloc.getCurrentUser(NoParams()), builder: (context, snapshot) { @@ -33,7 +33,7 @@ class MoreTab extends StatelessWidget { child: Text('Something went wrong. ${snapshot.error}'), ); } - + return SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -47,9 +47,7 @@ class MoreTab extends StatelessWidget { getAHaftDayName(context), snapshot.hasData ? snapshot.data.displayName - : S - .of(context) - .you), + : S.of(context).you), ), ), SizedBox( @@ -71,15 +69,13 @@ class MoreTab extends StatelessWidget { children: [ SettingOptionButton( name: S.of(context).more_change_nickname, - onPress: () => - userSettingBloc - .add(PressOnChangeNicknameButton(context: context)), + onPress: () => userSettingBloc + .add(PressOnChangeNicknameButton(context: context)), ), SettingOptionButton( name: S.of(context).more_change_status, - onPress: () => - userSettingBloc - .add(PressOnChangeUserNeedsButton(context: context)), + onPress: () => userSettingBloc + .add(PressOnChangeUserNeedsButton(context: context)), ), SizedBox( height: screenUtil.setHeight(Dimens.xlarge_space), diff --git a/lib/features/user_setting/presentations/pages/user_needs_screen.dart b/lib/features/user_setting/presentations/pages/user_needs_screen.dart index c94927f..bcaa109 100644 --- a/lib/features/user_setting/presentations/pages/user_needs_screen.dart +++ b/lib/features/user_setting/presentations/pages/user_needs_screen.dart @@ -1,33 +1,20 @@ -import 'package:better_help/common/data/models/user.dart'; import 'package:better_help/common/dimens.dart'; import 'package:better_help/common/ui/screen_caption.dart'; import 'package:better_help/common/ui/screen_title.dart'; -import 'package:better_help/features/user_setting/user_needs/bloc/user_needs_bloc.dart'; +import 'package:better_help/features/user_setting/domain/entities/user.dart'; +import 'package:better_help/features/user_setting/presentations/bloc/bloc.dart'; import 'package:better_help/generated/i18n.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import '../../user_needs/bloc/bloc.dart'; -import '../../user_needs/bloc/user_needs_event.dart'; import '../widgets/needs_button.dart'; -class UserNeedsScreen extends StatefulWidget { - @override - _UserNeedsScreenState createState() => _UserNeedsScreenState(); -} - -class _UserNeedsScreenState extends State { - final userNeedBloc = UserNeedsBloc(); - - @override - void dispose() { - super.dispose(); - userNeedBloc.close(); - } - +class UserNeedsScreen extends StatelessWidget { @override Widget build(BuildContext context) { + final userSettingBloc = BlocProvider.of(context); final screenUtil = ScreenUtil.getInstance(); return CupertinoPageScaffold( @@ -43,45 +30,35 @@ class _UserNeedsScreenState extends State { ), Center( child: ScreenTitle( - title: S - .of(context) - .user_type_title, + title: S.of(context).user_type_title, ), ), SizedBox( height: screenUtil.setHeight(Dimens.large_space), ), NeedsButton( - content: S - .of(context) - .option_teenage, + content: S.of(context).option_teenage, color: userNeedMapColor[UserNeeds.TEENAGE], - onPress: () => - userNeedBloc.add(SelectOptionTeenageEvent(context)), + onPress: () => userSettingBloc.add(PressOnNeedOption( + context: context, userNeeds: UserNeeds.TEENAGE)), ), NeedsButton( - content: S - .of(context) - .option_love, + content: S.of(context).option_love, color: userNeedMapColor[UserNeeds.LOVE], - onPress: () => - userNeedBloc.add(SelectOptionLoveEvent(context)), + onPress: () => userSettingBloc.add(PressOnNeedOption( + context: context, userNeeds: UserNeeds.LOVE)), ), NeedsButton( - content: S - .of(context) - .option_family, + content: S.of(context).option_family, color: userNeedMapColor[UserNeeds.FAMILY], - onPress: () => - userNeedBloc.add(SelectOptionFamilyEvent(context)), + onPress: () => userSettingBloc.add(PressOnNeedOption( + context: context, userNeeds: UserNeeds.FAMILY)), ), NeedsButton( - content: S - .of(context) - .option_go_a_head, + content: S.of(context).option_go_a_head, color: userNeedMapColor[UserNeeds.GO_AHEAD], - onPress: () => - userNeedBloc.add(SelectOptionGoAheadEvent(context)), + onPress: () => userSettingBloc.add(PressOnNeedOption( + context: context, userNeeds: UserNeeds.GO_AHEAD)), ), SizedBox( height: screenUtil.setHeight(Dimens.large_space), @@ -96,9 +73,7 @@ class _UserNeedsScreenState extends State { height: screenUtil.setHeight(Dimens.normal_space), ), ScreenCaption( - caption: S - .of(context) - .user_type_subtitle, + caption: S.of(context).user_type_subtitle, ), SizedBox( height: screenUtil.setHeight(Dimens.normal_space), @@ -112,9 +87,7 @@ class _UserNeedsScreenState extends State { child: Padding( padding: const EdgeInsets.all(12.0), child: Text( - S - .of(context) - .user_type_volunteer_register, + S.of(context).user_type_volunteer_register, style: TextStyle( fontSize: screenUtil.setSp(Dimens.h2_size), fontWeight: FontWeight.bold, @@ -124,7 +97,7 @@ class _UserNeedsScreenState extends State { ), ), onPressed: () => - userNeedBloc.add(JoinVolunteerEvent(context)), + userSettingBloc.add(JoinVolunteer(context: context)), ), SizedBox( height: screenUtil.setHeight(Dimens.normal_space), @@ -137,3 +110,10 @@ class _UserNeedsScreenState extends State { ); } } + +final userNeedMapColor = { + UserNeeds.TEENAGE: Colors.blue, + UserNeeds.FAMILY: Colors.yellow[700], + UserNeeds.LOVE: Colors.pink, + UserNeeds.GO_AHEAD: Colors.greenAccent, +}; diff --git a/lib/features/user_setting/user_needs/bloc/bloc.dart b/lib/features/user_setting/user_needs/bloc/bloc.dart deleted file mode 100644 index a7135bd..0000000 --- a/lib/features/user_setting/user_needs/bloc/bloc.dart +++ /dev/null @@ -1,3 +0,0 @@ -export 'user_needs_bloc.dart'; -export 'user_needs_event.dart'; -export 'user_needs_state.dart'; diff --git a/lib/features/user_setting/user_needs/bloc/user_needs_bloc.dart b/lib/features/user_setting/user_needs/bloc/user_needs_bloc.dart deleted file mode 100644 index 2fffce5..0000000 --- a/lib/features/user_setting/user_needs/bloc/user_needs_bloc.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'dart:async'; -import 'dart:developer'; - -import 'package:better_help/common/auth0/auth.dart'; -import 'package:better_help/common/data/dao/user_dao.dart'; -import 'package:better_help/common/data/models/user.dart'; -import 'package:better_help/common/route/route.dart'; -import 'package:better_help/features/main/main_screen.dart'; -import 'package:bloc/bloc.dart'; - -import './bloc.dart'; - -class UserNeedsBloc extends Bloc { - static final _key = 'needs'; - - @override - UserNeedsState get initialState => InitialUserNeedsState(); - - @override - Stream mapEventToState(UserNeedsEvent event,) async* { - log(event.toString()); - if (event is SelectOptionTeenageEvent) { - await updateUserNeeds(UserNeeds.TEENAGE); - } else if (event is SelectOptionLoveEvent) { - await updateUserNeeds(UserNeeds.LOVE); - } else if (event is SelectOptionFamilyEvent) { - await updateUserNeeds(UserNeeds.FAMILY); - } else if (event is SelectOptionGoAheadEvent) { - await updateUserNeeds(UserNeeds.GO_AHEAD); - } else if (event is JoinVolunteerEvent) { - await addVolunteerType(); - } - final result = backToLastScreen(event.context); - if (!result) { - final user = await Auth.currentUser(); - goToMainScreen(event.context, deleteAllLastScreen: true, - arguments: MainArgument(user: user)); - } - } - - Future updateUserNeeds(UserNeeds needs) async { - final user = await Auth.currentUser(); - final json = user.toJson(); - json[_key] = userNeedMap[needs]; - log(json[_key].toString()); - await UserDao.updateUser(user: User.fromJson(json)); - } - - Future addVolunteerType() async { - final user = await Auth.currentUser(); - user.types.add(UserType.VOLUNTEER); - await UserDao.updateUser(user: user); - } -} diff --git a/lib/features/user_setting/user_needs/bloc/user_needs_event.dart b/lib/features/user_setting/user_needs/bloc/user_needs_event.dart deleted file mode 100644 index a8dfe15..0000000 --- a/lib/features/user_setting/user_needs/bloc/user_needs_event.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'package:equatable/equatable.dart'; -import 'package:flutter/widgets.dart'; - -abstract class UserNeedsEvent extends Equatable { - final BuildContext context; - - const UserNeedsEvent(this.context); -} - -class SelectOptionTeenageEvent extends UserNeedsEvent { - final BuildContext context; - - SelectOptionTeenageEvent(this.context) : super(context); - - @override - List get props => null; -} - -class SelectOptionLoveEvent extends UserNeedsEvent { - final BuildContext context; - - SelectOptionLoveEvent(this.context) : super(context); - - @override - List get props => null; -} - -class SelectOptionFamilyEvent extends UserNeedsEvent { - final BuildContext context; - - SelectOptionFamilyEvent(this.context) : super(context); - - @override - List get props => null; -} - -class SelectOptionGoAheadEvent extends UserNeedsEvent { - final BuildContext context; - - SelectOptionGoAheadEvent(this.context) : super(context); - - @override - List get props => null; -} - -class JoinVolunteerEvent extends UserNeedsEvent { - final BuildContext context; - - JoinVolunteerEvent(this.context) : super(context); - - @override - List get props => null; -} diff --git a/lib/features/user_setting/user_needs/bloc/user_needs_state.dart b/lib/features/user_setting/user_needs/bloc/user_needs_state.dart deleted file mode 100644 index 887d441..0000000 --- a/lib/features/user_setting/user_needs/bloc/user_needs_state.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'package:equatable/equatable.dart'; - -abstract class UserNeedsState extends Equatable { - const UserNeedsState(); -} - -class InitialUserNeedsState extends UserNeedsState { - @override - List get props => []; -} From 49ebfd9d1e8ee86afc80b78b653fadcdac703e79 Mon Sep 17 00:00:00 2001 From: linhngo Date: Fri, 6 Dec 2019 23:27:02 +0700 Subject: [PATCH 4/6] Make user need UI better --- .../presentations/bloc/user_setting_bloc.dart | 5 + .../bloc/user_setting_event.dart | 5 + .../bloc/user_setting_state.dart | 5 + .../pages/user_needs_screen.dart | 169 ++++++++++-------- 4 files changed, 106 insertions(+), 78 deletions(-) diff --git a/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart b/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart index 8a7cd4b..251ae8c 100644 --- a/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart +++ b/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart @@ -66,6 +66,11 @@ class UserSettingBloc extends Bloc { if (!result) { goToMainScreen(event.context); } + } else if (event is CheckUserType) { + final user = (await getCurrentUser(NoParams())); + if (user.types.contains(UserType.VOLUNTEER)) { + yield AlreadyVolunteer(); + } } } } diff --git a/lib/features/user_setting/presentations/bloc/user_setting_event.dart b/lib/features/user_setting/presentations/bloc/user_setting_event.dart index dab94ec..a7e8236 100644 --- a/lib/features/user_setting/presentations/bloc/user_setting_event.dart +++ b/lib/features/user_setting/presentations/bloc/user_setting_event.dart @@ -61,3 +61,8 @@ class JoinVolunteer extends UserSettingEvent { @override List get props => []; } + +class CheckUserType extends UserSettingEvent { + @override + List get props => []; +} diff --git a/lib/features/user_setting/presentations/bloc/user_setting_state.dart b/lib/features/user_setting/presentations/bloc/user_setting_state.dart index e0b9e1c..c1dfaf8 100644 --- a/lib/features/user_setting/presentations/bloc/user_setting_state.dart +++ b/lib/features/user_setting/presentations/bloc/user_setting_state.dart @@ -8,3 +8,8 @@ class InitialUserSettingState extends UserSettingState { @override List get props => []; } + +class AlreadyVolunteer extends UserSettingState { + @override + List get props => []; +} diff --git a/lib/features/user_setting/presentations/pages/user_needs_screen.dart b/lib/features/user_setting/presentations/pages/user_needs_screen.dart index bcaa109..9f019cd 100644 --- a/lib/features/user_setting/presentations/pages/user_needs_screen.dart +++ b/lib/features/user_setting/presentations/pages/user_needs_screen.dart @@ -15,100 +15,113 @@ class UserNeedsScreen extends StatelessWidget { @override Widget build(BuildContext context) { final userSettingBloc = BlocProvider.of(context); + userSettingBloc.add(CheckUserType()); final screenUtil = ScreenUtil.getInstance(); return CupertinoPageScaffold( + navigationBar: CupertinoNavigationBar(), child: SafeArea( child: Container( height: double.infinity, child: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - SizedBox( - height: screenUtil.setHeight(Dimens.top_space), - ), - Center( - child: ScreenTitle( - title: S.of(context).user_type_title, - ), - ), - SizedBox( - height: screenUtil.setHeight(Dimens.large_space), - ), - NeedsButton( - content: S.of(context).option_teenage, - color: userNeedMapColor[UserNeeds.TEENAGE], - onPress: () => userSettingBloc.add(PressOnNeedOption( - context: context, userNeeds: UserNeeds.TEENAGE)), - ), - NeedsButton( - content: S.of(context).option_love, - color: userNeedMapColor[UserNeeds.LOVE], - onPress: () => userSettingBloc.add(PressOnNeedOption( - context: context, userNeeds: UserNeeds.LOVE)), - ), - NeedsButton( - content: S.of(context).option_family, - color: userNeedMapColor[UserNeeds.FAMILY], - onPress: () => userSettingBloc.add(PressOnNeedOption( - context: context, userNeeds: UserNeeds.FAMILY)), - ), - NeedsButton( - content: S.of(context).option_go_a_head, - color: userNeedMapColor[UserNeeds.GO_AHEAD], - onPress: () => userSettingBloc.add(PressOnNeedOption( - context: context, userNeeds: UserNeeds.GO_AHEAD)), - ), - SizedBox( - height: screenUtil.setHeight(Dimens.large_space), - ), - Divider( - height: 1.0, - thickness: 3.0, - indent: screenUtil.setHeight(Dimens.horizontal_space), - endIndent: screenUtil.setHeight(Dimens.horizontal_space), - ), - SizedBox( - height: screenUtil.setHeight(Dimens.normal_space), - ), - ScreenCaption( - caption: S.of(context).user_type_subtitle, - ), - SizedBox( - height: screenUtil.setHeight(Dimens.normal_space), - ), - RaisedButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), + child: BlocBuilder( + bloc: userSettingBloc, + builder: (context, state) => Column( + children: [ + SizedBox( + height: screenUtil.setHeight(Dimens.top_space), ), - elevation: Dimens.elevation, - color: Colors.white, - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Text( - S.of(context).user_type_volunteer_register, - style: TextStyle( - fontSize: screenUtil.setSp(Dimens.h2_size), - fontWeight: FontWeight.bold, - color: Colors.black, - ), - textAlign: TextAlign.center, + Center( + child: ScreenTitle( + title: S.of(context).user_type_title, ), ), - onPressed: () => - userSettingBloc.add(JoinVolunteer(context: context)), - ), - SizedBox( - height: screenUtil.setHeight(Dimens.normal_space), - ), - ], + SizedBox( + height: screenUtil.setHeight(Dimens.large_space), + ), + NeedsButton( + content: S.of(context).option_teenage, + color: userNeedMapColor[UserNeeds.TEENAGE], + onPress: () => userSettingBloc.add(PressOnNeedOption( + context: context, userNeeds: UserNeeds.TEENAGE)), + ), + NeedsButton( + content: S.of(context).option_love, + color: userNeedMapColor[UserNeeds.LOVE], + onPress: () => userSettingBloc.add(PressOnNeedOption( + context: context, userNeeds: UserNeeds.LOVE)), + ), + NeedsButton( + content: S.of(context).option_family, + color: userNeedMapColor[UserNeeds.FAMILY], + onPress: () => userSettingBloc.add(PressOnNeedOption( + context: context, userNeeds: UserNeeds.FAMILY)), + ), + NeedsButton( + content: S.of(context).option_go_a_head, + color: userNeedMapColor[UserNeeds.GO_AHEAD], + onPress: () => userSettingBloc.add(PressOnNeedOption( + context: context, userNeeds: UserNeeds.GO_AHEAD)), + ), + SizedBox( + height: screenUtil.setHeight(Dimens.large_space), + ), + Divider( + height: 1.0, + thickness: 3.0, + indent: screenUtil.setHeight(Dimens.horizontal_space), + endIndent: screenUtil.setHeight(Dimens.horizontal_space), + ), + state is AlreadyVolunteer + ? Container() + : joinVolunteerWidgets(screenUtil, context, userSettingBloc), + SizedBox( + height: screenUtil.setHeight(Dimens.normal_space), + ), + ], + ), ), ), ), ), ); } + + Widget joinVolunteerWidgets(ScreenUtil screenUtil, BuildContext context, UserSettingBloc userSettingBloc) => + Column( + children: [ + SizedBox( + height: screenUtil.setHeight(Dimens.normal_space), + ), + ScreenCaption( + caption: S.of(context).user_type_subtitle, + ), + SizedBox( + height: screenUtil.setHeight(Dimens.normal_space), + ), + RaisedButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + elevation: Dimens.elevation, + color: Colors.white, + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Text( + S.of(context).user_type_volunteer_register, + style: TextStyle( + fontSize: screenUtil.setSp(Dimens.h2_size), + fontWeight: FontWeight.bold, + color: Colors.black, + ), + textAlign: TextAlign.center, + ), + ), + onPressed: () => + userSettingBloc.add(JoinVolunteer(context: context)), + ), + ], + ); } final userNeedMapColor = { From a59802a8994952a2ac3353470b36582fa8836a86 Mon Sep 17 00:00:00 2001 From: linhngo Date: Fri, 6 Dec 2019 23:29:32 +0700 Subject: [PATCH 5/6] Make nickname UI better --- .../user_setting/presentations/pages/nickname_screen.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/features/user_setting/presentations/pages/nickname_screen.dart b/lib/features/user_setting/presentations/pages/nickname_screen.dart index 04c556a..ad3e73d 100644 --- a/lib/features/user_setting/presentations/pages/nickname_screen.dart +++ b/lib/features/user_setting/presentations/pages/nickname_screen.dart @@ -17,6 +17,7 @@ class NicknameScreen extends StatelessWidget { final textNicknameStyle = Theme.of(context).primaryTextTheme.body1; return CupertinoPageScaffold( + navigationBar: CupertinoNavigationBar(), child: Container( margin: EdgeInsets.symmetric( horizontal: screenUtil.setWidth(Dimens.horizontal_space)), From a2b08c0c3136a90fbb0a20d38acf18b3fc51ec2a Mon Sep 17 00:00:00 2001 From: linhngo Date: Sat, 7 Dec 2019 08:45:20 +0700 Subject: [PATCH 6/6] Fix bug update bug --- .../user_setting/data/models/user_model.dart | 15 +++++++++++++++ .../user_setting_repository_impl.dart | 3 ++- .../data/user_setting_data_source.dart | 7 ++----- .../presentations/bloc/user_setting_bloc.dart | 2 -- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/lib/features/user_setting/data/models/user_model.dart b/lib/features/user_setting/data/models/user_model.dart index 5c6c223..3d5d1d1 100644 --- a/lib/features/user_setting/data/models/user_model.dart +++ b/lib/features/user_setting/data/models/user_model.dart @@ -40,6 +40,21 @@ class UserModel extends User { factory UserModel.fromJson(Map json) => _$UserModelFromJson(json); + factory UserModel.fromUser(User user) => UserModel( + id: user.id, + displayName: user.displayName, + email: user.email, + photoUrl: user.photoUrl, + created: user.created, + updated: user.updated, + phoneNumber: user.phoneNumber, + tokens: user.tokens, + types: user.types, + needs: user.needs, + friendIds: user.friendIds, + online: user.online, + ); + Map toJson() => _$UserModelToJson(this); } diff --git a/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart b/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart index ac09ac1..cb4261a 100644 --- a/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart +++ b/lib/features/user_setting/data/repositories/user_setting_repository_impl.dart @@ -1,3 +1,4 @@ +import 'package:better_help/features/user_setting/data/models/user_model.dart'; import 'package:better_help/features/user_setting/data/user_setting_data_source.dart'; import 'package:better_help/features/user_setting/domain/entities/user.dart'; import 'package:better_help/features/user_setting/domain/repositories/user_setting_repository.dart'; @@ -9,7 +10,7 @@ class UserSettingRepositoryImpl implements UserSettingRepository { UserSettingRepositoryImpl({@required this.dataSource}); @override - Future updateUser(User user) => dataSource.updateUser(user); + Future updateUser(User user) => dataSource.updateUser(UserModel.fromUser(user)); @override Future getUser(String id) => dataSource.getUser(id); diff --git a/lib/features/user_setting/data/user_setting_data_source.dart b/lib/features/user_setting/data/user_setting_data_source.dart index 0a6c546..9dae648 100644 --- a/lib/features/user_setting/data/user_setting_data_source.dart +++ b/lib/features/user_setting/data/user_setting_data_source.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:developer'; import 'package:better_help/core/error/exception.dart'; import 'package:better_help/features/user_setting/data/models/user_model.dart'; @@ -16,10 +15,8 @@ class UserSettingDataSourceImpl implements UserSettingDataSource { Firestore.instance.collection('users'); @override - Future updateUser(UserModel user) { - log(user.id); - return _userCollection.document(user.id).updateData(user.toJson()); - } + Future updateUser(UserModel user) => + _userCollection.document(user.id).updateData(user.toJson()); @override Future getUser(String id) async { diff --git a/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart b/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart index 251ae8c..4541aa2 100644 --- a/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart +++ b/lib/features/user_setting/presentations/bloc/user_setting_bloc.dart @@ -50,9 +50,7 @@ class UserSettingBloc extends Bloc { .copyWith(updated: DateTime.now(), needs: event.userNeeds); updateUser(user); - log('aaa'); final result = backToLastScreen(event.context); - log('bbb'); if (!result) { goToMainScreen(event.context); }