diff --git a/lib/core/routes/plausible_tracker.dart b/lib/core/routes/plausible_tracker.dart index 716d04f..0ef7518 100644 --- a/lib/core/routes/plausible_tracker.dart +++ b/lib/core/routes/plausible_tracker.dart @@ -4,19 +4,20 @@ import 'dart:convert'; /// Plausible class. Use the constructor to set the parameters. class PlausibleTracker { - /// The url of your plausible server e.g. https://plausible.io String serverUrl; String userAgent; String domain; String screenWidth; String xForwardedFor; - bool enabled = true; + bool enabled = false; /// Constructor - PlausibleTracker(this.serverUrl, this.domain, - {this.userAgent = "", - this.screenWidth = "", - this.xForwardedFor = "127.0.0.1"}); + PlausibleTracker( + {required this.serverUrl, + required this.domain, + required this.userAgent, + required this.screenWidth, + required this.xForwardedFor}); /// Post event to plausible Future event( @@ -75,6 +76,8 @@ class PlausibleTracker { /// check if plausible is UP Future hello() async { + this.enabled = false; + try { final client = HttpClient(); final request = await client.getUrl(Uri.parse(serverUrl + '/api/health')); @@ -88,7 +91,7 @@ class PlausibleTracker { final postgresStatus = json['postgres']; final sitesCacheStatus = json['sites_cache']; - return clickhouseStatus == 'ok' && + this.enabled = clickhouseStatus == 'ok' && postgresStatus == 'ok' && sitesCacheStatus == 'ok'; } @@ -98,6 +101,6 @@ class PlausibleTracker { } } - return false; + return this.enabled; } } diff --git a/lib/main.dart b/lib/main.dart index f7e743f..c676a9f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,6 +16,7 @@ import 'package:mobdr/cubit/language/initial_language.dart'; import 'package:mobdr/service/shared_prefs.dart'; import 'package:mobdr/ui/splash_screen.dart'; import 'package:mobdr/service/device_info.dart'; +import 'package:mobdr/service/package_info.dart'; import 'package:mobdr/service/directories.dart'; import 'package:mobdr/service/plausible.dart'; @@ -55,11 +56,18 @@ Future main() async { // get/set device informations await device_info_plus().initPlatformState(); + // get/set device informations + await package_info_plus().initPackageInfo(); + + // set device screenWidth/height + SharedPrefs().screenWidth = window.physicalSize.width; + SharedPrefs().screenHeight = window.physicalSize.height; + // initialize directories await directories().initDirectories(); /// initialize tracker plausible analytics - await PlausibleUtil.initializePlausible(window.physicalSize.width); + await PlausibleUtil.initializePlausible(); // initialize time zone current device SharedPrefs().timeZone = getCurrentTimeZone(DateTime.now()); @@ -69,14 +77,8 @@ Future main() async { 'https://mp4.ikksgroup.com/MobilePortal4/index.html#ajax/dashboard.html'; // track MobBR - LoggerUtil.dblog('LOG', 'MOBDR', 'Ouverture application', 0); - PlausibleUtil.addEvent( - name: 'access', - page: 'access', - referrer: 'referrerPage', - props: { - 'name': SharedPrefs().login, - }); + LoggerUtil.dblog( + 'LOG', 'MOBDR', 'Démarrage MobDR ' + SharedPrefs().appVersion, 0); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) .then((_) { @@ -112,20 +114,8 @@ class MyApp extends StatelessWidget with WidgetsBindingObserver { } else if (state == AppLifecycleState.resumed) { LoggerUtil.logNStackInfo("The application is resumed"); - if (PlausibleUtil.isPlausibleInitialized()) { - // check if plausible is UP - await PlausibleUtil.hello(); - - PlausibleUtil.addEvent( - name: 'access', - page: 'access', - referrer: 'referrerPage', - props: { - 'name': SharedPrefs().login, - }); - } else { - await PlausibleUtil.initializePlausible(window.physicalSize.width); - } + // check if plausible is up and running + await PlausibleUtil.checkPlausibleUp(); } else if (state == AppLifecycleState.inactive) { LoggerUtil.logNStackInfo("The application is inactive"); } else if (state == AppLifecycleState.detached) { diff --git a/lib/network/api_provider.dart b/lib/network/api_provider.dart index 9e7e60c..37b9c0d 100644 --- a/lib/network/api_provider.dart +++ b/lib/network/api_provider.dart @@ -1,5 +1,4 @@ import 'dart:io'; - import 'package:dio/dio.dart'; import 'dart:convert'; import 'package:crypto/crypto.dart'; @@ -118,25 +117,23 @@ class ApiProvider { Future login( String userName, String pinCode, String securityCode) async { var body = { - // TODO A REMPLIR - "application": "MobDR ", //+ ExeInfo(exeVersion) + "application": "MobDR " + SharedPrefs().appVersion, "pin_code": md5.convert(utf8.encode(pinCode)), - "security_code": securityCode, //sCodeSecurite - "langage": "fr", - "screenheight": "0", //SysYRes() - "screenwidth": "0", //SysXRes() + "security_code": securityCode, + "langage": SharedPrefs().langage, + "screenheight": SharedPrefs().screenHeight.truncate().toString(), + "screenwidth": SharedPrefs().screenWidth.truncate().toString(), "browser_name": "Natif", - "browser_version": "Application", - "engine_name": "Android", - "device_model": "", - "device_type": "mobile", //SysInfoAppareil(sysModele) WDM 23 - "device_vendor": "", //SysInfoAppareil(sysFabricant) WDM 23 + "browser_version": "Flutter", + "engine_name": SharedPrefs().systemName, + "device_model": SharedPrefs().deviceModel, + "device_type": SharedPrefs().deviceName, + "device_vendor": SharedPrefs().systemName, "ismobile": 1, - "engine_version": "", // SysVersionAndroid(sysVersionApiLevel) - "os_name": "", // SysVersionAndroid(sysVersionPlateForme) - "os_version": "", //SysVersionAndroid(sysVersionNumÈro) - "fingerprint": - "aa" // TODO: on peut mettre un fingerprint sur la version ou sur l'heure + "engine_version": SharedPrefs().systemName, + "os_name": SharedPrefs().systemName, + "os_version": SharedPrefs().systemVersion, + "fingerprint": SharedPrefs().fingerPrint }; Response response; @@ -150,8 +147,6 @@ class ApiProvider { '/guid', body); - print('res : ' + response.toString()); - switch (response.data['autorisation']) { case 1: diff --git a/lib/network/get_ip_address.dart b/lib/network/get_ip_address.dart index c9bbf9a..b1436f7 100644 --- a/lib/network/get_ip_address.dart +++ b/lib/network/get_ip_address.dart @@ -1,14 +1,23 @@ - import 'package:http/http.dart' as http; import 'dart:convert'; +import 'package:mobdr/service/logger_util.dart'; Future getPublicIPAddress() async { try { - var response = - await http.get(Uri.parse('https://api.ipify.org/?format=json')); + Stopwatch stopwatch = Stopwatch()..start(); + + var response = await http + .get(Uri.parse('https://api.bigdatacloud.net/data/client-ip')); + + stopwatch.stop(); + + // log tracker + LoggerUtil.dblog( + 'LOG', 'MOBDR', 'Get IPAddress', stopwatch.elapsedMilliseconds); + if (response.statusCode == 200) { var data = json.decode(response.body); - return data['ip']; + return data['ipString']; } } catch (e) { print(e.toString()); diff --git a/lib/service/device_info.dart b/lib/service/device_info.dart index 61dbb39..d164428 100644 --- a/lib/service/device_info.dart +++ b/lib/service/device_info.dart @@ -1,7 +1,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'dart:io'; - +import 'dart:convert'; +import 'package:crypto/crypto.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:mobdr/service/logger_util.dart'; import 'package:mobdr/service/shared_prefs.dart'; @@ -19,8 +20,27 @@ class device_info_plus { if (Platform.isAndroid) { deviceData = _readAndroidBuildData(await deviceInfoPlugin.androidInfo); + + // device related info + SharedPrefs().systemName = deviceData['brand']; + SharedPrefs().deviceModel = deviceData['model']; + SharedPrefs().deviceName = deviceData['device']; + SharedPrefs().systemVersion = deviceData['version.release']; + SharedPrefs().fingerPrint = md5 + .convert(utf8.encode("${deviceData['fingerprint']}")) + .toString(); } else if (Platform.isIOS) { deviceData = _readIosDeviceInfo(await deviceInfoPlugin.iosInfo); + + // device related info + SharedPrefs().systemName = deviceData['systemName']; + SharedPrefs().deviceModel = deviceData['model']; + SharedPrefs().deviceName = deviceData['name']; + SharedPrefs().systemVersion = deviceData['systemVersion']; + SharedPrefs().fingerPrint = md5 + .convert(utf8.encode( + "${deviceData['name']}${deviceData['model']}${deviceData['identifierForVendor']}${deviceData['systemVersion']}${deviceData['systemName']}${deviceData['localizedModel']}")) + .toString(); } else if (Platform.isLinux) { deviceData = _readLinuxDeviceInfo(await deviceInfoPlugin.linuxInfo); } else if (Platform.isMacOS) { @@ -198,10 +218,11 @@ class device_info_plus { } String buildUserAgent(Map deviceData) { - String systemName = deviceData['systemName']; - String systemVersion = deviceData['systemVersion']; - String model = deviceData['model']; - - return '$systemName $systemVersion; $model'; + if (Platform.isAndroid) { + return "${deviceData['brand']} ${deviceData['version.release']}; ${deviceData['model']}"; + } else if (Platform.isIOS) { + return "${deviceData['systemName']} ${deviceData['systemVersion']}; ${deviceData['model']}"; + } else + return "NO_USER_AGENT"; } } diff --git a/lib/service/package_info.dart b/lib/service/package_info.dart new file mode 100644 index 0000000..7d142b6 --- /dev/null +++ b/lib/service/package_info.dart @@ -0,0 +1,12 @@ +import 'package:flutter/foundation.dart'; +import 'package:package_info_plus/package_info_plus.dart'; +import 'package:mobdr/service/shared_prefs.dart'; + +class package_info_plus { + Future initPackageInfo() async { + if (!kIsWeb) { + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + SharedPrefs().appVersion = packageInfo.version; + } + } +} diff --git a/lib/service/plausible.dart b/lib/service/plausible.dart index 1a0dfc2..6b3dce6 100644 --- a/lib/service/plausible.dart +++ b/lib/service/plausible.dart @@ -5,39 +5,50 @@ import 'package:mobdr/network/get_ip_address.dart'; class PlausibleUtil { static PlausibleTracker? plausible; - static bool isPlausibleInitialized() { - return plausible != null; - } + static Future initializePlausible() async { + final ipAddress = await getPublicIPAddress(); - static Future initializePlausible(double screenWidth) async { plausible = PlausibleTracker( - "https://plausible.q2ii.fr", - "mobdr.ikksgroup.com", + serverUrl: "https://plausible.q2ii.fr", + domain: "mobdr.ikksgroup.com", + userAgent: SharedPrefs().mobileUserAgent, + screenWidth: SharedPrefs().screenWidth.toString(), + xForwardedFor: ipAddress, ); - - await plausible!.hello(); - - plausible!.userAgent = SharedPrefs().mobileUserAgent; - plausible!.xForwardedFor = await getPublicIPAddress(); - plausible!.screenWidth = screenWidth.toString(); - plausible!.enabled = await plausible!.hello(); } - static Future hello() async { - plausible!.enabled = await plausible!.hello(); + static bool isPlausibleEnabled() { + return plausible?.enabled ?? false; } - static void addEvent({ + static Future checkPlausibleUp() async { + await plausible?.hello(); + + if (isPlausibleEnabled() && SharedPrefs().login.isNotEmpty) { + // track application access + PlausibleUtil.addEventAsync( + name: 'access', + page: 'access', + referrer: 'referrerPage', + props: { + 'name': SharedPrefs().login, + }); + } + } + + static void addEventAsync({ required String name, required String page, String? referrer, Map? props, - }) { - PlausibleUtil.plausible?.event( - name: name, - page: page, - referrer: referrer ?? '', - props: props ?? {}, - ); + }) async { + if (isPlausibleEnabled()) { + plausible?.event( + name: name, + page: page, + referrer: referrer ?? '', + props: props ?? {}, + ); + } } } diff --git a/lib/service/shared_prefs.dart b/lib/service/shared_prefs.dart index e537bf8..88c174d 100644 --- a/lib/service/shared_prefs.dart +++ b/lib/service/shared_prefs.dart @@ -177,9 +177,68 @@ class SharedPrefs { } /// get/set user time zone - String get timeZone => _sharedPrefs.getString('key_timeZone') ?? ""; + String get timeZone => _sharedPrefs.getString('key_timezone') ?? ""; set timeZone(String value) { - _sharedPrefs.setString('key_timeZone', value); + _sharedPrefs.setString('key_timezone', value); + } + + /// get/set screenWidth + double get screenWidth => _sharedPrefs.getDouble('key_screenwidth') ?? 0; + + set screenWidth(double value) { + _sharedPrefs.setDouble('key_screenwidth', value); + } + + /// get/set screenHeight + double get screenHeight => _sharedPrefs.getDouble('key_screenheight') ?? 0; + + set screenHeight(double value) { + _sharedPrefs.setDouble('key_screenheight', value); + } + + /// get/set appVersion + String get appVersion => _sharedPrefs.getString('key_appversion') ?? ""; + + set appVersion(String value) { + _sharedPrefs.setString('key_appversion', value); + } + + /// get/set fingerPrint + String get fingerPrint => + _sharedPrefs.getString('key_fingerprint') ?? + "b42c213ee55376e501bbf4a7a8607bdc"; //NOFINGERPRINT" + + set fingerPrint(String value) { + _sharedPrefs.setString('key_fingerprint', value); + } + + /// get/set systemName + String get systemName => _sharedPrefs.getString('key_systemname') ?? ""; + + set systemName(String value) { + _sharedPrefs.setString('key_systemname', value); + } + + /// get/set device_model + String get deviceModel => _sharedPrefs.getString('key_device_model') ?? ""; + + set deviceModel(String value) { + _sharedPrefs.setString('key_device_model', value); + } + + /// get/set device Name + String get deviceName => _sharedPrefs.getString('key_device_name') ?? ""; + + set deviceName(String value) { + _sharedPrefs.setString('key_device_name', value); + } + + /// get/set systemVersion + String get systemVersion => + _sharedPrefs.getString('key_system_version') ?? ""; + + set systemVersion(String value) { + _sharedPrefs.setString('key_system_version', value); } } diff --git a/lib/ui/account/about.dart b/lib/ui/account/about.dart index 99b9c02..0ad8848 100644 --- a/lib/ui/account/about.dart +++ b/lib/ui/account/about.dart @@ -1,9 +1,8 @@ import 'package:mobdr/config/constant.dart'; import 'package:mobdr/config/global_style.dart'; +import 'package:mobdr/service/shared_prefs.dart'; import 'package:mobdr/ui/reusable/reusable_widget.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:package_info_plus/package_info_plus.dart'; class AboutPage extends StatefulWidget { @override @@ -14,20 +13,8 @@ class _AboutPageState extends State { // initialize reusable widget final _reusableWidget = ReusableWidget(); - String _version = '1.0.0'; - - Future _getSystemDevice() async { - PackageInfo packageInfo = await PackageInfo.fromPlatform(); - setState(() { - _version = packageInfo.version; - }); - } - @override void initState() { - if (!kIsWeb) { - _getSystemDevice(); - } super.initState(); } @@ -64,7 +51,7 @@ class _AboutPageState extends State { height: 5, ), Text( - _version, + SharedPrefs().appVersion, style: TextStyle(fontSize: 14, color: CHARCOAL), ), ], diff --git a/lib/ui/account/log.dart b/lib/ui/account/log.dart index 139b06c..7664101 100644 --- a/lib/ui/account/log.dart +++ b/lib/ui/account/log.dart @@ -77,7 +77,7 @@ class _LogPageState extends State { // track & log page access final page = 'log'; LoggerUtil.dblog('LOG', 'MOBDR', 'Page : ${page}', 0); - PlausibleUtil.addEvent(name: 'pageview', page: page); + PlausibleUtil.addEventAsync(name: 'pageview', page: page); } @override @@ -90,7 +90,7 @@ class _LogPageState extends State { context: context, builder: (context) => AlertDialog( title: Text('Confirmation'), - content: Text('Are you sure you want to delete this log?'), + content: Text('Are you sure you want to delete these logs ?'), actions: [ TextButton( child: Text('Cancel'), diff --git a/lib/ui/account/settings.dart b/lib/ui/account/settings.dart index 509f5c5..d0b104d 100644 --- a/lib/ui/account/settings.dart +++ b/lib/ui/account/settings.dart @@ -28,7 +28,7 @@ class _SettingsPageState extends State { // track & log page access final page = 'settings'; LoggerUtil.dblog('LOG', 'MOBDR', 'Page : ${page}', 0); - PlausibleUtil.addEvent(name: 'pageview', page: page); + PlausibleUtil.addEventAsync(name: 'pageview', page: page); setState(() { _photoQuality = SharedPrefs().photoQuality; @@ -315,6 +315,7 @@ class _SettingsPageState extends State { SharedPrefs().langage = 'fr'; break; default: + // TODO a vérifier _language = 'French'; break; } diff --git a/lib/ui/authentication/signin.dart b/lib/ui/authentication/signin.dart index 100a24e..36ce44a 100644 --- a/lib/ui/authentication/signin.dart +++ b/lib/ui/authentication/signin.dart @@ -5,6 +5,7 @@ import 'package:mobdr/network/api_provider.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:mobdr/ui/home.dart'; import 'package:mobdr/ui/authentication/verification.dart'; +import 'package:mobdr/service/shared_prefs.dart'; class SigninPage extends StatefulWidget { @override @@ -37,8 +38,21 @@ class _SigninPageState extends State { @override void initState() { - _etUserName = TextEditingController(text: 'fbenoist'); - _etPinCode = TextEditingController(text: '9295'); + _etUserName = TextEditingController(text: SharedPrefs().login); + _etPinCode = TextEditingController(text: ''); + + // clear all user information except login + SharedPrefs().id_utilisateur = 0; + SharedPrefs().email = ""; + SharedPrefs().expire = 0; + SharedPrefs().guid = ""; + SharedPrefs().langage = ""; + SharedPrefs().last_traduction = ""; + SharedPrefs().nom = ""; + SharedPrefs().prenom = ""; + SharedPrefs().version = ""; + SharedPrefs().photo = ""; + super.initState(); } @@ -106,7 +120,7 @@ class _SigninPageState extends State { height: 20, ), TextField( - keyboardType: TextInputType.emailAddress, + keyboardType: TextInputType.text, controller: _etUserName, decoration: InputDecoration( focusedBorder: UnderlineInputBorder( @@ -116,7 +130,7 @@ class _SigninPageState extends State { borderSide: BorderSide(color: _underlineColor), ), - labelText: 'Email', + labelText: 'User name', labelStyle: TextStyle(color: Colors.grey[700])), ), @@ -125,6 +139,7 @@ class _SigninPageState extends State { ), TextField( obscureText: _obscureText, + keyboardType: TextInputType.number, controller: _etPinCode, decoration: InputDecoration( focusedBorder: UnderlineInputBorder( @@ -166,6 +181,7 @@ class _SigninPageState extends State { //Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => HomePage()), (Route route) => false); var apiResponse = await _apiProvider.login( _etUserName.text, _etPinCode.text, ''); + if (apiResponse == 'OK') { Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute( @@ -175,8 +191,10 @@ class _SigninPageState extends State { Navigator.push( context, MaterialPageRoute( - builder: (_) => - VerificationPage())); + builder: (_) => VerificationPage( + pp_userName: _etUserName.text, + pp_pinCode: + _etPinCode.text))); } else { Fluttertoast.showToast( msg: apiResponse, diff --git a/lib/ui/authentication/verification.dart b/lib/ui/authentication/verification.dart index 3dfdfe0..e94e67c 100644 --- a/lib/ui/authentication/verification.dart +++ b/lib/ui/authentication/verification.dart @@ -1,16 +1,27 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:pin_code_fields/pin_code_fields.dart'; + +import 'package:mobdr/config/global_style.dart'; +import 'package:mobdr/ui/reusable/reusable_widget.dart'; import 'package:mobdr/network/api_provider.dart'; import 'package:mobdr/ui/home.dart'; import 'package:mobdr/ui/authentication/signin.dart'; class VerificationPage extends StatefulWidget { + final String pp_userName; + final String pp_pinCode; + + VerificationPage({required this.pp_userName, required this.pp_pinCode}); + @override _VerificationPageState createState() => _VerificationPageState(); } class _VerificationPageState extends State { + // initialize reusable widget + final _reusableWidget = ReusableWidget(); + Color _color1 = Color(0xFF07ac12); Color _color2 = Color(0xFF515151); Color _color3 = Color(0xff777777); @@ -33,140 +44,159 @@ class _VerificationPageState extends State { @override Widget build(BuildContext context) { return Scaffold( + appBar: AppBar( + iconTheme: IconThemeData( + color: GlobalStyle.appBarIconThemeColor, + ), + elevation: GlobalStyle.appBarElevation, + title: Text( + 'Two factor authentification', + style: GlobalStyle.appBarTitle, + ), + backgroundColor: GlobalStyle.appBarBackgroundColor, + systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle, + bottom: _reusableWidget.bottomAppBar(), + ), body: ListView( - padding: EdgeInsets.fromLTRB(30, 120, 30, 30), - children: [ - Center(child: Icon(Icons.phone_android, color: _color1, size: 50)), - SizedBox(height: 20), - Center( - child: Text( - 'Enter the Verification Code', - style: TextStyle( - fontSize: 16, fontWeight: FontWeight.bold, color: _color2), - )), - SizedBox( - height: 20, - ), - Container( - width: MediaQuery.of(context).size.width / 1.5, - child: Text( - 'The verification code has been sent by mail', - style: TextStyle(fontSize: 13, color: _color3), - textAlign: TextAlign.center, - ), - ), - SizedBox( - height: 40, - ), - Padding( - padding: EdgeInsets.symmetric(horizontal: 50), - child: PinCodeTextField( - autoFocus: true, - appContext: context, - keyboardType: TextInputType.number, - length: 4, - showCursor: false, - obscureText: false, - animationType: AnimationType.fade, - pinTheme: PinTheme( - shape: PinCodeFieldShape.underline, - fieldHeight: 50, - fieldWidth: 40, - inactiveColor: _color4, - activeColor: _color1, - selectedColor: _color1), - animationDuration: Duration(milliseconds: 300), - backgroundColor: Colors.transparent, - onChanged: (value) { - setState(() { - if (value.length == 4) { - _buttonDisabled = false; - } else { - _buttonDisabled = true; - } - _securityCode = value; - }); - }, - beforeTextPaste: (text) { - return false; - }, - ), - ), - SizedBox( - height: 40, - ), - Container( - child: SizedBox( - width: double.maxFinite, - child: TextButton( - style: ButtonStyle( - backgroundColor: MaterialStateProperty.resolveWith( - (Set states) => - _buttonDisabled ? Colors.grey[300]! : _color1, - ), - overlayColor: MaterialStateProperty.all(Colors.transparent), - shape: MaterialStateProperty.all(RoundedRectangleBorder( - borderRadius: BorderRadius.circular(3.0), - )), - ), - onPressed: () async { - if (!_buttonDisabled) { - FocusScope.of(context).unfocus(); - - var apiResponse = await _apiProvider.login( - 'fbenoist', '9295', _securityCode); - if (apiResponse == 'OK') { - Navigator.of(context).pushAndRemoveUntil( - MaterialPageRoute(builder: (context) => HomePage()), - (Route route) => false); - } else { - Fluttertoast.showToast( - msg: apiResponse, toastLength: Toast.LENGTH_SHORT); - Navigator.of(context).pushAndRemoveUntil( - MaterialPageRoute( - builder: (context) => SigninPage()), - (Route route) => false); - } - } - }, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 5.0), - child: Text( - 'Verify', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: _buttonDisabled - ? Colors.grey[600] - : Colors.white), - textAlign: TextAlign.center, - ), - ))), - ), - SizedBox( - height: 40, - ), - Center( - child: Wrap( - children: [ - Text( - "Didn't receive the code? ", - style: TextStyle(fontSize: 13, color: _color4), - ), - GestureDetector( - onTap: () { - Fluttertoast.showToast( - msg: 'Click resend', toastLength: Toast.LENGTH_SHORT); - }, + padding: EdgeInsets.fromLTRB(30, 120, 30, 30), + children: [ + Center(child: Icon(Icons.phone_android, color: _color1, size: 50)), + SizedBox(height: 20), + Center( child: Text( - 'Resend', - style: TextStyle(fontSize: 13, color: _color1), - ), - ) - ], - ), - ), - ], - )); + 'Enter the Verification Code', + style: TextStyle( + fontSize: 16, fontWeight: FontWeight.bold, color: _color2), + )), + SizedBox( + height: 20, + ), + Container( + width: MediaQuery.of(context).size.width / 1.5, + child: Text( + 'The verification code has been sent by mail', + style: TextStyle(fontSize: 13, color: _color3), + textAlign: TextAlign.center, + ), + ), + SizedBox( + height: 40, + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 50), + child: PinCodeTextField( + autoFocus: true, + appContext: context, + keyboardType: TextInputType.text, + length: 4, + showCursor: false, + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + shape: PinCodeFieldShape.underline, + fieldHeight: 50, + fieldWidth: 40, + inactiveColor: _color4, + activeColor: _color1, + selectedColor: _color1), + animationDuration: Duration(milliseconds: 300), + backgroundColor: Colors.transparent, + onChanged: (value) { + setState(() { + if (value.length == 4) { + _buttonDisabled = false; + } else { + _buttonDisabled = true; + } + _securityCode = value; + }); + }, + beforeTextPaste: (text) { + return false; + }, + ), + ), + SizedBox( + height: 40, + ), + Container( + child: SizedBox( + width: double.maxFinite, + child: TextButton( + style: ButtonStyle( + backgroundColor: + MaterialStateProperty.resolveWith( + (Set states) => + _buttonDisabled ? Colors.grey[300]! : _color1, + ), + overlayColor: + MaterialStateProperty.all(Colors.transparent), + shape: MaterialStateProperty.all(RoundedRectangleBorder( + borderRadius: BorderRadius.circular(3.0), + )), + ), + onPressed: () async { + if (!_buttonDisabled) { + FocusScope.of(context).unfocus(); + + var apiResponse = await _apiProvider.login( + widget.pp_userName, + widget.pp_pinCode, + _securityCode); + if (apiResponse == 'OK') { + Navigator.of(context).pushAndRemoveUntil( + MaterialPageRoute( + builder: (context) => HomePage()), + (Route route) => false); + } else { + Fluttertoast.showToast( + msg: apiResponse, + toastLength: Toast.LENGTH_SHORT); + Navigator.of(context).pushAndRemoveUntil( + MaterialPageRoute( + builder: (context) => SigninPage()), + (Route route) => false); + } + } + }, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 5.0), + child: Text( + 'Verify', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: _buttonDisabled + ? Colors.grey[600] + : Colors.white), + textAlign: TextAlign.center, + ), + ))), + ), + SizedBox( + height: 40, + ), + Center( + child: Wrap( + children: [ + Text( + "Didn't receive the code? ", + style: TextStyle(fontSize: 13, color: _color4), + ), + GestureDetector( + onTap: () { + Fluttertoast.showToast( + msg: 'Click resend', toastLength: Toast.LENGTH_SHORT); + }, + child: Text( + 'Resend', + style: TextStyle(fontSize: 13, color: _color1), + ), + ) + ], + ), + ), + ], + )); } } diff --git a/lib/ui/general/notification.dart b/lib/ui/general/notification.dart index 9439b35..8725bc9 100644 --- a/lib/ui/general/notification.dart +++ b/lib/ui/general/notification.dart @@ -23,7 +23,7 @@ class _NotificationPageState extends State { // track & log page access final page = 'notification'; LoggerUtil.dblog('LOG', 'MOBDR', 'Page : ${page}', 0); - PlausibleUtil.addEvent(name: 'pageview', page: page); + PlausibleUtil.addEventAsync(name: 'pageview', page: page); } @override diff --git a/lib/ui/home.dart b/lib/ui/home.dart index 34d2844..b4c2252 100644 --- a/lib/ui/home.dart +++ b/lib/ui/home.dart @@ -11,6 +11,7 @@ import 'package:mobdr/config/constant.dart'; import 'package:mobdr/events.dart'; import 'package:mobdr/service/plausible.dart'; import 'package:mobdr/service/logger_util.dart'; +import 'package:mobdr/service/plausible.dart'; class HomePage extends StatefulWidget { @override @@ -55,9 +56,18 @@ class _HomePageState extends State _isSyncing = e.isRunning; }); + // check if plausible is up and running + doAsyncPlausibleCheck().then((_) { + PlausibleUtil.addEventAsync(name: 'pageview', page: 'tab_home'); + }); + super.initState(); } + Future doAsyncPlausibleCheck() async { + await PlausibleUtil.checkPlausibleUp(); + } + void _handleTabSelection() { /* setState(() { @@ -161,6 +171,6 @@ class _HomePageState extends State } LoggerUtil.dblog('LOG', 'MOBDR', 'Page : ${page}', 0); - PlausibleUtil.addEvent(name: 'pageview', page: page); + PlausibleUtil.addEventAsync(name: 'pageview', page: page); } } diff --git a/lib/ui/splash_screen.dart b/lib/ui/splash_screen.dart index 5c771fd..974c7ce 100644 --- a/lib/ui/splash_screen.dart +++ b/lib/ui/splash_screen.dart @@ -4,11 +4,10 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:mobdr/service/shared_prefs.dart'; -import 'package:mobdr/service/plausible.dart'; - import 'package:mobdr/config/constant.dart'; import 'package:mobdr/ui/onboarding.dart'; import 'package:mobdr/ui/home.dart'; +import 'package:mobdr/ui/authentication/signin.dart'; class SplashScreenPage extends StatefulWidget { @override @@ -28,13 +27,22 @@ class _SplashScreenPageState extends State { if (_second == 0) { _cancelFlashsaleTimer(); - if (SharedPrefs().onboarding == 0) { + // if the user has never seen the onboarding page or the user is not logged in + if (SharedPrefs().onboarding == 0 || + SharedPrefs().id_utilisateur == 0) { + // see ! SharedPrefs().onboarding = 1; - PlausibleUtil.addEvent(name: 'pageview', page: 'onboarding'); + + // go to OnBoarding page Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => OnBoardingPage())); + // if the user is not logged in + } else if (SharedPrefs().id_utilisateur == 0) { + // go to sign'in page + Navigator.pushReplacement( + context, MaterialPageRoute(builder: (context) => SigninPage())); } else { - PlausibleUtil.addEvent(name: 'pageview', page: 'tab_home'); + // go to home page ! Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => HomePage())); } diff --git a/lib/ui/visit/visit_photo_typology.dart b/lib/ui/visit/visit_photo_typology.dart index 64e95e5..ac58eee 100644 --- a/lib/ui/visit/visit_photo_typology.dart +++ b/lib/ui/visit/visit_photo_typology.dart @@ -110,7 +110,7 @@ class _VisitPhotoTypologyPageState extends State { // track & log page access final page = 'visit_photo_typology'; LoggerUtil.dblog('LOG', 'MOBDR', 'Page : ${page}', 0); - PlausibleUtil.addEvent(name: 'pageview', page: page); + PlausibleUtil.addEventAsync(name: 'pageview', page: page); } @override diff --git a/lib/ui/visit/visit_photo_typology_detail.dart b/lib/ui/visit/visit_photo_typology_detail.dart index 14c1dfb..d4bd320 100644 --- a/lib/ui/visit/visit_photo_typology_detail.dart +++ b/lib/ui/visit/visit_photo_typology_detail.dart @@ -65,7 +65,7 @@ class _VisitPhotoTypologyDetailPageState // track & log page access final page = 'visit_photo_typology_detail'; LoggerUtil.dblog('LOG', 'MOBDR', 'Page : ${page}', 0); - PlausibleUtil.addEvent(name: 'pageview', page: page); + PlausibleUtil.addEventAsync(name: 'pageview', page: page); loadData(widget.pp_imageId).then((_) { setState(() { diff --git a/lib/ui/visit/visit_photo_typology_list.dart b/lib/ui/visit/visit_photo_typology_list.dart index e93fbe7..999d3a4 100644 --- a/lib/ui/visit/visit_photo_typology_list.dart +++ b/lib/ui/visit/visit_photo_typology_list.dart @@ -72,7 +72,7 @@ class _VisitPhotoTypologyListPageState // track & log page access final page = 'visit_photo_typology_list'; LoggerUtil.dblog('LOG', 'MOBDR', 'Page : ${page}', 0); - PlausibleUtil.addEvent(name: 'pageview', page: page); + PlausibleUtil.addEventAsync(name: 'pageview', page: page); loadData(); }