From 0207669ffd2eb95a6542ab62323cd6b8bf88653c Mon Sep 17 00:00:00 2001 From: Techno-Disaster Date: Mon, 27 Jul 2020 18:11:39 +0530 Subject: [PATCH 1/7] migrated to 5.0 --- lib/auth/auth_bloc.dart | 5 +---- lib/bloc_delegate.dart | 2 +- lib/main.dart | 2 +- lib/screens/home/bloc/home_bloc.dart | 3 +-- .../pages/members/bloc/members_page_bloc.dart | 7 +++--- .../pages/profile/bloc/profile_page_bloc.dart | 7 +++--- .../home/pages/profile/profile_page.dart | 1 - .../relation/bloc/relation_page_bloc.dart | 6 ++--- .../home/pages/relation/relation_page.dart | 2 +- .../requests/bloc/requests_page_bloc.dart | 7 +++--- .../home/pages/requests/requests_page.dart | 1 - .../pages/stats/bloc/stats_page_bloc.dart | 7 +++--- lib/screens/home/pages/stats/stats_page.dart | 1 - lib/screens/login/bloc/login_bloc.dart | 5 +---- .../bloc/request_detail_bloc.dart | 7 +++--- .../send_request/bloc/send_request_bloc.dart | 7 +++--- pubspec.lock | 22 +++++++++++++++---- pubspec.yaml | 4 ++-- 18 files changed, 46 insertions(+), 50 deletions(-) diff --git a/lib/auth/auth_bloc.dart b/lib/auth/auth_bloc.dart index 81b8dc4..4b2020b 100644 --- a/lib/auth/auth_bloc.dart +++ b/lib/auth/auth_bloc.dart @@ -9,10 +9,7 @@ import 'bloc.dart'; class AuthBloc extends Bloc { final AuthRepository userRepository; - AuthBloc(this.userRepository); - - @override - AuthState get initialState => AuthUninitialized(); + AuthBloc(this.userRepository) : super(AuthUninitialized()); @override Stream mapEventToState(AuthEvent event) async* { diff --git a/lib/bloc_delegate.dart b/lib/bloc_delegate.dart index f98f290..f49350c 100644 --- a/lib/bloc_delegate.dart +++ b/lib/bloc_delegate.dart @@ -2,7 +2,7 @@ import 'package:bloc/bloc.dart'; import 'package:logging/logging.dart'; /// BlocDelegate which logs all BLOC events, errors and transitions. -class SimpleBlocDelegate extends BlocDelegate { +class SimpleBlocDelegate extends BlocObserver { @override void onEvent(Bloc bloc, Object event) { super.onEvent(bloc, event); diff --git a/lib/main.dart b/lib/main.dart index f33e260..bb5bbdf 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,7 +12,7 @@ import 'package:toast/toast.dart'; void main() { // Logs all BLoC transitions - BlocSupervisor.delegate = SimpleBlocDelegate(); + Bloc.observer = SimpleBlocDelegate(); _setupLogging(); // Providing app-wide auth bloc, so that app state changes immediately when diff --git a/lib/screens/home/bloc/home_bloc.dart b/lib/screens/home/bloc/home_bloc.dart index bc6bf8b..1da6837 100644 --- a/lib/screens/home/bloc/home_bloc.dart +++ b/lib/screens/home/bloc/home_bloc.dart @@ -5,8 +5,7 @@ import 'package:bloc/bloc.dart'; import './bloc.dart'; class HomeBloc extends Bloc { - @override - HomeState get initialState => HomeScreenStats(); + HomeBloc() : super(HomeScreenStats()); @override Stream mapEventToState(HomeEvent event) async* { diff --git a/lib/screens/home/pages/members/bloc/members_page_bloc.dart b/lib/screens/home/pages/members/bloc/members_page_bloc.dart index 0af083c..b98f4dd 100644 --- a/lib/screens/home/pages/members/bloc/members_page_bloc.dart +++ b/lib/screens/home/pages/members/bloc/members_page_bloc.dart @@ -12,9 +12,9 @@ import './bloc.dart'; class MembersPageBloc extends Bloc { final UserRepository userRepository; int pageNumber = 1; - MembersPageBloc({@required this.userRepository}) : assert(userRepository != null); - @override - MembersPageState get initialState => MembersPageInitial(); + MembersPageBloc({@required this.userRepository}) + : assert(userRepository != null), + super(MembersPageInitial()); @override Stream mapEventToState(MembersPageEvent event) async* { @@ -53,7 +53,6 @@ class MembersPageBloc extends Bloc { } Stream _mapEventToMembersRefresh(MembersPageEvent event) async* { - final currentState = state; if (event is MembersPageRefresh) { try { diff --git a/lib/screens/home/pages/profile/bloc/profile_page_bloc.dart b/lib/screens/home/pages/profile/bloc/profile_page_bloc.dart index aa5ed7b..6e333ce 100644 --- a/lib/screens/home/pages/profile/bloc/profile_page_bloc.dart +++ b/lib/screens/home/pages/profile/bloc/profile_page_bloc.dart @@ -14,10 +14,9 @@ class ProfilePageBloc extends Bloc { final UserRepository userRepository; User _user; // User object which will receive possible edits - ProfilePageBloc({@required this.userRepository}) : assert(userRepository != null); - - @override - ProfilePageState get initialState => ProfilePageInitial(); + ProfilePageBloc({@required this.userRepository}) + : assert(userRepository != null), + super(ProfilePageInitial()); @override Stream mapEventToState(ProfilePageEvent event) async* { diff --git a/lib/screens/home/pages/profile/profile_page.dart b/lib/screens/home/pages/profile/profile_page.dart index 70f3f06..406c7e6 100644 --- a/lib/screens/home/pages/profile/profile_page.dart +++ b/lib/screens/home/pages/profile/profile_page.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:mentorship_client/extensions/context.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/profile/bloc/bloc.dart'; import 'package:mentorship_client/widgets/loading_indicator.dart'; import 'dart:async'; diff --git a/lib/screens/home/pages/relation/bloc/relation_page_bloc.dart b/lib/screens/home/pages/relation/bloc/relation_page_bloc.dart index b37870f..29743c2 100644 --- a/lib/screens/home/pages/relation/bloc/relation_page_bloc.dart +++ b/lib/screens/home/pages/relation/bloc/relation_page_bloc.dart @@ -18,10 +18,8 @@ class RelationPageBloc extends Bloc { RelationPageBloc({@required this.relationRepository, @required this.taskRepository}) : assert(relationRepository != null), - assert(taskRepository != null); - - @override - RelationPageState get initialState => RelationPageLoading(); + assert(taskRepository != null), + super(RelationPageLoading()); @override Stream mapEventToState(RelationPageEvent event) async* { diff --git a/lib/screens/home/pages/relation/relation_page.dart b/lib/screens/home/pages/relation/relation_page.dart index 869cce6..3f78990 100644 --- a/lib/screens/home/pages/relation/relation_page.dart +++ b/lib/screens/home/pages/relation/relation_page.dart @@ -210,7 +210,7 @@ class _RelationPageState extends State { Task task = state.tasks[index]; //ignore: close_sinks final bloc = BlocProvider.of(context); - + return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/screens/home/pages/requests/bloc/requests_page_bloc.dart b/lib/screens/home/pages/requests/bloc/requests_page_bloc.dart index 6a0dae3..32305f5 100644 --- a/lib/screens/home/pages/requests/bloc/requests_page_bloc.dart +++ b/lib/screens/home/pages/requests/bloc/requests_page_bloc.dart @@ -12,10 +12,9 @@ import './bloc.dart'; class RequestsPageBloc extends Bloc { final RelationRepository relationRepository; - RequestsPageBloc({@required this.relationRepository}) : assert(relationRepository != null); - - @override - RequestsPageState get initialState => RequestsPageLoading(); + RequestsPageBloc({@required this.relationRepository}) + : assert(relationRepository != null), + super(RequestsPageLoading()); @override Stream mapEventToState(RequestsPageEvent event) async* { diff --git a/lib/screens/home/pages/requests/requests_page.dart b/lib/screens/home/pages/requests/requests_page.dart index d4add32..91c3cd5 100644 --- a/lib/screens/home/pages/requests/requests_page.dart +++ b/lib/screens/home/pages/requests/requests_page.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:mentorship_client/extensions/datetime.dart'; import 'package:mentorship_client/remote/models/relation.dart'; -import 'package:mentorship_client/screens/home/pages/members/bloc/bloc.dart'; import 'package:mentorship_client/screens/home/pages/requests/bloc/bloc.dart'; import 'package:mentorship_client/screens/request_detail/request_detail.dart'; import 'package:mentorship_client/widgets/bold_text.dart'; diff --git a/lib/screens/home/pages/stats/bloc/stats_page_bloc.dart b/lib/screens/home/pages/stats/bloc/stats_page_bloc.dart index 94c1a5f..2438f15 100644 --- a/lib/screens/home/pages/stats/bloc/stats_page_bloc.dart +++ b/lib/screens/home/pages/stats/bloc/stats_page_bloc.dart @@ -11,10 +11,9 @@ import './bloc.dart'; class StatsPageBloc extends Bloc { final UserRepository userRepository; - StatsPageBloc({this.userRepository}) : assert(userRepository != null); - - @override - StatsPageState get initialState => StatsPageInitial(); + StatsPageBloc({this.userRepository}) + : assert(userRepository != null), + super(StatsPageInitial()); @override Stream mapEventToState(StatsPageEvent event) async* { diff --git a/lib/screens/home/pages/stats/stats_page.dart b/lib/screens/home/pages/stats/stats_page.dart index a978bcb..81aa2ac 100644 --- a/lib/screens/home/pages/stats/stats_page.dart +++ b/lib/screens/home/pages/stats/stats_page.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:mentorship_client/remote/models/task.dart'; -import 'package:mentorship_client/remote/repositories/user_repository.dart'; import 'package:mentorship_client/screens/home/pages/stats/bloc/bloc.dart'; import 'package:mentorship_client/widgets/loading_indicator.dart'; import 'dart:async'; diff --git a/lib/screens/login/bloc/login_bloc.dart b/lib/screens/login/bloc/login_bloc.dart index c865312..d154e6d 100644 --- a/lib/screens/login/bloc/login_bloc.dart +++ b/lib/screens/login/bloc/login_bloc.dart @@ -10,10 +10,7 @@ class LoginBloc extends Bloc { final AuthRepository authRepository; final AuthBloc authBloc; - LoginBloc(this.authRepository, this.authBloc); - - @override - get initialState => LoginInitial(); + LoginBloc(this.authRepository, this.authBloc) : super(LoginInitial()); @override Stream mapEventToState(event) async* { diff --git a/lib/screens/request_detail/bloc/request_detail_bloc.dart b/lib/screens/request_detail/bloc/request_detail_bloc.dart index a505576..3f7099d 100644 --- a/lib/screens/request_detail/bloc/request_detail_bloc.dart +++ b/lib/screens/request_detail/bloc/request_detail_bloc.dart @@ -12,10 +12,9 @@ import './bloc.dart'; class RequestDetailBloc extends Bloc { final RelationRepository relationRepository; - RequestDetailBloc({@required this.relationRepository}) : assert(relationRepository != null); - - @override - RequestDetailState get initialState => InitialRequestDetailState(); + RequestDetailBloc({@required this.relationRepository}) + : assert(relationRepository != null), + super(InitialRequestDetailState()); @override Stream mapEventToState(RequestDetailEvent event) async* { diff --git a/lib/screens/send_request/bloc/send_request_bloc.dart b/lib/screens/send_request/bloc/send_request_bloc.dart index 0001732..028b0c4 100644 --- a/lib/screens/send_request/bloc/send_request_bloc.dart +++ b/lib/screens/send_request/bloc/send_request_bloc.dart @@ -12,10 +12,9 @@ import './bloc.dart'; class SendRequestBloc extends Bloc { final RelationRepository relationRepository; - SendRequestBloc({@required this.relationRepository}) : assert(relationRepository != null); - - @override - SendRequestState get initialState => InitialSendRequestState(); + SendRequestBloc({@required this.relationRepository}) + : assert(relationRepository != null), + super(InitialSendRequestState()); @override Stream mapEventToState(SendRequestEvent event) async* { diff --git a/pubspec.lock b/pubspec.lock index 4604539..c6875be 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -49,7 +49,7 @@ packages: name: bloc url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "5.0.1" boolean_selector: dependency: transitive description: @@ -197,6 +197,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.16.1" + cubit: + dependency: transitive + description: + name: cubit + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2" cupertino_icons: dependency: "direct main" description: @@ -250,7 +257,14 @@ packages: name: flutter_bloc url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "5.0.1" + flutter_cubit: + dependency: transitive + description: + name: flutter_cubit + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.1" flutter_native_splash: dependency: "direct dev" description: @@ -463,7 +477,7 @@ packages: name: provider url: "https://pub.dartlang.org" source: hosted - version: "4.0.5" + version: "4.3.1" pub_semver: dependency: transitive description: @@ -646,4 +660,4 @@ packages: version: "2.2.0" sdks: dart: ">=2.7.0 <3.0.0" - flutter: ">=1.12.13+hotfix.5 <2.0.0" + flutter: ">=1.16.0 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index cabde04..9599853 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -33,8 +33,8 @@ dependencies: expandable: ^4.1.3 auto_size_text: ^2.1.0 # Bloc - bloc: ^4.0.0 - flutter_bloc: ^4.0.0 + bloc: ^5.0.0 + flutter_bloc: ^5.0.0 chopper: ^3.0.2 # plugins not needed in app From 80c70ab2aff9de77372583f45ce2e35d651521cb Mon Sep 17 00:00:00 2001 From: Techno-Disaster Date: Mon, 27 Jul 2020 18:18:16 +0530 Subject: [PATCH 2/7] migrated to 6.0.1 --- lib/bloc_delegate.dart | 4 ++-- pubspec.lock | 18 ++---------------- pubspec.yaml | 4 ++-- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/lib/bloc_delegate.dart b/lib/bloc_delegate.dart index f49350c..0c401b6 100644 --- a/lib/bloc_delegate.dart +++ b/lib/bloc_delegate.dart @@ -10,8 +10,8 @@ class SimpleBlocDelegate extends BlocObserver { } @override - void onError(Bloc bloc, Object error, StackTrace stacktrace) { - super.onError(bloc, error, stacktrace); + void onError(Cubit cubit, Object error, StackTrace stacktrace) { + super.onError(cubit, error, stacktrace); Logger.root.severe(error); } diff --git a/pubspec.lock b/pubspec.lock index c6875be..03a5e4d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -49,7 +49,7 @@ packages: name: bloc url: "https://pub.dartlang.org" source: hosted - version: "5.0.1" + version: "6.0.1" boolean_selector: dependency: transitive description: @@ -197,13 +197,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.16.1" - cubit: - dependency: transitive - description: - name: cubit - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.2" cupertino_icons: dependency: "direct main" description: @@ -257,14 +250,7 @@ packages: name: flutter_bloc url: "https://pub.dartlang.org" source: hosted - version: "5.0.1" - flutter_cubit: - dependency: transitive - description: - name: flutter_cubit - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.1" + version: "6.0.1" flutter_native_splash: dependency: "direct dev" description: diff --git a/pubspec.yaml b/pubspec.yaml index 9599853..b8a877f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -33,8 +33,8 @@ dependencies: expandable: ^4.1.3 auto_size_text: ^2.1.0 # Bloc - bloc: ^5.0.0 - flutter_bloc: ^5.0.0 + bloc: ^6.0.1 + flutter_bloc: ^6.0.1 chopper: ^3.0.2 # plugins not needed in app From 2520de384579e554d057feb302a3944bea5c59c1 Mon Sep 17 00:00:00 2001 From: Jayesh Nirve Date: Mon, 24 Aug 2020 06:48:16 +0530 Subject: [PATCH 3/7] bloc and networking for comments done --- lib/remote/api_manager.dart | 2 + lib/remote/models/comment.dart | 17 +++ lib/remote/models/comment.g.dart | 29 +++++ .../repositories/comment_repository.dart | 53 ++++++++ lib/remote/requests/comment_request.dart | 16 +++ .../services/comment_service.chopper.dart | 52 ++++++++ lib/remote/services/comment_service.dart | 51 ++++++++ lib/screens/comment/bloc/bloc.dart | 3 + .../comment/bloc/comment_page_bloc.dart | 56 +++++++++ .../comment/bloc/comment_page_event.dart | 43 +++++++ .../comment/bloc/comment_page_state.dart | 38 ++++++ lib/screens/comment/comments_page.dart | 118 ++++++++++++++++++ .../home/pages/relation/relation_page.dart | 87 ++++++++----- lib/screens/login/login_screen.dart | 2 +- .../send_request/send_request_screen.dart | 2 - pubspec.lock | 54 +++++--- pubspec.yaml | 3 +- token.txt | 1 + 18 files changed, 572 insertions(+), 55 deletions(-) create mode 100644 lib/remote/models/comment.dart create mode 100644 lib/remote/models/comment.g.dart create mode 100644 lib/remote/repositories/comment_repository.dart create mode 100644 lib/remote/requests/comment_request.dart create mode 100644 lib/remote/services/comment_service.chopper.dart create mode 100644 lib/remote/services/comment_service.dart create mode 100644 lib/screens/comment/bloc/bloc.dart create mode 100644 lib/screens/comment/bloc/comment_page_bloc.dart create mode 100644 lib/screens/comment/bloc/comment_page_event.dart create mode 100644 lib/screens/comment/bloc/comment_page_state.dart create mode 100644 lib/screens/comment/comments_page.dart create mode 100644 token.txt diff --git a/lib/remote/api_manager.dart b/lib/remote/api_manager.dart index cc91a59..d88b8e8 100644 --- a/lib/remote/api_manager.dart +++ b/lib/remote/api_manager.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:logging/logging.dart'; import 'package:mentorship_client/failure.dart'; import 'package:mentorship_client/remote/services/auth_service.dart'; +import 'package:mentorship_client/remote/services/comment_service.dart'; import 'package:mentorship_client/remote/services/relation_service.dart'; import 'package:mentorship_client/remote/services/task_service.dart'; import 'package:mentorship_client/remote/services/user_service.dart'; @@ -16,6 +17,7 @@ class ApiManager { final UserService userService = UserService.create(); final RelationService relationService = RelationService.create(); final TaskService taskService = TaskService.create(); + final CommentService commentService = CommentService.create(); ApiManager._internal(); diff --git a/lib/remote/models/comment.dart b/lib/remote/models/comment.dart new file mode 100644 index 0000000..ae28817 --- /dev/null +++ b/lib/remote/models/comment.dart @@ -0,0 +1,17 @@ +import 'package:json_annotation/json_annotation.dart'; +part 'comment.g.dart'; +@JsonSerializable(fieldRename: FieldRename.snake) +class Comment { + final int id; + final int userId; + final int taskId; + final int relationId; + final double creationDate; + final double modificationDate; + final String comment; + + Comment(this.id, this.userId, this.taskId, this.relationId, this.creationDate, + this.modificationDate, this.comment); + factory Comment.fromJson(Map json) => _$CommentFromJson(json); + Map toJson() => _$CommentToJson(this); +} diff --git a/lib/remote/models/comment.g.dart b/lib/remote/models/comment.g.dart new file mode 100644 index 0000000..0de7932 --- /dev/null +++ b/lib/remote/models/comment.g.dart @@ -0,0 +1,29 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'comment.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Comment _$CommentFromJson(Map json) { + return Comment( + json['id'] as int, + json['user_id'] as int, + json['task_id'] as int, + json['relation_id'] as int, + (json['creation_date'] as num)?.toDouble(), + (json['modification_date'] as num)?.toDouble(), + json['comment'] as String, + ); +} + +Map _$CommentToJson(Comment instance) => { + 'id': instance.id, + 'user_id': instance.userId, + 'task_id': instance.taskId, + 'relation_id': instance.relationId, + 'creation_date': instance.creationDate, + 'modification_date': instance.modificationDate, + 'comment': instance.comment, + }; diff --git a/lib/remote/repositories/comment_repository.dart b/lib/remote/repositories/comment_repository.dart new file mode 100644 index 0000000..f4fa6c9 --- /dev/null +++ b/lib/remote/repositories/comment_repository.dart @@ -0,0 +1,53 @@ +import 'package:mentorship_client/remote/api_manager.dart'; +import 'package:mentorship_client/remote/models/comment.dart'; +import 'package:mentorship_client/remote/requests/comment_request.dart'; +import 'package:mentorship_client/remote/responses/custom_response.dart'; + +class CommentRepository { + static final CommentRepository instance = CommentRepository._internal(); + + CommentRepository._internal(); + + Future> getAllComments(int relationId, int taskId) async { + final body = await ApiManager.callSafely( + () => ApiManager.instance.commentService.getAllComments(relationId, taskId)); + List comments = []; + + for (var json in body) { + comments.add(Comment.fromJson(json)); + } + + return comments; + } + + Future newComment( + int relationId, int taskId, CommentRequest commentRequest) async { + final body = await ApiManager.callSafely(() => ApiManager.instance.commentService.newComment( + relationId, + taskId, + commentRequest, + )); + + return CustomResponse.fromJson(body); + } + + Future editComment(int relationId, int taskId, int commentId) async { + final body = await ApiManager.callSafely(() => ApiManager.instance.commentService.editComment( + relationId, + taskId, + commentId, + )); + + return CustomResponse.fromJson(body); + } + + Future deleteCommemt(int relationId, int taskId, int commentId) async { + final body = await ApiManager.callSafely(() => ApiManager.instance.commentService.deleteComment( + relationId, + taskId, + commentId, + )); + + return CustomResponse.fromJson(body); + } +} diff --git a/lib/remote/requests/comment_request.dart b/lib/remote/requests/comment_request.dart new file mode 100644 index 0000000..cf0bbbf --- /dev/null +++ b/lib/remote/requests/comment_request.dart @@ -0,0 +1,16 @@ +import 'package:flutter/cupertino.dart'; + +class CommentRequest { + String comment; + + CommentRequest({@required this.comment}); + + factory CommentRequest.fromJson(Map json) => + CommentRequest(comment: json["comment"]); + + Map toJson() { + final Map data = new Map(); + data['comment'] = this.comment; + return data; + } +} diff --git a/lib/remote/services/comment_service.chopper.dart b/lib/remote/services/comment_service.chopper.dart new file mode 100644 index 0000000..d055266 --- /dev/null +++ b/lib/remote/services/comment_service.chopper.dart @@ -0,0 +1,52 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'comment_service.dart'; + +// ************************************************************************** +// ChopperGenerator +// ************************************************************************** + +// ignore_for_file: always_put_control_body_on_new_line, always_specify_types, prefer_const_declarations +class _$CommentService extends CommentService { + _$CommentService([ChopperClient client]) { + if (client == null) return; + this.client = client; + } + + @override + final definitionType = CommentService; + + @override + Future>> getAllComments(int relationId, int taskId) { + final $url = 'mentorship_relation/$relationId/task/$taskId/comments'; + final $request = Request('GET', $url, client.baseUrl); + return client.send, List>($request); + } + + @override + Future>> newComment( + int relationId, int taskId, CommentRequest commentRequest) { + final $url = 'mentorship_relation/$relationId/task/$taskId/comment'; + final $body = commentRequest; + final $request = Request('POST', $url, client.baseUrl, body: $body); + return client.send, Map>($request); + } + + @override + Future>> editComment( + int relationId, int taskId, int commentId) { + final $url = + 'mentorship_relation/$relationId/task/$taskId/comment/$commentId'; + final $request = Request('PUT', $url, client.baseUrl); + return client.send, Map>($request); + } + + @override + Future>> deleteComment( + int relationId, int taskId, int commentId) { + final $url = + 'mentorship_relation/$relationId/task/$taskId/comment/$commentId'; + final $request = Request('DELETE', $url, client.baseUrl); + return client.send, Map>($request); + } +} diff --git a/lib/remote/services/comment_service.dart b/lib/remote/services/comment_service.dart new file mode 100644 index 0000000..85eeaf4 --- /dev/null +++ b/lib/remote/services/comment_service.dart @@ -0,0 +1,51 @@ +import 'package:chopper/chopper.dart'; +import 'package:mentorship_client/constants.dart'; +import 'package:mentorship_client/remote/auth_interceptor.dart'; +import 'package:mentorship_client/remote/requests/comment_request.dart'; + +part 'comment_service.chopper.dart'; + +@ChopperApi(baseUrl: "") +abstract class CommentService extends ChopperService { + @Get(path: "mentorship_relation/{relation_id}/task/{task_id}/comments") + Future>> getAllComments( + @Path("relation_id") int relationId, + @Path("task_id") int taskId, + ); + + @Post(path: "mentorship_relation/{relation_id}/task/{task_id}/comment") + Future>> newComment( + @Path("relation_id") int relationId, + @Path("task_id") int taskId, + @Body() CommentRequest commentRequest, + ); + + @Put(path: "mentorship_relation/{relation_id}/task/{task_id}/comment/{comment_id}") + Future>> editComment( + @Path("relation_id") int relationId, + @Path("task_id") int taskId, + @Path("comment_id") int commentId, + ); + + @Delete(path: "mentorship_relation/{relation_id}/task/{task_id}/comment/{comment_id}") + Future>> deleteComment( + @Path("relation_id") int relationId, + @Path("task_id") int taskId, + @Path("comment_id") int commentId, + ); + + static CommentService create() { + final client = ChopperClient( + baseUrl: API_URL, + services: [ + _$CommentService(), + ], + converter: JsonConverter(), + interceptors: [ + HttpLoggingInterceptor(), + AuthInterceptor(), + ]); + + return _$CommentService(client); + } +} diff --git a/lib/screens/comment/bloc/bloc.dart b/lib/screens/comment/bloc/bloc.dart new file mode 100644 index 0000000..47056b3 --- /dev/null +++ b/lib/screens/comment/bloc/bloc.dart @@ -0,0 +1,3 @@ +export 'comment_page_bloc.dart'; +export 'comment_page_event.dart'; +export 'comment_page_state.dart'; diff --git a/lib/screens/comment/bloc/comment_page_bloc.dart b/lib/screens/comment/bloc/comment_page_bloc.dart new file mode 100644 index 0000000..c6027b6 --- /dev/null +++ b/lib/screens/comment/bloc/comment_page_bloc.dart @@ -0,0 +1,56 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:logging/logging.dart'; +import 'package:mentorship_client/failure.dart'; +import 'package:mentorship_client/remote/models/comment.dart'; +import 'package:mentorship_client/remote/repositories/comment_repository.dart'; +import 'package:mentorship_client/remote/repositories/relation_repository.dart'; +import 'package:mentorship_client/remote/repositories/task_repository.dart'; +import 'package:mentorship_client/remote/responses/custom_response.dart'; +import 'bloc.dart'; + +class CommentPageBloc extends Bloc { + final RelationRepository relationRepository; + final TaskRepository taskRepository; + final CommentRepository commentRepository; + CommentPageBloc(this.relationRepository, this.taskRepository, this.commentRepository) + : super(CommentPageInitial()); + + @override + Stream mapEventToState(CommentPageEvent event) async* { + if (event is CommentPageShowed) { + yield CommentPageInitial(); + try { + List comments = + await commentRepository.getAllComments(event.relation.id, event.taskId); + yield CommentPageSuccess(comments); + } on Failure catch (failure) { + Logger.root.severe("CommentPageBloc: ${failure.message}"); + yield CommentPageFailure(message: failure.message); + } + } + if (event is CommentCreated) { + try { + CustomResponse response = await commentRepository.newComment( + event.relation.id, event.taskId, event.commentRequest); + var comments = await commentRepository.getAllComments(event.relation.id, event.taskId); + yield CommentPageSuccess(comments, message: response.message); + } on Failure catch (failure) { + Logger.root.severe("CommentPageBloc: ${failure.message}"); + yield CommentPageFailure(message: failure.message); + } + } + if (event is CommentDeleted) { + try { + CustomResponse response = + await commentRepository.deleteCommemt(event.relation.id, event.taskId, event.commentId); + var comments = await commentRepository.getAllComments(event.relation.id, event.taskId); + yield CommentPageSuccess(comments, message: response.message); + } on Failure catch (failure) { + Logger.root.severe("CommentPageBloc: ${failure.message}"); + yield CommentPageFailure(message: failure.message); + } + } + } +} diff --git a/lib/screens/comment/bloc/comment_page_event.dart b/lib/screens/comment/bloc/comment_page_event.dart new file mode 100644 index 0000000..ce1ad8c --- /dev/null +++ b/lib/screens/comment/bloc/comment_page_event.dart @@ -0,0 +1,43 @@ +import 'package:equatable/equatable.dart'; +import 'package:mentorship_client/remote/models/relation.dart'; +import 'package:mentorship_client/remote/requests/comment_request.dart'; + +abstract class CommentPageEvent extends Equatable { + const CommentPageEvent(); +} + +class CommentPageShowed extends CommentPageEvent { + final Relation relation; + final int taskId; + + CommentPageShowed(this.relation, this.taskId); + @override + List get props => [relation, taskId]; +} + +// class CommentPageRefresh extends CommentPageEvent { +// @override +// List get props => null; +// } + +class CommentCreated extends CommentPageEvent { + final Relation relation; + final int taskId; + final CommentRequest commentRequest; + + CommentCreated(this.relation, this.taskId, this.commentRequest); + + @override + List get props => [relation, taskId, commentRequest]; +} + +class CommentDeleted extends CommentPageEvent { + final Relation relation; + final int taskId; + final int commentId; + + CommentDeleted(this.relation, this.taskId, this.commentId); + + @override + List get props => [relation, taskId]; +} diff --git a/lib/screens/comment/bloc/comment_page_state.dart b/lib/screens/comment/bloc/comment_page_state.dart new file mode 100644 index 0000000..4f44e6f --- /dev/null +++ b/lib/screens/comment/bloc/comment_page_state.dart @@ -0,0 +1,38 @@ +import 'package:equatable/equatable.dart'; +import 'package:mentorship_client/remote/models/comment.dart'; +import 'package:mentorship_client/remote/models/relation.dart'; + +abstract class CommentPageState extends Equatable { + final String message; + + const CommentPageState({this.message}); + + @override + List get props => [message]; +} + +class CommentPageInitial extends CommentPageState { + CommentPageInitial({String message}) : super(message: message); + + @override + List get props => [message]; +} + +class CommentPageSuccess extends CommentPageState { + // final Relation relation; + // final int taskId; + final List comments; + + CommentPageSuccess(this.comments, {String message}) + : super(message: message); + + @override + List get props => [message, comments]; +} + +class CommentPageFailure extends CommentPageState { + CommentPageFailure({String message}) : super(message: message); + + @override + List get props => [message]; +} diff --git a/lib/screens/comment/comments_page.dart b/lib/screens/comment/comments_page.dart new file mode 100644 index 0000000..d56961c --- /dev/null +++ b/lib/screens/comment/comments_page.dart @@ -0,0 +1,118 @@ +import 'dart:async'; + +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:mentorship_client/remote/models/relation.dart'; +import 'package:mentorship_client/remote/models/task.dart'; +import 'package:mentorship_client/remote/repositories/comment_repository.dart'; +import 'package:mentorship_client/remote/repositories/relation_repository.dart'; +import 'package:mentorship_client/remote/repositories/task_repository.dart'; +import 'package:mentorship_client/screens/comment/bloc/bloc.dart'; +import 'package:mentorship_client/widgets/loading_indicator.dart'; + +class CommentsPage extends StatefulWidget { + final Relation relation; + final Task task; + CommentsPage({this.task, this.relation}); + + @override + _CommentsPageState createState() => _CommentsPageState(); +} + +class _CommentsPageState extends State { + ScrollController _scrollController = ScrollController(); + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => CommentPageBloc( + RelationRepository.instance, + TaskRepository.instance, + CommentRepository.instance, + + )..add(CommentPageShowed(widget.relation, widget.task.id)), + child: Scaffold( + appBar: AppBar( + title: Text("Comments"), + ), + body: BlocBuilder( + builder: (context, state) { + if (state is CommentPageSuccess) { + Timer( + Duration(milliseconds: 300), + () => _scrollController.animateTo( + _scrollController.position.maxScrollExtent, + duration: Duration(milliseconds: 500), + curve: Curves.fastOutSlowIn, + ), + ); + return Stack( + children: [ + Padding( + padding: EdgeInsets.only( + top: MediaQuery.of(context).size.height * 0.05, + bottom: MediaQuery.of(context).size.height * 0.08), + child: ListView.separated( + separatorBuilder: (context, index) => Divider(), + controller: _scrollController, + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: state.comments.length, + itemBuilder: (context, i) { + return ListTile( + title: Column( + children: [ + widget.relation.actionUserId == state.comments[i].userId + ? Text("You") + : Text(widget.relation.mentor.name), + Text(state.comments[i].comment), + ], + ), + ); + }, + ), + ), + Container( + padding: EdgeInsets.all(8), + child: AutoSizeText( + "Task: " + widget.task.description, + style: TextStyle(fontSize: MediaQuery.of(context).size.height * 0.04), + ), + width: double.infinity, + color: Colors.grey[100], + height: MediaQuery.of(context).size.height * 0.05, + ), + Align( + alignment: Alignment.bottomCenter, + child: Container( + color: Colors.white, + child: Padding( + padding: EdgeInsets.all(MediaQuery.of(context).size.height * 0.01), + child: TextField( + decoration: InputDecoration(hintText: "Enter your response."), + ), + ), + ), + ), + ], + ); + } + return LoadingIndicator(); + }, + ), + ), + ); + } +} + +// BlocBuilder( +// builder: (context, state) { +// if (state is CommentPageSuccess) { +// return Container( +// child: Text(relation.mentor.id.toString()), +// ); +// } +// return LoadingIndicator(); +// }, +// ), diff --git a/lib/screens/home/pages/relation/relation_page.dart b/lib/screens/home/pages/relation/relation_page.dart index 3f78990..9cdfe1c 100644 --- a/lib/screens/home/pages/relation/relation_page.dart +++ b/lib/screens/home/pages/relation/relation_page.dart @@ -9,6 +9,7 @@ import 'package:mentorship_client/remote/requests/task_request.dart'; import 'package:mentorship_client/screens/home/bloc/bloc.dart'; import 'package:mentorship_client/screens/home/bloc/home_bloc.dart'; import 'package:mentorship_client/screens/home/pages/relation/bloc/bloc.dart'; +import 'package:mentorship_client/screens/comment/comments_page.dart'; import 'package:mentorship_client/widgets/bold_text.dart'; import 'package:mentorship_client/widgets/loading_indicator.dart'; import 'package:auto_size_text/auto_size_text.dart'; @@ -211,38 +212,30 @@ class _RelationPageState extends State { //ignore: close_sinks final bloc = BlocProvider.of(context); - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - GestureDetector( - onTap: () { - if (!task.isDone) { - bloc.add(TaskCompleted(state.relation, task.id)); - showProgressIndicator(context); - } else - context.toast("Task already achieved."); - }, - child: Checkbox( - value: task.isDone, - ), + return ListTile( + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => CommentsPage( + relation: state.relation, + task: task, ), - Text(task.description), - ], - ), - IconButton( - icon: Icon( - Icons.delete, - color: Colors.grey[700], ), - onPressed: () { + ); + }, + title: Text( + task.description, + maxLines: 2, + ), + leading: Checkbox( + value: task.isDone, + onChanged: (value) { + if (!task.isDone) { showDialog( context: context, builder: (context) => AlertDialog( - title: Text("Delete task"), - content: Text("Are you sure you want to delete the task?"), + title: Text("Complete Task"), + content: Text("Mark task as completed?"), actions: [ FlatButton( onPressed: () { @@ -251,9 +244,9 @@ class _RelationPageState extends State { child: Text("Cancel"), ), FlatButton( - child: Text("Delete"), + child: Text("Yes"), onPressed: () { - bloc.add(TaskDeleted(state.relation, task.id)); + bloc.add(TaskCompleted(state.relation, task.id)); Navigator.of(context).pop(); showProgressIndicator(context); }, @@ -261,9 +254,41 @@ class _RelationPageState extends State { ], ), ); - }, + } else + context.toast("Task already achieved."); + }, + ), + trailing: IconButton( + icon: Icon( + Icons.delete, + color: Colors.grey[700], ), - ], + onPressed: () { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text("Delete task"), + content: Text("Are you sure you want to delete the task?"), + actions: [ + FlatButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text("Cancel"), + ), + FlatButton( + child: Text("Delete"), + onPressed: () { + bloc.add(TaskDeleted(state.relation, task.id)); + Navigator.of(context).pop(); + showProgressIndicator(context); + }, + ), + ], + ), + ); + }, + ), ); }, ); diff --git a/lib/screens/login/login_screen.dart b/lib/screens/login/login_screen.dart index 05f823f..5e0b319 100644 --- a/lib/screens/login/login_screen.dart +++ b/lib/screens/login/login_screen.dart @@ -23,7 +23,7 @@ class LoginScreen extends StatelessWidget { SizedBox(height: 24), Padding( padding: EdgeInsets.symmetric(horizontal: 24), - child: LoginForm(), + child: LoginForm(), ), ], ), diff --git a/lib/screens/send_request/send_request_screen.dart b/lib/screens/send_request/send_request_screen.dart index 6eb9228..f014418 100644 --- a/lib/screens/send_request/send_request_screen.dart +++ b/lib/screens/send_request/send_request_screen.dart @@ -7,7 +7,6 @@ import 'package:mentorship_client/remote/repositories/relation_repository.dart'; import 'package:mentorship_client/remote/requests/relation_requests.dart'; import 'package:mentorship_client/screens/send_request/bloc/bloc.dart'; import 'package:mentorship_client/widgets/loading_indicator.dart'; -import 'package:toast/toast.dart'; class SendRequestScreen extends StatefulWidget { final User otherUser; @@ -30,7 +29,6 @@ class _SendRequestScreenState extends State { @override Widget build(BuildContext context) { //ignore: close_sinks - return BlocProvider( create: (context) => SendRequestBloc(relationRepository: RelationRepository.instance), child: Scaffold( diff --git a/pubspec.lock b/pubspec.lock index dd4a0fe..ff5ded0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -35,7 +35,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.1" + version: "2.5.0-nullsafety" auto_size_text: dependency: "direct main" description: @@ -49,14 +49,14 @@ packages: name: bloc url: "https://pub.dartlang.org" source: hosted - version: "6.0.1" + version: "6.0.2" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety" bottom_navy_bar: dependency: "direct main" description: @@ -120,13 +120,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "7.0.9" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0-nullsafety.2" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.3" + version: "1.2.0-nullsafety" checked_yaml: dependency: transitive description: @@ -161,7 +168,7 @@ packages: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.1.0-nullsafety" code_builder: dependency: transitive description: @@ -175,7 +182,7 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.12" + version: "1.15.0-nullsafety.2" color: dependency: transitive description: @@ -238,7 +245,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.0-nullsafety" fixnum: dependency: transitive description: @@ -373,6 +380,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.1" + json_serializable: + dependency: "direct main" + description: + name: json_serializable + url: "https://pub.dartlang.org" + source: hosted + version: "3.4.0" logging: dependency: transitive description: @@ -386,14 +400,14 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.6" + version: "0.12.10-nullsafety" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety.2" mime: dependency: transitive description: @@ -442,7 +456,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety" pedantic: dependency: transitive description: @@ -531,28 +545,28 @@ packages: name: source_gen url: "https://pub.dartlang.org" source: hosted - version: "0.9.5" + version: "0.9.6" source_span: dependency: transitive description: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.10.0-nullsafety" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety" stream_transform: dependency: transitive description: @@ -566,21 +580,21 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0-nullsafety" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.16" + version: "0.2.19-nullsafety" timing: dependency: transitive description: @@ -601,7 +615,7 @@ packages: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0-nullsafety.2" url_launcher: dependency: "direct main" description: @@ -643,7 +657,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety.2" watcher: dependency: transitive description: @@ -673,5 +687,5 @@ packages: source: hosted version: "2.2.0" sdks: - dart: ">=2.7.0 <3.0.0" + dart: ">=2.10.0-0.0.dev <2.10.0" flutter: ">=1.16.0 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 4e2d84c..278ed03 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -33,8 +33,9 @@ dependencies: expandable: ^4.1.4 auto_size_text: ^2.1.0 flappy_search_bar: ^1.7.2 + json_serializable: ^3.4.0 # Bloc - bloc: ^6.0.1 + bloc: ^6.0.2 flutter_bloc: ^6.0.1 chopper: ^3.0.3 diff --git a/token.txt b/token.txt new file mode 100644 index 0000000..accd492 --- /dev/null +++ b/token.txt @@ -0,0 +1 @@ +Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTgwNDYxNjksIm5iZiI6MTU5ODA0NjE2OSwianRpIjoiMDYyN2E3NWYtOTkzYi00MDFhLTg2ZjEtMDUyNDExODlmODIyIiwiZXhwIjoxNTk4NjUwOTY5LCJpZGVudGl0eSI6MzYyLCJmcmVzaCI6ZmFsc2UsInR5cGUiOiJhY2Nlc3MifQ.EuWP-C3DyWqc5-TUD-nh7Zk7el-ZiFob6AjSj74z73M \ No newline at end of file From f15ca79c4533d6b95692cf477b30dc06812668d6 Mon Sep 17 00:00:00 2001 From: Jayesh Nirve Date: Mon, 24 Aug 2020 06:50:11 +0530 Subject: [PATCH 4/7] Delete token.txt --- token.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 token.txt diff --git a/token.txt b/token.txt deleted file mode 100644 index accd492..0000000 --- a/token.txt +++ /dev/null @@ -1 +0,0 @@ -Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTgwNDYxNjksIm5iZiI6MTU5ODA0NjE2OSwianRpIjoiMDYyN2E3NWYtOTkzYi00MDFhLTg2ZjEtMDUyNDExODlmODIyIiwiZXhwIjoxNTk4NjUwOTY5LCJpZGVudGl0eSI6MzYyLCJmcmVzaCI6ZmFsc2UsInR5cGUiOiJhY2Nlc3MifQ.EuWP-C3DyWqc5-TUD-nh7Zk7el-ZiFob6AjSj74z73M \ No newline at end of file From 2391e8d7d38cdd5e702e5e19b7979bebf159cf90 Mon Sep 17 00:00:00 2001 From: Jayesh Nirve Date: Tue, 25 Aug 2020 05:54:00 +0530 Subject: [PATCH 5/7] Comments done :) --- lib/constants.dart | 2 +- lib/remote/models/user.dart | 2 +- .../repositories/comment_repository.dart | 4 +- lib/remote/requests/change_password.dart | 2 +- lib/remote/requests/comment_request.dart | 2 +- lib/remote/requests/relation_requests.dart | 2 +- lib/remote/requests/task_request.dart | 2 +- .../services/comment_service.chopper.dart | 7 +- lib/remote/services/comment_service.dart | 1 + .../comment/bloc/comment_page_bloc.dart | 13 +- .../comment/bloc/comment_page_event.dart | 12 + .../comment/bloc/comment_page_state.dart | 8 +- lib/screens/comment/comments_page.dart | 274 +++++++++++++++--- 13 files changed, 275 insertions(+), 56 deletions(-) diff --git a/lib/constants.dart b/lib/constants.dart index 9f02ac1..c5b374c 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -1,4 +1,4 @@ -const String API_URL = "https://mentorship-backend-temp.herokuapp.com/"; +const String API_URL = "http://f8f090446eef.ngrok.io/"; const String STATS_PAGE_TITLE = "Home"; const String PROFILE_PAGE_TITLE = "My Profile"; diff --git a/lib/remote/models/user.dart b/lib/remote/models/user.dart index 40d4d46..4fead77 100644 --- a/lib/remote/models/user.dart +++ b/lib/remote/models/user.dart @@ -58,7 +58,7 @@ class User { ); Map toJson() { - final Map data = new Map(); + final Map data = Map(); data['id'] = this.id; data['username'] = this.username; data['name'] = this.name; diff --git a/lib/remote/repositories/comment_repository.dart b/lib/remote/repositories/comment_repository.dart index f4fa6c9..e3337f1 100644 --- a/lib/remote/repositories/comment_repository.dart +++ b/lib/remote/repositories/comment_repository.dart @@ -31,11 +31,13 @@ class CommentRepository { return CustomResponse.fromJson(body); } - Future editComment(int relationId, int taskId, int commentId) async { + Future editComment( + int relationId, int taskId, int commentId, CommentRequest commentRequest) async { final body = await ApiManager.callSafely(() => ApiManager.instance.commentService.editComment( relationId, taskId, commentId, + commentRequest, )); return CustomResponse.fromJson(body); diff --git a/lib/remote/requests/change_password.dart b/lib/remote/requests/change_password.dart index 210590b..2a730d6 100644 --- a/lib/remote/requests/change_password.dart +++ b/lib/remote/requests/change_password.dart @@ -14,7 +14,7 @@ class ChangePassword { } Map toJson() { - final Map data = new Map(); + final Map data = Map(); data["current_password"] = this.currentPassword; data["new_password"] = this.newPassword; return data; diff --git a/lib/remote/requests/comment_request.dart b/lib/remote/requests/comment_request.dart index cf0bbbf..895f8db 100644 --- a/lib/remote/requests/comment_request.dart +++ b/lib/remote/requests/comment_request.dart @@ -9,7 +9,7 @@ class CommentRequest { CommentRequest(comment: json["comment"]); Map toJson() { - final Map data = new Map(); + final Map data = Map(); data['comment'] = this.comment; return data; } diff --git a/lib/remote/requests/relation_requests.dart b/lib/remote/requests/relation_requests.dart index 9e9ee92..1786a1c 100644 --- a/lib/remote/requests/relation_requests.dart +++ b/lib/remote/requests/relation_requests.dart @@ -19,7 +19,7 @@ class RelationRequest { ); Map toJson() { - final Map data = new Map(); + final Map data = Map(); data['mentor_id'] = this.mentorId; data['mentee_id'] = this.menteeId; data['notes'] = this.notes; diff --git a/lib/remote/requests/task_request.dart b/lib/remote/requests/task_request.dart index 6a50c77..2439018 100644 --- a/lib/remote/requests/task_request.dart +++ b/lib/remote/requests/task_request.dart @@ -9,7 +9,7 @@ class TaskRequest { TaskRequest(description: json["description"]); Map toJson() { - final Map data = new Map(); + final Map data = Map(); data['description'] = this.description; return data; } diff --git a/lib/remote/services/comment_service.chopper.dart b/lib/remote/services/comment_service.chopper.dart index d055266..9c7e37e 100644 --- a/lib/remote/services/comment_service.chopper.dart +++ b/lib/remote/services/comment_service.chopper.dart @@ -33,11 +33,12 @@ class _$CommentService extends CommentService { } @override - Future>> editComment( - int relationId, int taskId, int commentId) { + Future>> editComment(int relationId, int taskId, + int commentId, CommentRequest commentRequest) { final $url = 'mentorship_relation/$relationId/task/$taskId/comment/$commentId'; - final $request = Request('PUT', $url, client.baseUrl); + final $body = commentRequest; + final $request = Request('PUT', $url, client.baseUrl, body: $body); return client.send, Map>($request); } diff --git a/lib/remote/services/comment_service.dart b/lib/remote/services/comment_service.dart index 85eeaf4..1fe5239 100644 --- a/lib/remote/services/comment_service.dart +++ b/lib/remote/services/comment_service.dart @@ -25,6 +25,7 @@ abstract class CommentService extends ChopperService { @Path("relation_id") int relationId, @Path("task_id") int taskId, @Path("comment_id") int commentId, + @Body() CommentRequest commentRequest, ); @Delete(path: "mentorship_relation/{relation_id}/task/{task_id}/comment/{comment_id}") diff --git a/lib/screens/comment/bloc/comment_page_bloc.dart b/lib/screens/comment/bloc/comment_page_bloc.dart index c6027b6..92dc6b9 100644 --- a/lib/screens/comment/bloc/comment_page_bloc.dart +++ b/lib/screens/comment/bloc/comment_page_bloc.dart @@ -20,7 +20,7 @@ class CommentPageBloc extends Bloc { @override Stream mapEventToState(CommentPageEvent event) async* { if (event is CommentPageShowed) { - yield CommentPageInitial(); + yield CommentPageLoading(); try { List comments = await commentRepository.getAllComments(event.relation.id, event.taskId); @@ -41,6 +41,17 @@ class CommentPageBloc extends Bloc { yield CommentPageFailure(message: failure.message); } } + if (event is CommentEditing) { + try { + CustomResponse response = await commentRepository.editComment( + event.relation.id, event.taskId, event.commentId, event.commentRequest); + var comments = await commentRepository.getAllComments(event.relation.id, event.taskId); + yield CommentPageSuccess(comments, message: response.message); + } on Failure catch (failure) { + Logger.root.severe("CommentPageBloc: ${failure.message}"); + yield CommentPageFailure(message: failure.message); + } + } if (event is CommentDeleted) { try { CustomResponse response = diff --git a/lib/screens/comment/bloc/comment_page_event.dart b/lib/screens/comment/bloc/comment_page_event.dart index ce1ad8c..7099bc0 100644 --- a/lib/screens/comment/bloc/comment_page_event.dart +++ b/lib/screens/comment/bloc/comment_page_event.dart @@ -31,6 +31,18 @@ class CommentCreated extends CommentPageEvent { List get props => [relation, taskId, commentRequest]; } +class CommentEditing extends CommentPageEvent { + final Relation relation; + final int taskId; + final int commentId; + final CommentRequest commentRequest; + + CommentEditing(this.relation, this.taskId, this.commentId, this.commentRequest); + + @override + List get props => [relation, taskId]; +} + class CommentDeleted extends CommentPageEvent { final Relation relation; final int taskId; diff --git a/lib/screens/comment/bloc/comment_page_state.dart b/lib/screens/comment/bloc/comment_page_state.dart index 4f44e6f..8c0271a 100644 --- a/lib/screens/comment/bloc/comment_page_state.dart +++ b/lib/screens/comment/bloc/comment_page_state.dart @@ -1,6 +1,5 @@ import 'package:equatable/equatable.dart'; import 'package:mentorship_client/remote/models/comment.dart'; -import 'package:mentorship_client/remote/models/relation.dart'; abstract class CommentPageState extends Equatable { final String message; @@ -18,13 +17,16 @@ class CommentPageInitial extends CommentPageState { List get props => [message]; } +class CommentPageLoading extends CommentPageState { + CommentPageLoading({String message}) : super(message: message); +} + class CommentPageSuccess extends CommentPageState { // final Relation relation; // final int taskId; final List comments; - CommentPageSuccess(this.comments, {String message}) - : super(message: message); + CommentPageSuccess(this.comments, {String message}) : super(message: message); @override List get props => [message, comments]; diff --git a/lib/screens/comment/comments_page.dart b/lib/screens/comment/comments_page.dart index d56961c..760cfa0 100644 --- a/lib/screens/comment/comments_page.dart +++ b/lib/screens/comment/comments_page.dart @@ -4,13 +4,16 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:intl/intl.dart'; import 'package:mentorship_client/remote/models/relation.dart'; import 'package:mentorship_client/remote/models/task.dart'; import 'package:mentorship_client/remote/repositories/comment_repository.dart'; import 'package:mentorship_client/remote/repositories/relation_repository.dart'; import 'package:mentorship_client/remote/repositories/task_repository.dart'; +import 'package:mentorship_client/remote/requests/comment_request.dart'; import 'package:mentorship_client/screens/comment/bloc/bloc.dart'; import 'package:mentorship_client/widgets/loading_indicator.dart'; +import 'package:toast/toast.dart'; class CommentsPage extends StatefulWidget { final Relation relation; @@ -23,14 +26,23 @@ class CommentsPage extends StatefulWidget { class _CommentsPageState extends State { ScrollController _scrollController = ScrollController(); + final _textController = TextEditingController(); + + @override + void dispose() { + _scrollController.dispose(); + _textController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { + final focus = FocusNode(); return BlocProvider( create: (context) => CommentPageBloc( RelationRepository.instance, TaskRepository.instance, CommentRepository.instance, - )..add(CommentPageShowed(widget.relation, widget.task.id)), child: Scaffold( appBar: AppBar( @@ -40,39 +52,52 @@ class _CommentsPageState extends State { builder: (context, state) { if (state is CommentPageSuccess) { Timer( - Duration(milliseconds: 300), - () => _scrollController.animateTo( - _scrollController.position.maxScrollExtent, - duration: Duration(milliseconds: 500), - curve: Curves.fastOutSlowIn, - ), + Duration(milliseconds: 0), + () => _scrollController.jumpTo(_scrollController.position.maxScrollExtent), ); return Stack( children: [ - Padding( - padding: EdgeInsets.only( - top: MediaQuery.of(context).size.height * 0.05, - bottom: MediaQuery.of(context).size.height * 0.08), - child: ListView.separated( - separatorBuilder: (context, index) => Divider(), - controller: _scrollController, - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: state.comments.length, - itemBuilder: (context, i) { - return ListTile( - title: Column( - children: [ - widget.relation.actionUserId == state.comments[i].userId - ? Text("You") - : Text(widget.relation.mentor.name), - Text(state.comments[i].comment), - ], + state.comments.isEmpty + ? Center( + child: Text("You can add comments about the task here"), + ) + : Padding( + padding: EdgeInsets.only( + top: MediaQuery.of(context).size.height * 0.1, + bottom: MediaQuery.of(context).size.height * 0.08), + child: ListView.separated( + separatorBuilder: (context, index) => Divider(), + controller: _scrollController, + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: state.comments.length, + itemBuilder: (context, i) { + return GestureDetector( + onLongPressStart: (LongPressStartDetails details) { + _showPopupMenu( + context, + details.globalPosition, + _textController, + widget.relation, + widget.task.id, + state.comments[i].id, + state.comments[i].comment, + ); + }, + child: ListTile( + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + readTimestamp(state.comments[i].creationDate).toString()), + Text(state.comments[i].comment), + ], + ), + ), + ); + }, ), - ); - }, - ), - ), + ), Container( padding: EdgeInsets.all(8), child: AutoSizeText( @@ -81,7 +106,7 @@ class _CommentsPageState extends State { ), width: double.infinity, color: Colors.grey[100], - height: MediaQuery.of(context).size.height * 0.05, + height: MediaQuery.of(context).size.height * 0.1, ), Align( alignment: Alignment.bottomCenter, @@ -90,7 +115,28 @@ class _CommentsPageState extends State { child: Padding( padding: EdgeInsets.all(MediaQuery.of(context).size.height * 0.01), child: TextField( - decoration: InputDecoration(hintText: "Enter your response."), + focusNode: focus, + controller: _textController, + decoration: InputDecoration( + hintText: "Add your comment.", + suffixIcon: IconButton( + icon: Icon(Icons.send), + onPressed: () { + BlocProvider.of(context) + ..add( + CommentCreated( + widget.relation, + widget.task.id, + CommentRequest( + comment: _textController.text, + ), + ), + ); + _textController.clear(); + FocusScope.of(context).requestFocus(FocusNode()); + Toast.show("Sending...", context, duration: 1); + }), + ), ), ), ), @@ -98,6 +144,24 @@ class _CommentsPageState extends State { ], ); } + if (state is CommentPageFailure) { + return Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(state.message), + RaisedButton( + child: Text("Go Back"), + onPressed: () => Navigator.pop(context), + ), + ], + ), + ); + } + if (state is CommentPageLoading) { + return LoadingIndicator(); + } return LoadingIndicator(); }, ), @@ -106,13 +170,139 @@ class _CommentsPageState extends State { } } -// BlocBuilder( -// builder: (context, state) { -// if (state is CommentPageSuccess) { -// return Container( -// child: Text(relation.mentor.id.toString()), -// ); -// } -// return LoadingIndicator(); -// }, -// ), +void _showPopupMenu(context, Offset offset, TextEditingController textEditingController, + Relation relation, int taskId, int commentId, String comment) async { + // ignore: close_sinks + final bloc = BlocProvider.of(context); + + double left = offset.dx; + double top = offset.dy; + await showMenu( + context: context, + position: RelativeRect.fromLTRB(left, top, 100000, 0), + items: [ + PopupMenuItem( + child: MaterialButton( + elevation: 0, + child: Text("Delete comment"), + onPressed: () { + Navigator.pop(context); + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text("Delete comment"), + content: Text("Are you sure you want to delete this comment?"), + actions: [ + FlatButton( + onPressed: () { + Navigator.pop(context); + }, + child: Text("Cancel"), + ), + FlatButton( + child: Text("Delete"), + onPressed: () { + bloc.add( + CommentDeleted( + relation, + taskId, + commentId, + ), + ); + Navigator.pop(context); + Toast.show("Deleting...", context, duration: 1); + }, + ), + ], + ), + ); + }, + ), + ), + PopupMenuItem( + child: MaterialButton( + elevation: 0, + child: Text("Edit comment"), + onPressed: () { + Navigator.pop(context); + _showDialog(context, comment, relation, taskId, commentId); + // FocusScope.of(context).requestFocus(focus); + }, + ), + ), + ], + ); +} + +_showDialog(context, String comment, Relation relation, int taskId, int commentId) async { + TextEditingController editingController = TextEditingController()..text = comment; + // ignore: close_sinks + final bloc = BlocProvider.of(context); + await showDialog( + context: context, + child: AlertDialog( + contentPadding: const EdgeInsets.all(16.0), + content: Row( + children: [ + Expanded( + child: TextField( + controller: editingController, + decoration: InputDecoration(labelText: 'Edit comment'), + ), + ) + ], + ), + actions: [ + FlatButton( + child: const Text('Cancel'), + onPressed: () { + Navigator.pop(context); + }), + FlatButton( + child: Text('Edit'), + onPressed: () { + bloc.add( + CommentEditing( + relation, + taskId, + commentId, + CommentRequest( + comment: editingController.text, + ), + ), + ); + Navigator.pop(context); + }) + ], + ), + ); +} + +String readTimestamp(double timestamp) { + var now = DateTime.now(); + var format = DateFormat('HH:mm a'); + var date = DateTime.fromMillisecondsSinceEpoch((timestamp * 1000).toInt()); + var diff = now.difference(date); + var time = ''; + + if (diff.inSeconds <= 0 || + diff.inSeconds > 0 && diff.inMinutes == 0 || + diff.inMinutes > 0 && diff.inHours == 0 || + diff.inHours > 0 && diff.inDays == 0) { + time = format.format(date); + } else if (diff.inDays > 0 && diff.inDays < 7) { + if (diff.inDays == 1) { + time = diff.inDays.toString() + ' day ago'; + } else { + time = diff.inDays.toString() + ' days ago'; + } + } else { + if (diff.inDays == 7) { + time = (diff.inDays / 7).floor().toString() + ' week ago'; + } else { + time = (diff.inDays / 7).floor().toString() + ' weeks ago'; + } + } + + return time; +} From ebb52edbc6b991f13868bf6a087f5c3223e7119b Mon Sep 17 00:00:00 2001 From: Jayesh Nirve Date: Tue, 25 Aug 2020 05:56:08 +0530 Subject: [PATCH 6/7] fix backend url --- lib/constants.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/constants.dart b/lib/constants.dart index c5b374c..9f02ac1 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -1,4 +1,4 @@ -const String API_URL = "http://f8f090446eef.ngrok.io/"; +const String API_URL = "https://mentorship-backend-temp.herokuapp.com/"; const String STATS_PAGE_TITLE = "Home"; const String PROFILE_PAGE_TITLE = "My Profile"; From dce385794677a280bc192c339fb2dd0b3bfb6b05 Mon Sep 17 00:00:00 2001 From: Jayesh Nirve Date: Tue, 25 Aug 2020 06:01:07 +0530 Subject: [PATCH 7/7] toast --- lib/screens/comment/comments_page.dart | 28 ++++++++++++++------------ 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/screens/comment/comments_page.dart b/lib/screens/comment/comments_page.dart index 760cfa0..c04dd41 100644 --- a/lib/screens/comment/comments_page.dart +++ b/lib/screens/comment/comments_page.dart @@ -259,20 +259,22 @@ _showDialog(context, String comment, Relation relation, int taskId, int commentI Navigator.pop(context); }), FlatButton( - child: Text('Edit'), - onPressed: () { - bloc.add( - CommentEditing( - relation, - taskId, - commentId, - CommentRequest( - comment: editingController.text, - ), + child: Text('Edit'), + onPressed: () { + bloc.add( + CommentEditing( + relation, + taskId, + commentId, + CommentRequest( + comment: editingController.text, ), - ); - Navigator.pop(context); - }) + ), + ); + Navigator.pop(context); + Toast.show("Editing...", context, duration: 1); + }, + ) ], ), );