From 8567453770d1162ee0d97ab33fd55d23f374a592 Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Thu, 24 Jun 2021 18:55:00 +0700 Subject: [PATCH 01/12] Fix: Wrong API URL --- lib/_utils/secret/url/base.dart | 2 +- lib/main.dart | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/_utils/secret/url/base.dart b/lib/_utils/secret/url/base.dart index 6ef716b..9f08a38 100644 --- a/lib/_utils/secret/url/base.dart +++ b/lib/_utils/secret/url/base.dart @@ -19,7 +19,7 @@ class Host { String get crawlBase { if (mode.isRelease){ - return 'https://utcapi.herokuapp.herokuapp.com/api-v2/app/crawl/'; + return 'https://utcapi.herokuapp.com/api-v2/app/crawl/'; } if (mode.isStaging){ diff --git a/lib/main.dart b/lib/main.dart index c8ffce4..85d780c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -18,14 +18,14 @@ void main() async { Paint.enableDithering = true; - AppMode mode = AppMode.staging; + AppMode mode = kReleaseMode ? AppMode.release : AppMode.staging; - print('Running in mode ${kReleaseMode ? AppMode.release : mode}'); + print('Running in mode $mode'); runApp( Phoenix( child: AppModeWidget( - mode: kReleaseMode ? AppMode.release : mode, + mode: mode, child: Application(), ), ), From a1c0cca47608e1d6389fca5c0562e89a8383fe1b Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Thu, 24 Jun 2021 22:04:10 +0700 Subject: [PATCH 02/12] Feat: Press back button to pop "Edit event" widget and "Notification details" widget --- lib/_widgets/wrapper/navigable_plan_page.dart | 5 +- lib/main.dart | 3 +- lib/notification/view/notification_page.dart | 8 ++++ lib/plan/bloc/plan_bloc.dart | 47 ++++++++++++------- lib/plan/view/plan_page.dart | 44 ++++++----------- lib/schedule/view/schedule_page.dart | 19 ++++---- 6 files changed, 67 insertions(+), 59 deletions(-) diff --git a/lib/_widgets/wrapper/navigable_plan_page.dart b/lib/_widgets/wrapper/navigable_plan_page.dart index 30f1071..a731202 100644 --- a/lib/_widgets/wrapper/navigable_plan_page.dart +++ b/lib/_widgets/wrapper/navigable_plan_page.dart @@ -20,7 +20,10 @@ class NavigablePlanPage extends StatelessWidget { return InheritedScrollToPlanPage( panelController: _panelController, child: BlocProvider( - create: (_) => PlanBloc(context), + create: (_) => PlanBloc( + context, + panelController: _panelController, + ), child: Stack( children: [ child, diff --git a/lib/main.dart b/lib/main.dart index 85d780c..ab56d32 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -18,7 +18,8 @@ void main() async { Paint.enableDithering = true; - AppMode mode = kReleaseMode ? AppMode.release : AppMode.staging; + AppMode devMode = AppMode.staging; + AppMode mode = kReleaseMode ? AppMode.release : devMode; print('Running in mode $mode'); diff --git a/lib/notification/view/notification_page.dart b/lib/notification/view/notification_page.dart index 3bc6384..51da6b5 100644 --- a/lib/notification/view/notification_page.dart +++ b/lib/notification/view/notification_page.dart @@ -41,6 +41,14 @@ class _NotificationPageState extends State { child: Stack( children: [ SharedUI( + onWillPop: () async{ + if (_panelController.isPanelOpen){ + await _panelController.close(); + return false; + } + + return true; + }, stable: false, child: Item( child: SmartRefresher( diff --git a/lib/plan/bloc/plan_bloc.dart b/lib/plan/bloc/plan_bloc.dart index f82daab..70b5f32 100644 --- a/lib/plan/bloc/plan_bloc.dart +++ b/lib/plan/bloc/plan_bloc.dart @@ -4,6 +4,7 @@ import 'package:app_qldt/_models/user_event_model.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; +import 'package:sliding_up_panel/sliding_up_panel.dart'; import 'enum/enum.dart'; @@ -14,7 +15,12 @@ part 'plan_event.dart'; part 'plan_state.dart'; class PlanBloc extends Bloc { - PlanBloc(BuildContext context) : super(PlanState(fromDay: DateTime.now(), toDay: DateTime.now())); + final PanelController panelController; + + PlanBloc( + BuildContext context, { + required this.panelController, + }) : super(PlanState(fromDay: DateTime.now(), toDay: DateTime.now())); @override Stream mapEventToState( @@ -45,15 +51,15 @@ class PlanBloc extends Bloc { } else if (event is PlanTimeChangedToCurrentTime) { yield _mapPlanChangedToCurrentTimeToState(event); } else if (event is ShowApartPlanPage) { - yield _mapShowApartPlanPageToState(event); + yield* _mapShowApartPlanPageToState(event); } else if (event is EditSchedule) { - yield _mapEditScheduleToState(event); + yield* _mapEditScheduleToState(event); } else if (event is EditEvent) { - yield _mapEditEventToState(event); + yield* _mapEditEventToState(event); } else if (event is OpenPlanPage) { - yield _mapOpenPlanPageToState(event); + yield* _mapOpenPlanPageToState(event); } else if (event is ClosePlanPage) { - yield _mapClosePlanPageToState(); + yield* _mapClosePlanPageToState(); } } @@ -108,18 +114,20 @@ class PlanBloc extends Bloc { ); } - PlanState _mapShowApartPlanPageToState(ShowApartPlanPage event) { - return state.copyWith( + Stream _mapShowApartPlanPageToState(ShowApartPlanPage event) async* { + yield state.copyWith( from: event.dateTime, to: event.dateTime.add(Duration(hours: 1)), visibility: PlanPageVisibility.apart, ); + + await panelController.animatePanelToPosition(0.3); } - PlanState _mapEditScheduleToState(EditSchedule event) { + Stream _mapEditScheduleToState(EditSchedule event) async* { final newEvent = event.event; - return state.copyWith( + yield state.copyWith( id: newEvent.id, title: newEvent.eventName, color: newEvent.color, @@ -129,12 +137,14 @@ class PlanBloc extends Bloc { location: newEvent.location, type: PlanType.editSchedule, ); + + await panelController.open(); } - PlanState _mapEditEventToState(EditEvent event) { + Stream _mapEditEventToState(EditEvent event) async* { final newEvent = event.event; - return state.copyWith( + yield state.copyWith( id: newEvent.id, title: newEvent.eventName, color: newEvent.color, @@ -144,10 +154,12 @@ class PlanBloc extends Bloc { visibility: PlanPageVisibility.open, type: PlanType.editEvent, ); + + await panelController.open(); } - PlanState _mapOpenPlanPageToState(OpenPlanPage event) { - return state.copyWith( + Stream _mapOpenPlanPageToState(OpenPlanPage event) async* { + yield state.copyWith( title: '', color: PlanColors.defaultColor, location: '', @@ -157,9 +169,12 @@ class PlanBloc extends Bloc { visibility: PlanPageVisibility.open, type: event.type ?? PlanType.create, ); + + await panelController.open(); } - PlanState _mapClosePlanPageToState() { - return state.copyWith(visibility: PlanPageVisibility.close); + Stream _mapClosePlanPageToState() async* { + yield state.copyWith(visibility: PlanPageVisibility.close); + await panelController.close(); } } diff --git a/lib/plan/view/plan_page.dart b/lib/plan/view/plan_page.dart index 90c81c2..2fdad44 100644 --- a/lib/plan/view/plan_page.dart +++ b/lib/plan/view/plan_page.dart @@ -2,11 +2,9 @@ import 'package:app_qldt/_widgets/list_tile/custom_list_tile.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:sliding_up_panel/sliding_up_panel.dart'; import 'package:app_qldt/plan/plan.dart'; import 'package:app_qldt/_utils/helper/day_of_week_vn.dart'; -import 'package:app_qldt/_widgets/model/inherited_scroll_to_plan_page.dart'; import 'local_widgets/local_widgets.dart'; @@ -27,34 +25,20 @@ class PlanPage extends StatefulWidget { class _PlanPageState extends State { @override Widget build(BuildContext context) { - return BlocListener( - listener: (context, state) async { - PanelController panelController = InheritedScrollToPlanPage.of(context).panelController; - - if (state.visibility == PlanPageVisibility.close && !panelController.isPanelClosed) { - await panelController.close(); - } else if (state.visibility == PlanPageVisibility.open && !panelController.isPanelOpen) { - await panelController.open(); - } else if (state.visibility == PlanPageVisibility.apart && - panelController.panelPosition != 0.3) { - await panelController.animatePanelToPosition(0.3); - } - }, - child: Scaffold( - body: BlocBuilder( - buildWhen: (previous, current) => - previous.fromDay != current.fromDay || previous.visibility != current.visibility, - builder: (context, state) { - if (state.visibility == PlanPageVisibility.open) { - return _FullPlanPage( - onCloseButtonTap: widget.onCloseButtonTap, - scrollController: widget.scrollController, - ); - } - - return _ApartPlanPage(onCloseButtonTap: widget.onCloseButtonTap); - }, - ), + return Scaffold( + body: BlocBuilder( + buildWhen: (previous, current) => + previous.fromDay != current.fromDay || previous.visibility != current.visibility, + builder: (context, state) { + if (state.visibility == PlanPageVisibility.open) { + return _FullPlanPage( + onCloseButtonTap: widget.onCloseButtonTap, + scrollController: widget.scrollController, + ); + } + + return _ApartPlanPage(onCloseButtonTap: widget.onCloseButtonTap); + }, ), ); } diff --git a/lib/schedule/view/schedule_page.dart b/lib/schedule/view/schedule_page.dart index 107a376..4ad1a10 100644 --- a/lib/schedule/view/schedule_page.dart +++ b/lib/schedule/view/schedule_page.dart @@ -35,7 +35,14 @@ class _SchedulePageState extends State { child: BlocBuilder( builder: (context, state) { return SharedUI( - onWillPop: () => _onWillPop(state), + onWillPop: () { + if (state.visibility != PlanPageVisibility.close) { + context.read().add(ClosePlanPage()); + return Future.value(false); + } + + return Future.value(null); + }, child: Item( child: Theme( key: _globalKey, @@ -63,14 +70,4 @@ class _SchedulePageState extends State { void _onPanelClose() { _controller.selectedDate = null; } - - Future _onWillPop(PlanState state) { - if (state.visibility != PlanPageVisibility.close) { - _controller.selectedDate = null; - context.read().add(ClosePlanPage()); - return Future.value(false); - } - - return Future.value(null); - } } From 339db9212c3e2516f0dde7c19802c0d52333c2ac Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Thu, 24 Jun 2021 22:04:10 +0700 Subject: [PATCH 03/12] Feat: Press back button to pop "Edit event" widget and "Notification details" widget --- lib/_widgets/wrapper/navigable_plan_page.dart | 5 +- lib/main.dart | 3 +- lib/notification/view/notification_page.dart | 8 ++++ lib/plan/bloc/plan_bloc.dart | 47 ++++++++++++------- lib/plan/view/plan_page.dart | 44 ++++++----------- lib/schedule/view/schedule_page.dart | 19 ++++---- 6 files changed, 67 insertions(+), 59 deletions(-) diff --git a/lib/_widgets/wrapper/navigable_plan_page.dart b/lib/_widgets/wrapper/navigable_plan_page.dart index 30f1071..a731202 100644 --- a/lib/_widgets/wrapper/navigable_plan_page.dart +++ b/lib/_widgets/wrapper/navigable_plan_page.dart @@ -20,7 +20,10 @@ class NavigablePlanPage extends StatelessWidget { return InheritedScrollToPlanPage( panelController: _panelController, child: BlocProvider( - create: (_) => PlanBloc(context), + create: (_) => PlanBloc( + context, + panelController: _panelController, + ), child: Stack( children: [ child, diff --git a/lib/main.dart b/lib/main.dart index 85d780c..ab56d32 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -18,7 +18,8 @@ void main() async { Paint.enableDithering = true; - AppMode mode = kReleaseMode ? AppMode.release : AppMode.staging; + AppMode devMode = AppMode.staging; + AppMode mode = kReleaseMode ? AppMode.release : devMode; print('Running in mode $mode'); diff --git a/lib/notification/view/notification_page.dart b/lib/notification/view/notification_page.dart index 3bc6384..4cc5b45 100644 --- a/lib/notification/view/notification_page.dart +++ b/lib/notification/view/notification_page.dart @@ -41,6 +41,14 @@ class _NotificationPageState extends State { child: Stack( children: [ SharedUI( + onWillPop: () async { + if (_panelController.isPanelOpen){ + await _panelController.close(); + return Future.value(false); + } + + return Future.value(null); + }, stable: false, child: Item( child: SmartRefresher( diff --git a/lib/plan/bloc/plan_bloc.dart b/lib/plan/bloc/plan_bloc.dart index f82daab..70b5f32 100644 --- a/lib/plan/bloc/plan_bloc.dart +++ b/lib/plan/bloc/plan_bloc.dart @@ -4,6 +4,7 @@ import 'package:app_qldt/_models/user_event_model.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; +import 'package:sliding_up_panel/sliding_up_panel.dart'; import 'enum/enum.dart'; @@ -14,7 +15,12 @@ part 'plan_event.dart'; part 'plan_state.dart'; class PlanBloc extends Bloc { - PlanBloc(BuildContext context) : super(PlanState(fromDay: DateTime.now(), toDay: DateTime.now())); + final PanelController panelController; + + PlanBloc( + BuildContext context, { + required this.panelController, + }) : super(PlanState(fromDay: DateTime.now(), toDay: DateTime.now())); @override Stream mapEventToState( @@ -45,15 +51,15 @@ class PlanBloc extends Bloc { } else if (event is PlanTimeChangedToCurrentTime) { yield _mapPlanChangedToCurrentTimeToState(event); } else if (event is ShowApartPlanPage) { - yield _mapShowApartPlanPageToState(event); + yield* _mapShowApartPlanPageToState(event); } else if (event is EditSchedule) { - yield _mapEditScheduleToState(event); + yield* _mapEditScheduleToState(event); } else if (event is EditEvent) { - yield _mapEditEventToState(event); + yield* _mapEditEventToState(event); } else if (event is OpenPlanPage) { - yield _mapOpenPlanPageToState(event); + yield* _mapOpenPlanPageToState(event); } else if (event is ClosePlanPage) { - yield _mapClosePlanPageToState(); + yield* _mapClosePlanPageToState(); } } @@ -108,18 +114,20 @@ class PlanBloc extends Bloc { ); } - PlanState _mapShowApartPlanPageToState(ShowApartPlanPage event) { - return state.copyWith( + Stream _mapShowApartPlanPageToState(ShowApartPlanPage event) async* { + yield state.copyWith( from: event.dateTime, to: event.dateTime.add(Duration(hours: 1)), visibility: PlanPageVisibility.apart, ); + + await panelController.animatePanelToPosition(0.3); } - PlanState _mapEditScheduleToState(EditSchedule event) { + Stream _mapEditScheduleToState(EditSchedule event) async* { final newEvent = event.event; - return state.copyWith( + yield state.copyWith( id: newEvent.id, title: newEvent.eventName, color: newEvent.color, @@ -129,12 +137,14 @@ class PlanBloc extends Bloc { location: newEvent.location, type: PlanType.editSchedule, ); + + await panelController.open(); } - PlanState _mapEditEventToState(EditEvent event) { + Stream _mapEditEventToState(EditEvent event) async* { final newEvent = event.event; - return state.copyWith( + yield state.copyWith( id: newEvent.id, title: newEvent.eventName, color: newEvent.color, @@ -144,10 +154,12 @@ class PlanBloc extends Bloc { visibility: PlanPageVisibility.open, type: PlanType.editEvent, ); + + await panelController.open(); } - PlanState _mapOpenPlanPageToState(OpenPlanPage event) { - return state.copyWith( + Stream _mapOpenPlanPageToState(OpenPlanPage event) async* { + yield state.copyWith( title: '', color: PlanColors.defaultColor, location: '', @@ -157,9 +169,12 @@ class PlanBloc extends Bloc { visibility: PlanPageVisibility.open, type: event.type ?? PlanType.create, ); + + await panelController.open(); } - PlanState _mapClosePlanPageToState() { - return state.copyWith(visibility: PlanPageVisibility.close); + Stream _mapClosePlanPageToState() async* { + yield state.copyWith(visibility: PlanPageVisibility.close); + await panelController.close(); } } diff --git a/lib/plan/view/plan_page.dart b/lib/plan/view/plan_page.dart index 90c81c2..2fdad44 100644 --- a/lib/plan/view/plan_page.dart +++ b/lib/plan/view/plan_page.dart @@ -2,11 +2,9 @@ import 'package:app_qldt/_widgets/list_tile/custom_list_tile.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:sliding_up_panel/sliding_up_panel.dart'; import 'package:app_qldt/plan/plan.dart'; import 'package:app_qldt/_utils/helper/day_of_week_vn.dart'; -import 'package:app_qldt/_widgets/model/inherited_scroll_to_plan_page.dart'; import 'local_widgets/local_widgets.dart'; @@ -27,34 +25,20 @@ class PlanPage extends StatefulWidget { class _PlanPageState extends State { @override Widget build(BuildContext context) { - return BlocListener( - listener: (context, state) async { - PanelController panelController = InheritedScrollToPlanPage.of(context).panelController; - - if (state.visibility == PlanPageVisibility.close && !panelController.isPanelClosed) { - await panelController.close(); - } else if (state.visibility == PlanPageVisibility.open && !panelController.isPanelOpen) { - await panelController.open(); - } else if (state.visibility == PlanPageVisibility.apart && - panelController.panelPosition != 0.3) { - await panelController.animatePanelToPosition(0.3); - } - }, - child: Scaffold( - body: BlocBuilder( - buildWhen: (previous, current) => - previous.fromDay != current.fromDay || previous.visibility != current.visibility, - builder: (context, state) { - if (state.visibility == PlanPageVisibility.open) { - return _FullPlanPage( - onCloseButtonTap: widget.onCloseButtonTap, - scrollController: widget.scrollController, - ); - } - - return _ApartPlanPage(onCloseButtonTap: widget.onCloseButtonTap); - }, - ), + return Scaffold( + body: BlocBuilder( + buildWhen: (previous, current) => + previous.fromDay != current.fromDay || previous.visibility != current.visibility, + builder: (context, state) { + if (state.visibility == PlanPageVisibility.open) { + return _FullPlanPage( + onCloseButtonTap: widget.onCloseButtonTap, + scrollController: widget.scrollController, + ); + } + + return _ApartPlanPage(onCloseButtonTap: widget.onCloseButtonTap); + }, ), ); } diff --git a/lib/schedule/view/schedule_page.dart b/lib/schedule/view/schedule_page.dart index 107a376..4ad1a10 100644 --- a/lib/schedule/view/schedule_page.dart +++ b/lib/schedule/view/schedule_page.dart @@ -35,7 +35,14 @@ class _SchedulePageState extends State { child: BlocBuilder( builder: (context, state) { return SharedUI( - onWillPop: () => _onWillPop(state), + onWillPop: () { + if (state.visibility != PlanPageVisibility.close) { + context.read().add(ClosePlanPage()); + return Future.value(false); + } + + return Future.value(null); + }, child: Item( child: Theme( key: _globalKey, @@ -63,14 +70,4 @@ class _SchedulePageState extends State { void _onPanelClose() { _controller.selectedDate = null; } - - Future _onWillPop(PlanState state) { - if (state.visibility != PlanPageVisibility.close) { - _controller.selectedDate = null; - context.read().add(ClosePlanPage()); - return Future.value(false); - } - - return Future.value(null); - } } From 5b9a48220146d06cd1375445043d42b4ab7127cc Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Thu, 24 Jun 2021 23:07:04 +0700 Subject: [PATCH 04/12] Refactor code --- lib/_widgets/wrapper/navigable_plan_page.dart | 4 ++-- lib/calendar/view/calendar_page.dart | 2 +- lib/home/view/home_page.dart | 2 +- lib/plan/bloc/enum/visibility.dart | 6 ++++++ lib/plan/view/plan_page.dart | 2 +- lib/schedule/view/local_widgets/schedule.dart | 8 ++++++-- lib/schedule/view/schedule_page.dart | 2 +- 7 files changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/_widgets/wrapper/navigable_plan_page.dart b/lib/_widgets/wrapper/navigable_plan_page.dart index a731202..be4cb98 100644 --- a/lib/_widgets/wrapper/navigable_plan_page.dart +++ b/lib/_widgets/wrapper/navigable_plan_page.dart @@ -75,7 +75,7 @@ class _SlideState extends State { } void _onPanelClosed(PlanState state) { - if (state.visibility != PlanPageVisibility.close) { + if (!state.visibility.isClosed) { context.read().add(ClosePlanPage()); if (widget.onPanelClose != null) { widget.onPanelClose!.call(); @@ -84,7 +84,7 @@ class _SlideState extends State { } void _onPanelSlide(double position, PlanState state) { - if (position > 0.31 && state.visibility == PlanPageVisibility.apart) { + if (position > 0.31 && state.visibility.isOpenedApart) { context.read().add(OpenPlanPage()); } } diff --git a/lib/calendar/view/calendar_page.dart b/lib/calendar/view/calendar_page.dart index 5968389..cd37866 100644 --- a/lib/calendar/view/calendar_page.dart +++ b/lib/calendar/view/calendar_page.dart @@ -35,7 +35,7 @@ class _CalendarPageState extends State { builder: (context, state) { return SharedUI( onWillPop: () { - if (state.visibility != PlanPageVisibility.close) { + if (!state.visibility.isClosed) { context.read().add(ClosePlanPage()); return Future.value(false); } diff --git a/lib/home/view/home_page.dart b/lib/home/view/home_page.dart index 1c1e6d6..b30ab86 100644 --- a/lib/home/view/home_page.dart +++ b/lib/home/view/home_page.dart @@ -19,7 +19,7 @@ class _HomePageState extends State { builder: (context, state) { return SharedUI( onWillPop: () { - if (state.visibility != PlanPageVisibility.close) { + if (!state.visibility.isClosed) { context.read().add(ClosePlanPage()); return Future.value(false); } diff --git a/lib/plan/bloc/enum/visibility.dart b/lib/plan/bloc/enum/visibility.dart index d21cc7a..a105dfa 100644 --- a/lib/plan/bloc/enum/visibility.dart +++ b/lib/plan/bloc/enum/visibility.dart @@ -3,3 +3,9 @@ enum PlanPageVisibility { apart, open, } + +extension PlanPageVisibilityExtension on PlanPageVisibility { + bool get isClosed => this == PlanPageVisibility.close; + bool get isOpened => this == PlanPageVisibility.open; + bool get isOpenedApart => this == PlanPageVisibility.apart; +} diff --git a/lib/plan/view/plan_page.dart b/lib/plan/view/plan_page.dart index 2fdad44..704e214 100644 --- a/lib/plan/view/plan_page.dart +++ b/lib/plan/view/plan_page.dart @@ -30,7 +30,7 @@ class _PlanPageState extends State { buildWhen: (previous, current) => previous.fromDay != current.fromDay || previous.visibility != current.visibility, builder: (context, state) { - if (state.visibility == PlanPageVisibility.open) { + if (state.visibility.isOpened) { return _FullPlanPage( onCloseButtonTap: widget.onCloseButtonTap, scrollController: widget.scrollController, diff --git a/lib/schedule/view/local_widgets/schedule.dart b/lib/schedule/view/local_widgets/schedule.dart index 9eb2ca3..7d1ffad 100644 --- a/lib/schedule/view/local_widgets/schedule.dart +++ b/lib/schedule/view/local_widgets/schedule.dart @@ -82,7 +82,7 @@ class _ScheduleState extends State { } if (details.targetElement == CalendarElement.calendarCell) { - if (state.visibility == PlanPageVisibility.close) { + if (state.visibility.isClosed) { context.read().add(ShowApartPlanPage(details.date!)); } else if (_previousSelectedDay != null && details.date == _previousSelectedDay) { widget.controller.selectedDate = null; @@ -94,7 +94,7 @@ class _ScheduleState extends State { _previousSelectedDay = details.date!; } else if (details.targetElement == CalendarElement.appointment) { - if (state.visibility != PlanPageVisibility.close) { + if (!state.visibility.isClosed) { context.read().add(ClosePlanPage()); } else { Navigator.of(context).push( @@ -102,6 +102,10 @@ class _ScheduleState extends State { } widget.controller.selectedDate = null; + } else { + if (!state.visibility.isClosed) { + context.read().add(ClosePlanPage()); + } } } diff --git a/lib/schedule/view/schedule_page.dart b/lib/schedule/view/schedule_page.dart index 4ad1a10..f35edcc 100644 --- a/lib/schedule/view/schedule_page.dart +++ b/lib/schedule/view/schedule_page.dart @@ -36,7 +36,7 @@ class _SchedulePageState extends State { builder: (context, state) { return SharedUI( onWillPop: () { - if (state.visibility != PlanPageVisibility.close) { + if (!state.visibility.isClosed) { context.read().add(ClosePlanPage()); return Future.value(false); } From d3a1bbb674a6c8aee8134a84834277c2b6fee20e Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Thu, 24 Jun 2021 23:29:19 +0700 Subject: [PATCH 05/12] Feat: Close apart of PlanPage before open sidebar --- lib/_widgets/sidebar/view/sidebar.dart | 2 +- lib/_widgets/topbar/view/topbar.dart | 27 ++++++++++++++++++++------ lib/_widgets/wrapper/shared_ui.dart | 7 +++++-- lib/schedule/view/schedule_page.dart | 5 +++++ 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/lib/_widgets/sidebar/view/sidebar.dart b/lib/_widgets/sidebar/view/sidebar.dart index 4453bb1..14dd170 100644 --- a/lib/_widgets/sidebar/view/sidebar.dart +++ b/lib/_widgets/sidebar/view/sidebar.dart @@ -31,7 +31,7 @@ class Sidebar extends StatelessWidget { child: CloseSidebarButton(), ), Container( - width: screenWidth * 0.6, + width: screenWidth * 0.7, padding: EdgeInsets.only(top: 50), child: Column( mainAxisSize: MainAxisSize.max, diff --git a/lib/_widgets/topbar/view/topbar.dart b/lib/_widgets/topbar/view/topbar.dart index 00404d0..59c06ca 100644 --- a/lib/_widgets/topbar/view/topbar.dart +++ b/lib/_widgets/topbar/view/topbar.dart @@ -1,11 +1,12 @@ import 'package:app_qldt/_widgets/element/unstable_button.dart'; import 'package:flutter/material.dart'; -class TopBar extends StatelessWidget { +class TopBar extends StatefulWidget { final Widget? topRightWidget; final Color? backgroundColor; final Color? iconColor; final bool? stable; + final Function()? beforeOpenSidebar; const TopBar({ Key? key, @@ -13,12 +14,18 @@ class TopBar extends StatelessWidget { this.backgroundColor, this.iconColor, this.stable, + this.beforeOpenSidebar, }) : super(key: key); + @override + _TopBarState createState() => _TopBarState(); +} + +class _TopBarState extends State { @override Widget build(BuildContext context) { return Container( - color: backgroundColor ?? Colors.transparent, + color: widget.backgroundColor ?? Colors.transparent, height: 60, child: Padding( padding: EdgeInsets.symmetric(horizontal: 10), @@ -27,13 +34,13 @@ class TopBar extends StatelessWidget { children: [ TopBarItem( icon: Icons.menu, - color: iconColor, - onTap: () => Scaffold.of(context)..openDrawer(), + color: widget.iconColor, + onTap: _onTap, ), Row( children: [ - stable! ? Container() : UnstableButton(), - topRightWidget ?? Container(), + widget.stable! ? Container() : UnstableButton(), + widget.topRightWidget ?? Container(), ], ), ], @@ -41,6 +48,14 @@ class TopBar extends StatelessWidget { ), ); } + + void _onTap() { + if (widget.beforeOpenSidebar != null) { + widget.beforeOpenSidebar!.call(); + } + + Scaffold.of(context)..openDrawer(); + } } class TopBarItem extends StatelessWidget { diff --git a/lib/_widgets/wrapper/shared_ui.dart b/lib/_widgets/wrapper/shared_ui.dart index 1b41b2c..415ac00 100644 --- a/lib/_widgets/wrapper/shared_ui.dart +++ b/lib/_widgets/wrapper/shared_ui.dart @@ -11,6 +11,7 @@ class SharedUI extends StatelessWidget { final Color? topbarIconColor; final bool? stable; final Future Function()? onWillPop; + final Function()? beforeOpenSidebar; const SharedUI({ Key? key, @@ -21,6 +22,7 @@ class SharedUI extends StatelessWidget { this.topbarIconColor, this.stable, this.onWillPop, + this.beforeOpenSidebar, }) : super(key: key); @override @@ -39,13 +41,14 @@ class SharedUI extends StatelessWidget { backgroundColor: topbarColor, iconColor: topbarIconColor, stable: stable ?? true, + beforeOpenSidebar: beforeOpenSidebar, ), Expanded( child: WillPopScope( onWillPop: () async { - if (onWillPop != null){ + if (onWillPop != null) { bool? pop = await onWillPop!.call(); - if (pop != null){ + if (pop != null) { return Future.value(pop); } } diff --git a/lib/schedule/view/schedule_page.dart b/lib/schedule/view/schedule_page.dart index f35edcc..3ab495a 100644 --- a/lib/schedule/view/schedule_page.dart +++ b/lib/schedule/view/schedule_page.dart @@ -35,6 +35,11 @@ class _SchedulePageState extends State { child: BlocBuilder( builder: (context, state) { return SharedUI( + beforeOpenSidebar: () { + if (!state.visibility.isClosed) { + context.read().add(ClosePlanPage()); + } + }, onWillPop: () { if (!state.visibility.isClosed) { context.read().add(ClosePlanPage()); From df06fe71f304a4443d680e239843ee701b1740ed Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Tue, 29 Jun 2021 03:36:58 +0700 Subject: [PATCH 06/12] Feat: Upgrade version to 0.4.1+6 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index d8d5a98..140790b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.4.0+5 +version: 0.4.1+6 environment: sdk: ">=2.12.0 <3.0.0" From 5d1522eab5f6b8feca52976a69f53a4a3a4be59f Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Tue, 29 Jun 2021 03:37:15 +0700 Subject: [PATCH 07/12] Feat: Rename property of UserDataModel from idStudent to idUser --- lib/_crawler/bloc/crawler_bloc.dart | 2 +- lib/_models/user_data_model.dart | 4 ++-- lib/exam_schedule/bloc/exam_schedule_bloc.dart | 4 ++-- lib/score/bloc/score_bloc.dart | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/_crawler/bloc/crawler_bloc.dart b/lib/_crawler/bloc/crawler_bloc.dart index 5c36677..09a73d1 100644 --- a/lib/_crawler/bloc/crawler_bloc.dart +++ b/lib/_crawler/bloc/crawler_bloc.dart @@ -61,7 +61,7 @@ class CrawlerBloc extends Bloc { if (state.formStatus.isValidated) { UserDataModel userDataModel = context.read().userDataModel; - String idStudent = userDataModel.idStudent; + String idStudent = userDataModel.idUser; String idAccount = userDataModel.idAccount; yield state.copyWith( diff --git a/lib/_models/user_data_model.dart b/lib/_models/user_data_model.dart index ac7f4fe..b172f52 100644 --- a/lib/_models/user_data_model.dart +++ b/lib/_models/user_data_model.dart @@ -9,7 +9,7 @@ class UserDataModel { final NotificationServiceController notificationServiceController; final ExamScheduleServiceController examScheduleServiceController; final String idAccount; - final String idStudent; + final String idUser; UserDataModel({ required this.eventServiceController, @@ -17,6 +17,6 @@ class UserDataModel { required this.notificationServiceController, required this.examScheduleServiceController, required this.idAccount, - required this.idStudent, + required this.idUser, }); } diff --git a/lib/exam_schedule/bloc/exam_schedule_bloc.dart b/lib/exam_schedule/bloc/exam_schedule_bloc.dart index 99b7ec9..9bb48f3 100644 --- a/lib/exam_schedule/bloc/exam_schedule_bloc.dart +++ b/lib/exam_schedule/bloc/exam_schedule_bloc.dart @@ -67,7 +67,7 @@ class ExamScheduleBloc extends Bloc { // Also request to crawl score CrawlerStatus scoreCrawlerStatus = await _crawlerService.crawlScore( ScoreCrawlerModel( - idStudent: _userDataModel.idStudent, + idStudent: _userDataModel.idUser, idAccount: _userDataModel.idAccount, ), ); @@ -78,7 +78,7 @@ class ExamScheduleBloc extends Bloc { CrawlerStatus examScheduleCrawlerStatus = await _crawlerService.crawlExamSchedule( ExamScheduleCrawlerModel( - idStudent: _userDataModel.idStudent, + idStudent: _userDataModel.idUser, idAccount: _userDataModel.idAccount, ), ); diff --git a/lib/score/bloc/score_bloc.dart b/lib/score/bloc/score_bloc.dart index b16b076..663d38d 100644 --- a/lib/score/bloc/score_bloc.dart +++ b/lib/score/bloc/score_bloc.dart @@ -102,7 +102,7 @@ class ScoreBloc extends Bloc { CrawlerStatus scoreCrawlerStatus = await _crawlerService.crawlScore( ScoreCrawlerModel( - idStudent: _userDataModel.idStudent, + idStudent: _userDataModel.idUser, idAccount: _userDataModel.idAccount, ), ); @@ -111,7 +111,7 @@ class ScoreBloc extends Bloc { // Also request to crawl exam schedule CrawlerStatus examScheduleCrawlerStatus = await _crawlerService.crawlExamSchedule( ExamScheduleCrawlerModel( - idStudent: _userDataModel.idStudent, + idStudent: _userDataModel.idUser, idAccount: _userDataModel.idAccount, ), ); From 6f0060e1d6c750e2ff9c894d622c31499af8a674 Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Tue, 29 Jun 2021 03:38:30 +0700 Subject: [PATCH 08/12] Feat: Return null when an error occurs in DbNotification.lastId --- lib/_utils/database/table/db_notification.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/_utils/database/table/db_notification.dart b/lib/_utils/database/table/db_notification.dart index 5a31e75..074a85a 100644 --- a/lib/_utils/database/table/db_notification.dart +++ b/lib/_utils/database/table/db_notification.dart @@ -60,8 +60,9 @@ class DbNotification extends TableModel { print('Last notification id: $lastId'); return lastId; - } on Exception catch (e) { + } on Error catch (e) { print('$e in DbNotification.lastId'); + return null; } } From e2e112adae43c01a1f107f0c194d2419205400e4 Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Tue, 29 Jun 2021 03:41:44 +0700 Subject: [PATCH 09/12] Feat: Optimize asynchronous --- lib/_preload/bloc/preload_bloc.dart | 283 ++++++++++-------- lib/_preload/bloc/preload_state.dart | 22 +- .../notification_service_controller.dart | 21 +- 3 files changed, 181 insertions(+), 145 deletions(-) diff --git a/lib/_preload/bloc/preload_bloc.dart b/lib/_preload/bloc/preload_bloc.dart index 77017ca..9fbd106 100644 --- a/lib/_preload/bloc/preload_bloc.dart +++ b/lib/_preload/bloc/preload_bloc.dart @@ -28,13 +28,16 @@ part 'preload_state.dart'; class PreloadBloc extends Bloc { final BuildContext context; final NavigatorState? navigator; - final User user; + final String _idAccount; + final String _idUser; PreloadBloc({ required this.context, required this.navigator, - required this.user, - }) : super(PreloadInitial()); + required User user, + }) : _idAccount = user.accountId, + _idUser = user.id, + super(PreloadInitial()); @override Stream mapEventToState( @@ -59,115 +62,125 @@ class PreloadBloc extends Bloc { Stopwatch stopwatch = Stopwatch()..start(); final minTurnAroundTime = const Duration(seconds: 2); final ApiUrl apiUrl = AppModeWidget.of(context).apiUrl; + final serviceControllers = _ServiceControllers( + apiUrl: apiUrl, + idUser: _idUser, + idAccount: _idAccount, + ); - /// Khởi động các service - final tokenService = TokenService(apiUrl); - await tokenService.init(); - await tokenService.upsert(user.id); + await Future.wait([ + upsertToken(apiUrl), + initControllersAndRefreshNewVersion(serviceControllers, apiUrl), + ]); - String idAccount = user.accountId; - String idUser = user.id; + final timeEnded = stopwatch.elapsed; + stopwatch.stop(); - final DatabaseProvider databaseProvider = DatabaseProvider(); - await databaseProvider.init(); + print(timeEnded); - final ServiceControllerData controllerData = ServiceControllerData( - databaseProvider: databaseProvider, - apiUrl: apiUrl, - idUser: idUser, + final userDataModel = UserDataModel( + eventServiceController: serviceControllers.event, + scoreServiceController: serviceControllers.score, + notificationServiceController: serviceControllers.notification, + examScheduleServiceController: serviceControllers.examSchedule, + idAccount: _idAccount, + idUser: _idUser, ); - EventServiceController eventServiceController = EventServiceController(controllerData); - NotificationServiceController notificationServiceController = - NotificationServiceController(controllerData, idAccount); - ScoreServiceController scoreServiceController = ScoreServiceController(controllerData); - ExamScheduleServiceController examScheduleServiceController = - ExamScheduleServiceController(controllerData); + context.read().userDataModel = userDataModel; - print('Event: ${stopwatch.elapsed}'); - await eventServiceController.load(); - - print('Notification: ${stopwatch.elapsed}'); - await notificationServiceController.load(); + await Future.delayed( + timeEnded < minTurnAroundTime ? minTurnAroundTime - timeEnded : const Duration(seconds: 0), () async { + await navigator?.pushNamedAndRemoveUntil(Const.defaultPage, (_) => false); + }); - print('Score: ${stopwatch.elapsed}'); - await scoreServiceController.load(); + yield PreloadState.loaded(userDataModel); + } - print('Exam Schedule: ${stopwatch.elapsed}'); - await examScheduleServiceController.load(); + Stream _mapPreloadLoadingAfterLoginToState(PreloadLoadingAfterLogin event) async* { + yield PreloadState.loadingAfterLogin(); - Map versionMap = await VersionService( + Stopwatch stopwatch = Stopwatch()..start(); + final minTurnAroundTime = const Duration(seconds: 2); + final ApiUrl apiUrl = AppModeWidget.of(context).apiUrl; + final serviceControllers = _ServiceControllers( apiUrl: apiUrl, - idStudent: idUser, - ).getServerDataVersion(); - if (versionMap.isNotEmpty) { - print(versionMap); + idUser: _idUser, + idAccount: _idAccount, + ); - DbDataVersion version = eventServiceController.localService.databaseProvider.dataVersion; - - if (versionMap['Schedule']! as int > version.schedule) { - await eventServiceController.refresh(); - } - if (versionMap['Notification']! as int > version.notification) { - await notificationServiceController.refresh(); - } - if (versionMap['Exam_Schedule']! as int > version.examSchedule) { - await examScheduleServiceController.refresh(); - } else if (version.examSchedule > 0) { - examScheduleServiceController.setConnected(); - } - if (versionMap['Module_Score']! as int > version.score) { - await scoreServiceController.refresh(); - } else if (version.score > 0) { - scoreServiceController.setConnected(); - } - } + await Future.wait([ + upsertToken(apiUrl), + initControllersAndForceRefresh(serviceControllers), + ]); final timeEnded = stopwatch.elapsed; stopwatch.stop(); print(timeEnded); - context.read().userDataModel = UserDataModel( - eventServiceController: eventServiceController, - scoreServiceController: scoreServiceController, - notificationServiceController: notificationServiceController, - examScheduleServiceController: examScheduleServiceController, - idAccount: idAccount, - idStudent: idUser, + final userDataModel = UserDataModel( + eventServiceController: serviceControllers.event, + scoreServiceController: serviceControllers.score, + notificationServiceController: serviceControllers.notification, + examScheduleServiceController: serviceControllers.examSchedule, + idAccount: _idAccount, + idUser: _idUser, ); + context.read().userDataModel = userDataModel; + await Future.delayed( - timeEnded < minTurnAroundTime ? minTurnAroundTime - timeEnded : const Duration(seconds: 0), - () async { + timeEnded < minTurnAroundTime ? minTurnAroundTime - timeEnded : const Duration(seconds: 0), () async { await navigator?.pushNamedAndRemoveUntil(Const.defaultPage, (_) => false); }); - yield PreloadState.loaded( - eventServiceController: eventServiceController, - scoreServiceController: scoreServiceController, - notificationServiceController: notificationServiceController, - examScheduleServiceController: examScheduleServiceController, - idAccount: idAccount, - idUser: idUser, - ); + yield PreloadState.loaded(userDataModel); } - Stream _mapPreloadLoadingAfterLoginToState(PreloadLoadingAfterLogin event) async* { - yield PreloadState.loadingAfterLogin(); - - Stopwatch stopwatch = Stopwatch()..start(); - final minTurnAroundTime = const Duration(seconds: 2); - final ApiUrl apiUrl = AppModeWidget.of(context).apiUrl; - - /// Khởi động các service + Future upsertToken(ApiUrl apiUrl) async { final tokenService = TokenService(apiUrl); await tokenService.init(); - await tokenService.upsert(user.id); + await tokenService.upsert(_idUser); + } + + Future initControllersAndRefreshNewVersion( + _ServiceControllers serviceControllers, ApiUrl apiUrl) async { + await serviceControllers.init(loadOldData: true); + + Map versionMap = await VersionService( + apiUrl: apiUrl, + idStudent: _idUser, + ).getServerDataVersion(); + + if (versionMap.isNotEmpty) { + print(versionMap); + await serviceControllers.refresh(versionMap); + } + } - String idAccount = user.accountId; - String idUser = user.id; + Future initControllersAndForceRefresh(_ServiceControllers serviceControllers) async { + await serviceControllers.init(); + await serviceControllers.forceRefresh(); + } +} +class _ServiceControllers { + late final EventServiceController event; + late final ScoreServiceController score; + late final NotificationServiceController notification; + late final ExamScheduleServiceController examSchedule; + final ApiUrl apiUrl; + final String idUser; + final String idAccount; + + _ServiceControllers({ + required this.apiUrl, + required this.idAccount, + required this.idUser, + }); + + Future init({bool loadOldData = false}) async { final DatabaseProvider databaseProvider = DatabaseProvider(); await databaseProvider.init(); @@ -177,52 +190,82 @@ class PreloadBloc extends Bloc { idUser: idUser, ); - EventServiceController eventServiceController = EventServiceController(controllerData); - ScoreServiceController scoreServiceController = ScoreServiceController(controllerData); - NotificationServiceController notificationServiceController = - NotificationServiceController(controllerData, idAccount); - ExamScheduleServiceController examScheduleServiceController = - ExamScheduleServiceController(controllerData); + event = EventServiceController(controllerData); + score = ScoreServiceController(controllerData); + notification = NotificationServiceController(controllerData, idAccount); + examSchedule = ExamScheduleServiceController(controllerData); + + if (loadOldData) { + await Future.wait([ + event.load(), + notification.load(), + score.load(), + examSchedule.load(), + ]); + } + } - print('Event: ${stopwatch.elapsed}'); - await eventServiceController.refresh(); + Future refresh(Map versionMap) async { + DbDataVersion version = event.localService.databaseProvider.dataVersion; - print('Notification: ${stopwatch.elapsed}'); - await notificationServiceController.refresh(getAll: true); + await Future.wait([ + _refreshEvent(versionMap['Schedule']! as int, version.schedule), + _refreshNotification(versionMap['Notification']! as int, version.notification), + _refreshExamSchedule(versionMap['Exam_Schedule']! as int, version.examSchedule), + _refreshScore(versionMap['Module_Score']! as int, version.score), + ]); + } - print('Score: ${stopwatch.elapsed}'); - await scoreServiceController.refresh(); + Future forceRefresh() async { + await Future.wait([ + _forceRefreshEvent(), + _forceRefreshNotification(getAll: true), + _forceRefreshExamSchedule(), + _forceRefreshScore(), + ]); + } - print('Exam Schedule: ${stopwatch.elapsed}'); - await examScheduleServiceController.refresh(); + Future _refreshEvent(int serverVersion, localVersion) async { + if (serverVersion > localVersion) { + await _forceRefreshEvent(); + } + } - final timeEnded = stopwatch.elapsed; - stopwatch.stop(); + Future _forceRefreshEvent() async { + await event.refresh(); + } - print(timeEnded); + Future _refreshNotification(int serverVersion, localVersion) async { + if (serverVersion > localVersion) { + await _forceRefreshNotification(); + } else if (localVersion > 0) { + examSchedule.setConnected(); + } + } - context.read().userDataModel = UserDataModel( - eventServiceController: eventServiceController, - scoreServiceController: scoreServiceController, - notificationServiceController: notificationServiceController, - examScheduleServiceController: examScheduleServiceController, - idAccount: idAccount, - idStudent: idUser, - ); + Future _forceRefreshNotification({bool getAll = false}) async { + await notification.refresh(getAll: getAll); + } - await Future.delayed( - timeEnded < minTurnAroundTime ? minTurnAroundTime - timeEnded : const Duration(seconds: 0), - () async { - await navigator?.pushNamedAndRemoveUntil(Const.defaultPage, (_) => false); - }); + Future _refreshExamSchedule(int serverVersion, localVersion) async { + if (serverVersion > localVersion) { + await _forceRefreshExamSchedule(); + } + } - yield PreloadState.loaded( - eventServiceController: eventServiceController, - scoreServiceController: scoreServiceController, - notificationServiceController: notificationServiceController, - examScheduleServiceController: examScheduleServiceController, - idAccount: idAccount, - idUser: idUser, - ); + Future _forceRefreshExamSchedule() async { + await examSchedule.refresh(); + } + + Future _refreshScore(int serverVersion, localVersion) async { + if (serverVersion > localVersion) { + await _forceRefreshScore(); + } else if (localVersion > 0) { + score.setConnected(); + } + } + + Future _forceRefreshScore() async { + await score.refresh(); } } diff --git a/lib/_preload/bloc/preload_state.dart b/lib/_preload/bloc/preload_state.dart index b5a46a5..c506a8e 100644 --- a/lib/_preload/bloc/preload_state.dart +++ b/lib/_preload/bloc/preload_state.dart @@ -57,21 +57,15 @@ class PreloadState extends Equatable { const PreloadState.loadingAfterLogin() : this(status: PreloadStatus.loadingAfterLogin); - const PreloadState.loaded({ - required String idAccount, - required String idUser, - required EventServiceController eventServiceController, - required ScoreServiceController scoreServiceController, - required NotificationServiceController notificationServiceController, - required ExamScheduleServiceController examScheduleServiceController, - }) : this( + PreloadState.loaded(UserDataModel userDataModel) + : this( status: PreloadStatus.loaded, - idAccount: idAccount, - idUser: idUser, - eventServiceController: eventServiceController, - scoreServiceController: scoreServiceController, - notificationServiceController: notificationServiceController, - examScheduleServiceController: examScheduleServiceController, + idAccount: userDataModel.idAccount, + idUser: userDataModel.idUser, + eventServiceController: userDataModel.eventServiceController, + scoreServiceController: userDataModel.scoreServiceController, + notificationServiceController: userDataModel.notificationServiceController, + examScheduleServiceController: userDataModel.examScheduleServiceController, ); @override diff --git a/lib/_services/controller/notification_service_controller.dart b/lib/_services/controller/notification_service_controller.dart index 53395c8..391f2fa 100644 --- a/lib/_services/controller/notification_service_controller.dart +++ b/lib/_services/controller/notification_service_controller.dart @@ -10,13 +10,13 @@ class NotificationServiceController extends ServiceController { NotificationServiceController(ServiceControllerData data, String idAccount) : super( - LocalNotificationService(databaseProvider: data.databaseProvider), - ApiNotificationService( - apiUrl: data.apiUrl, - idAccount: idAccount, - idStudent: data.idUser, - ), - ); + LocalNotificationService(databaseProvider: data.databaseProvider), + ApiNotificationService( + apiUrl: data.apiUrl, + idAccount: idAccount, + idStudent: data.idUser, + ), + ); List get notificationData => localService.notificationData; @@ -26,17 +26,16 @@ class NotificationServiceController if (response.statusCode == 200) { List? senderList = SenderModel.fromList(response.data['sender']); List? notificationList = - ReceiveNotificationModel.fromList(response.data['notification']); + ReceiveNotificationModel.fromList(response.data['notification']); List? deleteList; - if (response.data['index_del'] != null){ + if (response.data['index_del'] != null) { deleteList = List.generate( response.data['index_del'].length, (index) => response.data['index_del'][index] as int); } await localService.saveNewData(senderList, notificationList, deleteList); await localService.updateVersion(response.version!); - } - else { + } else { if (response.statusCode == 204) { print('There are no new data'); } else { From ac71470d41449955ded0d1ce687af7a565876782 Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Sat, 3 Jul 2021 00:37:13 +0700 Subject: [PATCH 10/12] Fix: Version of score and examSchedule are not updated when login --- lib/_preload/bloc/preload_bloc.dart | 52 ++++++++++--------- .../exam_schedule_service_controller.dart | 4 +- .../controller/score_service_controller.dart | 4 +- lib/_services/local/local_event_service.dart | 2 +- .../local/local_exam_schedule_service.dart | 4 +- .../local/local_notification_service.dart | 2 +- lib/_services/local/local_score_service.dart | 4 +- lib/_utils/database/table/data_version.dart | 24 ++++++--- 8 files changed, 55 insertions(+), 41 deletions(-) diff --git a/lib/_preload/bloc/preload_bloc.dart b/lib/_preload/bloc/preload_bloc.dart index 9fbd106..016e1ce 100644 --- a/lib/_preload/bloc/preload_bloc.dart +++ b/lib/_preload/bloc/preload_bloc.dart @@ -69,8 +69,8 @@ class PreloadBloc extends Bloc { ); await Future.wait([ - upsertToken(apiUrl), - initControllersAndRefreshNewVersion(serviceControllers, apiUrl), + _upsertToken(apiUrl), + _initControllersAndRefreshServices(serviceControllers, apiUrl), ]); final timeEnded = stopwatch.elapsed; @@ -110,8 +110,8 @@ class PreloadBloc extends Bloc { ); await Future.wait([ - upsertToken(apiUrl), - initControllersAndForceRefresh(serviceControllers), + _upsertToken(apiUrl), + _initControllersAndRefreshServices(serviceControllers, apiUrl, force: true), ]); final timeEnded = stopwatch.elapsed; @@ -138,15 +138,18 @@ class PreloadBloc extends Bloc { yield PreloadState.loaded(userDataModel); } - Future upsertToken(ApiUrl apiUrl) async { + Future _upsertToken(ApiUrl apiUrl) async { final tokenService = TokenService(apiUrl); await tokenService.init(); await tokenService.upsert(_idUser); } - Future initControllersAndRefreshNewVersion( - _ServiceControllers serviceControllers, ApiUrl apiUrl) async { - await serviceControllers.init(loadOldData: true); + Future _initControllersAndRefreshServices( + _ServiceControllers serviceControllers, + ApiUrl apiUrl, { + bool force = false, + }) async { + await serviceControllers.init(loadOldData: !force); Map versionMap = await VersionService( apiUrl: apiUrl, @@ -155,14 +158,13 @@ class PreloadBloc extends Bloc { if (versionMap.isNotEmpty) { print(versionMap); - await serviceControllers.refresh(versionMap); + if (force) { + await serviceControllers.forceRefresh(versionMap); + } else { + await serviceControllers.refresh(versionMap); + } } } - - Future initControllersAndForceRefresh(_ServiceControllers serviceControllers) async { - await serviceControllers.init(); - await serviceControllers.forceRefresh(); - } } class _ServiceControllers { @@ -216,12 +218,12 @@ class _ServiceControllers { ]); } - Future forceRefresh() async { + Future forceRefresh(Map versionMap) async { await Future.wait([ _forceRefreshEvent(), _forceRefreshNotification(getAll: true), - _forceRefreshExamSchedule(), - _forceRefreshScore(), + _forceRefreshExamSchedule(versionMap['Exam_Schedule']! as int), + _forceRefreshScore(versionMap['Module_Score']! as int), ]); } @@ -238,8 +240,6 @@ class _ServiceControllers { Future _refreshNotification(int serverVersion, localVersion) async { if (serverVersion > localVersion) { await _forceRefreshNotification(); - } else if (localVersion > 0) { - examSchedule.setConnected(); } } @@ -249,23 +249,25 @@ class _ServiceControllers { Future _refreshExamSchedule(int serverVersion, localVersion) async { if (serverVersion > localVersion) { - await _forceRefreshExamSchedule(); + await _forceRefreshExamSchedule(serverVersion); + } else if (localVersion > 0) { + examSchedule.setConnected(); } } - Future _forceRefreshExamSchedule() async { - await examSchedule.refresh(); + Future _forceRefreshExamSchedule([int? newVersion]) async { + await examSchedule.refresh(newVersion); } Future _refreshScore(int serverVersion, localVersion) async { if (serverVersion > localVersion) { - await _forceRefreshScore(); + await _forceRefreshScore(serverVersion); } else if (localVersion > 0) { score.setConnected(); } } - Future _forceRefreshScore() async { - await score.refresh(); + Future _forceRefreshScore([int? newVersion]) async { + await score.refresh(newVersion); } } diff --git a/lib/_services/controller/exam_schedule_service_controller.dart b/lib/_services/controller/exam_schedule_service_controller.dart index 9c8dd88..3ed1efa 100644 --- a/lib/_services/controller/exam_schedule_service_controller.dart +++ b/lib/_services/controller/exam_schedule_service_controller.dart @@ -24,12 +24,12 @@ class ExamScheduleServiceController SemesterModel? get lastSemester => semester.length == 0 ? null : semester[semester.length - 1]; - Future refresh() async { + Future refresh([int? newVersion]) async { ServiceResponse response = await apiService.request(); if (response.statusCode == 200) { List newData = _parseData(response.data); - await localService.updateVersion(); + await localService.updateVersion(newVersion); await localService.saveNewData(newData); setConnected(); } else { diff --git a/lib/_services/controller/score_service_controller.dart b/lib/_services/controller/score_service_controller.dart index bf01cae..6be268d 100644 --- a/lib/_services/controller/score_service_controller.dart +++ b/lib/_services/controller/score_service_controller.dart @@ -21,13 +21,13 @@ class ScoreServiceController extends ServiceController get semester => localService.semester; - Future refresh() async { + Future refresh([int? newVersion]) async { ServiceResponse response = await apiService.request(); if (response.statusCode == 200) { List newData = _parseData(response.data); await localService.saveNewData(newData); - await localService.updateVersion(response.version!); + await localService.updateVersion(newVersion); setConnected(); } else { await localService.loadOldData(); diff --git a/lib/_services/local/local_event_service.dart b/lib/_services/local/local_event_service.dart index b27eaf1..eae6124 100644 --- a/lib/_services/local/local_event_service.dart +++ b/lib/_services/local/local_event_service.dart @@ -49,7 +49,7 @@ class LocalEventService extends LocalService { } Future updateVersion(int newVersion) async { - await databaseProvider.dataVersion.setScheduleVersion(newVersion); + await databaseProvider.dataVersion.updateScheduleVersion(newVersion); } Future loadOldData() async { diff --git a/lib/_services/local/local_exam_schedule_service.dart b/lib/_services/local/local_exam_schedule_service.dart index dc4506f..21da62d 100644 --- a/lib/_services/local/local_exam_schedule_service.dart +++ b/lib/_services/local/local_exam_schedule_service.dart @@ -30,8 +30,8 @@ class LocalExamScheduleService extends LocalService { return this.examScheduleData; } - Future updateVersion() async { - await databaseProvider.dataVersion.setExamScheduleVersion(); + Future updateVersion(int? newVersion) async { + await databaseProvider.dataVersion.updateExamScheduleVersion(newVersion); } Future loadOldData() async { diff --git a/lib/_services/local/local_notification_service.dart b/lib/_services/local/local_notification_service.dart index b92cba7..bf63d7b 100644 --- a/lib/_services/local/local_notification_service.dart +++ b/lib/_services/local/local_notification_service.dart @@ -33,7 +33,7 @@ class LocalNotificationService extends LocalService { } Future updateVersion(int newVersion) async { - await databaseProvider.dataVersion.setNotificationVersion(newVersion); + await databaseProvider.dataVersion.updateNotificationVersion(newVersion); } Future loadOldData() async { diff --git a/lib/_services/local/local_score_service.dart b/lib/_services/local/local_score_service.dart index a7e1e8d..9232b93 100644 --- a/lib/_services/local/local_score_service.dart +++ b/lib/_services/local/local_score_service.dart @@ -38,8 +38,8 @@ class LocalScoreService extends LocalService { await databaseProvider.score.insert(rawData); } - Future updateVersion(int newVersion) async { - await databaseProvider.dataVersion.setScoreVersion(); + Future updateVersion(int? newVersion) async { + await databaseProvider.dataVersion.updateScoreVersion(newVersion); } Future loadOldData() async { diff --git a/lib/_utils/database/table/data_version.dart b/lib/_utils/database/table/data_version.dart index d5e7b4f..d93171e 100644 --- a/lib/_utils/database/table/data_version.dart +++ b/lib/_utils/database/table/data_version.dart @@ -90,22 +90,34 @@ class DbDataVersion extends TableModel { ); } - Future setScheduleVersion(int newVersion) async { + Future updateScheduleVersion(int newVersion) async { await _setVersion('schedule', newVersion); schedule = newVersion; } - Future setNotificationVersion(int newVersion) async { + Future updateNotificationVersion(int newVersion) async { await _setVersion('notification', newVersion); notification = newVersion; } - Future setExamScheduleVersion() async { - await _setVersion('exam_schedule', ++examSchedule); + Future updateExamScheduleVersion(int? newVersion) async { + if (newVersion != null) { + examSchedule = newVersion; + } else { + examSchedule++; + } + + await _setVersion('exam_schedule', examSchedule); } - Future setScoreVersion() async { - await _setVersion('score', ++score); + Future updateScoreVersion(int? newVersion) async { + if (newVersion != null) { + score = newVersion; + } else { + score++; + } + + await _setVersion('score', score); } Future delete() async { From fde540dc46c9d7ae176d7fafc5a2213913906c7d Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Sat, 3 Jul 2021 00:50:02 +0700 Subject: [PATCH 11/12] Fix: Application's name is not displayed in multitask --- android/app/src/main/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index dec76e5..c520f90 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -25,7 +25,7 @@ android:name=".MainActivity" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" - android:launchMode="singleTop" + android:launchMode="singleTask" android:showWhenLocked="true" android:theme="@style/LaunchTheme" android:turnScreenOn="true" From c413cdddac9296cf5611a424868a31b1fa0c8edb Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Sat, 3 Jul 2021 00:50:43 +0700 Subject: [PATCH 12/12] Upgrade to version 0.4.2+7 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 140790b..895f50f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.4.1+6 +version: 0.4.2+7 environment: sdk: ">=2.12.0 <3.0.0"