Skip to content

Commit

Permalink
FIX: build schedule in next week and from cache (#90)
Browse files Browse the repository at this point in the history
* FIX: build schedule in next week and from cache

* FIX: add mCurrentDate to getSemesterStart method call

* FIX: add Dio timeout settings
  • Loading branch information
0niel authored Sep 8, 2021
1 parent d7fec74 commit 029aab0
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 74 deletions.
10 changes: 1 addition & 9 deletions lib/common/calendar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,7 @@ abstract class Calendar {
static int getCurrentWeek(
{DateTime? mCurrentDate, final Clock clock = const Clock()}) {
DateTime currentDate = mCurrentDate ?? clock.now();
int currentYear = currentDate.year;

DateTime startDate;

if (currentDate.month >= DateTime.september) {
startDate = DateTime.utc(currentYear, 9, 1);
} else {
startDate = DateTime.utc(currentYear, 2, 8);
}
DateTime startDate = getSemesterStart(mCurrentDate: currentDate);

int week = 1;
int prevWeekday = startDate.weekday;
Expand Down
75 changes: 44 additions & 31 deletions lib/presentation/bloc/schedule_bloc/schedule_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,29 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
/// List of all groups (1028+)
static List<String> groupsList = [];

late List<String> downloadedGroups;
late List<String> _downloadedGroups;

/// [groupSuggestion] is used when selecting a group in [AutocompleteGroupSelector]
String groupSuggestion = '';
/// [_groupSuggestion] is used when selecting a group in [AutocompleteGroupSelector]
String _groupSuggestion = '';

@override
Stream<ScheduleState> mapEventToState(
ScheduleEvent event,
) async* {
if (event is ScheduleOpenEvent) {
// Getting a list of all groups from a remote API
_downloadGroups();

// The group for which the schedule is selected
final activeGroup = await getActiveGroup();
String? activeGroupName;
activeGroup.fold((failure) => null, (group) => activeGroupName = group);

if (activeGroupName != null) {
yield* activeGroup.fold((failure) async* {
yield ScheduleActiveGroupEmpty(groups: groupsList);
}, (activeGroupName) async* {
final schedule = await getSchedule(
GetScheduleParams(group: activeGroupName!, fromRemote: false));
final downloadedScheduleGroups = await _getDownloadedScheduleGroups();
GetScheduleParams(group: activeGroupName, fromRemote: false));
final downloadedScheduleGroups =
await _getAllDownloadedScheduleGroups();
final scheduleSettings = await getScheduleSettings();

// If we have a schedule in the cache then we display it
Expand All @@ -69,54 +72,64 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
yield* schedule.fold((failure) async* {
yield ScheduleLoading();
final remoteSchedule = await getSchedule(
GetScheduleParams(group: activeGroupName!, fromRemote: true));
GetScheduleParams(group: activeGroupName, fromRemote: true));
yield remoteSchedule.fold(
(failureRemote) => ScheduleLoadError(
errorMessage: _mapFailureToMessage(failureRemote)),
(scheduleFromRemote) => ScheduleLoaded(
schedule: scheduleFromRemote,
activeGroup: activeGroupName!,
activeGroup: activeGroupName,
downloadedScheduleGroups: downloadedScheduleGroups,
scheduleSettings: scheduleSettings,
));
}, (schedule) async* {
}, (localSchedule) async* {
// display cached schedule
yield ScheduleLoaded(
schedule: schedule,
activeGroup: activeGroupName!,
schedule: localSchedule,
activeGroup: activeGroupName,
downloadedScheduleGroups: downloadedScheduleGroups,
scheduleSettings: scheduleSettings,
);

// We will update the schedule, but without the loading indicator
getSchedule(
GetScheduleParams(group: activeGroupName!, fromRemote: true));
final remoteSchedule = await getSchedule(
GetScheduleParams(group: activeGroupName, fromRemote: true));
if (remoteSchedule.isRight()) {
yield remoteSchedule.foldRight(
ScheduleInitial(),
(actualSchedule, previous) => ScheduleLoaded(
schedule: actualSchedule,
activeGroup: activeGroupName,
downloadedScheduleGroups: downloadedScheduleGroups,
scheduleSettings: scheduleSettings,
),
);
}
});
} else {
yield ScheduleActiveGroupEmpty(groups: groupsList);
}
});
} else if (event is ScheduleUpdateGroupSuggestionEvent) {
groupSuggestion = event.suggestion;
_groupSuggestion = event.suggestion;
} else if (event is ScheduleSetActiveGroupEvent) {
if (groupsList.contains(groupSuggestion) || event.group != null) {
if (groupsList.contains(_groupSuggestion) || event.group != null) {
// on update active group from drawer group list
if (event.group != null) groupSuggestion = event.group!;
if (event.group != null) _groupSuggestion = event.group!;

yield ScheduleLoading();

await setActiveGroup(SetActiveGroupParams(groupSuggestion));
await setActiveGroup(SetActiveGroupParams(_groupSuggestion));

final schedule = await getSchedule(
GetScheduleParams(group: groupSuggestion, fromRemote: true));
GetScheduleParams(group: _groupSuggestion, fromRemote: true));

downloadedGroups = await _getDownloadedScheduleGroups();
_downloadedGroups = await _getAllDownloadedScheduleGroups();
final scheduleSettings = await getScheduleSettings();
yield schedule.fold(
(failure) =>
ScheduleLoadError(errorMessage: _mapFailureToMessage(failure)),
(schedule) => ScheduleLoaded(
schedule: schedule,
activeGroup: groupSuggestion,
downloadedScheduleGroups: downloadedGroups,
activeGroup: _groupSuggestion,
downloadedScheduleGroups: _downloadedGroups,
scheduleSettings: scheduleSettings,
));
} else {
Expand All @@ -132,27 +145,27 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
GetScheduleParams(group: event.group, fromRemote: true));

if (event.group == event.activeGroup) {
downloadedGroups = await _getDownloadedScheduleGroups();
_downloadedGroups = await _getAllDownloadedScheduleGroups();
final scheduleSettings = await getScheduleSettings();
yield schedule.fold(
(failure) =>
ScheduleLoadError(errorMessage: _mapFailureToMessage(failure)),
(schedule) => ScheduleLoaded(
schedule: schedule,
activeGroup: event.activeGroup,
downloadedScheduleGroups: downloadedGroups,
downloadedScheduleGroups: _downloadedGroups,
scheduleSettings: scheduleSettings,
),
);
}
} else if (event is ScheduleDeleteEvent) {
await deleteSchedule(DeleteScheduleParams(group: event.group));
downloadedGroups = await _getDownloadedScheduleGroups();
_downloadedGroups = await _getAllDownloadedScheduleGroups();
final scheduleSettings = await getScheduleSettings();
yield ScheduleLoaded(
schedule: event.schedule,
activeGroup: event.schedule.group,
downloadedScheduleGroups: downloadedGroups,
downloadedScheduleGroups: _downloadedGroups,
scheduleSettings: scheduleSettings,
);
} else if (event is ScheduleUpdateSettingsEvent) {
Expand Down Expand Up @@ -188,7 +201,7 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
}

/// Returns list of cached schedules or empty list
Future<List<String>> _getDownloadedScheduleGroups() async {
Future<List<String>> _getAllDownloadedScheduleGroups() async {
late List<String> downloadedScheduleGroups;
final downloadedSchedules = await getDownloadedSchedules();
downloadedSchedules.fold((failure) {
Expand Down
4 changes: 2 additions & 2 deletions lib/presentation/bloc/schedule_bloc/schedule_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ class ScheduleUpdateGroupSuggestionEvent extends ScheduleEvent {
class ScheduleGroupsLoadEvent extends ScheduleEvent {}

/// The event should be called to set the active group for which
/// the schedule will be taken. The group name is the [groupSuggestion]
/// field in [ScheduleBloc]. [groupSuggestion] should be set every
/// the schedule will be taken. The group name is the [_groupSuggestion]
/// field in [ScheduleBloc]. [_groupSuggestion] should be set every
/// time the input is updated using the event
/// [ScheduleUpdateGroupSuggestionEvent].
class ScheduleSetActiveGroupEvent extends ScheduleEvent {
Expand Down
4 changes: 3 additions & 1 deletion lib/presentation/pages/schedule/schedule_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,10 @@ class _ScheduleScreenState extends State<ScheduleScreen> {
body: SafeArea(
child: BlocBuilder<ScheduleBloc, ScheduleState>(
buildWhen: (prevState, currentState) {
if (prevState is ScheduleLoaded && currentState is ScheduleLoaded)
if (prevState is ScheduleLoaded &&
currentState is ScheduleLoaded) {
return prevState != currentState;
}
return true;
},
builder: (context, state) {
Expand Down
57 changes: 27 additions & 30 deletions lib/presentation/pages/schedule/widgets/schedule_page_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ class _SchedulePageViewState extends State<SchedulePageView> {
final DateTime _lastCalendarDay =
DateTime.utc(2021, 12, 19); // TODO: create method for it

late List<List<Lesson>> _allLessonsInWeek;

@override
void initState() {
super.initState();
Expand All @@ -45,7 +43,6 @@ class _SchedulePageViewState extends State<SchedulePageView> {
_controller = PageController(initialPage: _selectedPage);
_selectedDay = DateTime.now();
_selectedWeek = Calendar.getCurrentWeek();
_allLessonsInWeek = _getLessonsByWeek(_selectedWeek, widget.schedule);
_calendarFormat = CalendarFormat.values[
(BlocProvider.of<ScheduleBloc>(context).state as ScheduleLoaded)
.scheduleSettings
Expand Down Expand Up @@ -133,16 +130,15 @@ class _SchedulePageViewState extends State<SchedulePageView> {
return lessons;
}

Widget _buildPageViewContent(BuildContext context, int index) {
Widget _buildPageViewContent(BuildContext context, int index, int week) {
if (index == 6) {
return _buildEmptyLessons();
} else {
var lessons = _allLessonsInWeek[index];
var lessons = _getLessonsByWeek(week, widget.schedule)[index];

if (lessons.length == 0) return _buildEmptyLessons();

final state =
(BlocProvider.of<ScheduleBloc>(context).state as ScheduleLoaded);
final state = context.read<ScheduleBloc>().state as ScheduleLoaded;
final ScheduleSettings settings = state.scheduleSettings;
if (settings.showEmptyLessons) {
lessons = _getLessonsWithEmpty(lessons, state.activeGroup);
Expand Down Expand Up @@ -177,13 +173,6 @@ class _SchedulePageViewState extends State<SchedulePageView> {
}
}

void _setLessonsByWeek(int week) {
if (week != _selectedWeek) {
_selectedWeek = week;
_allLessonsInWeek = _getLessonsByWeek(week, widget.schedule);
}
}

@override
Widget build(BuildContext context) {
return Column(
Expand Down Expand Up @@ -270,12 +259,11 @@ class _SchedulePageViewState extends State<SchedulePageView> {
Calendar.getCurrentWeek(mCurrentDate: selectedDay);
// Call `setState()` when updating the selected day
setState(() {
_setLessonsByWeek(currentNewWeek);
_selectedWeek = currentNewWeek;
_selectedPage =
selectedDay.difference(_firstCalendarDay).inDays;
_selectedDay = selectedDay;
_focusedDay = focusedDay;
_selectedWeek = currentNewWeek;
_controller.jumpToPage(_selectedPage);
});
}
Expand All @@ -302,6 +290,8 @@ class _SchedulePageViewState extends State<SchedulePageView> {
_focusedDay = currentDate;
_selectedDay = currentDate;
_selectedPage = _selectedDay.difference(_firstCalendarDay).inDays;
_selectedWeek =
Calendar.getCurrentWeek(mCurrentDate: _selectedDay);
_controller.jumpToPage(_selectedPage);
});
},
Expand All @@ -327,15 +317,19 @@ class _SchedulePageViewState extends State<SchedulePageView> {
),
onPressed: () {
setState(() {
_selectedWeek = i;
_selectedDay =
Calendar.getDaysInWeek(_selectedWeek)[0];
_focusedDay = _selectedDay;
if (i == 1) {
_selectedDay = Calendar.getDaysInWeek(
i)[Calendar.getSemesterStart().weekday - 1];
} else {
_selectedDay = Calendar.getDaysInWeek(i)[0];
}

_selectedDay = _selectedDay;
_selectedPage = _selectedDay
.difference(_firstCalendarDay)
.inDays;
_allLessonsInWeek = _getLessonsByWeek(
_selectedWeek, widget.schedule);
_selectedWeek = i;
_focusedDay = _selectedDay;
_controller.jumpToPage(_selectedPage);
});
},
Expand All @@ -358,14 +352,17 @@ class _SchedulePageViewState extends State<SchedulePageView> {
physics: ClampingScrollPhysics(),
onPageChanged: (value) {
setState(() {
if (value > _selectedPage)
_selectedDay = _selectedDay.add(Duration(days: 1));
else if (value < _selectedPage)
_selectedDay = _selectedDay.subtract(Duration(days: 1));
final int currentNewWeek =
Calendar.getCurrentWeek(mCurrentDate: _selectedDay);
// if the pages are moved by swipes
if ((value - _selectedPage).abs() == 1) {
if (value > _selectedPage)
_selectedDay = _selectedDay.add(Duration(days: 1));
else if (value < _selectedPage)
_selectedDay = _selectedDay.subtract(Duration(days: 1));
final int currentNewWeek =
Calendar.getCurrentWeek(mCurrentDate: _selectedDay);
_selectedWeek = currentNewWeek;
}
_focusedDay = _selectedDay;
_setLessonsByWeek(currentNewWeek);
_selectedPage = value;
});
},
Expand All @@ -379,7 +376,7 @@ class _SchedulePageViewState extends State<SchedulePageView> {
week >= 1 && week <= Calendar.kMaxWeekInSemester
? lessonDay.weekday - 1
: 6;
return _buildPageViewContent(context, lessonIndex);
return _buildPageViewContent(context, lessonIndex, week);
}),
)
],
Expand Down
3 changes: 2 additions & 1 deletion lib/service_locator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ Future<void> setup() async {
// Common / Core

// External Dependency
getIt.registerLazySingleton(() => Dio());
getIt.registerLazySingleton(
() => Dio(BaseOptions(connectTimeout: 3000, receiveTimeout: 3000)));
final sharedPreferences = await SharedPreferences.getInstance();
getIt.registerLazySingleton(() => sharedPreferences);
getIt.registerLazySingleton(() => InternetConnectionChecker());
Expand Down

0 comments on commit 029aab0

Please sign in to comment.