Skip to content

Commit

Permalink
Offline detection UI (PalisadoesFoundation#2524)
Browse files Browse the repository at this point in the history
* Developed the business logic of offline detection mechanism

* fixed dropped coverage

* Offline detection UI built

* increased overall coverage

* fixed minor linting error

* fixed minor formatting error

* increased code coverage

* refactored code

* added tests

* main_page_test

* fixed run check ignore

* fixed failing test

* fixed failing test

* fixed failing test

* fixed failing test

* fixed failing test

* fixed failing test

* fixed failing test
  • Loading branch information
Azad99-9 authored Jul 12, 2024
1 parent 17c0e3d commit d2c9bdd
Show file tree
Hide file tree
Showing 80 changed files with 999 additions and 428 deletions.
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
android:label="talawa"
android:icon="@mipmap/ic_launcher"
android:allowBackup="false"
android:enableOnBackInvokedCallback="true"
tools:replace="android:label">
<activity
android:name=".MainActivity"
Expand Down
10 changes: 6 additions & 4 deletions lib/locator.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:get_it/get_it.dart';
import 'package:http/http.dart' as http;
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:talawa/main.dart';
Expand Down Expand Up @@ -32,6 +31,7 @@ import 'package:talawa/view_model/after_auth_view_models/feed_view_models/organi
import 'package:talawa/view_model/after_auth_view_models/profile_view_models/edit_profile_view_model.dart';
import 'package:talawa/view_model/after_auth_view_models/profile_view_models/profile_page_view_model.dart';
import 'package:talawa/view_model/after_auth_view_models/settings_view_models/app_setting_view_model.dart';
import 'package:talawa/view_model/connectivity_view_model.dart';
import 'package:talawa/view_model/lang_view_model.dart';
import 'package:talawa/view_model/main_screen_view_model.dart';
import 'package:talawa/view_model/pre_auth_view_models/login_view_model.dart';
Expand Down Expand Up @@ -89,7 +89,7 @@ final sessionManager = locator<SessionManager>();
///
/// **returns**:
/// None
void setupLocator() {
Future<void> setupLocator() async {
//services
locator.registerSingleton(NavigationService());

Expand All @@ -116,17 +116,19 @@ void setupLocator() {
locator.registerLazySingleton(() => ImagePicker());
locator.registerLazySingleton(() => ImageCropper());

locator.registerSingleton(ConnectivityService(client: http.Client()));

//graphql
locator.registerSingleton(GraphqlConfig());

//databaseMutationFunction
locator.registerSingleton(DataBaseMutationFunctions());

locator.registerSingleton(ConnectivityService());

//queries
locator.registerSingleton(Queries());

locator.registerFactory(() => AppConnectivity());

//Page viewModels
locator.registerFactory(() => DemoViewModel());
// locator.registerFactory(() => OrganizationFeedViewModel());
Expand Down
92 changes: 42 additions & 50 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import 'package:hive/hive.dart';
import 'package:path_provider/path_provider.dart' as path;
import 'package:provider/provider.dart';
import 'package:quick_actions/quick_actions.dart';
import 'package:talawa/constants/custom_theme.dart';
import 'package:talawa/constants/quick_actions.dart';
import 'package:talawa/locator.dart';
import 'package:talawa/models/asymetric_keys/asymetric_keys.dart';
Expand All @@ -17,6 +16,7 @@ import 'package:talawa/plugins/fetch_plugin_list.dart';
import 'package:talawa/router.dart' as router;
import 'package:talawa/utils/app_localization.dart';
import 'package:talawa/view_model/base_view_model.dart';
import 'package:talawa/view_model/connectivity_view_model.dart';
import 'package:talawa/view_model/lang_view_model.dart';
import 'package:talawa/view_model/theme_view_model.dart';
import 'package:talawa/views/base_view.dart';
Expand All @@ -39,6 +39,7 @@ Future<void> main() async {
await Hive.openBox('url');

setupLocator();

// The runApp() function takes the given Widget and makes it the root of the widget tree.
runApp(MyApp());
}
Expand Down Expand Up @@ -118,55 +119,46 @@ class _MyAppState extends State<MyApp> {
return BaseView<AppTheme>(
onModelReady: (model) => model.initialize(),
builder: (context, model, child) {
return MaterialApp(
locale: langModel.appLocal,
supportedLocales: [
const Locale('en', 'US'),
const Locale('es', 'ES'),
const Locale('fr', 'FR'),
const Locale('hi', 'IN'),
const Locale('zh', 'CN'),
const Locale('de', 'DE'),
const Locale('ja', 'JP'),
const Locale('pt', 'PT'),
],
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
title: 'Talawa',
theme: Provider.of<AppTheme>(context).isdarkTheme
? TalawaTheme.darkTheme
: TalawaTheme.lightTheme,
debugShowCheckedModeBanner: false,
navigatorKey: navigationService.navigatorKey,
onGenerateRoute: router.generateRoute,
localeResolutionCallback:
(Locale? locale, Iterable<Locale> supportedLocales) {
if (locale == null) {
debugPrint("*language locale is null!!!");
return supportedLocales.first;
}
for (final Locale supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale.languageCode ||
supportedLocale.countryCode == locale.countryCode) {
return supportedLocale;
}
}
return supportedLocales.first;
},
initialRoute: '/',
onGenerateInitialRoutes: (String initialRouteName) {
return [
router.generateRoute(
RouteSettings(
name: '/',
arguments: mainScreenQuickActionindex,
),
),
];
return BaseView<AppConnectivity>(
onModelReady: (connectivityModel) =>
connectivityModel.initialise(),
builder: (context, connectivityModel, child) {
return MaterialApp(
locale: langModel.appLocal,
supportedLocales: [
const Locale('en', 'US'),
const Locale('es', 'ES'),
const Locale('fr', 'FR'),
const Locale('hi', 'IN'),
const Locale('zh', 'CN'),
const Locale('de', 'DE'),
const Locale('ja', 'JP'),
const Locale('pt', 'PT'),
],
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
title: 'Talawa',
theme: Provider.of<AppTheme>(context).theme,
debugShowCheckedModeBanner: false,
navigatorKey: navigationService.navigatorKey,
onGenerateRoute: router.generateRoute,
localeResolutionCallback: langModel.localeResoultion,
initialRoute: '/',
onGenerateInitialRoutes: (String initialRouteName) {
return [
router.generateRoute(
RouteSettings(
name: '/',
arguments: mainScreenQuickActionindex,
),
),
];
},
);
},
);
},
Expand Down
8 changes: 4 additions & 4 deletions lib/services/database_mutation_functions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:talawa/enums/enums.dart';
import 'package:talawa/locator.dart';
import 'package:talawa/models/organization/org_info.dart';
import 'package:talawa/utils/queries.dart';
import 'package:talawa/view_model/connectivity_view_model.dart';

/// DataBaseMutationFunctions class provides different services that are under the context of graphQL mutations and queries.
///
Expand Down Expand Up @@ -34,8 +35,10 @@ class DataBaseMutationFunctions {
/// **returns**:
/// None
void init() {
graphqlConfig.getOrgUrl();
clientNonAuth = graphqlConfig.clientToQuery();
clientAuth = graphqlConfig.authClient();
print('ajkjkdjkjkdjieiejie');
_query = Queries();
}

Expand Down Expand Up @@ -104,10 +107,7 @@ class DataBaseMutationFunctions {
debugPrint(exception.linkException.toString());
if (showSnackBar) {
WidgetsBinding.instance.addPostFrameCallback(
(_) => navigationService.showTalawaErrorSnackBar(
"Server not running/wrong url",
MessageType.info,
),
(_) => AppConnectivity.showSnackbar(isOnline: false),
);
}
return false;
Expand Down
1 change: 1 addition & 0 deletions lib/services/event_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import 'package:talawa/widgets/custom_progress_dialog.dart';
class EventService {
EventService() {
_eventStream = _eventStreamController.stream.asBroadcastStream();
print(_eventStream);
_currentOrg = _userConfig.currentOrg;
_userConfig.initialiseStream();
setOrgStreamSubscription();
Expand Down
107 changes: 24 additions & 83 deletions lib/services/third_party_service/connectivity_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,71 +9,48 @@ import 'package:talawa/locator.dart';
/// It includes methods for:
/// * Initializing the network service - [initConnectivity]
/// * Monitoring connectivity changes - [enableSubscription]
/// * Handling online and offline states - [_handleOnline], [_handleOffline]
/// * Handling online and offline states - [handleOnline], [handleOffline]
/// * Checking reachability of a given URI - [isReachable]
/// * Handling the device's connectivity status - [handleConnection]
/// * Checking if the device has any type of network connection - [hasConnection]
class ConnectivityService {
/// This function is used to initialize the network service.
/// Stream controller for network status changes.
late StreamController<ConnectivityResult> connectionStatusController;

/// Getter for the stream of connection status changes.
Stream<ConnectivityResult> get connectionStream =>
connectionStatusController.stream;

/// Checks the current internet connectivity status of the device.
///
/// **params**:
/// None
///
/// **returns**:
/// None
ConnectivityService({required http.Client client}) {
_client = client;
_connectionStatusController = StreamController<ConnectivityResult>();
initConnectivity();
/// * `Future<ConnectivityResult>`: indicates if the url is reachable.
Future<ConnectivityResult> getConnectionType() async {
final result = await connectivity.checkConnectivity();
return result;
}

/// Stream controller for network status changes
late StreamController<ConnectivityResult> _connectionStatusController;

/// Getter for the stream of connection status changes.
Stream<ConnectivityResult> get connectionStream =>
_connectionStatusController.stream;

/// Client to access internet.
late final http.Client _client;

/// This function initializes connectivity monitoring.
///
/// **params**:
/// None
/// * `client`: An instance of `http.Client` to make the HTTP request.
///
/// **returns**:
/// None
Future<void> initConnectivity() async {
/// Try getting initial connectivity status
checkInitialConnection();
Future<void> initConnectivity({required http.Client client}) async {
_client = client;
connectionStatusController = StreamController<ConnectivityResult>();

/// Listen for future changes in connectivity
enableSubscription();
}

/// This function checks the initial connection status.
///
/// **params**:
/// None
///
/// **returns**:
/// None
Future<void> checkInitialConnection() async {
try {
final result = await connectivity.checkConnectivity();
print(result);
_connectionStatusController.add(result);
handleConnection(result);
} catch (e) {
// Handle other exceptions
print('Error checking connectivity: $e');
_connectionStatusController
.add(ConnectivityResult.none); // Assume no connection on error
handleConnection(ConnectivityResult.none);
}
}

/// This function enables the subscription to connectivity changes.
///
/// **params**:
Expand All @@ -85,8 +62,7 @@ class ConnectivityService {
connectivity.onConnectivityChanged.listen(
(ConnectivityResult result) {
print(result);
_connectionStatusController.add(result);
handleConnection(result);
connectionStatusController.add(result);
},
onError: (error) {
// Handle errors during listening for changes
Expand All @@ -95,34 +71,14 @@ class ConnectivityService {
);
}

/// This function handles the actions to be taken when the device is online.
///
/// **params**:
/// None
///
/// **returns**:
/// None
Future<void> _handleOnline() async {
// To be implemented.
}

/// This function handles the actions to be taken when the device is offline.
///
/// **params**:
/// None
///
/// **returns**:
/// None
Future<void> _handleOffline() async {
// To be implemented.
}

/// This function checks if a given URI is reachable within a specified timeout period.
///
/// Specifically designed to
///
/// **params**:
/// * `client`: An instance of `http.Client` to make the HTTP request.
/// * `uriString`: An optional `String` specifying the URI to check.
/// Defaults to 'http://www.google.com' if not provided.
/// Defaults to 'org link' if not provided.
///
/// **returns**:
/// * `Future<bool>`: indicates if the url is reachable.
Expand All @@ -133,30 +89,15 @@ class ConnectivityService {
try {
client ??= _client;
await client
.get(Uri.parse(uriString ?? 'http://www.google.com'))
.timeout(const Duration(seconds: 5));
.get(Uri.parse(uriString ?? graphqlConfig.httpLink.uri.toString()))
.timeout(const Duration(seconds: 30));
return true;
} catch (e) {
print('Timeout while checking reachability: $e');
return false;
}
}

/// This function handles the device's connectivity status based on the provided `ConnectivityResult`.
///
/// **params**:
/// * `result`: A `ConnectivityResult` indicating the current connectivity status.
///
/// **returns**:
/// None
Future<void> handleConnection(ConnectivityResult result) async {
if (await hasConnection() && await isReachable(client: _client)) {
_handleOnline();
} else {
_handleOffline();
}
}

/// This function checks if the device currently has any type of network connection.
///
/// **params**:
Expand All @@ -166,7 +107,7 @@ class ConnectivityService {
/// * `Future<bool>`: indicating whether the device has a network connection.
Future<bool> hasConnection() async {
try {
final result = await connectivity.checkConnectivity();
final result = await getConnectionType();
return result != ConnectivityResult.none;
} catch (e) {
return false;
Expand Down
Loading

0 comments on commit d2c9bdd

Please sign in to comment.