Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/mobile/lib/src/app/dashboard/pages/dashboard_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -263,18 +263,21 @@ class _DashboardPageState extends State<DashboardPage> with UiLoggy {
}

if (state is DashboardLoadingError && !state.hasCache) {
final isOffline = state.isOffline;
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.cloud_off,
isOffline ? Icons.cloud_off : Icons.error_outline,
size: 64,
color: Colors.grey,
),
SizedBox(height: 16),
TranslatedText(
"Couldn't connect to the internet",
isOffline
? "Couldn't connect to the internet"
: "Couldn't load air quality data",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
Expand All @@ -283,7 +286,9 @@ class _DashboardPageState extends State<DashboardPage> with UiLoggy {
),
SizedBox(height: 8),
TranslatedText(
"Please check your connection and try again",
isOffline
? "Please check your connection and try again"
: "Something went wrong. Please try again later",
style: TextStyle(
fontSize: 16,
color: Theme.of(context).textTheme.bodyMedium?.color,
Expand Down
10 changes: 9 additions & 1 deletion src/mobile/lib/src/app/learn/bloc/kya_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:airqo/src/app/learn/models/lesson_response_model.dart';
import 'package:airqo/src/app/learn/repository/kya_repository.dart';
import 'package:airqo/src/app/shared/services/cache_manager.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:loggy/loggy.dart';
Expand All @@ -9,6 +10,8 @@ part 'kya_state.dart';

class KyaBloc extends Bloc<KyaEvent, KyaState> with UiLoggy {
final KyaRepository repository;
final CacheManager _cacheManager = CacheManager();

KyaBloc(this.repository) : super(KyaInitial()) {
on<LoadLessons>(_onLoadLessons);
on<RefreshLessons>(_onRefreshLessons);
Expand All @@ -32,10 +35,14 @@ class KyaBloc extends Bloc<KyaEvent, KyaState> with UiLoggy {
emit(LessonsLoadingError(
message: e.toString(),
cachedModel: cachedModel,
isOffline: !_cacheManager.isConnected,
));
} catch (cacheError) {
loggy.error('Error fetching cached lessons: $cacheError');
emit(LessonsLoadingError(message: e.toString()));
emit(LessonsLoadingError(
message: e.toString(),
isOffline: !_cacheManager.isConnected,
));
}
}
}
Expand All @@ -62,6 +69,7 @@ class KyaBloc extends Bloc<KyaEvent, KyaState> with UiLoggy {
emit(LessonsLoadingError(
message: e.toString(),
cachedModel: cachedModel,
isOffline: !_cacheManager.isConnected,
));
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/mobile/lib/src/app/learn/bloc/kya_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ class LessonsLoaded extends KyaState {
class LessonsLoadingError extends KyaState {
final String message;
final LessonResponseModel? cachedModel;

final bool isOffline;

const LessonsLoadingError({
required this.message,
this.cachedModel,
this.isOffline = false,
});

@override
List<Object?> get props => [message, cachedModel];
List<Object?> get props => [message, cachedModel, isOffline];
}
10 changes: 8 additions & 2 deletions src/mobile/lib/src/app/learn/pages/kya_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,11 @@ class _KyaPageState extends State<KyaPage> with UiLoggy {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.cloud_off, size: 64, color: Colors.grey),
Icon(
state.isOffline ? Icons.cloud_off : Icons.error_outline,
size: 64,
color: Colors.grey,
),
const SizedBox(height: 16),
TranslatedText(
"Unable to load content",
Expand All @@ -212,7 +216,9 @@ class _KyaPageState extends State<KyaPage> with UiLoggy {
Padding(
padding: const EdgeInsets.symmetric(horizontal: 32.0),
child: TranslatedText(
"Please check your connection and try again",
state.isOffline
? "Please check your connection and try again"
: "Something went wrong. Please try again later",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
Expand Down
5 changes: 4 additions & 1 deletion src/mobile/lib/src/app/map/pages/map_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'package:airqo/src/app/map/widgets/map_overlay_controls.dart';
import 'package:airqo/src/app/map/widgets/map_search_sheet.dart';
import 'package:airqo/src/app/map/widgets/map_style_picker.dart';
import 'package:airqo/src/app/other/places/bloc/google_places_bloc.dart';
import 'package:airqo/src/app/shared/services/cache_manager.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
Expand Down Expand Up @@ -348,6 +349,8 @@ class _MapScreenState extends State<MapScreen>
(markers.isEmpty || allMeasurements.isEmpty)) {
_initializeWithData(response);
}
} else if (state is MapLoadingError) {
if (mounted) setState(() => isInitializing = false);
}
},
),
Expand Down Expand Up @@ -383,7 +386,7 @@ class _MapScreenState extends State<MapScreen>
markers.isEmpty &&
allMeasurements.isEmpty &&
!isRetrying)
? MapErrorView(onRetry: _retryLoading)
? MapErrorView(onRetry: _retryLoading, isOffline: !CacheManager().isConnected)
: _buildMapView(),
),
);
Expand Down
9 changes: 6 additions & 3 deletions src/mobile/lib/src/app/map/widgets/map_error_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ import 'package:flutter/material.dart';

class MapErrorView extends StatelessWidget {
final VoidCallback onRetry;
final bool isOffline;

const MapErrorView({super.key, required this.onRetry});
const MapErrorView({super.key, required this.onRetry, this.isOffline = false});

@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.map_outlined, size: 64, color: Colors.grey),
Icon(isOffline ? Icons.cloud_off : Icons.map_outlined, size: 64, color: Colors.grey),
const SizedBox(height: 16),
TranslatedText(
"Unable to load map data",
Expand All @@ -24,7 +25,9 @@ class MapErrorView extends StatelessWidget {
),
const SizedBox(height: 8),
TranslatedText(
"Please check your connection and try again",
isOffline
? "Please check your connection and try again"
: "Something went wrong. Please try again later",
style: TextStyle(
fontSize: 16,
color: Theme.of(context).textTheme.bodyMedium?.color),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class _SelectLanguagePageState extends State<SelectLanguagePage> {
if (needsMlKitDownload) {
await MlKitTranslationService()
.prepareModel(language.code)
.timeout(const Duration(seconds: 30));
.timeout(const Duration(minutes: 3));
await MlKitTranslationService()
.prepareCriticalStrings(language.code)
.timeout(const Duration(seconds: 30));
Expand All @@ -88,10 +88,12 @@ class _SelectLanguagePageState extends State<SelectLanguagePage> {
debugPrint('Language preparation failed: $e\n$stackTrace');
if (!mounted) return;
setState(() => _preparingCode = null);
final isNetworkError = e is SocketException || e is TimeoutException;
final isNetworkError = e is SocketException;
final message = isNetworkError
? 'No internet connection. Please check your network and try again.'
: 'Failed to prepare language. Please try again.';
: e is TimeoutException
? 'Download is taking too long. Please check your connection and try again.'
: 'Failed to prepare language. Please try again.';
messenger.showSnackBar(
SnackBar(
content: Text(message),
Expand Down
Loading