Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sai Srinivas
GEN_ERP_2025
Commits
f7b0d1aa
Commit
f7b0d1aa
authored
May 17, 2025
by
Sai Srinivas
Browse files
ios changes
parent
64c42cd9
Changes
6
Hide whitespace changes
Inline
Side-by-side
ios/Podfile.lock
View file @
f7b0d1aa
...
@@ -56,6 +56,8 @@ PODS:
...
@@ -56,6 +56,8 @@ PODS:
- Flutter
- Flutter
- flutter_local_notifications (0.0.1):
- flutter_local_notifications (0.0.1):
- Flutter
- Flutter
- flutter_pdfview (1.0.2):
- Flutter
- flutter_ringtone_player (0.0.1):
- flutter_ringtone_player (0.0.1):
- Flutter
- Flutter
- fluttertoast (0.0.2):
- fluttertoast (0.0.2):
...
@@ -136,6 +138,8 @@ PODS:
...
@@ -136,6 +138,8 @@ PODS:
- FlutterMacOS
- FlutterMacOS
- permission_handler_apple (9.3.0):
- permission_handler_apple (9.3.0):
- Flutter
- Flutter
- printing (1.0.0):
- Flutter
- PromisesObjC (2.4.0)
- PromisesObjC (2.4.0)
- qr_code_scanner (0.2.0):
- qr_code_scanner (0.2.0):
- Flutter
- Flutter
...
@@ -154,6 +158,8 @@ PODS:
...
@@ -154,6 +158,8 @@ PODS:
- sqflite_darwin (0.0.4):
- sqflite_darwin (0.0.4):
- Flutter
- Flutter
- FlutterMacOS
- FlutterMacOS
- syncfusion_flutter_pdfviewer (0.0.1):
- Flutter
- url_launcher_ios (0.0.1):
- url_launcher_ios (0.0.1):
- Flutter
- Flutter
- webview_flutter_wkwebview (0.0.1):
- webview_flutter_wkwebview (0.0.1):
...
@@ -172,6 +178,7 @@ DEPENDENCIES:
...
@@ -172,6 +178,7 @@ DEPENDENCIES:
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_pdfview (from `.symlinks/plugins/flutter_pdfview/ios`)
- flutter_ringtone_player (from `.symlinks/plugins/flutter_ringtone_player/ios`)
- flutter_ringtone_player (from `.symlinks/plugins/flutter_ringtone_player/ios`)
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- geocoding_ios (from `.symlinks/plugins/geocoding_ios/ios`)
- geocoding_ios (from `.symlinks/plugins/geocoding_ios/ios`)
...
@@ -182,10 +189,12 @@ DEPENDENCIES:
...
@@ -182,10 +189,12 @@ DEPENDENCIES:
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- printing (from `.symlinks/plugins/printing/ios`)
- qr_code_scanner (from `.symlinks/plugins/qr_code_scanner/ios`)
- qr_code_scanner (from `.symlinks/plugins/qr_code_scanner/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- syncfusion_flutter_pdfviewer (from `.symlinks/plugins/syncfusion_flutter_pdfviewer/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`)
...
@@ -232,6 +241,8 @@ EXTERNAL SOURCES:
...
@@ -232,6 +241,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
flutter_local_notifications:
flutter_local_notifications:
:path: ".symlinks/plugins/flutter_local_notifications/ios"
:path: ".symlinks/plugins/flutter_local_notifications/ios"
flutter_pdfview:
:path: ".symlinks/plugins/flutter_pdfview/ios"
flutter_ringtone_player:
flutter_ringtone_player:
:path: ".symlinks/plugins/flutter_ringtone_player/ios"
:path: ".symlinks/plugins/flutter_ringtone_player/ios"
fluttertoast:
fluttertoast:
...
@@ -252,6 +263,8 @@ EXTERNAL SOURCES:
...
@@ -252,6 +263,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
:path: ".symlinks/plugins/path_provider_foundation/darwin"
permission_handler_apple:
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
:path: ".symlinks/plugins/permission_handler_apple/ios"
printing:
:path: ".symlinks/plugins/printing/ios"
qr_code_scanner:
qr_code_scanner:
:path: ".symlinks/plugins/qr_code_scanner/ios"
:path: ".symlinks/plugins/qr_code_scanner/ios"
share_plus:
share_plus:
...
@@ -260,6 +273,8 @@ EXTERNAL SOURCES:
...
@@ -260,6 +273,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sqflite_darwin:
sqflite_darwin:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
:path: ".symlinks/plugins/sqflite_darwin/darwin"
syncfusion_flutter_pdfviewer:
:path: ".symlinks/plugins/syncfusion_flutter_pdfviewer/ios"
url_launcher_ios:
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
:path: ".symlinks/plugins/url_launcher_ios/ios"
webview_flutter_wkwebview:
webview_flutter_wkwebview:
...
@@ -282,6 +297,7 @@ SPEC CHECKSUMS:
...
@@ -282,6 +297,7 @@ SPEC CHECKSUMS:
flutter_inappwebview_ios: 8d8d2c6290a3c4787cad303603662fac9a788f75
flutter_inappwebview_ios: 8d8d2c6290a3c4787cad303603662fac9a788f75
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
flutter_local_notifications: ff50f8405aaa0ccdc7dcfb9022ca192e8ad9688f
flutter_local_notifications: ff50f8405aaa0ccdc7dcfb9022ca192e8ad9688f
flutter_pdfview: 2e4d13ffb774858562ffbdfdb61b40744b191adc
flutter_ringtone_player: 15eba85187230b87b2512f0e1b92225618bc03e7
flutter_ringtone_player: 15eba85187230b87b2512f0e1b92225618bc03e7
fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f
fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f
geocoding_ios: d7460f56e80e118d57678efe5c2cdc888739ff18
geocoding_ios: d7460f56e80e118d57678efe5c2cdc888739ff18
...
@@ -301,6 +317,7 @@ SPEC CHECKSUMS:
...
@@ -301,6 +317,7 @@ SPEC CHECKSUMS:
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
printing: 233e1b73bd1f4a05615548e9b5a324c98588640b
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
...
@@ -308,6 +325,7 @@ SPEC CHECKSUMS:
...
@@ -308,6 +325,7 @@ SPEC CHECKSUMS:
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
syncfusion_flutter_pdfviewer: cfcf23c03816192575902e615fa50adc9f95b724
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
webview_flutter_wkwebview: ab1e58b71690b7e61b58eae7a963b68ee286a146
webview_flutter_wkwebview: ab1e58b71690b7e61b58eae7a963b68ee286a146
...
...
lib/screens/HomeScreen.dart
View file @
f7b0d1aa
import
'dart:async'
;
import
'dart:async'
;
import
'dart:io'
;
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
...
@@ -10,6 +11,7 @@ import 'package:generp/Notifiers/LogoutNotifier.dart';
...
@@ -10,6 +11,7 @@ import 'package:generp/Notifiers/LogoutNotifier.dart';
import
'package:generp/Notifiers/ProfileNotifier.dart'
;
import
'package:generp/Notifiers/ProfileNotifier.dart'
;
import
'package:generp/screens/LoginScreen.dart'
;
import
'package:generp/screens/LoginScreen.dart'
;
import
'package:generp/screens/ScannerLogin.dart'
;
import
'package:generp/screens/ScannerLogin.dart'
;
import
'package:generp/screens/WebERPIOS.dart'
;
import
'package:generp/screens/WebERPScreen.dart'
;
import
'package:generp/screens/WebERPScreen.dart'
;
import
'package:generp/screens/WebWhizzdomScreen.dart'
;
import
'package:generp/screens/WebWhizzdomScreen.dart'
;
import
'package:generp/screens/finance/financeDashboard.dart'
;
import
'package:generp/screens/finance/financeDashboard.dart'
;
...
@@ -127,8 +129,8 @@ class _MyHomePageState extends State<MyHomePage> {
...
@@ -127,8 +129,8 @@ class _MyHomePageState extends State<MyHomePage> {
"Nearby"
,
"Nearby"
,
"Inventory"
,
"Inventory"
,
"Whizzdom"
,
"Whizzdom"
,
"CRM"
,
//
"CRM",
"Finance"
,
//
"Finance",
];
];
final
icons
=
[
final
icons
=
[
"assets/svg/home_icons_1.svg"
,
"assets/svg/home_icons_1.svg"
,
...
@@ -138,8 +140,8 @@ class _MyHomePageState extends State<MyHomePage> {
...
@@ -138,8 +140,8 @@ class _MyHomePageState extends State<MyHomePage> {
"assets/svg/home_icons_5.svg"
,
"assets/svg/home_icons_5.svg"
,
"assets/svg/home_icons_6.svg"
,
"assets/svg/home_icons_6.svg"
,
"assets/svg/home_icons_81.svg"
,
"assets/svg/home_icons_81.svg"
,
"assets/svg/home_icons_8.svg"
,
//
"assets/svg/home_icons_8.svg",
"assets/svg/home_icons_8.svg"
,
//
"assets/svg/home_icons_8.svg",
];
];
final
requiredRoles
=
[
final
requiredRoles
=
[
"430"
,
"430"
,
...
@@ -149,8 +151,8 @@ class _MyHomePageState extends State<MyHomePage> {
...
@@ -149,8 +151,8 @@ class _MyHomePageState extends State<MyHomePage> {
"433"
,
"433"
,
"432"
,
"432"
,
"431"
,
"431"
,
"431"
,
//
"431",
"431"
,
//
"431",
];
];
final
filteredItems
=
<
Map
<
String
,
String
>>[];
final
filteredItems
=
<
Map
<
String
,
String
>>[];
...
@@ -372,15 +374,28 @@ class _MyHomePageState extends State<MyHomePage> {
...
@@ -372,15 +374,28 @@ class _MyHomePageState extends State<MyHomePage> {
bool
isGpsEnabled
=
bool
isGpsEnabled
=
await
Geolocator
.
isLocationServiceEnabled
();
await
Geolocator
.
isLocationServiceEnabled
();
if
(
isGpsEnabled
)
{
if
(
isGpsEnabled
)
{
res
=
await
Navigator
.
push
(
if
(
Platform
.
isAndroid
)
{
context
,
res
=
await
Navigator
.
push
(
MaterialPageRoute
(
context
,
builder:
MaterialPageRoute
(
(
context
)
=>
WebErpScreen
(
builder:
erp_url:
homescreen
.
webPageUrl
,
(
context
)
=>
WebErpScreen
(
),
erp_url:
),
homescreen
.
webPageUrl
,
);
),
),
);
}
else
{
res
=
await
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
WebERPIOS
(
url:
homescreen
.
webPageUrl
,
),
),
);
}
}
else
{
}
else
{
requestGpsPermission
();
requestGpsPermission
();
}
}
...
@@ -445,13 +460,13 @@ class _MyHomePageState extends State<MyHomePage> {
...
@@ -445,13 +460,13 @@ class _MyHomePageState extends State<MyHomePage> {
//res = await Navigator.push(context, MaterialPageRoute(builder: (context)=>CRMScreen()));
//res = await Navigator.push(context, MaterialPageRoute(builder: (context)=>CRMScreen()));
break
;
break
;
case
"Finance"
:
case
"Finance"
:
res
=
await
Navigator
.
push
(
//
res = await Navigator.push(
context
,
//
context,
MaterialPageRoute
(
//
MaterialPageRoute(
builder:
//
builder:
(
context
)
=>
Financedashboard
(),
//
(context) => Financedashboard(),
),
//
),
);
//
);
break
;
break
;
default
:
default
:
print
(
"111"
);
print
(
"111"
);
...
...
lib/screens/WebERPIOS.dart
0 → 100644
View file @
f7b0d1aa
import
'dart:async'
;
import
'dart:io'
;
import
'package:dio/dio.dart'
;
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_downloader/flutter_downloader.dart'
;
import
'package:flutter_inappwebview/flutter_inappwebview.dart'
;
import
'package:flutter_download_manager/flutter_download_manager.dart'
;
import
'package:flutter_svg/svg.dart'
;
import
'package:generp/Utils/app_colors.dart'
;
import
'package:generp/Utils/commonWidgets.dart'
;
import
'package:generp/screens/WebERPScreen.dart'
;
import
'package:permission_handler/permission_handler.dart'
;
import
'package:url_launcher/url_launcher.dart'
;
const
MAX_PROGRESS
=
100
;
Future
main
(
)
async
{
await
FlutterDownloader
.
initialize
(
debug:
true
,
// optional: set false to disable printing logs to console
);
await
Permission
.
storage
.
request
();
}
class
WebERPIOS
extends
StatefulWidget
{
final
String
url
;
const
WebERPIOS
({
Key
?
key
,
required
this
.
url
})
:
super
(
key:
key
);
@override
State
<
WebERPIOS
>
createState
()
=>
_WebERPIOSState
();
}
class
_WebERPIOSState
extends
State
<
WebERPIOS
>
{
final
Completer
<
InAppWebViewController
>
_controller
=
Completer
<
InAppWebViewController
>();
var
empId
=
""
;
var
sessionId
=
""
;
bool
isLoading
=
true
;
InAppWebViewController
?
webViewController
;
PullToRefreshController
?
pullToRefreshController
;
PullToRefreshSettings
pullToRefreshSettings
=
PullToRefreshSettings
(
color:
AppColors
.
app_blue
,
);
bool
pullToRefreshEnabled
=
true
;
final
GlobalKey
webViewKey
=
GlobalKey
();
var
dl
=
DownloadManager
();
@override
void
initState
()
{
// loadData();
pullToRefreshController
=
kIsWeb
?
null
:
PullToRefreshController
(
settings:
pullToRefreshSettings
,
onRefresh:
()
async
{
if
(
defaultTargetPlatform
==
Platform
.
isAndroid
)
{
webViewController
?.
reload
();
}
else
if
(
defaultTargetPlatform
==
Platform
.
isIOS
)
{
webViewController
?.
loadUrl
(
urlRequest:
URLRequest
(
url:
await
webViewController
?.
getUrl
(),
),
);
}
},
);
print
(
"WebURL:
${widget.url}
"
);
super
.
initState
();
}
@override
void
dispose
()
{
super
.
dispose
();
}
@override
Widget
build
(
BuildContext
context
)
{
return
WillPopScope
(
onWillPop:
()
async
{
if
(
await
webViewController
!.
canGoBack
())
{
webViewController
!.
goBack
();
return
false
;
// Prevent default back button behavior
}
return
true
;
// Allow default back button behavior
},
child:
Scaffold
(
appBar:
appbar
(
context
,
"Web ERP"
),
body:
Container
(
child:
Column
(
children:
<
Widget
>[
Expanded
(
child:
Stack
(
children:
[
InAppWebView
(
initialUrlRequest:
URLRequest
(
url:
WebUri
(
widget
.
url
.
toString
()),
),
androidOnGeolocationPermissionsShowPrompt:
(
InAppWebViewController
controller
,
String
origin
,
)
async
{
return
GeolocationPermissionShowPromptResponse
(
origin:
origin
,
allow:
true
,
retain:
true
,
);
},
initialOptions:
InAppWebViewGroupOptions
(
android:
AndroidInAppWebViewOptions
(
useWideViewPort:
true
,
loadWithOverviewMode:
true
,
allowContentAccess:
true
,
geolocationEnabled:
true
,
allowFileAccess:
true
,
databaseEnabled:
true
,
// Enables the WebView database
domStorageEnabled:
true
,
// Enables DOM storage
builtInZoomControls:
true
,
// Enables the built-in zoom controls
displayZoomControls:
false
,
// Disables displaying zoom controls
safeBrowsingEnabled:
true
,
// Enables Safe Browsing
),
ios:
IOSInAppWebViewOptions
(
allowsInlineMediaPlayback:
true
,
allowsLinkPreview:
true
,
allowsBackForwardNavigationGestures:
true
,
),
),
androidOnPermissionRequest:
(
InAppWebViewController
controller
,
String
origin
,
List
<
String
>
resources
,
)
async
{
return
PermissionRequestResponse
(
resources:
resources
,
action:
PermissionRequestResponseAction
.
GRANT
,
);
},
initialSettings:
InAppWebViewSettings
(
javaScriptEnabled:
true
,
allowFileAccess:
true
,
allowContentAccess:
true
,
clearCache:
true
,
blockNetworkLoads:
false
,
networkAvailable:
true
,
useOnLoadResource:
true
,
thirdPartyCookiesEnabled:
true
,
supportZoom:
false
,
geolocationEnabled:
true
,
safeBrowsingEnabled:
false
,
saveFormData:
true
,
allowFileAccessFromFileURLs:
true
,
useWideViewPort:
true
,
databaseEnabled:
true
,
domStorageEnabled:
true
,
allowsBackForwardNavigationGestures:
true
,
allowUniversalAccessFromFileURLs:
true
,
allowsLinkPreview:
true
,
),
onPermissionRequest:
(
controller
,
request
)
async
{
return
PermissionResponse
(
resources:
request
.
resources
,
action:
PermissionResponseAction
.
GRANT
,
);
},
keepAlive:
InAppWebViewKeepAlive
(),
// initialData:
// InAppWebViewInitialData(baseUrl: WebUri(widget.url),data: ),
onWebViewCreated:
(
controller
)
{
webViewController
=
controller
;
_controller
.
complete
(
controller
);
},
pullToRefreshController:
pullToRefreshController
,
shouldOverrideUrlLoading:
(
controller
,
navigationAction
,
)
async
{
var
uri
=
navigationAction
.
request
.
url
!;
print
(
"urib scgefes"
);
print
(
uri
);
print
(
uri
.
scheme
);
if
(
uri
.
scheme
==
"tel"
)
{
// Launch the phone dialer app with the specified phone number
if
(
await
canLaunch
(
uri
.
toString
()))
{
await
launch
(
uri
.
toString
());
return
NavigationActionPolicy
.
CANCEL
;
}
}
else
if
(
uri
.
scheme
==
"mailto"
)
{
if
(
await
canLaunch
(
uri
.
toString
()))
{
await
launch
(
uri
.
toString
());
return
NavigationActionPolicy
.
CANCEL
;
}
}
else
if
(
uri
.
scheme
==
"whatsapp"
)
{
// Launch WhatsApp with the specified chat or phone number
if
(
await
canLaunch
(
uri
.
toString
()))
{
await
launch
(
uri
.
toString
());
return
NavigationActionPolicy
.
CANCEL
;
}
}
// // Check if the URL is trying to access the camera for image upload
// if (uri.scheme == 'camera' && uri.path.contains('/camera/')) {
// // Handle camera image upload here
// // You might want to display a custom UI for image selection or directly trigger the camera
// // You can use platform-specific plugins like image_picker for this purpose
// // Once the image is selected, you can pass it to the web view using JavaScript injection
// if (await canLaunch(uri.toString())) {
// await launch(uri.toString());
// return NavigationActionPolicy.CANCEL;
// }
// }
return
NavigationActionPolicy
.
ALLOW
;
},
onLoadStart:
(
controller
,
url
)
{
return
setState
(()
{
isLoading
=
true
;
});
},
onLoadStop:
(
controller
,
url
)
{
pullToRefreshController
?.
endRefreshing
();
return
setState
(()
{
isLoading
=
false
;
});
},
onReceivedError:
(
controller
,
request
,
error
)
{
pullToRefreshController
?.
endRefreshing
();
},
onProgressChanged:
(
controller
,
progress
)
{
if
(
progress
==
100
)
{
pullToRefreshController
?.
endRefreshing
();
}
},
),
if
(
isLoading
)
...[
Container
(
color:
Colors
.
white
.
withOpacity
(
0.7
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
center
,
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
SpinKitRing
(
color:
AppColors
.
app_blue
,
lineWidth:
4
,
// duration: Duration(seconds: 2),
size:
50
,
),
const
SizedBox
(
height:
15
),
SizedBox
(
width:
200
,
child:
Text
(
"Please wait......."
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
decorationThickness:
0
,
fontSize:
15
,
fontWeight:
FontWeight
.
normal
,
color:
AppColors
.
app_blue
,
),
),
),
// SvgPicture.asset("/assets/images/NutsLoader.gif")
],
),
),
],
],
),
),
],
),
),
),
);
}
}
lib/screens/WebERPScreen.dart
View file @
f7b0d1aa
...
@@ -19,17 +19,19 @@ import 'dart:math';
...
@@ -19,17 +19,19 @@ import 'dart:math';
import
'package:flutter/widgets.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:url_launcher/url_launcher.dart'
;
import
'package:url_launcher/url_launcher.dart'
;
const
MAX_PROGRESS
=
100
;
const
MAX_PROGRESS
=
100
;
Future
main
(
)
async
{
Future
main
(
)
async
{
await
FlutterDownloader
.
initialize
(
await
FlutterDownloader
.
initialize
(
debug:
true
// optional: set false to disable printing logs to console
debug:
true
,
// optional: set false to disable printing logs to console
);
);
await
Permission
.
storage
.
request
();
await
Permission
.
storage
.
request
();
}
}
class
WebErpScreen
extends
StatefulWidget
{
class
WebErpScreen
extends
StatefulWidget
{
final
String
erp_url
;
final
String
erp_url
;
const
WebErpScreen
({
super
.
key
,
required
this
.
erp_url
});
const
WebErpScreen
({
super
.
key
,
required
this
.
erp_url
});
@override
@override
State
<
WebErpScreen
>
createState
()
=>
_WebErpScreenState
();
State
<
WebErpScreen
>
createState
()
=>
_WebErpScreenState
();
...
@@ -37,7 +39,7 @@ class WebErpScreen extends StatefulWidget {
...
@@ -37,7 +39,7 @@ class WebErpScreen extends StatefulWidget {
class
_WebErpScreenState
extends
State
<
WebErpScreen
>
{
class
_WebErpScreenState
extends
State
<
WebErpScreen
>
{
final
Completer
<
InAppWebViewController
>
_controller
=
final
Completer
<
InAppWebViewController
>
_controller
=
Completer
<
InAppWebViewController
>();
Completer
<
InAppWebViewController
>();
var
empId
=
""
;
var
empId
=
""
;
var
sessionId
=
""
;
var
sessionId
=
""
;
bool
isLoading
=
true
;
bool
isLoading
=
true
;
...
@@ -47,7 +49,8 @@ class _WebErpScreenState extends State<WebErpScreen> {
...
@@ -47,7 +49,8 @@ class _WebErpScreenState extends State<WebErpScreen> {
color:
AppColors
.
app_blue
,
color:
AppColors
.
app_blue
,
);
);
bool
pullToRefreshEnabled
=
true
;
bool
pullToRefreshEnabled
=
true
;
final
FlutterLocalNotificationsPlugin
_notificationsPlugin
=
FlutterLocalNotificationsPlugin
();
final
FlutterLocalNotificationsPlugin
_notificationsPlugin
=
FlutterLocalNotificationsPlugin
();
static
const
platform
=
MethodChannel
(
'in.webgrid.generp/download'
);
static
const
platform
=
MethodChannel
(
'in.webgrid.generp/download'
);
final
GlobalKey
webViewKey
=
GlobalKey
();
final
GlobalKey
webViewKey
=
GlobalKey
();
...
@@ -56,30 +59,32 @@ class _WebErpScreenState extends State<WebErpScreen> {
...
@@ -56,30 +59,32 @@ class _WebErpScreenState extends State<WebErpScreen> {
void
initState
()
{
void
initState
()
{
// loadData();
// loadData();
super
.
initState
();
super
.
initState
();
pullToRefreshController
=
kIsWeb
pullToRefreshController
=
?
null
kIsWeb
:
PullToRefreshController
(
?
null
settings:
pullToRefreshSettings
,
:
PullToRefreshController
(
onRefresh:
()
async
{
settings:
pullToRefreshSettings
,
if
(
defaultTargetPlatform
==
TargetPlatform
.
android
)
{
onRefresh:
()
async
{
_webViewController
?.
reload
();
if
(
defaultTargetPlatform
==
TargetPlatform
.
android
)
{
}
else
if
(
defaultTargetPlatform
==
TargetPlatform
.
iOS
)
{
_webViewController
?.
reload
();
_webViewController
?.
loadUrl
(
}
else
if
(
defaultTargetPlatform
==
TargetPlatform
.
iOS
)
{
urlRequest:
_webViewController
?.
loadUrl
(
URLRequest
(
url:
await
_webViewController
?.
getUrl
()));
urlRequest:
URLRequest
(
}
url:
await
_webViewController
?.
getUrl
(),
},
),
);
);
}
},
);
// print("URL:${widget.url}");
// print("URL:${widget.url}");
_initializeNotifications
();
_initializeNotifications
();
}
}
Future
<
void
>
_initializeNotifications
()
async
{
Future
<
void
>
_initializeNotifications
()
async
{
const
AndroidInitializationSettings
initializationSettingsAndroid
=
const
AndroidInitializationSettings
initializationSettingsAndroid
=
AndroidInitializationSettings
(
'@mipmap/ic_launcher'
);
AndroidInitializationSettings
(
'@mipmap/ic_launcher'
);
final
InitializationSettings
initializationSettings
=
InitializationSettings
(
final
InitializationSettings
initializationSettings
=
android:
initializationSettingsAndroid
,
InitializationSettings
(
android:
initializationSettingsAndroid
);
);
await
_notificationsPlugin
.
initialize
(
initializationSettings
);
await
_notificationsPlugin
.
initialize
(
initializationSettings
);
// Create a notification channel for Android
// Create a notification channel for Android
...
@@ -90,7 +95,9 @@ class _WebErpScreenState extends State<WebErpScreen> {
...
@@ -90,7 +95,9 @@ class _WebErpScreenState extends State<WebErpScreen> {
importance:
Importance
.
high
,
importance:
Importance
.
high
,
);
);
await
_notificationsPlugin
await
_notificationsPlugin
.
resolvePlatformSpecificImplementation
<
AndroidFlutterLocalNotificationsPlugin
>()
.
resolvePlatformSpecificImplementation
<
AndroidFlutterLocalNotificationsPlugin
>()
?.
createNotificationChannel
(
channel
);
?.
createNotificationChannel
(
channel
);
}
}
...
@@ -98,6 +105,7 @@ class _WebErpScreenState extends State<WebErpScreen> {
...
@@ -98,6 +105,7 @@ class _WebErpScreenState extends State<WebErpScreen> {
void
dispose
()
{
void
dispose
()
{
super
.
dispose
();
super
.
dispose
();
}
}
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
WillPopScope
(
return
WillPopScope
(
...
@@ -110,272 +118,428 @@ class _WebErpScreenState extends State<WebErpScreen> {
...
@@ -110,272 +118,428 @@ class _WebErpScreenState extends State<WebErpScreen> {
},
},
child:
Scaffold
(
child:
Scaffold
(
resizeToAvoidBottomInset:
true
,
resizeToAvoidBottomInset:
true
,
appBar:
appbar
(
context
,
"Web ERP"
),
appBar:
appbar
(
context
,
"Web ERP"
),
body:
Container
(
body:
Container
(
child:
Column
(
children:
<
Widget
>[
child:
Column
(
children:
<
Widget
>[
Expanded
(
Expanded
(
child:
Stack
(
child:
Stack
(
children:
[
children:
[
InAppWebView
(
InAppWebView
(
initialUrlRequest:
URLRequest
(
initialUrlRequest:
URLRequest
(
url:
WebUri
(
widget
.
erp_url
),
url:
WebUri
(
widget
.
erp_url
),
allowsCellularAccess:
true
,
allowsCellularAccess:
true
,
allowsConstrainedNetworkAccess:
true
,
allowsConstrainedNetworkAccess:
true
,
allowsExpensiveNetworkAccess:
true
,
allowsExpensiveNetworkAccess:
true
,
),
),
androidOnGeolocationPermissionsShowPrompt:
(
androidOnGeolocationPermissionsShowPrompt:
InAppWebViewController
controller
,
(
InAppWebViewController
controller
,
String
origin
)
async
{
String
origin
,
return
GeolocationPermissionShowPromptResponse
(
)
async
{
origin:
origin
,
allow:
true
,
retain:
true
);
return
GeolocationPermissionShowPromptResponse
(
},
origin:
origin
,
initialOptions:
InAppWebViewGroupOptions
(
allow:
true
,
retain:
true
,
android:
AndroidInAppWebViewOptions
(
);
},
useWideViewPort:
true
,
initialOptions:
InAppWebViewGroupOptions
(
loadWithOverviewMode:
true
,
android:
AndroidInAppWebViewOptions
(
allowContentAccess:
true
,
geolocationEnabled:
true
,
allowFileAccess:
true
,
databaseEnabled:
true
,
// Enables the WebView database
domStorageEnabled:
true
,
// Enables DOM storage
builtInZoomControls:
true
,
// Enables the built-in zoom controls
displayZoomControls:
false
,
// Disables displaying zoom controls
safeBrowsingEnabled:
true
,
// Enables Safe Browsing
clearSessionCache:
true
,
loadsImagesAutomatically:
true
,
thirdPartyCookiesEnabled:
true
,
blockNetworkImage:
false
,
supportMultipleWindows:
true
,
// Enable camera access
),
ios:
IOSInAppWebViewOptions
(
allowsInlineMediaPlayback:
true
,
),
crossPlatform:
InAppWebViewOptions
(
javaScriptEnabled:
true
,
useOnDownloadStart:
true
,
allowFileAccessFromFileURLs:
true
,
allowUniversalAccessFromFileURLs:
true
,
mediaPlaybackRequiresUserGesture:
true
,
),
),
androidOnPermissionRequest:
(
InAppWebViewController
controller
,
String
origin
,
List
<
String
>
resources
)
async
{
return
PermissionRequestResponse
(
resources:
resources
,
action:
PermissionRequestResponseAction
.
GRANT
);
},
onWebViewCreated:
(
controller
)
{
_webViewController
=
controller
;
_controller
.
complete
(
controller
);
_webViewController
!.
addJavaScriptHandler
(
handlerName:
'MobileAppJavascriptInterface'
,
callback:
(
args
)
{
print
(
"JavaScript called MobileAppJavascriptInterface with args:
$args
"
);
return
{
'status'
:
'success'
};
},
);
_webViewController
!.
addJavaScriptHandler
(
handlerName:
'downloadFile'
,
callback:
(
args
)
async
{
final
url
=
args
[
0
]
as
String
;
await
_handleDownload
(
url
,
''
,
'application/octet-stream'
,
''
);
},
);
},
pullToRefreshController:
pullToRefreshController
,
onLoadStart:
(
controller
,
url
)
{
return
setState
(()
{
isLoading
=
true
;
});
},
initialSettings:
InAppWebViewSettings
(
allowUniversalAccessFromFileURLs:
true
,
allowFileAccessFromFileURLs:
true
,
allowFileAccess:
true
,
allowsInlineMediaPlayback:
true
,
allowsPictureInPictureMediaPlayback:
true
,
allowsBackForwardNavigationGestures:
true
,
iframeAllow:
"camera;microphone;files;media;"
,
domStorageEnabled:
true
,
allowContentAccess:
true
,
javaScriptEnabled:
true
,
supportZoom:
true
,
builtInZoomControls:
true
,
displayZoomControls:
false
,
textZoom:
125
,
blockNetworkImage:
false
,
loadsImagesAutomatically:
true
,
safeBrowsingEnabled:
true
,
useWideViewPort:
true
,
useWideViewPort:
true
,
loadWithOverviewMode:
true
,
loadWithOverviewMode:
true
,
javaScriptCanOpenWindowsAutomatically:
true
,
allowContentAccess:
true
,
mediaPlaybackRequiresUserGesture:
false
,
geolocationEnabled:
true
,
geolocationEnabled:
true
,
useOnDownloadStart:
true
,
allowFileAccess:
true
,
allowsLinkPreview:
true
,
databaseEnabled:
true
,
// Enables the WebView database
databaseEnabled:
true
,
// Enables the WebView database
domStorageEnabled:
true
,
// Enables DOM storage
builtInZoomControls:
true
,
// Enables the built-in zoom controls
displayZoomControls:
false
,
// Disables displaying zoom controls
safeBrowsingEnabled:
true
,
// Enables Safe Browsing
clearSessionCache:
true
,
clearSessionCache:
true
,
mediaType:
"image/*"
,
loadsImagesAutomatically:
true
,
thirdPartyCookiesEnabled:
true
,
blockNetworkImage:
false
,
supportMultipleWindows:
true
,
// Enable camera access
),
),
shouldOverrideUrlLoading:
ios:
IOSInAppWebViewOptions
(
(
controller
,
navigationAction
)
async
{
allowsInlineMediaPlayback:
true
,
var
uri
=
navigationAction
.
request
.
url
!;
allowsLinkPreview:
true
,
print
(
"urib scgefes"
);
allowsBackForwardNavigationGestures:
true
,
print
(
uri
);
),
print
(
uri
.
scheme
);
crossPlatform:
InAppWebViewOptions
(
if
(
uri
.
scheme
==
"tel"
)
{
javaScriptEnabled:
true
,
// Launch the phone dialer app with the specified phone number
useOnDownloadStart:
true
,
if
(
await
canLaunch
(
uri
.
toString
()))
{
allowFileAccessFromFileURLs:
true
,
await
launch
(
uri
.
toString
());
allowUniversalAccessFromFileURLs:
true
,
return
NavigationActionPolicy
.
CANCEL
;
mediaPlaybackRequiresUserGesture:
true
,
}
),
}
else
if
(
uri
.
scheme
==
"mailto"
)
{
),
if
(
await
canLaunch
(
uri
.
toString
()))
{
await
launch
(
uri
.
toString
());
androidOnPermissionRequest:
(
return
NavigationActionPolicy
.
CANCEL
;
InAppWebViewController
controller
,
}
String
origin
,
}
else
if
(
uri
.
scheme
==
"whatsapp"
)
{
List
<
String
>
resources
,
// Launch WhatsApp with the specified chat or phone number
)
async
{
if
(
await
canLaunch
(
uri
.
toString
()))
{
return
PermissionRequestResponse
(
await
launch
(
uri
.
toString
());
resources:
resources
,
return
NavigationActionPolicy
.
CANCEL
;
action:
PermissionRequestResponseAction
.
GRANT
,
);
},
onPermissionRequest:
(
controller
,
request
)
async
{
return
PermissionResponse
(
resources:
request
.
resources
,
action:
PermissionResponseAction
.
GRANT
,
);
},
keepAlive:
InAppWebViewKeepAlive
(),
onWebViewCreated:
(
controller
)
{
_webViewController
=
controller
;
_controller
.
complete
(
controller
);
_webViewController
!.
addJavaScriptHandler
(
handlerName:
'MobileAppJavascriptInterface'
,
callback:
(
args
)
{
print
(
"JavaScript called MobileAppJavascriptInterface with args:
$args
"
,
);
return
{
'status'
:
'success'
};
},
);
_webViewController
!.
addJavaScriptHandler
(
handlerName:
'downloadFile'
,
callback:
(
args
)
async
{
if
(
Platform
.
isAndroid
)
{
final
url
=
args
[
0
]
as
String
;
await
_handleDownload
(
url
,
''
,
'application/octet-stream'
,
''
,
);
}
}
},
);
},
pullToRefreshController:
pullToRefreshController
,
onLoadStart:
(
controller
,
url
)
{
return
setState
(()
{
isLoading
=
true
;
});
},
initialSettings:
InAppWebViewSettings
(
allowUniversalAccessFromFileURLs:
true
,
allowFileAccessFromFileURLs:
true
,
allowFileAccess:
true
,
allowsInlineMediaPlayback:
true
,
allowsPictureInPictureMediaPlayback:
true
,
allowsBackForwardNavigationGestures:
true
,
iframeAllow:
"camera;microphone;files;media;"
,
domStorageEnabled:
true
,
allowContentAccess:
true
,
javaScriptEnabled:
true
,
supportZoom:
true
,
builtInZoomControls:
true
,
displayZoomControls:
false
,
textZoom:
125
,
blockNetworkImage:
false
,
loadsImagesAutomatically:
true
,
safeBrowsingEnabled:
true
,
useWideViewPort:
true
,
loadWithOverviewMode:
true
,
javaScriptCanOpenWindowsAutomatically:
true
,
mediaPlaybackRequiresUserGesture:
false
,
geolocationEnabled:
true
,
useOnDownloadStart:
true
,
allowsLinkPreview:
true
,
databaseEnabled:
true
,
// Enables the WebView database
clearSessionCache:
true
,
mediaType:
"image/*"
,
),
shouldOverrideUrlLoading:
(
controller
,
navigationAction
,
)
async
{
var
uri
=
navigationAction
.
request
.
url
!;
print
(
"urib scgefes"
);
print
(
uri
);
print
(
uri
.
scheme
);
if
(
uri
.
scheme
==
"tel"
)
{
// Launch the phone dialer app with the specified phone number
if
(
await
canLaunch
(
uri
.
toString
()))
{
await
launch
(
uri
.
toString
());
return
NavigationActionPolicy
.
CANCEL
;
}
}
// // Check if the URL is trying to access the camera for image upload
}
else
if
(
uri
.
scheme
==
"mailto"
)
{
// if (uri.scheme == 'camera' && uri.path.contains('/camera/')) {
if
(
await
canLaunch
(
uri
.
toString
()))
{
// // Handle camera image upload here
await
launch
(
uri
.
toString
());
// // You might want to display a custom UI for image selection or directly trigger the camera
return
NavigationActionPolicy
.
CANCEL
;
// // You can use platform-specific plugins like image_picker for this purpose
// // Once the image is selected, you can pass it to the web view using JavaScript injection
// if (await canLaunch(uri.toString())) {
// await launch(uri.toString());
// return NavigationActionPolicy.CANCEL;
// }
// }
return
NavigationActionPolicy
.
ALLOW
;
},
onLoadStop:
(
controller
,
url
)
{
pullToRefreshController
?.
endRefreshing
();
return
setState
(()
{
isLoading
=
false
;
});
},
onReceivedError:
(
controller
,
request
,
error
)
{
pullToRefreshController
?.
endRefreshing
();
},
onProgressChanged:
(
controller
,
progress
)
{
if
(
progress
==
100
)
{
pullToRefreshController
?.
endRefreshing
();
}
}
},
}
else
if
(
uri
.
scheme
==
"whatsapp"
)
{
onConsoleMessage:
(
controller
,
consoleMessage
)
{
// Launch WhatsApp with the specified chat or phone number
if
(
kDebugMode
)
{
if
(
await
canLaunch
(
uri
.
toString
()))
{
debugPrint
(
"consoleMessage
${consoleMessage}
"
);
await
launch
(
uri
.
toString
());
return
NavigationActionPolicy
.
CANCEL
;
}
}
debugPrint
(
}
"JavaScript console message:
${consoleMessage.message}
"
);
// // Check if the URL is trying to access the camera for image upload
},
// if (uri.scheme == 'camera' && uri.path.contains('/camera/')) {
// onDownloadStartRequest: (controller, url) async {
// // Handle camera image upload here
// await ApiCalling.download_files(
// // You might want to display a custom UI for image selection or directly trigger the camera
// empId, sessionId, "${url.url}", context)
// // You can use platform-specific plugins like image_picker for this purpose
// .then((data) => {debugPrint(data)});
// // Once the image is selected, you can pass it to the web view using JavaScript injection
//
// if (await canLaunch(uri.toString())) {
// },
// await launch(uri.toString());
onDownloadStartRequest:
(
controller
,
downloadStartRequest
)
async
{
// return NavigationActionPolicy.CANCEL;
// }
// }
return
NavigationActionPolicy
.
ALLOW
;
},
onLoadStop:
(
controller
,
url
)
{
pullToRefreshController
?.
endRefreshing
();
return
setState
(()
{
isLoading
=
false
;
});
},
onReceivedError:
(
controller
,
request
,
error
)
{
pullToRefreshController
?.
endRefreshing
();
return
setState
(()
{
isLoading
=
false
;
});
},
onProgressChanged:
(
controller
,
progress
)
{
if
(
progress
==
100
)
{
pullToRefreshController
?.
endRefreshing
();
}
},
onConsoleMessage:
(
controller
,
consoleMessage
)
{
if
(
kDebugMode
)
{
debugPrint
(
"consoleMessage
${consoleMessage}
"
);
}
debugPrint
(
"JavaScript console message:
${consoleMessage.message}
"
,
);
},
// onDownloadStartRequest: (controller, url) async {
// await ApiCalling.download_files(
// empId, sessionId, "${url.url}", context)
// .then((data) => {debugPrint(data)});
//
// },
onDownloadStartRequest:
(
controller
,
downloadStartRequest
,
)
async
{
if
(
Platform
.
isAndroid
)
{
await
_handleDownload
(
await
_handleDownload
(
downloadStartRequest
.
url
.
toString
(),
downloadStartRequest
.
url
.
toString
(),
downloadStartRequest
.
suggestedFilename
!,
downloadStartRequest
.
suggestedFilename
!,
downloadStartRequest
.
mimeType
??
'application/octet-stream'
,
downloadStartRequest
.
mimeType
??
'application/octet-stream'
,
downloadStartRequest
.
suggestedFilename
??
''
,
downloadStartRequest
.
suggestedFilename
??
''
,
);
);
}
},
},
shouldInterceptAjaxRequest:
(
controller
,
ajaxRequest
)
async
{
shouldInterceptAjaxRequest:
(
controller
,
ajaxRequest
,
)
async
{
if
(
Platform
.
isAndroid
)
{
if
(
ajaxRequest
.
url
.
toString
().
contains
(
'download'
))
{
if
(
ajaxRequest
.
url
.
toString
().
contains
(
'download'
))
{
await
_handleDownload
(
ajaxRequest
.
url
.
toString
(),
''
,
'application/octet-stream'
,
''
);
await
_handleDownload
(
return
ajaxRequest
;
ajaxRequest
.
url
.
toString
(),
''
,
'application/octet-stream'
,
''
,
);
}
}
return
ajaxRequest
;
return
ajaxRequest
;
},
}
),
return
ajaxRequest
;
if
(
isLoading
)
...[
Container
(
},
),
if
(
isLoading
)
...[
Container
(
color:
Colors
.
white
.
withOpacity
(
0.7
),
color:
Colors
.
white
.
withOpacity
(
0.7
),
child:
Column
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
center
,
crossAxisAlignment:
CrossAxisAlignment
.
center
,
mainAxisAlignment:
MainAxisAlignment
.
center
,
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
children:
[
SpinKitRing
(
SpinKitRing
(
color:
AppColors
.
app_blue
,
color:
AppColors
.
app_blue
,
lineWidth:
4
,
lineWidth:
4
,
// duration: Duration(seconds: 2),
// duration: Duration(seconds: 2),
size:
50
,
size:
50
,
),
),
const
SizedBox
(
const
SizedBox
(
height:
15
),
height:
15
,
),
SizedBox
(
SizedBox
(
width:
200
,
width:
200
,
child:
Text
(
child:
Text
(
"Please wait......."
,
"Please wait......."
,
textAlign:
TextAlign
.
center
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
style:
TextStyle
(
decorationThickness:
0
,
decorationThickness:
0
,
fontSize:
15
,
fontSize:
15
,
fontWeight:
FontWeight
.
normal
,
fontWeight:
FontWeight
.
normal
,
color:
AppColors
.
app_blue
),
color:
AppColors
.
app_blue
,
),
),
),
),
),
// SvgPicture.asset("/assets/images/NutsLoader.gif")
// SvgPicture.asset("/assets/images/NutsLoader.gif")
],
],
),
),
)
]
)
,
],
],
))
],
])),
),
),
],
),
),
),
),
);
);
}
}
Future
<
void
>
_handleDownload
(
String
url
,
String
contentDisposition
,
String
mimeType
,
String
suggestedFilename
)
async
{
Future
<
void
>
_handleDownload
(
String
url
,
String
contentDisposition
,
String
mimeType
,
String
suggestedFilename
,
)
async
{
// Request notification permission for Android 13+
// Request notification permission for Android 13+
if
(
await
Permission
.
notification
.
request
().
isGranted
)
{
if
(
Platform
.
isIOS
)
{
try
{
_handleIOSDownload
(
url
,
suggestedFilename
);
// Show custom notification (optional, since DownloadManager shows its own)
}
else
if
(
Platform
.
isAndroid
)
{
if
(
await
Permission
.
notification
.
request
().
isGranted
)
{
try
{
// Call native Android Download Manager
// Show custom notification (optional, since DownloadManager shows its own)
final
userAgent
=
'Flutter InAppWebView'
;
await
platform
.
invokeMethod
(
'startDownload'
,
{
if
(
Platform
.
isAndroid
)
{
'url'
:
url
,
// Call native Android Download Manager
'userAgent'
:
userAgent
,
final
userAgent
=
'Flutter InAppWebView'
;
'contentDisposition'
:
contentDisposition
,
await
platform
.
invokeMethod
(
'startDownload'
,
{
'mimeType'
:
mimeType
,
'url'
:
url
,
'suggestedFilename'
:
suggestedFilename
,
'userAgent'
:
userAgent
,
});
'contentDisposition'
:
contentDisposition
,
'mimeType'
:
mimeType
,
}
catch
(
e
)
{
'suggestedFilename'
:
suggestedFilename
,
print
(
"Download Error
$e
"
);
});
}
else
if
(
Platform
.
isIOS
)
{
_handleIOSDownload
(
url
,
suggestedFilename
);
}
}
catch
(
e
)
{
print
(
"Download Error
$e
"
);
}
}
else
{
toast
(
context
,
"Notification Permission Denied"
);
}
}
}
else
{
toast
(
context
,
"Notification Permission Denied"
);
}
}
}
}
}
Future
<
void
>
_handleIOSDownload
(
String
url
,
String
suggestedFilename
)
async
{
try
{
// Show initial download notification
await
_showDownloadNotification
(
0
,
suggestedFilename
,
isComplete:
false
);
// Get the temporary directory for iOS
final
tempDir
=
await
getTemporaryDirectory
();
final
fileName
=
suggestedFilename
.
isNotEmpty
?
suggestedFilename
:
url
.
split
(
'/'
).
last
;
final
filePath
=
'
${tempDir.path}
/
$fileName
'
;
// Download the file using http
final
response
=
await
http
.
get
(
Uri
.
parse
(
url
));
if
(
response
.
statusCode
==
200
)
{
// Save the file
final
file
=
File
(
filePath
);
await
file
.
writeAsBytes
(
response
.
bodyBytes
);
// Show completion notification
await
_showDownloadNotification
(
100
,
fileName
,
isComplete:
true
);
// Optionally, open the file or notify the user
toast
(
context
,
"File downloaded to
$filePath
"
);
}
else
{
throw
Exception
(
"Failed to download file: HTTP
${response.statusCode}
"
);
}
}
catch
(
e
)
{
print
(
"iOS Download Error:
$e
"
);
await
_showDownloadNotification
(
0
,
suggestedFilename
,
isComplete:
false
,
isError:
true
,
);
toast
(
context
,
"Failed to download file:
$e
"
);
}
}
Future
<
void
>
_showDownloadNotification
(
int
progress
,
String
fileName
,
{
bool
isComplete
=
false
,
bool
isError
=
false
,
})
async
{
final
androidDetails
=
AndroidNotificationDetails
(
'download_channel'
,
'Downloads'
,
channelDescription:
'Notifications for file downloads'
,
importance:
Importance
.
high
,
priority:
Priority
.
high
,
showProgress:
!
isComplete
&&
!
isError
,
maxProgress:
100
,
progress:
progress
,
ongoing:
!
isComplete
&&
!
isError
,
playSound:
isComplete
||
isError
,
styleInformation:
BigTextStyleInformation
(
isError
?
'Download failed for
$fileName
'
:
isComplete
?
'Download complete:
$fileName
'
:
'Downloading
$fileName
...'
,
),
);
final
iosDetails
=
DarwinNotificationDetails
(
presentAlert:
true
,
presentBadge:
true
,
presentSound:
isComplete
||
isError
,
subtitle:
isError
?
'Download failed'
:
isComplete
?
'Download complete'
:
'Downloading...'
,
threadIdentifier:
'download_thread'
,
);
final
notificationDetails
=
NotificationDetails
(
android:
androidDetails
,
iOS:
iosDetails
,
);
await
_notificationsPlugin
.
show
(
fileName
.
hashCode
,
// Unique ID for the notification
isError
?
'Download Failed'
:
isComplete
?
'Download Complete'
:
'Downloading File'
,
isError
?
'Failed to download
$fileName
'
:
isComplete
?
'Successfully downloaded
$fileName
'
:
'Downloading
$fileName
(
$progress
%)'
,
notificationDetails
,
);
}
}
class
SpinKitRing
extends
StatefulWidget
{
class
SpinKitRing
extends
StatefulWidget
{
const
SpinKitRing
({
const
SpinKitRing
({
...
@@ -397,7 +561,8 @@ class SpinKitRing extends StatefulWidget {
...
@@ -397,7 +561,8 @@ class SpinKitRing extends StatefulWidget {
State
<
SpinKitRing
>
createState
()
=>
_SpinKitRingState
();
State
<
SpinKitRing
>
createState
()
=>
_SpinKitRingState
();
}
}
class
_SpinKitRingState
extends
State
<
SpinKitRing
>
with
SingleTickerProviderStateMixin
{
class
_SpinKitRingState
extends
State
<
SpinKitRing
>
with
SingleTickerProviderStateMixin
{
late
AnimationController
_controller
;
late
AnimationController
_controller
;
late
Animation
<
double
>
_animation1
;
late
Animation
<
double
>
_animation1
;
late
Animation
<
double
>
_animation2
;
late
Animation
<
double
>
_animation2
;
...
@@ -407,13 +572,15 @@ class _SpinKitRingState extends State<SpinKitRing> with SingleTickerProviderStat
...
@@ -407,13 +572,15 @@ class _SpinKitRingState extends State<SpinKitRing> with SingleTickerProviderStat
void
initState
()
{
void
initState
()
{
super
.
initState
();
super
.
initState
();
_controller
=
(
widget
.
controller
??
AnimationController
(
vsync:
this
,
duration:
widget
.
duration
))
_controller
=
..
addListener
(()
{
(
widget
.
controller
??
if
(
mounted
)
{
AnimationController
(
vsync:
this
,
duration:
widget
.
duration
))
setState
(()
{});
..
addListener
(()
{
}
if
(
mounted
)
{
})
setState
(()
{});
..
repeat
();
}
})
..
repeat
();
_animation1
=
Tween
(
begin:
0.0
,
end:
1.0
).
animate
(
_animation1
=
Tween
(
begin:
0.0
,
end:
1.0
).
animate
(
CurvedAnimation
(
CurvedAnimation
(
parent:
_controller
,
parent:
_controller
,
...
@@ -446,7 +613,8 @@ class _SpinKitRingState extends State<SpinKitRing> with SingleTickerProviderStat
...
@@ -446,7 +613,8 @@ class _SpinKitRingState extends State<SpinKitRing> with SingleTickerProviderStat
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
Center
(
return
Center
(
child:
Transform
(
child:
Transform
(
transform:
Matrix4
.
identity
()..
rotateZ
((
_animation1
.
value
)
*
5
*
pi
/
6
),
transform:
Matrix4
.
identity
()..
rotateZ
((
_animation1
.
value
)
*
5
*
pi
/
6
),
alignment:
FractionalOffset
.
center
,
alignment:
FractionalOffset
.
center
,
child:
SizedBox
.
fromSize
(
child:
SizedBox
.
fromSize
(
size:
Size
.
square
(
widget
.
size
),
size:
Size
.
square
(
widget
.
size
),
...
@@ -470,11 +638,12 @@ class RingPainter extends CustomPainter {
...
@@ -470,11 +638,12 @@ class RingPainter extends CustomPainter {
this
.
progressPercent
,
this
.
progressPercent
,
this
.
startAngle
,
this
.
startAngle
,
required
this
.
trackColor
,
required
this
.
trackColor
,
})
:
trackPaint
=
Paint
()
})
:
trackPaint
=
..
color
=
trackColor
Paint
()
..
style
=
PaintingStyle
.
stroke
..
color
=
trackColor
..
strokeWidth
=
paintWidth
..
style
=
PaintingStyle
.
stroke
..
strokeCap
=
StrokeCap
.
square
;
..
strokeWidth
=
paintWidth
..
strokeCap
=
StrokeCap
.
square
;
final
double
paintWidth
;
final
double
paintWidth
;
final
Paint
trackPaint
;
final
Paint
trackPaint
;
...
...
pubspec.lock
View file @
f7b0d1aa
...
@@ -37,10 +37,10 @@ packages:
...
@@ -37,10 +37,10 @@ packages:
dependency: transitive
dependency: transitive
description:
description:
name: async
name: async
sha256:
d2872f9c1
97
3
1c
2
e5
f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
sha256:
"758e6d74e
971c
3
e5
aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "2.1
2
.0"
version: "2.1
3
.0"
barcode:
barcode:
dependency: transitive
dependency: transitive
description:
description:
...
@@ -285,10 +285,10 @@ packages:
...
@@ -285,10 +285,10 @@ packages:
dependency: transitive
dependency: transitive
description:
description:
name: fake_async
name: fake_async
sha256: "
6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc
"
sha256: "
5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44
"
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "1.3.
2
"
version: "1.3.
3
"
ffi:
ffi:
dependency: transitive
dependency: transitive
description:
description:
...
@@ -924,26 +924,26 @@ packages:
...
@@ -924,26 +924,26 @@ packages:
dependency: transitive
dependency: transitive
description:
description:
name: leak_tracker
name: leak_tracker
sha256:
c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
sha256:
"8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0"
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "1
0
.0.
8
"
version: "1
1
.0.
1
"
leak_tracker_flutter_testing:
leak_tracker_flutter_testing:
dependency: transitive
dependency: transitive
description:
description:
name: leak_tracker_flutter_testing
name: leak_tracker_flutter_testing
sha256:
f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
sha256:
"1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "3.0.
9
"
version: "3.0.
10
"
leak_tracker_testing:
leak_tracker_testing:
dependency: transitive
dependency: transitive
description:
description:
name: leak_tracker_testing
name: leak_tracker_testing
sha256: "
6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3
"
sha256: "
8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1
"
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "3.0.
1
"
version: "3.0.
2
"
lints:
lints:
dependency: transitive
dependency: transitive
description:
description:
...
@@ -1641,10 +1641,10 @@ packages:
...
@@ -1641,10 +1641,10 @@ packages:
dependency: transitive
dependency: transitive
description:
description:
name: vm_service
name: vm_service
sha256:
"0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
sha256:
ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "1
4.3.1
"
version: "1
5.0.0
"
web:
web:
dependency: transitive
dependency: transitive
description:
description:
...
...
pubspec.yaml
View file @
f7b0d1aa
...
@@ -180,3 +180,4 @@ flutter:
...
@@ -180,3 +180,4 @@ flutter:
# For details regarding fonts from package dependencies,
# For details regarding fonts from package dependencies,
# see https://flutter.dev/to/font-from-package
# see https://flutter.dev/to/font-from-package
generate
:
true
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment