import 'dart:async'; import 'dart:convert'; import 'package:checker/base/base_screen.dart'; import 'package:checker/base/base_state.dart'; import 'package:checker/common.dart'; import 'package:checker/consts.dart'; import 'package:checker/db.dart'; import 'package:checker/network.dart'; import 'package:checker/resources.dart'; import 'package:checker/screens/faq.dart'; import 'package:checker/screens/finish_registration.dart'; import 'package:checker/screens/purchase.dart'; import 'package:checker/screens/registration.dart'; import 'package:checker/screens/settings.dart'; import 'package:checker/strings.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:http/http.dart'; // FIXME: Сделать запуск всех экранов из одной точки через метод showNextScreen() class SplashScreen extends BaseScreen { SplashScreen(SqliteHelper helper, String app) : super(helper, app); @override State createState() => new _SplashScreenState(helper, app); } class _SplashScreenState extends BaseState { _SplashScreenState(SqliteHelper helper, String app) : super(helper, app); bool a = true; bool isAutomaticallyImplyLeading() => false; @override void initState() { init(); super.initState(); } @override Widget build(BuildContext ctx) { return !a ? new Container( decoration: new BoxDecoration( image: new DecorationImage( image: new ExactAssetImage(Resources.getSplash(null)), fit: BoxFit.cover))) : getScreenContent(); } @override Widget getScreenContent() { return new Stack(children: [ getBackground(), getLogo(), new Align( alignment: FractionalOffset.bottomRight, child: new Container( margin: new EdgeInsets.only(right: 11.0, bottom: 5.0), child: new Image.asset(powered_by_dinect_splash_png, height: 16.0, width: 122.0))) ]); } /// Возвращает столбец с логотипом приложения и текстом под ним. /// Столбец занимает не все доступное пространство, а необходимый минимум в центре экрана. getLogo() { return new Center( child: new Column(mainAxisSize: MainAxisSize.min, children: [ new Image.asset(Resources.getLogo(app), height: 112.0, width: 252.0), new Image.asset(splash_text_png, height: 40.0, width: 240.0) ])); } showNextScreen(Widget screen) { new Future.delayed(const Duration(milliseconds: 200), () { var route = new MaterialPageRoute( builder: (BuildContext context) => screen, fullscreenDialog: true); Navigator.of(context).push(route).then((token) { if (token == '') { showNextScreen(new RegistrationScreen(helper, app)); } else if (token != null) { _initAndStartScanner(context, app, token, helper); } else { platform.invokeMethod('logError', {"message":"Token is null"}).then((_) { helper.getToken().then((token) { _initAndStartScanner(context, app, token, helper); }); }); } }); }); } /// Запуск следующего экрана приложения. init() async { String token = await helper.getToken(); // В случае, если в приложении отсутствует токен, // необходимо запустить регистрацию кассы. if (token == null) { showNextScreen(new RegistrationScreen(helper, app)); } else { if (await platform.invokeMethod('isOnline')) { getCheckTokenStatusRequest(token).then((statusResponse) { handleStatusResponse(statusResponse, helper); }, onError: (e) { platform.invokeMethod('logError', {"message":e.toString()}); }); } } } /// Обработка ответа. /// В случае, если токен был удален может прийти active: false, либо 404. /// Если токен не активен, попробовать создать его еще раз. handleStatusResponse(var statusResponse, SqliteHelper helper) async { int code = statusResponse.statusCode; if (code == 404) { helper.clear().then((result) { showNextScreen(new RegistrationScreen(helper, app)); }); } else { Map status = JSON.decode(statusResponse.body); bool active = status['active'] == null ? false : status['active']; if (active) { helper.getToken().then((token) { _initAndStartScanner(context, app, token, helper); }); } else { if (await platform.invokeMethod('isOnline')) { _createToken(helper); } } } } /// Отправляется запрос на создание токена. /// /// Если вернулся код 409, значит такой токен уже существует и активирован. /// Нужно направить пользователя на экран подтверждения активации. /// /// Если вернулся код 200, значит токен был ранее удален и только что снова создался. /// Нужно удалить его и направить пользователя на экран регистрации. _createToken(SqliteHelper helper) async { String merchantID = await helper.getMerchantID(); String posID = await helper.getPosID(); getCreateTokenRequest({'merchant_shop': merchantID, 'pos': posID}) .then((response) { if (response.statusCode == 409) { showNextScreen(new FinishRegistrationScreen(helper, app)); } else if (response.statusCode == 201) { clearToken(response, helper); } }, onError: (e) { platform.invokeMethod('logError', {"message":e.toString()}); }); } /// Очищаем бд, делаем запрос на удаление токена. Future clearToken(Response response, SqliteHelper helper) async { helper.clear().then((_) { Map parsedMap = JSON.decode(response.body); getDeleteTokenRequest(parsedMap['token']).then((_) { showNextScreen(new RegistrationScreen(helper, app)); }, onError: (e) { platform.invokeMethod('logError', {"message":e.toString()}); }); }, onError: (e) { platform.invokeMethod('logError', {"message":e.toString()}); }); } /// Запуск спецефичной для каждой платформы части приложения - сканера. /// Может производиться с нескольких экранов (splash, finish_registration). _initAndStartScanner(BuildContext context, String app, String token, SqliteHelper helper) { // Канал ловит вызовы методов из "нативной" части приложения. // Могут быть вызваны либо exit либо faq, либо purchase. setState(() { a = false; }); platform.setMethodCallHandler((MethodCall call) async { print(this.toString()); if (call.method == 'findUser') { try { Response userResponse; switch (call.arguments[1]) { case 'card': userResponse = await getUserByCard(call.arguments[0], token); break; case 'phone': userResponse = await getUserByPhone(call.arguments[0], token); break; } if (userResponse != null) { print('I have user in method handler!'); List users = JSON.decode(userResponse.body); if (users.length > 0) { return users[0]; } else { throw new FlutterError("Users not found"); } } else { throw new FlutterError("Users not found"); } } catch (error) { print(error.toString()); throw new FlutterError("Users not found"); } } else if (call.method == 'faq') { new Future.delayed(const Duration(milliseconds: 200), () { var route = new MaterialPageRoute( builder: (BuildContext context) => new FAQScreen(helper, app), fullscreenDialog: true); Navigator.of(context).push(route).then((_) { _initAndStartScanner(context, app, token, helper); }); }); } else if (call.method == 'settings') { new Future.delayed(const Duration(milliseconds: 200), () { var route = new MaterialPageRoute( builder: (BuildContext context) => new SettingsScreen(helper, app, true), fullscreenDialog: true); Navigator.of(context).push(route).then((result) { if (result != null) { showNextScreen(new RegistrationScreen(helper, app)); } else { _initAndStartScanner(context, app, token, helper); } }); }); } else { String userString = call.arguments[0] is String ? call.arguments[0] : JSON.encode(call.arguments[0]); print(userString); String card = call.arguments[1]; showNextScreen(new PurchaseScreen(helper, app, userString, card)); } }); platform.invokeMethod('getEndpoint').then((url) { platform.invokeMethod('getAppToken').then((appToken) { Map args = StringsLocalization.strings; args['token'] = token; args['url'] = url; args['appToken'] = appToken; args['localeCode'] = StringsLocalization.localeCode; args['color'] = Resources .getPrimaryColor(app) .value .toString(); platform.invokeMethod('startScanner', args); }, onError: (e) { platform.invokeMethod('logError', {"message":e.toString()}); }); }, onError: (e) { platform.invokeMethod('logError', {"message":e.toString()}); }); } }