From 1f5b5e441b88741552ac4608d17613dd8f852371 Mon Sep 17 00:00:00 2001 From: Pranav <122373207+pranavkonidena@users.noreply.github.com> Date: Tue, 27 Feb 2024 11:28:41 +0530 Subject: [PATCH] Network Interceptor for noticeboard mobile (#35) * Bump up IOS version to 12 , added network interceptor in list_notices screen * Added network interceptor to all reqd widgets * Add Pranav to contributors.md * Added root context to the stream so that it is always mounted * Fix flutter analyze, removed deprecated willpopscope * Added dynamic fetch when back online All changes are as follows: I have updated the web view flutter package to 4.7.0 and upgraded flutter version to 3.19 because reloading the webview requires a webview controller, also added another stream for this purpose * Added EOF in enums, removed build files --- CONTRIBUTORS.md | 3 +- noticeboard/ios/.gitignore | 1 + .../ios/Flutter/AppFrameworkInfo.plist | 2 +- noticeboard/ios/Podfile | 2 +- noticeboard/ios/Podfile.lock | 14 +-- .../ios/Runner.xcodeproj/project.pbxproj | 14 +-- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- noticeboard/ios/Runner/Runner.entitlements | 5 ++ .../lib/bloc/connectivity_status_bloc.dart | 49 ++++++++++ noticeboard/lib/bloc/list_notices_bloc.dart | 1 - noticeboard/lib/bloc/notice_detail_bloc.dart | 12 +++ .../lib/enum/connectivity_status_enum.dart | 4 + noticeboard/lib/enum/current_widget_enum.dart | 4 + noticeboard/lib/global/global_functions.dart | 28 ++++++ noticeboard/lib/main.dart | 3 + noticeboard/lib/routes/routing.dart | 1 - .../lib/screens/bottom_navigation.dart | 20 ++++- noticeboard/lib/screens/filters.dart | 2 +- noticeboard/lib/screens/launching.dart | 1 - noticeboard/lib/screens/list_notices.dart | 19 +++- noticeboard/lib/screens/notice_detail.dart | 89 ++++++++++++------- noticeboard/lib/screens/profile.dart | 16 +++- noticeboard/pubspec.yaml | 2 +- 23 files changed, 230 insertions(+), 64 deletions(-) create mode 100644 noticeboard/ios/Runner/Runner.entitlements create mode 100644 noticeboard/lib/bloc/connectivity_status_bloc.dart create mode 100644 noticeboard/lib/bloc/notice_detail_bloc.dart create mode 100644 noticeboard/lib/enum/connectivity_status_enum.dart create mode 100644 noticeboard/lib/enum/current_widget_enum.dart diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1eded78..490ca1a 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -1,3 +1,4 @@ - [@Sparsh1212](https://github.com/Sparsh1212) - [@just-ary27](https://github.com/just-ary27) -- [@kmrinal19](https://github.com/kmrinal19) \ No newline at end of file +- [@kmrinal19](https://github.com/kmrinal19) +- [@pranavkonidena](https://github.com/pranavkonidena) \ No newline at end of file diff --git a/noticeboard/ios/.gitignore b/noticeboard/ios/.gitignore index e96ef60..9a29ebd 100644 --- a/noticeboard/ios/.gitignore +++ b/noticeboard/ios/.gitignore @@ -24,6 +24,7 @@ Flutter/flutter_assets/ Flutter/flutter_export_environment.sh ServiceDefinitions.json Runner/GeneratedPluginRegistrant.* +build/ # Exceptions to above rules. !default.mode1v3 diff --git a/noticeboard/ios/Flutter/AppFrameworkInfo.plist b/noticeboard/ios/Flutter/AppFrameworkInfo.plist index f2872cf..8c6e561 100644 --- a/noticeboard/ios/Flutter/AppFrameworkInfo.plist +++ b/noticeboard/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 12.0 diff --git a/noticeboard/ios/Podfile b/noticeboard/ios/Podfile index 52cd522..e0da1a9 100644 --- a/noticeboard/ios/Podfile +++ b/noticeboard/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project - platform :ios, '10.0' + platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/noticeboard/ios/Podfile.lock b/noticeboard/ios/Podfile.lock index 161b93f..34c0a76 100644 --- a/noticeboard/ios/Podfile.lock +++ b/noticeboard/ios/Podfile.lock @@ -7,7 +7,7 @@ PODS: - firebase_core (2.24.2): - Firebase/CoreOnly (= 10.18.0) - Flutter - - firebase_messaging (14.7.9): + - firebase_messaging (14.7.10): - Firebase/Messaging (= 10.18.0) - firebase_core - Flutter @@ -119,23 +119,23 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Firebase: 414ad272f8d02dfbf12662a9d43f4bba9bec2a06 firebase_core: 0af4a2b24f62071f9bf283691c0ee41556dcb3f5 - firebase_messaging: 875385354f623750aa03204a028d640108bc3412 + firebase_messaging: 90e8a6db84b6e1e876cebce4f30f01dc495e7014 FirebaseCore: 2322423314d92f946219c8791674d2f3345b598f FirebaseCoreInternal: b444828ea7cfd594fca83046b95db98a2be4f290 FirebaseInstallations: 033d199474164db20c8350736842a94fe717b960 FirebaseMessaging: 9bc34a98d2e0237e1b121915120d4d48ddcf301e - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be GoogleDataTransport: 57c22343ab29bc686febbf7cbb13bad167c2d8fe GoogleUtilities: 0759d1a57ebb953965c2dfe0ba4c82e95ccc2e34 nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5 - path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 + path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4 share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5 uni_links: d97da20c7701486ba192624d99bffaaffcfc298a - url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b - webview_flutter_wkwebview: b7e70ef1ddded7e69c796c7390ee74180182971f + url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812 + webview_flutter_wkwebview: be0f0d33777f1bfd0c9fdcb594786704dbf65f36 -PODFILE CHECKSUM: f3c6bbf2cd440a5be9eae241d089fc1e5c9e4ade +PODFILE CHECKSUM: 7b33e402635c950b38d380dc47108a3f46f265c2 COCOAPODS: 1.14.3 diff --git a/noticeboard/ios/Runner.xcodeproj/project.pbxproj b/noticeboard/ios/Runner.xcodeproj/project.pbxproj index a8ef9ee..7999777 100644 --- a/noticeboard/ios/Runner.xcodeproj/project.pbxproj +++ b/noticeboard/ios/Runner.xcodeproj/project.pbxproj @@ -158,7 +158,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -346,7 +346,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; ONLY_ACTIVE_ARCH = NO; SDKROOT = iphoneos; @@ -372,7 +372,7 @@ INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Noticeboard; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -436,7 +436,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = NO; SDKROOT = iphoneos; @@ -485,7 +485,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -512,7 +512,7 @@ INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Noticeboard; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -546,7 +546,7 @@ INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Noticeboard; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/noticeboard/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/noticeboard/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a6b826d..5e31d3d 100644 --- a/noticeboard/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/noticeboard/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ + + + + diff --git a/noticeboard/lib/bloc/connectivity_status_bloc.dart b/noticeboard/lib/bloc/connectivity_status_bloc.dart new file mode 100644 index 0000000..e23684b --- /dev/null +++ b/noticeboard/lib/bloc/connectivity_status_bloc.dart @@ -0,0 +1,49 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:noticeboard/bloc/notice_detail_bloc.dart'; +import 'package:noticeboard/enum/connectivity_status_enum.dart'; +import 'package:noticeboard/enum/current_widget_enum.dart'; + +class ConnectivityStatusBloc { + late BuildContext context; + late CurrentWidget currentWidget; + final _eventController = StreamController.broadcast(); + StreamSink get eventSink => _eventController.sink; + Stream get _eventStream => _eventController.stream; + ConnectivityStatus previousResult = ConnectivityStatus.connected; + + static final ConnectivityStatusBloc _connectivityStatusBloc = + ConnectivityStatusBloc._(); + + final networkSnackBar = + const SnackBar(content: Text("Please check your internet connection!")); + final backOnlineSnackbar = const SnackBar(content: Text("Back online!")); + + factory ConnectivityStatusBloc() => _connectivityStatusBloc; + final NoticeDetailBloc _noticeDetailBloc = NoticeDetailBloc(); + + ConnectivityStatusBloc._() { + _eventStream.listen((connectivityEvent) { + if (connectivityEvent == ConnectivityStatus.notConnected && + previousResult == ConnectivityStatus.connected && + context.mounted) { + ScaffoldMessenger.of(context).showSnackBar(networkSnackBar); + } else if (connectivityEvent == ConnectivityStatus.connected && + previousResult == ConnectivityStatus.notConnected) { + ScaffoldMessenger.of(context).showSnackBar(backOnlineSnackbar); + if (currentWidget == CurrentWidget.noticeDetail) { + // Add an event in the sink so that notice detail webview can be refetched + _noticeDetailBloc.eventSink.add(CurrentWidget.noticeDetail); + } else { + // User is on list of notices , refetch them + _noticeDetailBloc.eventSink.add(CurrentWidget.listNotices); + } + } + previousResult = connectivityEvent; + }); + } + + void disposeStream() { + _eventController.close(); + } +} diff --git a/noticeboard/lib/bloc/list_notices_bloc.dart b/noticeboard/lib/bloc/list_notices_bloc.dart index 7bd82e7..3194a88 100644 --- a/noticeboard/lib/bloc/list_notices_bloc.dart +++ b/noticeboard/lib/bloc/list_notices_bloc.dart @@ -314,7 +314,6 @@ class ListNoticesBloc { DynamicFetch.fetchInstituteNotices) filterResult.endpoint = 'api/noticeboard/institute_notices/?start=${filterResult.startDate}&end=${filterResult.endDate}'; - // TODO: Add the if condition for Institute Notices case } PaginatedInfo paginatedInfo = await _listNoticesRepository .fetchFilteredNotices(filterResult.endpoint!, page); diff --git a/noticeboard/lib/bloc/notice_detail_bloc.dart b/noticeboard/lib/bloc/notice_detail_bloc.dart new file mode 100644 index 0000000..eb2ed12 --- /dev/null +++ b/noticeboard/lib/bloc/notice_detail_bloc.dart @@ -0,0 +1,12 @@ +import 'dart:async'; + +import 'package:noticeboard/enum/current_widget_enum.dart'; + +class NoticeDetailBloc { + final _eventController = StreamController.broadcast(); + StreamSink get eventSink => _eventController.sink; + Stream get eventStream => _eventController.stream; + static final NoticeDetailBloc _noticeDetailBloc = NoticeDetailBloc._(); + factory NoticeDetailBloc() => _noticeDetailBloc; + NoticeDetailBloc._(); +} diff --git a/noticeboard/lib/enum/connectivity_status_enum.dart b/noticeboard/lib/enum/connectivity_status_enum.dart new file mode 100644 index 0000000..8802e2f --- /dev/null +++ b/noticeboard/lib/enum/connectivity_status_enum.dart @@ -0,0 +1,4 @@ +enum ConnectivityStatus{ + connected , + notConnected +} diff --git a/noticeboard/lib/enum/current_widget_enum.dart b/noticeboard/lib/enum/current_widget_enum.dart new file mode 100644 index 0000000..12268fd --- /dev/null +++ b/noticeboard/lib/enum/current_widget_enum.dart @@ -0,0 +1,4 @@ +enum CurrentWidget { + listNotices, + noticeDetail +} diff --git a/noticeboard/lib/global/global_functions.dart b/noticeboard/lib/global/global_functions.dart index fdec8b1..00cb984 100644 --- a/noticeboard/lib/global/global_functions.dart +++ b/noticeboard/lib/global/global_functions.dart @@ -1,6 +1,11 @@ +import 'dart:async'; +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:noticeboard/bloc/connectivity_status_bloc.dart'; +import 'package:noticeboard/enum/connectivity_status_enum.dart'; import 'package:noticeboard/global/global_constants.dart'; import 'package:shimmer/shimmer.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; @@ -206,3 +211,26 @@ void showGenericError() { content: Text("Error!"), )); } + +Future checkConnectivityStatus() async { + try { + final result = await InternetAddress.lookup("www.example.com"); + if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) { + return ConnectivityStatus.connected; + } else { + return ConnectivityStatus.notConnected; + } + } catch (e) { + return ConnectivityStatus.notConnected; + } +} + +Timer addConnectivityStatusToSink() { + final ConnectivityStatusBloc _connectivityStatusBloc = + ConnectivityStatusBloc(); + Timer _timer = Timer.periodic(Duration(seconds: 15), (timer) async { + ConnectivityStatus connectivityStatus = await checkConnectivityStatus(); + _connectivityStatusBloc.eventSink.add(connectivityStatus); + }); + return _timer; +} diff --git a/noticeboard/lib/main.dart b/noticeboard/lib/main.dart index 6d9aee2..85e3a58 100644 --- a/noticeboard/lib/main.dart +++ b/noticeboard/lib/main.dart @@ -1,5 +1,6 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; +import 'package:noticeboard/bloc/connectivity_status_bloc.dart'; import './routes/routing_constants.dart'; import './routes/routing.dart'; import 'global/global_constants.dart'; @@ -19,6 +20,8 @@ class _MyAppState extends State { // This widget is the root of your application. @override void initState() { + ConnectivityStatusBloc _connectivityStatusBloc = ConnectivityStatusBloc(); + _connectivityStatusBloc.context = context; super.initState(); } diff --git a/noticeboard/lib/routes/routing.dart b/noticeboard/lib/routes/routing.dart index 7248c2c..a90246e 100644 --- a/noticeboard/lib/routes/routing.dart +++ b/noticeboard/lib/routes/routing.dart @@ -6,7 +6,6 @@ import './routing_constants.dart'; import '../screens/login.dart'; import '../screens/list_notices.dart'; import '../screens/launching.dart'; -import '../models/notice_intro.dart'; import '../screens/notice_detail.dart'; class MyRouter { diff --git a/noticeboard/lib/screens/bottom_navigation.dart b/noticeboard/lib/screens/bottom_navigation.dart index b3cae16..bc62cdc 100644 --- a/noticeboard/lib/screens/bottom_navigation.dart +++ b/noticeboard/lib/screens/bottom_navigation.dart @@ -1,6 +1,8 @@ +import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:noticeboard/global/global_functions.dart'; import '../enum/dynamic_fetch_enum.dart'; import '../screens/list_notices.dart'; import '../models/notice_intro.dart'; @@ -14,6 +16,7 @@ class MyBottomNavigationBar extends StatefulWidget { class _MyBottomNavigationBarState extends State { BottomNavigatorBloc _bottomNavigatorBloc = BottomNavigatorBloc(); + late Timer _timer; final widgetOptions = [ ListNotices( listNoticeMetaData: ListNoticeMetaData( @@ -37,24 +40,33 @@ class _MyBottomNavigationBarState extends State { _bottomNavigatorBloc.indexSink.add(index); } + @override + void initState() { + _timer = addConnectivityStatusToSink(); + super.initState(); + } + @override void dispose() { _bottomNavigatorBloc.disposeStreams(); + if (_timer.isActive) _timer.cancel(); super.dispose(); } @override Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () async { + return PopScope( + canPop: false, + onPopInvoked: (didPop) async { + if (didPop) { + return; + } await Future.delayed( Duration(milliseconds: 500), ); if (Platform.isAndroid) { SystemNavigator.pop(); - return true; } else { - return false; } }, child: StreamBuilder( diff --git a/noticeboard/lib/screens/filters.dart b/noticeboard/lib/screens/filters.dart index c598264..72fefdd 100644 --- a/noticeboard/lib/screens/filters.dart +++ b/noticeboard/lib/screens/filters.dart @@ -55,7 +55,7 @@ class _FiltersState extends State { child: GestureDetector( onTap: () { _filtersBloc.eventSink.add(FilterEvents.resetGlobalSlug); - WidgetsBinding.instance!.addPostFrameCallback((time) { + WidgetsBinding.instance.addPostFrameCallback((time) { onFilterClear(); }); }, diff --git a/noticeboard/lib/screens/launching.dart b/noticeboard/lib/screens/launching.dart index 7a858d9..3f434ce 100644 --- a/noticeboard/lib/screens/launching.dart +++ b/noticeboard/lib/screens/launching.dart @@ -12,7 +12,6 @@ import '../models/notice_intro.dart'; import '../services/api_service/api_service.dart'; import '../services/auth/auth_repository.dart'; import '../global/global_functions.dart'; -import '../styles/launching_constants.dart'; import '../styles/login_constants.dart'; class Launcher extends StatefulWidget { diff --git a/noticeboard/lib/screens/list_notices.dart b/noticeboard/lib/screens/list_notices.dart index ccd2b05..56005c5 100644 --- a/noticeboard/lib/screens/list_notices.dart +++ b/noticeboard/lib/screens/list_notices.dart @@ -1,6 +1,11 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:focused_menu/modals.dart'; +import 'package:noticeboard/bloc/connectivity_status_bloc.dart'; +import 'package:noticeboard/bloc/notice_detail_bloc.dart'; +import 'package:noticeboard/enum/current_widget_enum.dart'; import 'package:noticeboard/models/filters_list.dart'; import 'package:noticeboard/models/notice_intro.dart'; import 'package:noticeboard/models/paginated_info.dart'; @@ -21,18 +26,28 @@ class ListNotices extends StatefulWidget { } class _ListNoticesState extends State { - final ListNoticesBloc _listNoticesBloc = ListNoticesBloc(); + final ListNoticesBloc _listNoticesBloc = ListNoticesBloc(); // search final AuthRepository _authRepository = AuthRepository(); - TextEditingController? _controller; // search + final NoticeDetailBloc _noticeDetailBloc = NoticeDetailBloc(); + final ConnectivityStatusBloc _connectivityStatusBloc = + ConnectivityStatusBloc(); + TextEditingController? _controller; @override void initState() { _controller = TextEditingController(); // search _listNoticesBloc.context = context; + _connectivityStatusBloc.context = context; + _connectivityStatusBloc.currentWidget = CurrentWidget.listNotices; _listNoticesBloc.listNoticeMetaData = widget.listNoticeMetaData; _controller!.addListener(_handleQueryChanges); _listNoticesBloc.dynamicFetch = widget.listNoticeMetaData!.dynamicFetch; _listNoticesBloc.dynamicFetchNotices(); + _noticeDetailBloc.eventStream.asBroadcastStream().listen((currentWidget) { + if (currentWidget == CurrentWidget.listNotices) { + _listNoticesBloc.dynamicFetchNotices(); + } + }); super.initState(); } diff --git a/noticeboard/lib/screens/notice_detail.dart b/noticeboard/lib/screens/notice_detail.dart index e6c62c9..ac7c23d 100644 --- a/noticeboard/lib/screens/notice_detail.dart +++ b/noticeboard/lib/screens/notice_detail.dart @@ -1,4 +1,9 @@ +import 'dart:async'; import 'dart:convert'; +import 'dart:io'; +import 'package:noticeboard/bloc/connectivity_status_bloc.dart'; +import 'package:noticeboard/bloc/notice_detail_bloc.dart'; +import 'package:noticeboard/enum/current_widget_enum.dart'; import 'package:noticeboard/enum/notice_content_enum.dart'; import 'package:noticeboard/routes/routing_constants.dart'; import 'package:url_launcher/url_launcher_string.dart'; @@ -20,23 +25,40 @@ class NoticeDetail extends StatefulWidget { class _NoticeDetailState extends State { final NoticeIntro? noticeIntro; + // ignore: unused_element _NoticeDetailState({this.noticeIntro}); - + final ConnectivityStatusBloc _connectivityStatusBloc = + ConnectivityStatusBloc(); NoticeContentBloc _noticeContentBloc = NoticeContentBloc(); + WebViewController _webViewController = WebViewController(); + NoticeDetailBloc _noticeDetailBloc = NoticeDetailBloc(); bool pdfAlreadyOpened = false; + late Timer _timer; @override void initState() { _noticeContentBloc.context = context; + _connectivityStatusBloc.context = context; + _connectivityStatusBloc.currentWidget = CurrentWidget.noticeDetail; _noticeContentBloc.noticeIntro = widget.noticeIntro; _noticeContentBloc.starred = widget.noticeIntro!.starred; _noticeContentBloc.eventSink.add(NoticeContentEvents.fetchContent); + _timer = addConnectivityStatusToSink(); + _noticeDetailBloc.eventStream.listen((event) { + if (event == CurrentWidget.noticeDetail) { + _noticeContentBloc.eventSink.add(NoticeContentEvents.fetchContent); + _webViewController.reload(); + } + }); super.initState(); } @override void dispose() { _noticeContentBloc.disposeStreams(); + if (_timer.isActive) { + _timer.cancel(); + } super.dispose(); } @@ -72,7 +94,7 @@ class _NoticeDetailState extends State { child: GestureDetector( onPanUpdate: (details) { // Can swipe anywhere and detects left swipe - if (details.delta.dx < 0) { + if (details.delta.dx < 0 && Platform.isIOS) { debugPrint("Left swipe occoured!"); if (previousRoute == launchingRoute) { navigatorKey.currentState! @@ -82,15 +104,18 @@ class _NoticeDetailState extends State { } } }, - child: WillPopScope( - onWillPop: () async { + child: PopScope( + canPop: false, + onPopInvoked: (didPop) async { + if (didPop) { + return; + } if (previousRoute == launchingRoute) { navigatorKey.currentState! .pushReplacementNamed(bottomNavigationRoute); } else { navigatorKey.currentState!.pop(); } - return false; }, child: Container( width: _width, @@ -98,7 +123,7 @@ class _NoticeDetailState extends State { child: Column( children: [ buildNoticeIntro(_width), - buildNoticeContent(_width) + buildNoticeContent(_width), ], ), ), @@ -135,35 +160,33 @@ class _NoticeDetailState extends State { mimeType: 'text/html', encoding: Encoding.getByName('utf-8'), ); - return Container( - padding: EdgeInsets.all(10.0), - child: WebView( - initialUrl: uri.toString(), - zoomEnabled: true, - javascriptMode: JavascriptMode.unrestricted, - allowsInlineMediaPlayback: true, - navigationDelegate: (navigation) async { - print(navigation.url); - if (navigation.url.endsWith("pdf") && !pdfAlreadyOpened) { - if (await canLaunchUrlString(navigation.url)) { - String newUrl = - "https://docs.google.com/gview?embedded=true&url=${navigation.url}"; - await launchUrlString(newUrl); - } + _webViewController + ..enableZoom(true) + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..setNavigationDelegate( + NavigationDelegate(onNavigationRequest: (navigation) async { + if (navigation.url.endsWith("pdf") && !pdfAlreadyOpened) { + if (await canLaunchUrlString(navigation.url)) { + String newUrl = + "https://docs.google.com/gview?embedded=true&url=${navigation.url}"; + await launchUrlString(newUrl); + } + return NavigationDecision.prevent; + } else { + if (await canLaunchUrlString(navigation.url)) { + await launchUrlString( + navigation.url, + mode: LaunchMode.externalApplication, + ); return NavigationDecision.prevent; - } else { - if (await canLaunchUrlString(navigation.url)) { - await launchUrlString( - navigation.url, - mode: LaunchMode.externalApplication, - ); - return NavigationDecision.prevent; - } } - return NavigationDecision.navigate; - }, - ), - ); + } + return NavigationDecision.navigate; + })) + ..loadRequest(uri); + return Container( + padding: EdgeInsets.all(10.0), + child: WebViewWidget(controller: _webViewController)); } Container buildNoticeIntro(double _width) { diff --git a/noticeboard/lib/screens/profile.dart b/noticeboard/lib/screens/profile.dart index 5504f7a..6b124f5 100644 --- a/noticeboard/lib/screens/profile.dart +++ b/noticeboard/lib/screens/profile.dart @@ -1,4 +1,7 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; +import 'package:noticeboard/bloc/connectivity_status_bloc.dart'; import 'package:noticeboard/global/global_constants.dart'; import 'package:noticeboard/global/global_functions.dart'; import 'package:noticeboard/models/user_profile.dart'; @@ -16,16 +19,24 @@ class Profile extends StatefulWidget { class _ProfileState extends State { final ProfileBloc _profileBloc = ProfileBloc(); final AuthRepository _authRepository = AuthRepository(); - + final ConnectivityStatusBloc _connectivityStatusBloc = + ConnectivityStatusBloc(); + late Timer _timer; @override void initState() { _profileBloc.context = context; + _connectivityStatusBloc.context = context; + _timer = addConnectivityStatusToSink(); super.initState(); } @override void dispose() { _profileBloc.disposeStreams(); + if(_timer.isActive){ + _timer.cancel(); + } + super.dispose(); } @@ -117,7 +128,8 @@ class _ProfileState extends State { 'Notification settings', ProfileEvents.notificationSettingsEvent), sizedBox(20.0), - buildMenuItem(aboutUsIcon, "About us", ProfileEvents.aboutUsEvent), + buildMenuItem( + aboutUsIcon, "About us", ProfileEvents.aboutUsEvent), sizedBox(20.0), buildMenuItem(logoutIcon, 'Logout', ProfileEvents.logoutEvent) ], diff --git a/noticeboard/pubspec.yaml b/noticeboard/pubspec.yaml index 0e602e6..01c8181 100644 --- a/noticeboard/pubspec.yaml +++ b/noticeboard/pubspec.yaml @@ -38,7 +38,7 @@ dependencies: flutter_form_builder: ^9.1.1 firebase_core: ^2.24.2 firebase_messaging: ^14.7.9 - webview_flutter: ^3.0.4 + webview_flutter: ^4.7.0 uni_links: ^0.5.1 form_builder_validators: ^9.1.0