From c2bace1363fc851a2020d0ed535342448121461e Mon Sep 17 00:00:00 2001 From: KaviHarjani Date: Sun, 19 Feb 2023 01:21:06 +0530 Subject: [PATCH 1/3] Upgrading webview to the latest version + adding refresh when the app is resued after being paused to address the hanging issue + Added title bar with dark mode support (to have some differentiation) + removed drag-to-refresh because it was causing issues, have a refresh button on the app bar --- .flutter-plugins | 47 ++--- assets/images/screener-logo.svg | 15 ++ lib/pull_to_refresh.dart | 135 -------------- lib/webview.dart | 299 +++++++++++++++++++++----------- pubspec.yaml | 5 +- 5 files changed, 241 insertions(+), 260 deletions(-) create mode 100644 assets/images/screener-logo.svg delete mode 100644 lib/pull_to_refresh.dart diff --git a/.flutter-plugins b/.flutter-plugins index 039d6b1..34a2a3e 100644 --- a/.flutter-plugins +++ b/.flutter-plugins @@ -1,22 +1,27 @@ # This is a generated file; do not edit or check into version control. -connectivity_plus=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\connectivity_plus-2.3.0\\ -connectivity_plus_linux=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\connectivity_plus_linux-1.3.0\\ -connectivity_plus_macos=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\connectivity_plus_macos-1.2.2\\ -connectivity_plus_web=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\connectivity_plus_web-1.2.0\\ -connectivity_plus_windows=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\connectivity_plus_windows-1.2.0\\ -fluttertoast=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\fluttertoast-8.0.9\\ -google_sign_in=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\google_sign_in-5.3.2\\ -google_sign_in_android=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\google_sign_in_android-5.2.8\\ -google_sign_in_ios=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\google_sign_in_ios-5.3.1\\ -google_sign_in_web=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\google_sign_in_web-0.10.1+2\\ -razorpay_flutter=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\razorpay_flutter-1.3.0\\ -url_launcher=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\url_launcher-6.1.2\\ -url_launcher_android=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\url_launcher_android-6.0.16\\ -url_launcher_ios=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\url_launcher_ios-6.0.15\\ -url_launcher_linux=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\url_launcher_linux-3.0.0\\ -url_launcher_macos=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\url_launcher_macos-3.0.0\\ -url_launcher_web=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\url_launcher_web-2.0.9\\ -url_launcher_windows=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\url_launcher_windows-3.0.0\\ -webview_flutter=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\webview_flutter-3.0.4\\ -webview_flutter_android=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\webview_flutter_android-2.8.6\\ -webview_flutter_wkwebview=D:\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\webview_flutter_wkwebview-2.7.3\\ +connectivity_plus=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus-2.3.9\\ +connectivity_plus_linux=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus_linux-1.3.1\\ +connectivity_plus_macos=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus_macos-1.2.6\\ +connectivity_plus_web=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus_web-1.2.5\\ +connectivity_plus_windows=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus_windows-1.2.2\\ +fluttertoast=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\fluttertoast-8.1.3\\ +google_sign_in=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\google_sign_in-5.4.4\\ +google_sign_in_android=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\google_sign_in_android-6.1.6\\ +google_sign_in_ios=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\google_sign_in_ios-5.5.1\\ +google_sign_in_web=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\google_sign_in_web-0.10.2+1\\ +package_info_plus=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\package_info_plus-1.4.3+1\\ +package_info_plus_linux=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\package_info_plus_linux-1.0.5\\ +package_info_plus_macos=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\package_info_plus_macos-1.3.0\\ +package_info_plus_web=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\package_info_plus_web-1.0.6\\ +package_info_plus_windows=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\package_info_plus_windows-2.1.0\\ +razorpay_flutter=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\razorpay_flutter-1.3.4\\ +url_launcher=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher-6.1.9\\ +url_launcher_android=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher_android-6.0.23\\ +url_launcher_ios=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher_ios-6.1.0\\ +url_launcher_linux=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher_linux-3.0.2\\ +url_launcher_macos=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher_macos-3.0.2\\ +url_launcher_web=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher_web-2.0.14\\ +url_launcher_windows=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher_windows-3.0.3\\ +webview_flutter=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\webview_flutter-4.0.2\\ +webview_flutter_android=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\webview_flutter_android-3.3.0\\ +webview_flutter_wkwebview=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\webview_flutter_wkwebview-3.1.0\\ diff --git a/assets/images/screener-logo.svg b/assets/images/screener-logo.svg new file mode 100644 index 0000000..328095b --- /dev/null +++ b/assets/images/screener-logo.svg @@ -0,0 +1,15 @@ + + + + logo-large + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/lib/pull_to_refresh.dart b/lib/pull_to_refresh.dart deleted file mode 100644 index ddebd5c..0000000 --- a/lib/pull_to_refresh.dart +++ /dev/null @@ -1,135 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'dart:async'; -import 'package:flutter/gestures.dart'; -import 'package:webview_flutter/webview_flutter.dart'; - -class DragGesturePullToRefresh extends VerticalDragGestureRecognizer { - static const double MAX_LOAD_TIME = 3000; - - late BuildContext _context; - late WebViewController _controller; - - Completer completer = Completer(); - int msLoading = 0; - bool isLoading = true; - - double height = 200; - bool dragStarted = false; - double dragDistance = 0; - - @override - void rejectGesture(int pointer) { - acceptGesture(pointer); - } - - void _clearDrag() { - dragStarted = false; - dragDistance = 0; - } - - DragGesturePullToRefresh setContext(BuildContext context) { - _context = context; - return this; - } - - DragGesturePullToRefresh setController(WebViewController controller) { - _controller = controller; - return this; - } - - void setHeight(double height) { - this.height = height; - } - - Future refresh() { - if (!completer.isCompleted) { - completer.complete(); - } - completer = Completer(); - started(); - _controller.reload(); - return completer.future; - } - - void started() { - msLoading = DateTime.now().millisecondsSinceEpoch; - isLoading = true; - } - - void finished() { - msLoading = 0; - isLoading = false; - // hide the RefreshIndicator - if (!completer.isCompleted) { - completer.complete(); - } - } - - FixedScrollMetrics _getMetrics(double minScrollExtent, double maxScrollExtent, - double pixels, double viewportDimension, AxisDirection axisDirection) { - return FixedScrollMetrics( - minScrollExtent: minScrollExtent, - maxScrollExtent: maxScrollExtent, - pixels: pixels, - viewportDimension: viewportDimension, - axisDirection: axisDirection); - } - - DragGesturePullToRefresh() { - onStart = (DragStartDetails dragDetails) { - if (!isLoading || - (msLoading > 0 && - (DateTime.now().millisecondsSinceEpoch - msLoading) > - MAX_LOAD_TIME)) { - _controller.getScrollY().then((scrollYPos) { - if (scrollYPos == 0) { - dragStarted = true; - dragDistance = 0; - ScrollStartNotification( - metrics: - _getMetrics(0, height, 0, height, AxisDirection.down), - dragDetails: dragDetails, - context: _context) - .dispatch(_context); - } - }); - } - }; - onUpdate = (DragUpdateDetails dragDetails) { - if (dragStarted) { - double dy = dragDetails.delta.dy; - dragDistance += dy; - ScrollUpdateNotification( - metrics: _getMetrics( - dy > 0 ? 0 : dragDistance, - height, - dy > 0 ? (-1) * dy : dragDistance, - height, - dragDistance < 0 ? AxisDirection.up : AxisDirection.down), - context: _context, - scrollDelta: (-1) * dy) - .dispatch(_context); - if (dragDistance < 0) { - _clearDrag(); - } - } - }; - onEnd = (DragEndDetails dragDetails) { - ScrollEndNotification( - metrics: _getMetrics( - 0, height, dragDistance, height, AxisDirection.down), - context: _context) - .dispatch(_context); - _clearDrag(); - }; - onCancel = () { - ScrollUpdateNotification( - metrics: _getMetrics(0, height, 1, height, AxisDirection.up), - context: _context, - scrollDelta: 0) - .dispatch(_context); - _clearDrag(); - }; - } -} diff --git a/lib/webview.dart b/lib/webview.dart index 8a37f63..6cb98c4 100644 --- a/lib/webview.dart +++ b/lib/webview.dart @@ -1,11 +1,17 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:razorpay_flutter/razorpay_flutter.dart'; import 'dart:convert'; -import './pull_to_refresh.dart'; import 'package:google_sign_in/google_sign_in.dart'; +import 'dart:async'; +// #docregion platform_imports +// Import for Android features. +import 'package:webview_flutter_android/webview_flutter_android.dart'; +// Import for iOS features. +import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart'; +// #enddocregion platform_imports class ScreenerApp extends StatefulWidget { final bool debug; @@ -15,8 +21,8 @@ class ScreenerApp extends StatefulWidget { State createState() => _ScreenerAppState(); } -class _ScreenerAppState extends State { - late WebViewController controller; +class _ScreenerAppState extends State with WidgetsBindingObserver { + late WebViewController _controller; final _razorpay = Razorpay(); var options = {}; late final String _screenerHomeUrl = @@ -25,28 +31,165 @@ class _ScreenerAppState extends State { late String googleLoginUrl = "'$_screenerHomeUrl/auth/flutter/'"; late String postParam = "{}"; late String requestMethod = "'post'"; - late DragGesturePullToRefresh dragGesturePullToRefresh; final GoogleSignIn _googleSignIn = GoogleSignIn(); late bool googleUser; + var _lightMode = true; + @override void initState() { super.initState(); - dragGesturePullToRefresh = DragGesturePullToRefresh(); + //RazorPay settings _razorpay.on(Razorpay.EVENT_PAYMENT_SUCCESS, _handlePaymentSuccess); _razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, _handlePaymentError); _razorpay.on(Razorpay.EVENT_EXTERNAL_WALLET, _handleExternalWallet); + + //Webview Controller + // #docregion platform_features + late final PlatformWebViewControllerCreationParams params; + if (WebViewPlatform.instance is WebKitWebViewPlatform) { + params = WebKitWebViewControllerCreationParams( + allowsInlineMediaPlayback: true, + mediaTypesRequiringUserAction: const {}, + ); + } else { + params = const PlatformWebViewControllerCreationParams(); + } + + final WebViewController controller = + WebViewController.fromPlatformCreationParams(params); + // #enddocregion platform_features + controller + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..setNavigationDelegate( + NavigationDelegate( + onWebResourceError: (WebResourceError error) { + debugPrint(''' + Page resource error: + code: ${error.errorCode} + description: ${error.description} + errorType: ${error.errorType} + isForMainFrame: ${error.isForMainFrame} + '''); + }, + onPageStarted: (String url) async { + if (url.contains('screener')) { + await controller.runJavaScript( + "if(document.querySelectorAll('.top-nav-holder')){" + "const topNavHolders = document.querySelectorAll('.top-nav-holder');" + "for (let i = 0; i < topNavHolders.length; i++) {" + " topNavHolders[i].style.display = 'none';}}"); + await controller.runJavaScript( + 'document.querySelector(\'button[onclick="SetTheme(\\\'light\\\')"]\').onclick = function() {window.MODES.postMessage(\'light\'); SetTheme(\'light\');};'); + await controller.runJavaScript( + 'document.querySelector(\'button[onclick="SetTheme(\\\'dark\\\')"]\').onclick = function() {window.MODES.postMessage(\'dark\'); SetTheme(\'dark\');};'); + } + }, + onPageFinished: (String url) async { + if (url.contains('screener')) { + await controller.runJavaScript( + "if(document.querySelectorAll('.top-nav-holder')){" + "const topNavHolders = document.querySelectorAll('.top-nav-holder');" + "for (let i = 0; i < topNavHolders.length; i++) {" + " topNavHolders[i].style.display = 'none';}}"); + await controller.runJavaScript( + 'document.querySelector(\'button[onclick="SetTheme(\\\'light\\\')"]\').onclick = function() {window.MODES.postMessage(\'light\'); SetTheme(\'light\');};'); + await controller.runJavaScript( + 'document.querySelector(\'button[onclick="SetTheme(\\\'dark\\\')"]\').onclick = function() {window.MODES.postMessage(\'dark\'); SetTheme(\'dark\');};'); + } + if (url.contains("premium")) { + await controller.runJavaScript("if (document.getElementById('razorpay-info')) {" + + "var info = document.getElementById('razorpay-info');" + + "btn1 = document.createElement('button');" + + "function cloneAttributes(element, sourceNode) { let attr; let attributes = Array.prototype.slice.call(sourceNode.attributes); while(attr =attributes.pop()) {element.setAttribute(attr.nodeName, attr.nodeValue);}};" + + "cloneAttributes(btn1, info);" + + "info.parentElement.append(btn1);" + + "info.style.display = 'none';" + + "btn1.innerText='BUY NOW';" + + "btn1.addEventListener('click', function() {" + + "options = {'key': info.getAttribute('data-key'),'amount': info.getAttribute('data-amount'),'currency': 'INR','name': 'Mittal Analytics (P) Ltd','description': info.getAttribute('data-description')," + + "'display_currency': info.getAttribute('data-display_currency'),'display_amount': info.getAttribute('data-display_amount'),'prefill': {'name': info.getAttribute('data-prefill.name')," + + "'email': info.getAttribute('data-prefill.email')}," + + "'handler': function (response) {var inputs = info.form.elements;for (var i = 0; i < inputs.length; i++) {if (inputs[i].name === 'razorpay_payment_id') {inputs[i].value = response.razorpay_payment_id}};info.form.submit()}," + + "'notes': {'plan_name': info.getAttribute('data-notes.plan_name')" + + ",'user_id': info.getAttribute('data-notes.user_id')}};RAZORPAY.postMessage(JSON.stringify(options))})}"); + } + }, + onNavigationRequest: (NavigationRequest request) { + if (request.url.endsWith('login/google/')) { + _handleSignIn(); + return NavigationDecision.prevent; + } else if (request.url.contains('home')) { + _handleSignOut(); + return NavigationDecision.navigate; + } else if (request.url.startsWith(_screenerHomeUrl)) { + return NavigationDecision.navigate; + } else if (request.url.contains("google")) { + return NavigationDecision.navigate; + } else { + _launchURL(request.url); + return NavigationDecision.prevent; + } + }, + ), + ) + //RazorPay channel + ..addJavaScriptChannel( + 'RAZORPAY', + onMessageReceived: (JavaScriptMessage message) async { + options = jsonDecode(message.message); + _razorpay.open(jsonDecode(message.message)); + }, + ) + // Managing Light-Dark Modes + ..addJavaScriptChannel( + 'MODES', + onMessageReceived: (JavaScriptMessage message) async { + if (message.message == "light") { + setState(() { + _lightMode = true; + }); + } + if (message.message == "dark") { + setState(() { + _lightMode = false; + }); + } + }, + ) + ..enableZoom(false) + ..setUserAgent("random") + ..loadRequest(Uri.parse(_screenerHomeUrl)); + // #docregion platform_features + if (controller.platform is AndroidWebViewController) { + AndroidWebViewController.enableDebugging(true); + (controller.platform as AndroidWebViewController) + .setMediaPlaybackRequiresUserGesture(false); + } + // #enddocregion platform_features + _controller = controller; + // Refresh whenever the app is resumed from the background + WidgetsBinding.instance.addObserver(this); } @override void dispose() { super.dispose(); _razorpay.clear(); + WidgetsBinding.instance.removeObserver(this); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.resumed) { + _controller.reload(); + } } void postFunction(postUrl, postParam, requestMethod) { postParam = "$postParam"; requestMethod = "'post'"; - controller.runJavascript("function post(path, params, method='post') {" + + _controller.runJavaScript("function post(path, params, method='post') {" + "const form = document.createElement('form');" + "form.method = method;" + "form.action = path;" + @@ -87,9 +230,11 @@ class _ScreenerAppState extends State { requestMethod); } } catch (error) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text("Error occured $error. Please try again later."), - )); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text("Error occured $error. Please try again later."), + ), + ); } } @@ -114,101 +259,51 @@ class _ScreenerAppState extends State { postFunction(paymentUrl, jsonEncode(body), requestMethod); } - void didChangeMetrics() { - // on portrait / landscape or other change, recalculate height - dragGesturePullToRefresh.setHeight(MediaQuery.of(context).size.height); - } - - JavascriptChannel _razorpayChannel() { - return JavascriptChannel( - name: 'RAZORPAY', - onMessageReceived: (JavascriptMessage message) async { - options = jsonDecode(message.message); - _razorpay.open(jsonDecode(message.message)); - }); - } - @override Widget build(BuildContext context) { - const _proxyUserAgent = "random"; - - return RefreshIndicator( - onRefresh: () => dragGesturePullToRefresh.refresh(), - child: Builder( - builder: (context) => MaterialApp( - debugShowCheckedModeBanner: false, - title: 'Screener', - home: WillPopScope( - onWillPop: () async { - if (await controller.canGoBack()) { - controller.goBack(); - return false; - } else { - return true; - } - }, - child: SafeArea( - child: Scaffold( - body: WebView( - initialUrl: _screenerHomeUrl, - javascriptMode: JavascriptMode.unrestricted, - gestureRecognizers: {Factory(() => dragGesturePullToRefresh)}, - userAgent: _proxyUserAgent, - onWebViewCreated: (controller) { - this.controller = controller; - dragGesturePullToRefresh - .setContext(context) - .setController(controller); - }, - zoomEnabled: false, - navigationDelegate: (NavigationRequest request) { - if (request.url.endsWith('login/google/')) { - _handleSignIn(); - return NavigationDecision.prevent; - } else if (request.url.contains('home')) { - _handleSignOut(); - return NavigationDecision.navigate; - } else if (request.url.startsWith(_screenerHomeUrl)) { - return NavigationDecision.navigate; - } else if (request.url.contains("google")) { - return NavigationDecision.navigate; - } else { - _launchURL(request.url); - return NavigationDecision.prevent; - } - }, - onPageStarted: (String url) { - dragGesturePullToRefresh.started(); - }, - - onPageFinished: (String url) async { - if (url.contains("premium")) { - await controller.runJavascript("if (document.getElementById('razorpay-info')) {" + - "var info = document.getElementById('razorpay-info');" + - "btn1 = document.createElement('button');" + - "function cloneAttributes(element, sourceNode) { let attr; let attributes = Array.prototype.slice.call(sourceNode.attributes); while(attr =attributes.pop()) {element.setAttribute(attr.nodeName, attr.nodeValue);}};" + - "cloneAttributes(btn1, info);" + - "info.parentElement.append(btn1);" + - "info.style.display = 'none';" + - "btn1.innerText='BUY NOW';" + - "btn1.addEventListener('click', function() {" + - "options = {'key': info.getAttribute('data-key'),'amount': info.getAttribute('data-amount'),'currency': 'INR','name': 'Mittal Analytics (P) Ltd','description': info.getAttribute('data-description')," + - "'display_currency': info.getAttribute('data-display_currency'),'display_amount': info.getAttribute('data-display_amount'),'prefill': {'name': info.getAttribute('data-prefill.name')," + - "'email': info.getAttribute('data-prefill.email')}," + - "'handler': function (response) {var inputs = info.form.elements;for (var i = 0; i < inputs.length; i++) {if (inputs[i].name === 'razorpay_payment_id') {inputs[i].value = response.razorpay_payment_id}};info.form.submit()}," + - "'notes': {'plan_name': info.getAttribute('data-notes.plan_name')" + - ",'user_id': info.getAttribute('data-notes.user_id')}};RAZORPAY.postMessage(JSON.stringify(options))})}"); - } - dragGesturePullToRefresh.finished(); - }, - onWebResourceError: (error) { - dragGesturePullToRefresh.finished(); - }, - // ignore: prefer_collection_literals - javascriptChannels: [ - _razorpayChannel(), - ].toSet(), + return Builder( + builder: (context) => MaterialApp( + debugShowCheckedModeBanner: false, + title: 'Screener', + home: WillPopScope( + onWillPop: () async { + if (await _controller.canGoBack()) { + _controller.goBack(); + return false; + } else { + return true; + } + }, + child: SafeArea( + child: Scaffold( + appBar: AppBar( + automaticallyImplyLeading: false, + title: SizedBox( + height: 150, + width: 150, + child: SvgPicture.asset( + 'assets/images/screener-logo.svg', + colorFilter: _lightMode + ? null + : const ColorFilter.mode(Colors.white, BlendMode.srcIn), + ), ), + elevation: 0, + backgroundColor: _lightMode + ? Colors.white + : const Color.fromARGB(255, 24, 34, 48), + actions: [ + IconButton( + onPressed: () => _controller.reload(), + icon: Icon( + Icons.replay, + color: _lightMode ? Colors.black : Colors.white, + ), + ) + ], + ), + body: WebViewWidget( + controller: _controller, ), ), ), diff --git a/pubspec.yaml b/pubspec.yaml index be2dc20..3ddc933 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -34,11 +34,12 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 - webview_flutter: ^3.0.4 + webview_flutter: ^4.0.2 url_launcher: ^6.0.20 connectivity_plus: ^2.2.0 razorpay_flutter: ^1.3.0 google_sign_in: ^5.3.0 + flutter_svg: ^2.0.1 dev_dependencies: flutter_test: @@ -71,7 +72,7 @@ flutter: # To add assets to your application, add an assets section, like this: assets: - assets/images/circle-icon@144px.png - + - assets/images/screener-logo.svg # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware. From af34ccdd4c51950a5712d5325bd54b199f2a9ec4 Mon Sep 17 00:00:00 2001 From: KaviHarjani Date: Wed, 22 Feb 2023 13:39:17 +0530 Subject: [PATCH 2/3] Fixing downloads, works on local now --- .flutter-plugins | 11 +++++++++++ lib/webview.dart | 36 +++++++++++++++++++++++++++++++++++- pubspec.yaml | 3 +++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/.flutter-plugins b/.flutter-plugins index 34a2a3e..ed451c8 100644 --- a/.flutter-plugins +++ b/.flutter-plugins @@ -4,6 +4,8 @@ connectivity_plus_linux=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pu connectivity_plus_macos=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus_macos-1.2.6\\ connectivity_plus_web=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus_web-1.2.5\\ connectivity_plus_windows=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus_windows-1.2.2\\ +file_picker=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\file_picker-5.2.5\\ +flutter_plugin_android_lifecycle=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\flutter_plugin_android_lifecycle-2.0.7\\ fluttertoast=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\fluttertoast-8.1.3\\ google_sign_in=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\google_sign_in-5.4.4\\ google_sign_in_android=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\google_sign_in_android-6.1.6\\ @@ -14,6 +16,15 @@ package_info_plus_linux=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pu package_info_plus_macos=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\package_info_plus_macos-1.3.0\\ package_info_plus_web=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\package_info_plus_web-1.0.6\\ package_info_plus_windows=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\package_info_plus_windows-2.1.0\\ +path_provider=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider-2.0.12\\ +path_provider_android=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_android-2.0.22\\ +path_provider_foundation=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_foundation-2.1.1\\ +path_provider_linux=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_linux-2.1.8\\ +path_provider_windows=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_windows-2.1.3\\ +permission_handler=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\permission_handler-10.2.0\\ +permission_handler_android=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\permission_handler_android-10.2.0\\ +permission_handler_apple=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\permission_handler_apple-9.0.7\\ +permission_handler_windows=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\permission_handler_windows-0.1.2\\ razorpay_flutter=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\razorpay_flutter-1.3.4\\ url_launcher=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher-6.1.9\\ url_launcher_android=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher_android-6.0.23\\ diff --git a/lib/webview.dart b/lib/webview.dart index 6cb98c4..22dd6aa 100644 --- a/lib/webview.dart +++ b/lib/webview.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:webview_flutter/webview_flutter.dart'; @@ -12,6 +14,9 @@ import 'package:webview_flutter_android/webview_flutter_android.dart'; // Import for iOS features. import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart'; // #enddocregion platform_imports +import 'package:http/http.dart' as http; +import 'package:permission_handler/permission_handler.dart'; +import 'package:file_picker/file_picker.dart'; class ScreenerApp extends StatefulWidget { final bool debug; @@ -34,7 +39,7 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { final GoogleSignIn _googleSignIn = GoogleSignIn(); late bool googleUser; var _lightMode = true; - + var _currentcompany = ''; @override void initState() { super.initState(); @@ -82,6 +87,10 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { 'document.querySelector(\'button[onclick="SetTheme(\\\'light\\\')"]\').onclick = function() {window.MODES.postMessage(\'light\'); SetTheme(\'light\');};'); await controller.runJavaScript( 'document.querySelector(\'button[onclick="SetTheme(\\\'dark\\\')"]\').onclick = function() {window.MODES.postMessage(\'dark\'); SetTheme(\'dark\');};'); + await controller.runJavaScript('let title = document.title;' + 'let index = title.indexOf(" Ltd");' + 'let companyName = title.substring(0, index + 4);' + 'CompanyName.postMessage(companyName)'); } }, onPageFinished: (String url) async { @@ -118,6 +127,9 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { if (request.url.endsWith('login/google/')) { _handleSignIn(); return NavigationDecision.prevent; + } else if (request.url.contains('export')) { + downloadFile(request.url, _currentcompany); + return NavigationDecision.prevent; } else if (request.url.contains('home')) { _handleSignOut(); return NavigationDecision.navigate; @@ -156,6 +168,12 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { } }, ) + ..addJavaScriptChannel('CompanyName', + onMessageReceived: (JavaScriptMessage message) async { + setState(() { + _currentcompany = message.message; + }); + }) ..enableZoom(false) ..setUserAgent("random") ..loadRequest(Uri.parse(_screenerHomeUrl)); @@ -305,6 +323,8 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { body: WebViewWidget( controller: _controller, ), + // floatingActionButton: + // const FloatingActionButton(onPressed: downloadFile), ), ), ), @@ -313,6 +333,20 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { } } +Future downloadFile(String url, String name) async { + final response = await http.post(Uri.parse(url)); + final bytes = response.bodyBytes; + var status = await Permission.storage.request(); + if (status != PermissionStatus.granted) { + throw Exception('Permission denied to write to storage'); + } + String? selectedDirectory = await FilePicker.platform.getDirectoryPath(); + if (selectedDirectory != null) { + final file = File('$selectedDirectory/$name.xlsx'); + await file.writeAsBytes(bytes); + } +} + _launchURL(String url) async { await launchUrl( Uri.parse(url), diff --git a/pubspec.yaml b/pubspec.yaml index 3ddc933..a64ff9b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,6 +40,9 @@ dependencies: razorpay_flutter: ^1.3.0 google_sign_in: ^5.3.0 flutter_svg: ^2.0.1 + path_provider: ^2.0.12 + permission_handler: ^10.2.0 + file_picker: ^5.2.5 dev_dependencies: flutter_test: From 5d7e5f28a66644d646312a57320208cd6bb00f44 Mon Sep 17 00:00:00 2001 From: KaviHarjani Date: Mon, 6 Mar 2023 01:32:23 +0530 Subject: [PATCH 3/3] Removing export to excel button --- .flutter-plugins | 11 ---- lib/webview.dart | 142 +++++++++++++++++++---------------------------- pubspec.yaml | 3 - 3 files changed, 58 insertions(+), 98 deletions(-) diff --git a/.flutter-plugins b/.flutter-plugins index ed451c8..34a2a3e 100644 --- a/.flutter-plugins +++ b/.flutter-plugins @@ -4,8 +4,6 @@ connectivity_plus_linux=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pu connectivity_plus_macos=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus_macos-1.2.6\\ connectivity_plus_web=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus_web-1.2.5\\ connectivity_plus_windows=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus_windows-1.2.2\\ -file_picker=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\file_picker-5.2.5\\ -flutter_plugin_android_lifecycle=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\flutter_plugin_android_lifecycle-2.0.7\\ fluttertoast=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\fluttertoast-8.1.3\\ google_sign_in=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\google_sign_in-5.4.4\\ google_sign_in_android=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\google_sign_in_android-6.1.6\\ @@ -16,15 +14,6 @@ package_info_plus_linux=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pu package_info_plus_macos=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\package_info_plus_macos-1.3.0\\ package_info_plus_web=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\package_info_plus_web-1.0.6\\ package_info_plus_windows=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\package_info_plus_windows-2.1.0\\ -path_provider=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider-2.0.12\\ -path_provider_android=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_android-2.0.22\\ -path_provider_foundation=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_foundation-2.1.1\\ -path_provider_linux=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_linux-2.1.8\\ -path_provider_windows=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_windows-2.1.3\\ -permission_handler=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\permission_handler-10.2.0\\ -permission_handler_android=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\permission_handler_android-10.2.0\\ -permission_handler_apple=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\permission_handler_apple-9.0.7\\ -permission_handler_windows=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\permission_handler_windows-0.1.2\\ razorpay_flutter=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\razorpay_flutter-1.3.4\\ url_launcher=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher-6.1.9\\ url_launcher_android=C:\\Users\\kavi_\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher_android-6.0.23\\ diff --git a/lib/webview.dart b/lib/webview.dart index 22dd6aa..eecbed7 100644 --- a/lib/webview.dart +++ b/lib/webview.dart @@ -1,5 +1,3 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:webview_flutter/webview_flutter.dart'; @@ -8,15 +6,7 @@ import 'package:razorpay_flutter/razorpay_flutter.dart'; import 'dart:convert'; import 'package:google_sign_in/google_sign_in.dart'; import 'dart:async'; -// #docregion platform_imports -// Import for Android features. import 'package:webview_flutter_android/webview_flutter_android.dart'; -// Import for iOS features. -import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart'; -// #enddocregion platform_imports -import 'package:http/http.dart' as http; -import 'package:permission_handler/permission_handler.dart'; -import 'package:file_picker/file_picker.dart'; class ScreenerApp extends StatefulWidget { final bool debug; @@ -38,8 +28,9 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { late String requestMethod = "'post'"; final GoogleSignIn _googleSignIn = GoogleSignIn(); late bool googleUser; - var _lightMode = true; - var _currentcompany = ''; + bool _lightMode = true; + bool firstLoad = true; + @override void initState() { super.initState(); @@ -48,20 +39,9 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { _razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, _handlePaymentError); _razorpay.on(Razorpay.EVENT_EXTERNAL_WALLET, _handleExternalWallet); - //Webview Controller - // #docregion platform_features - late final PlatformWebViewControllerCreationParams params; - if (WebViewPlatform.instance is WebKitWebViewPlatform) { - params = WebKitWebViewControllerCreationParams( - allowsInlineMediaPlayback: true, - mediaTypesRequiringUserAction: const {}, - ); - } else { - params = const PlatformWebViewControllerCreationParams(); - } - final WebViewController controller = - WebViewController.fromPlatformCreationParams(params); + WebViewController.fromPlatformCreationParams( + const PlatformWebViewControllerCreationParams()); // #enddocregion platform_features controller ..setJavaScriptMode(JavaScriptMode.unrestricted) @@ -78,19 +58,37 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { }, onPageStarted: (String url) async { if (url.contains('screener')) { + if (firstLoad == true) { + final cookieString = await controller + .runJavaScriptReturningResult('document.cookie'); + final cookies = cookieString.toString().split(';'); + for (final cookie in cookies) { + final parts = cookie.split('='); + final name = parts[0].trim(); + final value = parts.length > 1 ? parts[1].trim() : ''; + + if (name == 'theme') { + if (value.trim().contains("dark")) { + setState(() { + _lightMode = false; + }); + } + break; + } + } + setState(() { + firstLoad = false; + }); + } await controller.runJavaScript( "if(document.querySelectorAll('.top-nav-holder')){" "const topNavHolders = document.querySelectorAll('.top-nav-holder');" "for (let i = 0; i < topNavHolders.length; i++) {" " topNavHolders[i].style.display = 'none';}}"); - await controller.runJavaScript( - 'document.querySelector(\'button[onclick="SetTheme(\\\'light\\\')"]\').onclick = function() {window.MODES.postMessage(\'light\'); SetTheme(\'light\');};'); - await controller.runJavaScript( - 'document.querySelector(\'button[onclick="SetTheme(\\\'dark\\\')"]\').onclick = function() {window.MODES.postMessage(\'dark\'); SetTheme(\'dark\');};'); - await controller.runJavaScript('let title = document.title;' - 'let index = title.indexOf(" Ltd");' - 'let companyName = title.substring(0, index + 4);' - 'CompanyName.postMessage(companyName)'); + if (url.contains('company')) { + await controller.runJavaScript( + "const button = document.querySelector('[aria-label=\"Export to Excel\"]');button.style.display = 'none';"); + } } }, onPageFinished: (String url) async { @@ -106,20 +104,21 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { 'document.querySelector(\'button[onclick="SetTheme(\\\'dark\\\')"]\').onclick = function() {window.MODES.postMessage(\'dark\'); SetTheme(\'dark\');};'); } if (url.contains("premium")) { - await controller.runJavaScript("if (document.getElementById('razorpay-info')) {" + - "var info = document.getElementById('razorpay-info');" + - "btn1 = document.createElement('button');" + - "function cloneAttributes(element, sourceNode) { let attr; let attributes = Array.prototype.slice.call(sourceNode.attributes); while(attr =attributes.pop()) {element.setAttribute(attr.nodeName, attr.nodeValue);}};" + - "cloneAttributes(btn1, info);" + - "info.parentElement.append(btn1);" + - "info.style.display = 'none';" + - "btn1.innerText='BUY NOW';" + - "btn1.addEventListener('click', function() {" + - "options = {'key': info.getAttribute('data-key'),'amount': info.getAttribute('data-amount'),'currency': 'INR','name': 'Mittal Analytics (P) Ltd','description': info.getAttribute('data-description')," + - "'display_currency': info.getAttribute('data-display_currency'),'display_amount': info.getAttribute('data-display_amount'),'prefill': {'name': info.getAttribute('data-prefill.name')," + - "'email': info.getAttribute('data-prefill.email')}," + - "'handler': function (response) {var inputs = info.form.elements;for (var i = 0; i < inputs.length; i++) {if (inputs[i].name === 'razorpay_payment_id') {inputs[i].value = response.razorpay_payment_id}};info.form.submit()}," + - "'notes': {'plan_name': info.getAttribute('data-notes.plan_name')" + + await controller.runJavaScript( + "if (document.getElementById('razorpay-info')) {" + "var info = document.getElementById('razorpay-info');" + "btn1 = document.createElement('button');" + "function cloneAttributes(element, sourceNode) { let attr; let attributes = Array.prototype.slice.call(sourceNode.attributes); while(attr =attributes.pop()) {element.setAttribute(attr.nodeName, attr.nodeValue);}};" + "cloneAttributes(btn1, info);" + "info.parentElement.append(btn1);" + "info.style.display = 'none';" + "btn1.innerText='BUY NOW';" + "btn1.addEventListener('click', function() {" + "options = {'key': info.getAttribute('data-key'),'amount': info.getAttribute('data-amount'),'currency': 'INR','name': 'Mittal Analytics (P) Ltd','description': info.getAttribute('data-description')," + "'display_currency': info.getAttribute('data-display_currency'),'display_amount': info.getAttribute('data-display_amount'),'prefill': {'name': info.getAttribute('data-prefill.name')," + "'email': info.getAttribute('data-prefill.email')}," + "'handler': function (response) {var inputs = info.form.elements;for (var i = 0; i < inputs.length; i++) {if (inputs[i].name === 'razorpay_payment_id') {inputs[i].value = response.razorpay_payment_id}};info.form.submit()}," + "'notes': {'plan_name': info.getAttribute('data-notes.plan_name')" ",'user_id': info.getAttribute('data-notes.user_id')}};RAZORPAY.postMessage(JSON.stringify(options))})}"); } }, @@ -127,9 +126,6 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { if (request.url.endsWith('login/google/')) { _handleSignIn(); return NavigationDecision.prevent; - } else if (request.url.contains('export')) { - downloadFile(request.url, _currentcompany); - return NavigationDecision.prevent; } else if (request.url.contains('home')) { _handleSignOut(); return NavigationDecision.navigate; @@ -168,18 +164,12 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { } }, ) - ..addJavaScriptChannel('CompanyName', - onMessageReceived: (JavaScriptMessage message) async { - setState(() { - _currentcompany = message.message; - }); - }) ..enableZoom(false) ..setUserAgent("random") ..loadRequest(Uri.parse(_screenerHomeUrl)); // #docregion platform_features if (controller.platform is AndroidWebViewController) { - AndroidWebViewController.enableDebugging(true); + AndroidWebViewController.enableDebugging(false); (controller.platform as AndroidWebViewController) .setMediaPlaybackRequiresUserGesture(false); } @@ -207,17 +197,17 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { void postFunction(postUrl, postParam, requestMethod) { postParam = "$postParam"; requestMethod = "'post'"; - _controller.runJavaScript("function post(path, params, method='post') {" + - "const form = document.createElement('form');" + - "form.method = method;" + - "form.action = path;" + - "for (const key in params) {" + - "if (params.hasOwnProperty(key)) {" + - "const hiddenField = document.createElement('input');" + - "hiddenField.type = 'hidden';" + - "hiddenField.name = key;" + - "hiddenField.value = params[key];" + - "form.appendChild(hiddenField);}}document.body.appendChild(form);form.submit();}" + + _controller.runJavaScript("function post(path, params, method='post') {" + "const form = document.createElement('form');" + "form.method = method;" + "form.action = path;" + "for (const key in params) {" + "if (params.hasOwnProperty(key)) {" + "const hiddenField = document.createElement('input');" + "hiddenField.type = 'hidden';" + "hiddenField.name = key;" + "hiddenField.value = params[key];" + "form.appendChild(hiddenField);}}document.body.appendChild(form);form.submit();}" "post($postUrl, $postParam, method=$requestMethod)"); } @@ -323,8 +313,6 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { body: WebViewWidget( controller: _controller, ), - // floatingActionButton: - // const FloatingActionButton(onPressed: downloadFile), ), ), ), @@ -333,20 +321,6 @@ class _ScreenerAppState extends State with WidgetsBindingObserver { } } -Future downloadFile(String url, String name) async { - final response = await http.post(Uri.parse(url)); - final bytes = response.bodyBytes; - var status = await Permission.storage.request(); - if (status != PermissionStatus.granted) { - throw Exception('Permission denied to write to storage'); - } - String? selectedDirectory = await FilePicker.platform.getDirectoryPath(); - if (selectedDirectory != null) { - final file = File('$selectedDirectory/$name.xlsx'); - await file.writeAsBytes(bytes); - } -} - _launchURL(String url) async { await launchUrl( Uri.parse(url), diff --git a/pubspec.yaml b/pubspec.yaml index a64ff9b..3ddc933 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,9 +40,6 @@ dependencies: razorpay_flutter: ^1.3.0 google_sign_in: ^5.3.0 flutter_svg: ^2.0.1 - path_provider: ^2.0.12 - permission_handler: ^10.2.0 - file_picker: ^5.2.5 dev_dependencies: flutter_test: