| @@ -28,14 +28,21 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" | |||||
| protobuf { | protobuf { | ||||
| protoc { | protoc { | ||||
| artifact = 'com.google.protobuf:protoc:3.8.0' | |||||
| if (osdetector.os == "osx") { | |||||
| artifact = 'com.google.protobuf:protoc:3.19.1:osx-x86_64' | |||||
| } else { | |||||
| artifact = 'com.google.protobuf:protoc:3.19.1' | |||||
| } | |||||
| // artifact = 'com.google.protobuf:protoc:3.8.0' | |||||
| } | } | ||||
| plugins { | plugins { | ||||
| javalite { | javalite { | ||||
| artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0' | |||||
| if (osdetector.os != "osx"){ | |||||
| artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0' | |||||
| } | |||||
| } | } | ||||
| grpc { | grpc { | ||||
| artifact = 'io.grpc:protoc-gen-grpc-java:1.0.0-pre2' | |||||
| artifact = 'io.grpc:protoc-gen-grpc-java:1.42.1' | |||||
| } | } | ||||
| } | } | ||||
| generateProtoTasks { | generateProtoTasks { | ||||
| @@ -2,3 +2,4 @@ org.gradle.jvmargs=-Xmx5120M | |||||
| android.enableR8=true | android.enableR8=true | ||||
| android.useAndroidX=true | android.useAndroidX=true | ||||
| android.enableJetifier=true | android.enableJetifier=true | ||||
| @@ -1 +1,2 @@ | |||||
| #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" | |||||
| #include "Generated.xcconfig" | #include "Generated.xcconfig" | ||||
| @@ -1 +1,2 @@ | |||||
| #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" | |||||
| #include "Generated.xcconfig" | #include "Generated.xcconfig" | ||||
| @@ -0,0 +1,41 @@ | |||||
| # Uncomment this line to define a global platform for your project | |||||
| # platform :ios, '9.0' | |||||
| # CocoaPods analytics sends network stats synchronously affecting flutter build latency. | |||||
| ENV['COCOAPODS_DISABLE_STATS'] = 'true' | |||||
| project 'Runner', { | |||||
| 'Debug' => :debug, | |||||
| 'Profile' => :release, | |||||
| 'Release' => :release, | |||||
| } | |||||
| def flutter_root | |||||
| generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) | |||||
| unless File.exist?(generated_xcode_build_settings_path) | |||||
| raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" | |||||
| end | |||||
| File.foreach(generated_xcode_build_settings_path) do |line| | |||||
| matches = line.match(/FLUTTER_ROOT\=(.*)/) | |||||
| return matches[1].strip if matches | |||||
| end | |||||
| raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" | |||||
| end | |||||
| require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) | |||||
| flutter_ios_podfile_setup | |||||
| target 'Runner' do | |||||
| use_frameworks! | |||||
| use_modular_headers! | |||||
| flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) | |||||
| end | |||||
| post_install do |installer| | |||||
| installer.pods_project.targets.each do |target| | |||||
| flutter_additional_ios_build_settings(target) | |||||
| end | |||||
| end | |||||
| @@ -81,7 +81,7 @@ class DBHelper { | |||||
| } | } | ||||
| Future<List<Unit>> searchAllUnits(String query,{inserted:false}) async { | Future<List<Unit>> searchAllUnits(String query,{inserted:false}) async { | ||||
| print("${(inserted)?"${columnName.flag} = 'TRUE' AND ":''} REPLACE(${columnName.mesin},'-','') like '%$query%' or ${columnName.rangka} like '%$query%' or ${columnName.mesin} like '%$query%' or ${columnName.timestamp} like '%$query%' or ${columnName.tipe} like '%$query%' or ${columnName.warna} like '%$query%' or UPPER(${columnName.state}) like '%$query%'"); | |||||
| // print("${(inserted)?"${columnName.flag} = 'TRUE' AND ":''} REPLACE(${columnName.mesin},'-','') like '%$query%' or ${columnName.rangka} like '%$query%' or ${columnName.mesin} like '%$query%' or ${columnName.timestamp} like '%$query%' or ${columnName.tipe} like '%$query%' or ${columnName.warna} like '%$query%' or UPPER(${columnName.state}) like '%$query%'"); | |||||
| final database = await db; | final database = await db; | ||||
| try{ | try{ | ||||
| var res = await database.query(tableName.master,where: "${(inserted)?"${columnName.flag} = 'TRUE' AND ":''} (REPLACE(${columnName.mesin},'-','') like '%$query%' or ${columnName.rangka} like '%$query%' or ${columnName.mesin} like '%$query%' or ${columnName.timestamp} like '%$query%' or ${columnName.tipe} like '%$query%' or ${columnName.warna} like '%$query%' or UPPER(${columnName.state}) like '%$query%')",orderBy: "CASE WHEN ${columnName.flag} = 'FALSE' THEN 0 ELSE 1 END, ${columnName.state} desc"); | var res = await database.query(tableName.master,where: "${(inserted)?"${columnName.flag} = 'TRUE' AND ":''} (REPLACE(${columnName.mesin},'-','') like '%$query%' or ${columnName.rangka} like '%$query%' or ${columnName.mesin} like '%$query%' or ${columnName.timestamp} like '%$query%' or ${columnName.tipe} like '%$query%' or ${columnName.warna} like '%$query%' or UPPER(${columnName.state}) like '%$query%')",orderBy: "CASE WHEN ${columnName.flag} = 'FALSE' THEN 0 ELSE 1 END, ${columnName.state} desc"); | ||||
| @@ -35,6 +35,7 @@ class columnName{ | |||||
| static String state = 'STATE'; | static String state = 'STATE'; | ||||
| static String no_urut = 'NO_URUT'; | static String no_urut = 'NO_URUT'; | ||||
| static String flag = 'FLAG_INSERT'; | static String flag = 'FLAG_INSERT'; | ||||
| static String channel = "CHANNEL"; | |||||
| } | } | ||||
| class tableName{ | class tableName{ | ||||
| static String master = 'refTable'; | static String master = 'refTable'; | ||||
| @@ -12,6 +12,7 @@ class Unit { | |||||
| String state; | String state; | ||||
| String flag; | String flag; | ||||
| String timestamp; | String timestamp; | ||||
| String channel; | |||||
| Unit({ | Unit({ | ||||
| @@ -25,6 +26,7 @@ class Unit { | |||||
| this.state, | this.state, | ||||
| this.flag, | this.flag, | ||||
| this.timestamp, | this.timestamp, | ||||
| this.channel, | |||||
| }); | }); | ||||
| factory Unit.fromJson(Map<String, dynamic> json) { | factory Unit.fromJson(Map<String, dynamic> json) { | ||||
| @@ -38,7 +40,8 @@ class Unit { | |||||
| warna : json[columnName.warna], | warna : json[columnName.warna], | ||||
| state: json[columnName.state], | state: json[columnName.state], | ||||
| flag: json[columnName.flag], | flag: json[columnName.flag], | ||||
| timestamp: json[columnName.timestamp]??'' | |||||
| timestamp: json[columnName.timestamp]??'', | |||||
| channel: json[columnName.channel], | |||||
| );} | );} | ||||
| Map<String, dynamic> toJson() => { | Map<String, dynamic> toJson() => { | ||||
| @@ -52,6 +55,7 @@ class Unit { | |||||
| columnName.state :state, | columnName.state :state, | ||||
| columnName.flag :flag, | columnName.flag :flag, | ||||
| columnName.timestamp :timestamp, | columnName.timestamp :timestamp, | ||||
| columnName.channel:channel, | |||||
| }; | }; | ||||
| } | } | ||||
| @@ -5,16 +5,74 @@ import 'package:flutter/services.dart'; | |||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
| import 'package:flushbar/flushbar.dart'; | import 'package:flushbar/flushbar.dart'; | ||||
| import 'package:http/io_client.dart'; | import 'package:http/io_client.dart'; | ||||
| import 'package:in_app_update/in_app_update.dart'; | |||||
| import 'package:url_launcher/url_launcher.dart'; | |||||
| import '../main.dart'; | import '../main.dart'; | ||||
| import 'package:location/location.dart'; | import 'package:location/location.dart'; | ||||
| import 'package:permission_handler/permission_handler.dart' as pHandler; | import 'package:permission_handler/permission_handler.dart' as pHandler; | ||||
| import 'Prefs.dart'; | import 'Prefs.dart'; | ||||
| import 'package:oauth2/oauth2.dart' as oauth2; | import 'package:oauth2/oauth2.dart' as oauth2; | ||||
| // import 'package:flutter_logs/flutter_logs.dart'; | |||||
| class Util{ | class Util{ | ||||
| bool tokenValidity = true; | bool tokenValidity = true; | ||||
| bool useLocal = false; | bool useLocal = false; | ||||
| getMinAppVer()async{ | |||||
| var req = await JsonDataGetRaw(null,'${prefs.getString(keyClass.hostAddress)}/app/min_ver/'); | |||||
| return req; | |||||
| } | |||||
| launchURL(String url) async { | |||||
| if (await canLaunch(url)) { | |||||
| await launch(url); | |||||
| } else { | |||||
| throw 'Could not launch $url'; | |||||
| } | |||||
| } | |||||
| updateDialog(context)async{ | |||||
| WidgetsBinding.instance.addPostFrameCallback((_) async { | |||||
| await showDialog( | |||||
| context: context, | |||||
| builder: (BuildContext context) { | |||||
| return WillPopScope( | |||||
| onWillPop: (){ | |||||
| return null; | |||||
| }, | |||||
| child: AlertDialog( | |||||
| title: Text('App version is too old'), | |||||
| content: Text('Please update the application'), | |||||
| actions: <Widget>[ | |||||
| TextButton( | |||||
| child: Text('Update',style: TextStyle(color: Colors.blue),), | |||||
| onPressed: ()async{ | |||||
| try{ | |||||
| AppUpdateInfo _updateInfo; | |||||
| _updateInfo = await InAppUpdate.checkForUpdate(); | |||||
| if(_updateInfo?.updateAvailability == 2){ | |||||
| await InAppUpdate.performImmediateUpdate(); | |||||
| } | |||||
| else throw {"message":"manual Update"}; | |||||
| // util.showFlushbar(context, "${_updateInfo?.updateAvailable}"); | |||||
| } | |||||
| catch(e){ | |||||
| await Future.delayed(Duration(milliseconds: 500)); | |||||
| await launchURL('https://play.google.com/store/apps/details?id=com.thamringroup.unitstocks'); | |||||
| // util.showFlushbar(context, "Failed checking updates. $e."); | |||||
| } | |||||
| }, | |||||
| ), | |||||
| ], | |||||
| ), | |||||
| ); | |||||
| }, | |||||
| barrierDismissible: false, | |||||
| ); | |||||
| }); | |||||
| } | |||||
| getOauth2Client() async { | getOauth2Client() async { | ||||
| bool resetClient = false; | bool resetClient = false; | ||||
| oauth2.Credentials restData = (prefs.getString(keyClass.rest_data)!=null&&prefs.getString(keyClass.rest_data).contains("accessToken"))?oauth2.Credentials.fromJson(prefs.getString(keyClass.rest_data)):null; | oauth2.Credentials restData = (prefs.getString(keyClass.rest_data)!=null&&prefs.getString(keyClass.rest_data).contains("accessToken"))?oauth2.Credentials.fromJson(prefs.getString(keyClass.rest_data)):null; | ||||
| @@ -101,6 +159,64 @@ class Util{ | |||||
| } | } | ||||
| } | } | ||||
| JsonDataGetRaw(Map jsonData, String url,{secure:true,timeout:false}) async{ | |||||
| var httpClient; | |||||
| const JsonDecoder decoder = const JsonDecoder(); | |||||
| var headers = {'Content-type': 'application/json'}; | |||||
| try { | |||||
| var response; | |||||
| if(secure) { | |||||
| httpClient = await getOauth2Client(); | |||||
| oauth2.Credentials tokenRestData = oauth2.Credentials.fromJson(prefs.getString(keyClass.rest_data)); | |||||
| headers["Authorization"] = | |||||
| "bearer ${tokenRestData.accessToken}"; | |||||
| } | |||||
| else { | |||||
| httpClient = http; | |||||
| } | |||||
| if(jsonData!= null&&jsonData.length!=0) { | |||||
| url = url + '?'; | |||||
| for (var i in jsonData.keys) { | |||||
| url = url + i + '=' + jsonData[i] + '&'; | |||||
| } | |||||
| url = url.substring(0, url.length - 1); | |||||
| } | |||||
| if (timeout) | |||||
| response = await httpClient.get( | |||||
| Uri.parse(url), headers: headers, | |||||
| ).timeout(const Duration(seconds: 10)); | |||||
| else | |||||
| response = await httpClient.get( | |||||
| Uri.parse(url), headers: {'Content-type': 'application/json'}, | |||||
| ); | |||||
| if(response.statusCode == 403) tokenValidity = false; | |||||
| if(htmlErrorTitle(response.body.toString())!=""){ | |||||
| return {"STATUS":(response.statusCode != 200)?0:1,"DATA":htmlErrorTitle(response.body.toString())}; | |||||
| } | |||||
| final Map data = decoder.convert(response.body); | |||||
| try{data["DATA"] = decoder.convert(data["DATA"]);}catch(e){} | |||||
| return data; | |||||
| } on TimeoutException catch(e){ | |||||
| return {"STATUS":0,"DATA":"Request Timeout"}; | |||||
| } | |||||
| on HandshakeException catch(e){ | |||||
| if(useLocal){ | |||||
| return {"STATUS":0,"DATA":"Not Connected to Server. $e"}; | |||||
| } | |||||
| else{ | |||||
| useLocal = true; | |||||
| http = IOClient(HttpClient(context: clientContext)); | |||||
| return await JsonDataPostRaw(jsonData, url,timeout:timeout,secure: secure); | |||||
| } | |||||
| } | |||||
| on Exception catch(exception){ | |||||
| print(url); | |||||
| // Toast("Not Connected to Server", Colors.red); | |||||
| return {"STATUS":0,"DATA":"Not Connected to Server. $exception"}; | |||||
| } | |||||
| } | |||||
| JsonDataPutRaw(Map jsonData, String url,{secure:true,timeout:false}) async{ | JsonDataPutRaw(Map jsonData, String url,{secure:true,timeout:false}) async{ | ||||
| var httpClient; | var httpClient; | ||||
| const JsonDecoder decoder = const JsonDecoder(); | const JsonDecoder decoder = const JsonDecoder(); | ||||
| @@ -154,12 +270,13 @@ class Util{ | |||||
| } | } | ||||
| htmlErrorTitle(String html){ | htmlErrorTitle(String html){ | ||||
| // FlutterLogs.logInfo("TAG", "subTag", html); | |||||
| try{ | try{ | ||||
| if(html.contains('<title>')) { | if(html.contains('<title>')) { | ||||
| String titleElement = html.substring(html.indexOf("<title>")+7,html.indexOf("<\/title>")); | String titleElement = html.substring(html.indexOf("<title>")+7,html.indexOf("<\/title>")); | ||||
| return titleElement; | return titleElement; | ||||
| } | } | ||||
| else return ''; | |||||
| return ''; | |||||
| } | } | ||||
| catch(e){ | catch(e){ | ||||
| return ''; | return ''; | ||||
| @@ -20,16 +20,25 @@ class file_Trans_Handler { | |||||
| StreamController _progress = new StreamController<double>(); | StreamController _progress = new StreamController<double>(); | ||||
| Stream<double> get progress =>_progress.stream; | Stream<double> get progress =>_progress.stream; | ||||
| bool useLocal = false; | bool useLocal = false; | ||||
| var httpClient; | |||||
| Client httpClient; | |||||
| downloadFile(String fileName,String link) async { | downloadFile(String fileName,String link) async { | ||||
| StreamedResponse _response; | StreamedResponse _response; | ||||
| List<int> _bytes = []; | List<int> _bytes = []; | ||||
| int _total = 0; | int _total = 0; | ||||
| httpClient = await util.getOauth2Client(); | httpClient = await util.getOauth2Client(); | ||||
| print('Start Download'); | |||||
| print('Start Download $link'); | |||||
| _progress.add(null); | _progress.add(null); | ||||
| try { | try { | ||||
| void mainThrow(e){ | |||||
| cancel(); | |||||
| _progress.add(-1.0); | |||||
| if(util.htmlErrorTitle(e.message??e)!=""){ | |||||
| _error = util.htmlErrorTitle(e.message??e); | |||||
| } | |||||
| else _error = e.message??e; | |||||
| // print("mainthrow $_error"); | |||||
| } | |||||
| Request req = new Request('GET', Uri.parse(link)); | Request req = new Request('GET', Uri.parse(link)); | ||||
| // req.headers = ''; | // req.headers = ''; | ||||
| @@ -48,38 +57,42 @@ class file_Trans_Handler { | |||||
| _progress.add(((_bytes.length / _total))); | _progress.add(((_bytes.length / _total))); | ||||
| } | } | ||||
| else{ | else{ | ||||
| // print("masuk error"); | |||||
| // this.cancel(); | |||||
| // cancel(); //stop stream | |||||
| String resString = utf8.decode(value); | String resString = utf8.decode(value); | ||||
| if(util.htmlErrorTitle(resString)!=""){ | |||||
| _error = util.htmlErrorTitle(resString); | |||||
| } | |||||
| _error = resString; | |||||
| // if(util.htmlErrorTitle(resString)!=""){ | |||||
| // _error = util.htmlErrorTitle(resString); | |||||
| // } | |||||
| // else | |||||
| // _error = resString; | |||||
| mainThrow(Exception(resString)); | |||||
| } | } | ||||
| }) | |||||
| ..onDone(() async { | |||||
| if(_error==''){ | |||||
| _progress.add(0.0); | |||||
| print('Finish Download'); | |||||
| final file = File( | |||||
| "${(await getApplicationDocumentsDirectory()).path}/$fileName"); | |||||
| await file.writeAsBytes(_bytes); | |||||
| _path = file.path; | |||||
| } | |||||
| else{ | |||||
| print('Error Download, $_error'); | |||||
| _progress.add(-1.0); | |||||
| } | |||||
| }) | |||||
| ..onError((e) async { | |||||
| print('Error Download, $e'); | |||||
| _progress.add(-1.0); | |||||
| _error = e.toString(); | |||||
| }); | |||||
| },onDone:() async { | |||||
| if(_error==''){ | |||||
| _progress.add(0.0); | |||||
| print('Finish Download'); | |||||
| final file = File( | |||||
| "${(await getApplicationDocumentsDirectory()).path}/$fileName"); | |||||
| await file.writeAsBytes(_bytes); | |||||
| _path = file.path; | |||||
| } | |||||
| else{ | |||||
| mainThrow(_error); | |||||
| } | |||||
| } ,onError: (e) async { | |||||
| mainThrow(e); | |||||
| },cancelOnError: true); | |||||
| } | } | ||||
| on HandshakeException catch(e){ | on HandshakeException catch(e){ | ||||
| cancel(); | |||||
| if(useLocal){ | if(useLocal){ | ||||
| print('Error Download, $e'); | |||||
| // print('Error Download 3, $e'); | |||||
| _progress.add(-1.0); | _progress.add(-1.0); | ||||
| _error = e.toString(); | |||||
| if(util.htmlErrorTitle(e.message ?? e)!=""){ | |||||
| _error = util.htmlErrorTitle(e.message ?? e); | |||||
| } | |||||
| else _error = e.toString(); | |||||
| } | } | ||||
| else{ | else{ | ||||
| useLocal = true; | useLocal = true; | ||||
| @@ -88,9 +101,12 @@ class file_Trans_Handler { | |||||
| } | } | ||||
| } | } | ||||
| catch(e){ | catch(e){ | ||||
| print('Error Download, $e'); | |||||
| cancel(); | |||||
| _progress.add(-1.0); | _progress.add(-1.0); | ||||
| _error = e.toString(); | |||||
| if(util.htmlErrorTitle(e.message??e)!=""){ | |||||
| _error = util.htmlErrorTitle(e.message??e); | |||||
| } | |||||
| else _error = e.toString(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -102,11 +118,12 @@ class file_Trans_Handler { | |||||
| String mimeType = 'application/vnd.sqlite3'; | String mimeType = 'application/vnd.sqlite3'; | ||||
| if(file.existsSync()){ | if(file.existsSync()){ | ||||
| Uint8List byte = file.readAsBytesSync(); | Uint8List byte = file.readAsBytesSync(); | ||||
| // print("file size ${file.lengthSync()/1024}"); | |||||
| try{ | try{ | ||||
| var _response = await httpClient.put( | var _response = await httpClient.put( | ||||
| Uri.parse(link), headers: {"cabangId":cabang_id,"company":company,'Content-type': mimeType,'Authorization':'Bearer ${tokenRestData.accessToken}'}, | Uri.parse(link), headers: {"cabangId":cabang_id,"company":company,'Content-type': mimeType,'Authorization':'Bearer ${tokenRestData.accessToken}'}, | ||||
| body: byte); | |||||
| body: byte).onError((error, stackTrace){ | |||||
| return new Response("Internal Server Error", 400); | |||||
| }); | |||||
| print('File send ${file.lengthSync()/1024} KB'); | print('File send ${file.lengthSync()/1024} KB'); | ||||
| if(_response.statusCode!=200){ | if(_response.statusCode!=200){ | ||||
| if(util.htmlErrorTitle(_response.body.toString())!=""){ | if(util.htmlErrorTitle(_response.body.toString())!=""){ | ||||
| @@ -241,7 +258,7 @@ class file_Trans_Handler { | |||||
| } | } | ||||
| cancel()async{ | cancel()async{ | ||||
| http?.close(); | |||||
| // http?.close(); | |||||
| await dlulStream?.cancel(); | await dlulStream?.cancel(); | ||||
| _progress?.close(); | _progress?.close(); | ||||
| } | } | ||||
| @@ -1,7 +1,10 @@ | |||||
| import 'dart:async'; | import 'dart:async'; | ||||
| import 'dart:io'; | import 'dart:io'; | ||||
| import 'package:flutter/foundation.dart'; | |||||
| import 'package:flutter/rendering.dart'; | import 'package:flutter/rendering.dart'; | ||||
| import 'package:flutter/widgets.dart'; | import 'package:flutter/widgets.dart'; | ||||
| import 'package:in_app_update/in_app_update.dart'; | |||||
| import 'package:package_info/package_info.dart'; | |||||
| import 'package:path/path.dart'; | import 'package:path/path.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
| @@ -108,7 +111,7 @@ class _HomePageState extends State<HomePage> { | |||||
| if(prefs.getString(keyClass.stock_id) == null) | if(prefs.getString(keyClass.stock_id) == null) | ||||
| { | { | ||||
| valueTab value = await DBHelper.database.getValue(keyClass.stock_id); | valueTab value = await DBHelper.database.getValue(keyClass.stock_id); | ||||
| await prefs.setString(keyClass.stock_id, value.value); | |||||
| if(value != null)await prefs.setString(keyClass.stock_id, value.value); | |||||
| } | } | ||||
| String stock_taking_id = prefs.getString(keyClass.stock_id); | String stock_taking_id = prefs.getString(keyClass.stock_id); | ||||
| if(company!=null&&stock_taking_id!=null){ | if(company!=null&&stock_taking_id!=null){ | ||||
| @@ -128,6 +131,63 @@ class _HomePageState extends State<HomePage> { | |||||
| loadState(); | loadState(); | ||||
| lastDownload = prefs.getString(keyClass.lastDownload)??''; | lastDownload = prefs.getString(keyClass.lastDownload)??''; | ||||
| lastUpload = prefs.getString(keyClass.lastUpload)??''; | lastUpload = prefs.getString(keyClass.lastUpload)??''; | ||||
| WidgetsBinding.instance.addPostFrameCallback((_) async { | |||||
| await _check_Update(); | |||||
| }); | |||||
| } | |||||
| _check_Update()async{ | |||||
| if(defaultTargetPlatform == TargetPlatform.android){ | |||||
| try{ | |||||
| final PackageInfo info = await PackageInfo.fromPlatform(); | |||||
| AppUpdateInfo _updateInfo = await InAppUpdate.checkForUpdate(); | |||||
| String currentVersion = info.version.trim(); | |||||
| String latestversion = '0.0.0'; | |||||
| var result = await util.getMinAppVer(); | |||||
| if(result['STATUS']==1){ | |||||
| latestversion = result['DATA']; | |||||
| } | |||||
| var current = currentVersion.split('.'); | |||||
| var latest = latestversion.split('.'); | |||||
| if(int.parse(current[0])==int.parse(latest[0])){ | |||||
| if(int.parse(current[1])==int.parse(latest[1])){ | |||||
| if(int.parse(current[2])<int.parse(latest[2])) { | |||||
| await util.updateDialog(context); | |||||
| } | |||||
| else{ | |||||
| if(_updateInfo?.updateAvailability == 2) { | |||||
| await InAppUpdate.startFlexibleUpdate(); | |||||
| await InAppUpdate.completeFlexibleUpdate(); | |||||
| } | |||||
| } | |||||
| } | |||||
| else if(int.parse(current[1])<int.parse(latest[1])) { | |||||
| await util.updateDialog(context); | |||||
| // await InAppUpdate.performImmediateUpdate(); | |||||
| } | |||||
| else{ | |||||
| if(_updateInfo?.updateAvailability == 2) { | |||||
| await InAppUpdate.startFlexibleUpdate(); | |||||
| await InAppUpdate.completeFlexibleUpdate(); | |||||
| } | |||||
| } | |||||
| } | |||||
| else if(int.parse(current[0])<int.parse(latest[0])) { | |||||
| await util.updateDialog(context); | |||||
| // await InAppUpdate.performImmediateUpdate(); | |||||
| } | |||||
| else{ | |||||
| if(_updateInfo?.updateAvailability == 2 ) { | |||||
| await InAppUpdate.startFlexibleUpdate(); | |||||
| await InAppUpdate.completeFlexibleUpdate(); | |||||
| } | |||||
| } | |||||
| } | |||||
| catch(e){ | |||||
| print("error Update $e"); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| changeCabang(context)async{ | changeCabang(context)async{ | ||||
| @@ -715,7 +775,7 @@ class _HomePageState extends State<HomePage> { | |||||
| setState(() { | setState(() { | ||||
| isLoading = false; | isLoading = false; | ||||
| }); | }); | ||||
| util.showFlushbar(context,'Data download error',color: Colors.red); | |||||
| util.showFlushbar(context,trans.error??'Data download error',color: Colors.red); | |||||
| } | } | ||||
| }); | }); | ||||
| // Navigator.popUntil(context, ModalRoute.withName('/home')); | // Navigator.popUntil(context, ModalRoute.withName('/home')); | ||||
| @@ -930,7 +990,7 @@ class _HomePageState extends State<HomePage> { | |||||
| )); | )); | ||||
| if(result){ | if(result){ | ||||
| util.showLoading(context); | util.showLoading(context); | ||||
| var unpack = await util.JsonDataPutRaw({"cabangId":prefs.getString(keyClass.cabang_id),"company":prefs.getString(keyClass.company),"dbPath":prefs.getString(keyClass.targetProccess)}, '${prefs.getString(keyClass.hostAddress)}/stock_taking/add_collection/'); | |||||
| var unpack = await util.JsonDataPutRaw({"userId":prefs.getString(keyClass.loginId),"cabangId":prefs.getString(keyClass.cabang_id),"company":prefs.getString(keyClass.company),"dbPath":prefs.getString(keyClass.targetProccess)}, '${prefs.getString(keyClass.hostAddress)}/stock_taking/add_collection/'); | |||||
| Navigator.pop(context); | Navigator.pop(context); | ||||
| util.showFlushbar(context, unpack['DATA'],color:(unpack['STATUS']!=1)?Colors.red:Colors.grey); | util.showFlushbar(context, unpack['DATA'],color:(unpack['STATUS']!=1)?Colors.red:Colors.grey); | ||||
| if(unpack['STATUS']==1){ | if(unpack['STATUS']==1){ | ||||
| @@ -25,13 +25,13 @@ class _LoginPageState extends State<LoginPage> { | |||||
| var result = await util.JsonDataPostRaw({"User":userCon.text,"Pass":passCon.text}, '${prefs.getString(keyClass.hostAddress)}/user//login/'); | var result = await util.JsonDataPostRaw({"User":userCon.text,"Pass":passCon.text}, '${prefs.getString(keyClass.hostAddress)}/user//login/'); | ||||
| if(result['STATUS']==1){ | if(result['STATUS']==1){ | ||||
| prefs.setString(keyClass.loginId, result['DATA'][keyClass.loginId.toLowerCase()]); | prefs.setString(keyClass.loginId, result['DATA'][keyClass.loginId.toLowerCase()]); | ||||
| print("user id ${result['DATA'][keyClass.loginId.toLowerCase()]}"); | |||||
| prefs.setString(keyClass.company, result['DATA'][keyClass.company.toLowerCase()]); | prefs.setString(keyClass.company, result['DATA'][keyClass.company.toLowerCase()]); | ||||
| prefs.setBool(keyClass.logged_in, true); | prefs.setBool(keyClass.logged_in, true); | ||||
| var cabangList = await util.JsonDataPostRaw({"company":prefs.getString(keyClass.company),"User":prefs.getString(keyClass.loginId)}, '${prefs.getString(keyClass.hostAddress)}/user/cabangs/'); | var cabangList = await util.JsonDataPostRaw({"company":prefs.getString(keyClass.company),"User":prefs.getString(keyClass.loginId)}, '${prefs.getString(keyClass.hostAddress)}/user/cabangs/'); | ||||
| Navigator.pop(context); | Navigator.pop(context); | ||||
| if(cabangList['STATUS']==1){ | if(cabangList['STATUS']==1){ | ||||
| cabangDrop = cabangList['DATA']; | cabangDrop = cabangList['DATA']; | ||||
| print(cabangList); | |||||
| selected = cabangDrop[0]['RETURN_VALUE']; | selected = cabangDrop[0]['RETURN_VALUE']; | ||||
| setState(() { | setState(() { | ||||
| }); | }); | ||||
| @@ -11,6 +11,7 @@ import 'unit_details.dart'; | |||||
| import 'package:shared_preferences/shared_preferences.dart'; | import 'package:shared_preferences/shared_preferences.dart'; | ||||
| import 'package:location/location.dart'; | import 'package:location/location.dart'; | ||||
| import 'Util/Util.dart'; | import 'Util/Util.dart'; | ||||
| import 'package:flutter_logs/flutter_logs.dart'; | |||||
| SharedPreferences prefs; | SharedPreferences prefs; | ||||
| @@ -33,6 +34,21 @@ void main() async{ | |||||
| await registerCert(); | await registerCert(); | ||||
| if( prefs.getString(keyClass.hostAddress) ==null)await prefs.setString(keyClass.hostAddress, "https://tbg.thamringroup.web.id/ords/tbs/unit/v1"); | if( prefs.getString(keyClass.hostAddress) ==null)await prefs.setString(keyClass.hostAddress, "https://tbg.thamringroup.web.id/ords/tbs/unit/v1"); | ||||
| await prefs.setString(keyClass.restTokenAddress, "https://tbg.thamringroup.web.id/ords/tbs/oauth/token"); | await prefs.setString(keyClass.restTokenAddress, "https://tbg.thamringroup.web.id/ords/tbs/oauth/token"); | ||||
| await FlutterLogs.initLogs( | |||||
| logLevelsEnabled: [ | |||||
| LogLevel.INFO, | |||||
| LogLevel.WARNING, | |||||
| LogLevel.ERROR, | |||||
| LogLevel.SEVERE | |||||
| ], | |||||
| timeStampFormat: TimeStampFormat.TIME_FORMAT_READABLE, | |||||
| directoryStructure: DirectoryStructure.FOR_DATE, | |||||
| logTypesEnabled: ["device","network","errors"], | |||||
| logFileExtension: LogFileExtension.LOG, | |||||
| logsWriteDirectoryName: "MyLogs", | |||||
| logsExportDirectoryName: "MyLogs/Exported", | |||||
| debugFileOperations: true, | |||||
| isDebuggable: true); | |||||
| SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) | SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) | ||||
| .then((_) { | .then((_) { | ||||
| runApp(new MyApp()); | runApp(new MyApp()); | ||||
| @@ -1,7 +1,6 @@ | |||||
| import 'dart:async'; | import 'dart:async'; | ||||
| import 'dart:typed_data'; | import 'dart:typed_data'; | ||||
| import 'package:flutter/services.dart'; | import 'package:flutter/services.dart'; | ||||
| import 'main.dart'; | import 'main.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
| @@ -10,7 +9,7 @@ import 'Util/DBHelper.dart'; | |||||
| import 'Util/UnitModel.dart'; | import 'Util/UnitModel.dart'; | ||||
| import 'Util/Util.dart'; | import 'Util/Util.dart'; | ||||
| import 'Util/photo_viewer.dart'; | import 'Util/photo_viewer.dart'; | ||||
| import 'package:barcode_scan/barcode_scan.dart'; | |||||
| import 'package:barcode_scan2/barcode_scan2.dart'; | |||||
| class Stocking extends StatefulWidget { | class Stocking extends StatefulWidget { | ||||
| Stocking({Key key}) : super(key: key); | Stocking({Key key}) : super(key: key); | ||||
| @@ -20,7 +19,6 @@ class Stocking extends StatefulWidget { | |||||
| } | } | ||||
| class _StockingState extends State<Stocking> with SingleTickerProviderStateMixin { | class _StockingState extends State<Stocking> with SingleTickerProviderStateMixin { | ||||
| // List<insertUnit> Units = []; | |||||
| List<Unit> unitsRef = []; | List<Unit> unitsRef = []; | ||||
| List<blobImage> Blobs = []; | List<blobImage> Blobs = []; | ||||
| List<blobImage> BlobsRef = []; | List<blobImage> BlobsRef = []; | ||||
| @@ -28,7 +26,6 @@ class _StockingState extends State<Stocking> with SingleTickerProviderStateMixin | |||||
| Util util = new Util(); | Util util = new Util(); | ||||
| int totalUnit = 0; | int totalUnit = 0; | ||||
| final search_controller = new TextEditingController(); | final search_controller = new TextEditingController(); | ||||
| // TabController _tabBarcontroller; | |||||
| bool hideAppbar = false; | bool hideAppbar = false; | ||||
| String search = ''; | String search = ''; | ||||
| @@ -24,6 +24,7 @@ class _UnitDetailsState extends State<UnitDetails> { | |||||
| final mesinController = TextEditingController(); | final mesinController = TextEditingController(); | ||||
| final tahunController = TextEditingController(); | final tahunController = TextEditingController(); | ||||
| final stateController = TextEditingController(); | final stateController = TextEditingController(); | ||||
| final channelController = TextEditingController(); | |||||
| // insertUnit _unitDetails; | // insertUnit _unitDetails; | ||||
| bool isChanged = false; | bool isChanged = false; | ||||
| @@ -39,37 +40,6 @@ class _UnitDetailsState extends State<UnitDetails> { | |||||
| // List<Unit> allUnits = []; | // List<Unit> allUnits = []; | ||||
| loadUnitDetails(context)async{ | loadUnitDetails(context)async{ | ||||
| // if(widget.idInsert!=null){ | |||||
| //// var result = await DBHelper.database.getInsertUnit(widget.idInsert); | |||||
| //// if(result!=null){ | |||||
| //// _unitDetails = result; | |||||
| //// mesinController.text = _unitDetails.mesin; | |||||
| //// tipeController.text= _unitDetails.tipe; | |||||
| //// rangkaController.text = _unitDetails.rangka; | |||||
| //// colorController.text = _unitDetails.warna; | |||||
| //// tahunController.text = _unitDetails.tahun; | |||||
| //// kodeController.text = _unitDetails.kode; | |||||
| //// stateController.text = _unitDetails.state; | |||||
| //// | |||||
| //// result = await DBHelper.database.getAllBlobImage(_unitDetails.id); | |||||
| //// if(result!=null){ | |||||
| //// for(int i =0; i<result.length;i++){ | |||||
| //// images.add(result[i].blob_file); | |||||
| //// blobIds.add(result[i].blob_id); | |||||
| //// jenisImages.add(result[i].jenis); | |||||
| //// } | |||||
| //// } | |||||
| //// setState(() { | |||||
| //// }); | |||||
| //// } | |||||
| //// else{ | |||||
| //// util.showFlushbar(context, 'Unit can\'t be found'); | |||||
| //// } | |||||
| // await DBHelper.database.closeDb(); | |||||
| // } | |||||
| // else{ | |||||
| // var result = await DBHelper.database.getUnitdetailMaster(widget.idRef); | |||||
| // if (result!=null){ | |||||
| _currentUnit = widget.unit; | _currentUnit = widget.unit; | ||||
| tipeController.text= _currentUnit.tipe; | tipeController.text= _currentUnit.tipe; | ||||
| rangkaController.text = _currentUnit.rangka; | rangkaController.text = _currentUnit.rangka; | ||||
| @@ -78,8 +48,7 @@ class _UnitDetailsState extends State<UnitDetails> { | |||||
| mesinController.text = _currentUnit.mesin; | mesinController.text = _currentUnit.mesin; | ||||
| tahunController.text = _currentUnit.tahun; | tahunController.text = _currentUnit.tahun; | ||||
| stateController.text = _currentUnit.state; | stateController.text = _currentUnit.state; | ||||
| // } | |||||
| // } | |||||
| channelController.text = (_currentUnit.channel==null||_currentUnit.channel==""||_currentUnit.channel=="null")?'-':_currentUnit.channel; | |||||
| await loadBlob(); | await loadBlob(); | ||||
| } | } | ||||
| // loadTipe() async{ | // loadTipe() async{ | ||||
| @@ -606,6 +575,21 @@ class _UnitDetailsState extends State<UnitDetails> { | |||||
| Row( | Row( | ||||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
| children: <Widget>[ | children: <Widget>[ | ||||
| Text('Channel : '), | |||||
| Expanded( | |||||
| child: TextFormField( | |||||
| enabled: false, | |||||
| style: TextStyle(color: Colors.grey), | |||||
| controller: channelController, | |||||
| decoration: InputDecoration.collapsed(hintText: null), | |||||
| ), | |||||
| ), | |||||
| ], | |||||
| ), | |||||
| Divider(), | |||||
| Row( | |||||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||||
| children: <Widget>[ | |||||
| TextButton( | TextButton( | ||||
| style: TextButton.styleFrom( | style: TextButton.styleFrom( | ||||
| backgroundColor: Colors.green, | backgroundColor: Colors.green, | ||||
| @@ -22,13 +22,13 @@ packages: | |||||
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "2.8.1" | version: "2.8.1" | ||||
| barcode_scan: | |||||
| barcode_scan2: | |||||
| dependency: "direct main" | dependency: "direct main" | ||||
| description: | description: | ||||
| name: barcode_scan | |||||
| name: barcode_scan2 | |||||
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "3.0.1" | |||||
| version: "4.1.4" | |||||
| boolean_selector: | boolean_selector: | ||||
| dependency: transitive | dependency: transitive | ||||
| description: | description: | ||||
| @@ -112,7 +112,7 @@ packages: | |||||
| name: fixnum | name: fixnum | ||||
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "0.10.11" | |||||
| version: "1.0.0" | |||||
| flushbar: | flushbar: | ||||
| dependency: "direct main" | dependency: "direct main" | ||||
| description: | description: | ||||
| @@ -132,6 +132,13 @@ packages: | |||||
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "0.9.2" | version: "0.9.2" | ||||
| flutter_logs: | |||||
| dependency: "direct dev" | |||||
| description: | |||||
| name: flutter_logs | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.1.4" | |||||
| flutter_plugin_android_lifecycle: | flutter_plugin_android_lifecycle: | ||||
| dependency: transitive | dependency: transitive | ||||
| description: | description: | ||||
| @@ -176,7 +183,7 @@ packages: | |||||
| name: image_picker | name: image_picker | ||||
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "0.8.4+2" | |||||
| version: "0.8.4+4" | |||||
| image_picker_for_web: | image_picker_for_web: | ||||
| dependency: transitive | dependency: transitive | ||||
| description: | description: | ||||
| @@ -191,6 +198,13 @@ packages: | |||||
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "2.4.1" | version: "2.4.1" | ||||
| in_app_update: | |||||
| dependency: "direct main" | |||||
| description: | |||||
| name: in_app_update | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.0" | |||||
| intl: | intl: | ||||
| dependency: "direct main" | dependency: "direct main" | ||||
| description: | description: | ||||
| @@ -247,6 +261,13 @@ packages: | |||||
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "2.0.0" | version: "2.0.0" | ||||
| package_info: | |||||
| dependency: "direct main" | |||||
| description: | |||||
| name: package_info | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.2" | |||||
| path: | path: | ||||
| dependency: transitive | dependency: transitive | ||||
| description: | description: | ||||
| @@ -260,7 +281,21 @@ packages: | |||||
| name: path_provider | name: path_provider | ||||
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "2.0.5" | |||||
| version: "2.0.7" | |||||
| path_provider_android: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: path_provider_android | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.9" | |||||
| path_provider_ios: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: path_provider_ios | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.7" | |||||
| path_provider_linux: | path_provider_linux: | ||||
| dependency: transitive | dependency: transitive | ||||
| description: | description: | ||||
| @@ -295,7 +330,7 @@ packages: | |||||
| name: permission_handler | name: permission_handler | ||||
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "8.2.2" | |||||
| version: "8.3.0" | |||||
| permission_handler_platform_interface: | permission_handler_platform_interface: | ||||
| dependency: transitive | dependency: transitive | ||||
| description: | description: | ||||
| @@ -344,13 +379,27 @@ packages: | |||||
| name: protobuf | name: protobuf | ||||
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "1.0.1" | |||||
| version: "2.0.1" | |||||
| shared_preferences: | shared_preferences: | ||||
| dependency: "direct main" | dependency: "direct main" | ||||
| description: | description: | ||||
| name: shared_preferences | name: shared_preferences | ||||
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "2.0.9" | |||||
| shared_preferences_android: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: shared_preferences_android | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.9" | |||||
| shared_preferences_ios: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: shared_preferences_ios | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.8" | version: "2.0.8" | ||||
| shared_preferences_linux: | shared_preferences_linux: | ||||
| dependency: transitive | dependency: transitive | ||||
| @@ -462,6 +511,62 @@ packages: | |||||
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "1.3.0" | version: "1.3.0" | ||||
| url_launcher: | |||||
| dependency: "direct main" | |||||
| description: | |||||
| name: url_launcher | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "6.0.17" | |||||
| url_launcher_android: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: url_launcher_android | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "6.0.13" | |||||
| url_launcher_ios: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: url_launcher_ios | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "6.0.13" | |||||
| url_launcher_linux: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: url_launcher_linux | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.2" | |||||
| url_launcher_macos: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: url_launcher_macos | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.2" | |||||
| url_launcher_platform_interface: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: url_launcher_platform_interface | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.4" | |||||
| url_launcher_web: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: url_launcher_web | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.5" | |||||
| url_launcher_windows: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: url_launcher_windows | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.2" | |||||
| vector_math: | vector_math: | ||||
| dependency: transitive | dependency: transitive | ||||
| description: | description: | ||||
| @@ -13,24 +13,28 @@ dependencies: | |||||
| # The following adds the Cupertino Icons font to your application. | # The following adds the Cupertino Icons font to your application. | ||||
| # Use with the CupertinoIcons class for iOS style icons. | # Use with the CupertinoIcons class for iOS style icons. | ||||
| cupertino_icons: | cupertino_icons: | ||||
| image_picker: ^0.8.4+2 | |||||
| image_picker: ^0.8.4+4 | |||||
| photo_view: ^0.13.0 | photo_view: ^0.13.0 | ||||
| sqflite: ^2.0.0+4 | sqflite: ^2.0.0+4 | ||||
| path_provider: ^2.0.5 | |||||
| path_provider: ^2.0.7 | |||||
| flushbar: ^1.10.4 | flushbar: ^1.10.4 | ||||
| http: ^0.13.4 | http: ^0.13.4 | ||||
| intl: ^0.17.0 | intl: ^0.17.0 | ||||
| shared_preferences: ^2.0.8 | |||||
| shared_preferences: ^2.0.9 | |||||
| location: ^4.3.0 | location: ^4.3.0 | ||||
| # path: 'local_plugin/location-3.0.2' | # path: 'local_plugin/location-3.0.2' | ||||
| permission_handler: ^8.2.2 | |||||
| permission_handler: ^8.3.0 | |||||
| # app_settings: | # app_settings: | ||||
| # autocomplete_textfield: | # autocomplete_textfield: | ||||
| barcode_scan: ^3.0.1 | |||||
| barcode_scan2: ^4.1.4 | |||||
| oauth2: ^2.0.0 | oauth2: ^2.0.0 | ||||
| in_app_update: ^2.0.0 | |||||
| url_launcher: ^6.0.17 | |||||
| package_info: ^2.0.2 | |||||
| dev_dependencies: | dev_dependencies: | ||||
| flutter_logs: | |||||
| flutter_launcher_icons: | flutter_launcher_icons: | ||||
| flutter_test: | flutter_test: | ||||
| sdk: flutter | sdk: flutter | ||||