Skip to content

Commit 889ab79

Browse files
JonathanDuvalVAlexandreMarkusMysticFragilist
authored
Bugfix/offline dashboard grades (#155)
* Fixed no internet message for dashboard and grade details * Added tests to verify networking service logic on course repository * Updated pubspec version * Replaced no connection toast by snackbar * Centralized snackbar to BottomBar class * Fixed test from pages using the networking service * Fixed formatting issue in quick links tests * Fixed tests * Cleaned up test using networking service * added icon and allow to dismiss after context change with maybeof # Deprecation Notice https://pub.dev/packages/connectivity -> https://pub.dev/packages/connectivity_plus * Listen to change in status of connection * Merge branch 'master' into bugfix/offline-dashboard-grades * Changed to text under navbar * [CI UPDATE GOLDENS] * Update golden files * Fixed pubspec * [CI UPDATE GOLDENS] * Update golden files * Updated version * Fix goldens * Changed background color of text under navbar * Removed unused import * [CI UPDATE GOLDENS] * Check connectivity on initial loading * Updated version * [CI UPDATE GOLDENS] * Remove unnecessary check Co-authored-by: alexandremarkus <alexandre.markus.1@ens.etsmtl.ca> Co-authored-by: JonathanDuvalV <JonathanDuvalV@users.noreply.github.com> Co-authored-by: Samuel Montambault <mont.samuel@outlook.com>
1 parent 4770eea commit 889ab79

39 files changed

+201
-130
lines changed

lib/core/managers/course_repository.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ class CourseRepository {
182182
}
183183
}
184184

185+
// Don't try to update cache when offline
186+
if (!(await _networkingService.hasConnectivity())) {
187+
return _sessions;
188+
}
189+
185190
try {
186191
// getPassword will try to authenticate the user if not authenticated.
187192
final String password = await _userRepository.getPassword();
@@ -309,6 +314,12 @@ class CourseRepository {
309314
/// version of the course. Return the course with the summary set.
310315
Future<Course> getCourseSummary(Course course) async {
311316
CourseSummary summary;
317+
318+
// Don't try to update the summary when user has no connection
319+
if (!(await _networkingService.hasConnectivity())) {
320+
return course;
321+
}
322+
312323
try {
313324
final String password = await _userRepository.getPassword();
314325
summary = await _signetsApi.getCourseSummary(

lib/core/services/networking_service.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
// FLUTTER / DART / THIRD-PARTIES
12
import 'dart:async';
2-
3-
import 'package:connectivity/connectivity.dart';
3+
import 'package:connectivity_plus/connectivity_plus.dart';
44

55
class NetworkingService {
66
final Connectivity _connectivity = Connectivity();

lib/core/utils/utils.dart

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ import 'package:fluttertoast/fluttertoast.dart';
44
import 'package:url_launcher/url_launcher.dart';
55
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
66

7-
// SERVICES
8-
import 'package:notredame/core/services/networking_service.dart';
9-
107
class Utils {
118
/// Used to open a url
129
static Future<void> launchURL(String url, AppIntl intl) async {
@@ -26,13 +23,6 @@ class Utils {
2623
return ((grade / maxGrade) * 100).roundToDouble();
2724
}
2825

29-
static Future showNoConnectionToast(
30-
NetworkingService networkingService, AppIntl intl) async {
31-
if (!await networkingService.hasConnectivity()) {
32-
Fluttertoast.showToast(msg: intl.no_connectivity);
33-
}
34-
}
35-
3626
static Color getColorByBrightness(
3727
BuildContext context, Color lightColor, Color darkColor) {
3828
return Theme.of(context).brightness == Brightness.light

lib/core/viewmodels/grades_viewmodel.dart

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@ import 'package:notredame/core/managers/course_repository.dart';
1010
// MODEL
1111
import 'package:notredame/core/models/course.dart';
1212

13-
// SERVICE
14-
import 'package:notredame/core/services/networking_service.dart';
15-
16-
// UTILS
17-
import 'package:notredame/core/utils/utils.dart';
18-
1913
// OTHER
2014
import 'package:notredame/locator.dart';
2115

@@ -26,9 +20,6 @@ class GradesViewModel extends FutureViewModel<Map<String, List<Course>>> {
2620
/// Localization class of the application.
2721
final AppIntl _appIntl;
2822

29-
/// Verify if user has an active internet connection
30-
final NetworkingService _networkingService = locator<NetworkingService>();
31-
3223
/// Contains all the courses of the student sorted by session
3324
final Map<String, List<Course>> coursesBySession = {};
3425

@@ -51,7 +42,6 @@ class GradesViewModel extends FutureViewModel<Map<String, List<Course>>> {
5142
}
5243
}).whenComplete(() {
5344
setBusy(false);
54-
Utils.showNoConnectionToast(_networkingService, _appIntl);
5545
});
5646

5747
return coursesBySession;

lib/core/viewmodels/profile_viewmodel.dart

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@ import 'package:notredame/core/managers/user_repository.dart';
1111
import 'package:notredame/core/models/profile_student.dart';
1212
import 'package:notredame/core/models/program.dart';
1313

14-
// SERVICE
15-
import 'package:notredame/core/services/networking_service.dart';
16-
17-
// UTILS
18-
import 'package:notredame/core/utils/utils.dart';
19-
2014
// OTHERS
2115
import '../../locator.dart';
2216

@@ -27,9 +21,6 @@ class ProfileViewModel extends FutureViewModel<List<Program>> {
2721
/// Localization class of the application.
2822
final AppIntl _appIntl;
2923

30-
/// Verify if user has an active internet connection
31-
final NetworkingService _networkingService = locator<NetworkingService>();
32-
3324
/// List of the programs
3425
List<Program> _programList = List.empty();
3526

@@ -81,7 +72,6 @@ class ProfileViewModel extends FutureViewModel<List<Program>> {
8172
.then((value) => _userRepository.getPrograms().catchError(onError))
8273
.whenComplete(() {
8374
setBusyForObject(isLoadingEvents, false);
84-
Utils.showNoConnectionToast(_networkingService, _appIntl);
8575
});
8676
return value;
8777
});

lib/core/viewmodels/schedule_viewmodel.dart

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,6 @@ import 'package:notredame/core/managers/settings_manager.dart';
1313
// MODELS
1414
import 'package:notredame/core/models/course_activity.dart';
1515

16-
// SERVICE
17-
import 'package:notredame/core/services/networking_service.dart';
18-
19-
// UTILS
20-
import 'package:notredame/core/utils/utils.dart';
21-
2216
// OTHER
2317
import 'package:notredame/locator.dart';
2418
import 'package:notredame/core/constants/preferences_flags.dart';
@@ -52,9 +46,6 @@ class ScheduleViewModel extends FutureViewModel<List<CourseActivity>> {
5246
/// Get current locale
5347
Locale get locale => _settingsManager.locale;
5448

55-
/// Verify if user has an active internet connection
56-
final NetworkingService _networkingService = locator<NetworkingService>();
57-
5849
ScheduleViewModel({@required AppIntl intl, DateTime initialSelectedDate})
5950
: _appIntl = intl,
6051
selectedDate = initialSelectedDate ?? DateTime.now(),
@@ -83,7 +74,6 @@ class ScheduleViewModel extends FutureViewModel<List<CourseActivity>> {
8374
}
8475
}).whenComplete(() {
8576
setBusyForObject(isLoadingEvents, false);
86-
Utils.showNoConnectionToast(_networkingService, _appIntl);
8777
});
8878
return value;
8979
});

lib/ui/widgets/base_scaffold.dart

Lines changed: 75 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
// FLUTTER / DART / THIRD-PARTIES
2+
import 'package:connectivity_plus/connectivity_plus.dart';
23
import 'package:flutter/material.dart';
4+
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
5+
6+
// UTILS
7+
import 'package:notredame/core/utils/utils.dart';
38
import 'package:notredame/ui/utils/loading.dart';
9+
import 'package:notredame/ui/utils/app_theme.dart';
410

511
// WIDGETS
612
import 'package:notredame/ui/widgets/bottom_bar.dart';
713

814
/// Basic Scaffold to avoid boilerplate code in the application.
915
/// Contains a loader controlled by [_isLoading]
10-
class BaseScaffold extends StatelessWidget {
16+
class BaseScaffold extends StatefulWidget {
1117
final AppBar appBar;
1218

1319
final Widget body;
@@ -35,25 +41,77 @@ class BaseScaffold extends StatelessWidget {
3541
_isLoading = isLoading,
3642
_isInteractionLimitedWhileLoading = isInteractionLimitedWhileLoading;
3743

44+
@override
45+
_BaseScaffoldState createState() => _BaseScaffoldState();
46+
}
47+
48+
class _BaseScaffoldState extends State<BaseScaffold> {
49+
// Displays text under the app bar when offline.
50+
static bool _isOffline = false;
51+
52+
@override
53+
void initState() {
54+
super.initState();
55+
_setOfflineValue();
56+
_listenToChangeInConnectivity();
57+
}
58+
59+
Future _setOfflineValue() async {
60+
final isOffline =
61+
await Connectivity().checkConnectivity() == ConnectivityResult.none;
62+
setState(() {
63+
_isOffline = isOffline;
64+
});
65+
}
66+
67+
void _listenToChangeInConnectivity() {
68+
Connectivity().onConnectivityChanged.listen((event) {
69+
setState(() {
70+
_isOffline = event == ConnectivityResult.none;
71+
});
72+
});
73+
}
74+
3875
@override
3976
Widget build(BuildContext context) => Scaffold(
40-
appBar: appBar,
41-
body: SafeArea(
42-
top: false,
43-
child: Stack(
44-
children: [
45-
body,
46-
if (_isLoading)
47-
buildLoading(
48-
isInteractionLimitedWhileLoading:
49-
_isInteractionLimitedWhileLoading)
50-
else
51-
const SizedBox()
52-
],
77+
body: Scaffold(
78+
appBar: widget.appBar,
79+
body: SafeArea(
80+
top: false,
81+
child: Stack(
82+
children: [
83+
widget.body,
84+
if (widget._isLoading)
85+
buildLoading(
86+
isInteractionLimitedWhileLoading:
87+
widget._isInteractionLimitedWhileLoading)
88+
else
89+
const SizedBox()
90+
],
91+
),
5392
),
93+
bottomNavigationBar: widget._showBottomBar ? BottomBar() : null,
94+
floatingActionButton: widget.fab,
95+
floatingActionButtonLocation: widget.fabPosition,
5496
),
55-
bottomNavigationBar: _showBottomBar ? BottomBar() : null,
56-
floatingActionButton: fab,
57-
floatingActionButtonLocation: fabPosition,
97+
bottomNavigationBar: _isOffline ? buildOfflineBar(context) : null,
5898
);
99+
100+
Widget buildOfflineBar(BuildContext context) {
101+
return Stack(
102+
alignment: Alignment.center,
103+
children: [
104+
Container(
105+
color: Utils.getColorByBrightness(context,
106+
AppTheme.lightThemeBackground, AppTheme.darkThemeBackground),
107+
width: MediaQuery.of(context).size.width,
108+
height: MediaQuery.of(context).size.height / 30,
109+
),
110+
Text(
111+
AppIntl.of(context).no_connectivity,
112+
textAlign: TextAlign.center,
113+
),
114+
],
115+
);
116+
}
59117
}

lib/ui/widgets/bottom_bar.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class BottomBar extends StatelessWidget {
2828
Widget build(BuildContext context) {
2929
return BottomNavigationBar(
3030
type: BottomNavigationBarType.fixed,
31+
elevation: 0,
3132
onTap: (value) => _onTap(value),
3233
items: _buildItems(context),
3334
currentIndex: _defineIndex(ModalRoute.of(context).settings.name),

pubspec.lock

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -106,34 +106,48 @@ packages:
106106
url: "https://pub.dartlang.org"
107107
source: hosted
108108
version: "1.15.0"
109-
connectivity:
109+
connectivity_plus:
110110
dependency: "direct main"
111111
description:
112-
name: connectivity
112+
name: connectivity_plus
113113
url: "https://pub.dartlang.org"
114114
source: hosted
115-
version: "3.0.6"
116-
connectivity_for_web:
115+
version: "1.0.4"
116+
connectivity_plus_linux:
117117
dependency: transitive
118118
description:
119-
name: connectivity_for_web
119+
name: connectivity_plus_linux
120120
url: "https://pub.dartlang.org"
121121
source: hosted
122-
version: "0.4.0"
123-
connectivity_macos:
122+
version: "1.0.3"
123+
connectivity_plus_macos:
124124
dependency: transitive
125125
description:
126-
name: connectivity_macos
126+
name: connectivity_plus_macos
127127
url: "https://pub.dartlang.org"
128128
source: hosted
129-
version: "0.2.0"
130-
connectivity_platform_interface:
129+
version: "1.0.2"
130+
connectivity_plus_platform_interface:
131131
dependency: transitive
132132
description:
133-
name: connectivity_platform_interface
133+
name: connectivity_plus_platform_interface
134134
url: "https://pub.dartlang.org"
135135
source: hosted
136-
version: "2.0.1"
136+
version: "1.0.2"
137+
connectivity_plus_web:
138+
dependency: transitive
139+
description:
140+
name: connectivity_plus_web
141+
url: "https://pub.dartlang.org"
142+
source: hosted
143+
version: "1.0.2"
144+
connectivity_plus_windows:
145+
dependency: transitive
146+
description:
147+
name: connectivity_plus_windows
148+
url: "https://pub.dartlang.org"
149+
source: hosted
150+
version: "1.0.2"
137151
convert:
138152
dependency: transitive
139153
description:
@@ -155,6 +169,13 @@ packages:
155169
url: "https://pub.dartlang.org"
156170
source: hosted
157171
version: "2.0.2"
172+
dbus:
173+
dependency: transitive
174+
description:
175+
name: dbus
176+
url: "https://pub.dartlang.org"
177+
source: hosted
178+
version: "0.5.4"
158179
enum_to_string:
159180
dependency: "direct main"
160181
description:

pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
1515
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
1616
# Read more about iOS versioning at
1717
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
18-
version: 4.1.3+1
18+
version: 4.1.4+1
1919

2020
environment:
2121
sdk: ">=2.10.0 <3.0.0"
@@ -62,7 +62,7 @@ dependencies:
6262
feature_discovery: ^0.14.0
6363
path_provider: ^2.0.1
6464
rive: ^0.7.3
65-
connectivity: ^3.0.4
65+
connectivity_plus: ^1.0.4
6666
flutter_svg: ^0.22.0
6767
font_awesome_flutter: ^9.1.0
6868

0 commit comments

Comments
 (0)