Продолжаю разбираться с локализацией
This commit is contained in:
@@ -38,6 +38,22 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
|
||||
en {
|
||||
buildConfigField "String", "locale", "\"en\""
|
||||
}
|
||||
|
||||
ru {
|
||||
buildConfigField "String", "locale", "\"ru\""
|
||||
}
|
||||
|
||||
ua {
|
||||
buildConfigField "String", "locale", "\"ua\""
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sourceSets.main {
|
||||
jniLibs.srcDir 'jniLibs'
|
||||
}
|
||||
|
||||
@@ -6,9 +6,11 @@ import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import com.dinect.checker.zbar.CameraActivity;
|
||||
import com.dinect.checker.zxing.ScannerActivity;
|
||||
import java.util.Locale;
|
||||
|
||||
import io.flutter.app.FlutterActivity;
|
||||
import io.flutter.plugins.GeneratedPluginRegistrant;
|
||||
@@ -47,7 +49,7 @@ public class MainActivity extends FlutterActivity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
GeneratedPluginRegistrant.registerWith(this);
|
||||
|
||||
loadLocale(this);
|
||||
mPreferences = getPreferences(Context.MODE_PRIVATE);
|
||||
|
||||
Log.d(TAG, "application prefs:");
|
||||
@@ -144,6 +146,29 @@ public class MainActivity extends FlutterActivity {
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadLocale(Context context) {
|
||||
Resources res = context.getResources();
|
||||
Configuration configuration = new Configuration(res.getConfiguration());
|
||||
switch (BuildConfig.locale) {
|
||||
case "en":
|
||||
configuration.locale = new Locale("en");
|
||||
Locale.setDefault(configuration.locale);
|
||||
res.updateConfiguration(configuration, res.getDisplayMetrics());
|
||||
break;
|
||||
case "ru":
|
||||
configuration.locale = new Locale("ru");
|
||||
Locale.setDefault(configuration.locale);
|
||||
res.updateConfiguration(configuration, res.getDisplayMetrics());
|
||||
break;
|
||||
case "ua":
|
||||
configuration.locale = new Locale("ua");
|
||||
Locale.setDefault(configuration.locale);
|
||||
res.updateConfiguration(configuration, res.getDisplayMetrics());
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void handleItemClick() {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,148 +1,154 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'common.dart';
|
||||
import 'consts.dart';
|
||||
import 'strings.dart';
|
||||
|
||||
abstract class BaseState<T> extends State<StatefulWidget> {
|
||||
abstract class BaseState<T extends StatefulWidget> extends State<T> {
|
||||
|
||||
/// Ожидание ответа от сервера.
|
||||
bool loading = false;
|
||||
|
||||
/// Текст ошибки, подставляется в подсказку, либо появляется над текстовым полем.
|
||||
String error;
|
||||
|
||||
/// Введенное пользователем значение.
|
||||
String textFieldValue = '';
|
||||
|
||||
TextEditingController controller = new TextEditingController();
|
||||
Strings s;
|
||||
|
||||
@override Widget build(BuildContext context) {
|
||||
return new Scaffold(appBar: getAppBar(context), body: getBody(context));
|
||||
@override Widget build(BuildContext ctx) {
|
||||
return new Scaffold(appBar: getAppBar(ctx),
|
||||
body: new Stack(children: <Widget>[
|
||||
getScreenContent(ctx),
|
||||
new Center(child: loading ? new CircularProgressIndicator() : null)
|
||||
]));
|
||||
}
|
||||
|
||||
AppBar getAppBar(BuildContext context) {
|
||||
return new AppBar(title: new Text(getTitle(), style: new TextStyle(fontSize: 18.0)),
|
||||
backgroundColor: primaryColor, actions: getMenuButtons(context));
|
||||
/// Возвращает контейнер с всеми виджетами экрана.
|
||||
Widget getScreenContent(BuildContext ctx);
|
||||
|
||||
/// Возвращает заголовок для AppBar
|
||||
String getTitle(BuildContext ctx);
|
||||
|
||||
AppBar getAppBar(BuildContext ctx) {
|
||||
return new AppBar(title: new Text(getTitle(ctx), style: new TextStyle(fontSize: 18.0)),
|
||||
backgroundColor: primaryColor, actions: getMenuButtons(ctx));
|
||||
}
|
||||
|
||||
getMenuButtons(BuildContext context) {
|
||||
List<Widget> getMenuButtons(BuildContext context) {
|
||||
return <Widget>[getFaqButton()];
|
||||
}
|
||||
|
||||
getFaqButton() {
|
||||
Widget getFaqButton() {
|
||||
return new IconButton(icon: new Icon(Icons.help_outline), onPressed: () => faq(context, false));
|
||||
}
|
||||
|
||||
getLogoutButton() {
|
||||
Widget getLogoutButton() {
|
||||
return new IconButton(icon: new Image.asset(logout_png, height: iconHeight, width: iconHeight), onPressed: () => logout(context));
|
||||
}
|
||||
|
||||
Widget getBody(BuildContext context) {
|
||||
return new Stack(children: <Widget>[getScreenContent(), getProgressIndicator()]);
|
||||
}
|
||||
|
||||
Widget getScreenContent();
|
||||
|
||||
String getTitle();
|
||||
|
||||
String getHint();
|
||||
|
||||
/// Метод возвращает контейнер с отступами, который содержит картинку с логотипом.
|
||||
getLogo() {
|
||||
double containerHeight = 92.0;
|
||||
double imageWidth = 156.0;
|
||||
return new Container(height: containerHeight, child: new Image.asset(logo_png, width: imageWidth));
|
||||
}
|
||||
|
||||
getHintLabel() {
|
||||
/// Возврвщает контейнер, внутри которого Text с подсказкой.
|
||||
Widget getHintLabel(BuildContext ctx) {
|
||||
double horizontalMargin = 8.0;
|
||||
return new Container(margin: new EdgeInsets.only(top: horizontalMargin, bottom: horizontalMargin, left: verticalMargin, right: verticalMargin),
|
||||
child: new Row(crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[new Text(getHintText(), textAlign: TextAlign.left,
|
||||
style: new TextStyle(fontWeight: FontWeight.w300, color: error == null ? greyTextColor : primaryColor, fontSize: 14.0))]));
|
||||
child: new Row(crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[new Text(getHintString(ctx), textAlign: TextAlign.left,
|
||||
style: new TextStyle(fontWeight: FontWeight.w300, color: error == null ? greyTextColor : primaryColor, fontSize: 14.0))]));
|
||||
}
|
||||
|
||||
getHintText() {
|
||||
/// Возвращает подсказку, либо ошибку, если введенные в поле ввода данные неверны.
|
||||
String getHintString(BuildContext ctx) {
|
||||
if (textFieldValue.length == 0 && error == null) {
|
||||
return ' ';
|
||||
} else if (error != null) {
|
||||
return error;
|
||||
} else {
|
||||
return getHint();
|
||||
return getHint(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/// Возвращает текст подсказки для поля ввода.
|
||||
/// Должен быть переопределен на экранах, на которых есть поле ввода.
|
||||
String getHint(BuildContext ctx) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Смена состояния экрана при изменении текста в поле ввода.
|
||||
handleUserInput(String text) {
|
||||
void handleUserInput(String text) {
|
||||
setState(() {
|
||||
textFieldValue = text;
|
||||
});
|
||||
}
|
||||
|
||||
/// Метод возвращает контейнер с установленными отступами, в котором размещен TextField обернутый в BoxDecoration.
|
||||
getDecoratedTextWidget() {
|
||||
/// Метод возвращает контейнер с полем ввода внутри.
|
||||
Widget getInputField(BuildContext ctx) {
|
||||
return new Container(margin: new EdgeInsets.only(left: verticalMargin, right: verticalMargin),
|
||||
padding: getPaddingForTextWidget(),
|
||||
decoration: getDecorationForTextWidget(),
|
||||
child: getTextWidget());
|
||||
padding: getInputFieldContainerPadding(),
|
||||
decoration: getInputFieldContainerDecoration(),
|
||||
child: new TextField(keyboardType: TextInputType.number,
|
||||
decoration: new InputDecoration.collapsed(hintText: getHint(ctx),
|
||||
hintStyle: new TextStyle(color: greyTextColor, fontSize: 16.0)),
|
||||
onChanged: (text) => handleUserInput(text)));
|
||||
}
|
||||
|
||||
getPaddingForTextWidget() {
|
||||
/// Возвращат паддинги для поля ввода.
|
||||
EdgeInsets getInputFieldContainerPadding() {
|
||||
const double verticalPadding = 12.0;
|
||||
const double horizontalPadding = 16.0;
|
||||
return new EdgeInsets.only(top: verticalPadding,
|
||||
bottom: verticalPadding,
|
||||
left: horizontalPadding,
|
||||
right: horizontalPadding);
|
||||
bottom: verticalPadding,
|
||||
left: horizontalPadding,
|
||||
right: horizontalPadding);
|
||||
}
|
||||
|
||||
/// Метод возвращает BoxDecoration для _getDecoratedInputField
|
||||
getDecorationForTextWidget() {
|
||||
return new BoxDecoration(color: getTextFilledBackground(),
|
||||
border: new Border.all(color: textBorderColor, width: 1.0),
|
||||
borderRadius: new BorderRadius.all(new Radius.circular(4.0)));
|
||||
BoxDecoration getInputFieldContainerDecoration() {
|
||||
return new BoxDecoration(color: inputFieldBackground,
|
||||
border: new Border.all(color: textBorderColor, width: 1.0),
|
||||
borderRadius: new BorderRadius.all(new Radius.circular(4.0)));
|
||||
}
|
||||
|
||||
Color getTextFilledBackground() {
|
||||
return const Color(0xffefefef);
|
||||
/// Возвращает выпуклую залитую фирменным цветом кнопку
|
||||
Widget buildRaisedButton(BuildContext context, String text, VoidCallback onPressed) {
|
||||
return new RaisedButton(child: new Text(text,
|
||||
style: new TextStyle(color: Colors.white)),
|
||||
onPressed: onPressed,
|
||||
color: primaryColor);
|
||||
}
|
||||
|
||||
Widget getTextWidget() {
|
||||
return new TextField(keyboardType: TextInputType.number,
|
||||
decoration: new InputDecoration.collapsed(hintText: getHint(),
|
||||
hintStyle: new TextStyle(color: greyTextColor, fontSize: 16.0)),
|
||||
onChanged: (text) => handleUserInput(text));
|
||||
/// Метод возвращает контейнер с отступами, который содержит картинку с логотипом.
|
||||
Widget getLogo() {
|
||||
double containerHeight = 92.0;
|
||||
double imageWidth = 156.0;
|
||||
return new Container(height: containerHeight, child: new Image.asset(logo_png, width: imageWidth));
|
||||
}
|
||||
|
||||
Widget getProgressIndicator() {
|
||||
return new Center(child: loading ? new CircularProgressIndicator() : null);
|
||||
}
|
||||
|
||||
Widget getValueWithTitle(String title, String value) {
|
||||
/// Возвращает текстовое поле, с однострочным пояснением над ним.
|
||||
Widget getValueWithDescription(String title, String value) {
|
||||
return new Container(padding: new EdgeInsets.only(left: verticalMargin, right: verticalMargin, top: 18.0),
|
||||
child: new Column(children: <Widget>[
|
||||
new Row(crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[new Text(title, textAlign: TextAlign.left, style: new TextStyle(color: greyTextColor, fontSize: 14.0))]),
|
||||
new Row(crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[new Expanded(child: new Text(value, textAlign: TextAlign.left, style: new TextStyle(color: Colors.black, fontSize: 20.0)))])
|
||||
]));
|
||||
child: new Column(children: <Widget>[
|
||||
new Row(crossAxisAlignment: CrossAxisAlignment.start, children: getDescriptionWidget(title)),
|
||||
new Row(crossAxisAlignment: CrossAxisAlignment.start, children: getValueWidget(value))
|
||||
]));
|
||||
}
|
||||
|
||||
/// Возвращает список, единственный элемент которого - Text с заголовком для текстового поля.
|
||||
List<Widget> getDescriptionWidget(String title) {
|
||||
return <Widget>[new Text(title, textAlign: TextAlign.left, style: new TextStyle(color: greyTextColor, fontSize: 14.0))]
|
||||
}
|
||||
|
||||
/// Возвращает список, единственный элемент которого - Text с информацией (размер скидки, сумма проведенной покупки).
|
||||
List<Widget> getValueWidget(String value) {
|
||||
return <Widget>[new Expanded(child: new Text(value, textAlign: TextAlign.left, style: new TextStyle(color: Colors.black, fontSize: 20.0)))];
|
||||
}
|
||||
|
||||
/// Возвращает кнопку, обернутую набором специфичных контейнеров.
|
||||
Widget buildButton(EdgeInsets margin, Widget widget) {
|
||||
return new Container(margin: margin, height: buttonHeight, child: new Row(children: <Widget>[new Expanded(child: widget)]));
|
||||
}
|
||||
|
||||
Widget buildRaisedButton(BuildContext context, String text, VoidCallback onPressed) {
|
||||
return new RaisedButton(child: new Text(text,
|
||||
style: new TextStyle(color: Colors.white)),
|
||||
onPressed: onPressed,
|
||||
color: primaryColor);
|
||||
}
|
||||
|
||||
Widget buildFlatButton(BuildContext context, String title, Color textColor) {
|
||||
return new Container(height: buttonHeight, child: new FlatButton(child: new Text(title,
|
||||
style: new TextStyle(color: textColor)),
|
||||
onPressed: () => startScanner(context)),
|
||||
decoration: getDecorationForScanButton());
|
||||
}
|
||||
|
||||
getDecorationForScanButton() {
|
||||
return new BoxDecoration(
|
||||
border: new Border.all(color: primaryColor, width: 1.0),
|
||||
borderRadius: new BorderRadius.all(new Radius.circular(4.0)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'consts.dart';
|
||||
import 'network.dart';
|
||||
import 'package:checker/registration/registration.dart';
|
||||
import 'package:checker/purchase/purchase.dart';
|
||||
import 'package:checker/registration.dart';
|
||||
import 'package:checker/purchase.dart';
|
||||
import 'faq.dart';
|
||||
import 'strings.dart';
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ const Color tokenActivateTextColor = const Color(0xff4e3a19);
|
||||
const Color greenBackground = const Color(0xff8ae28a);
|
||||
const Color faqGrey = const Color(0xff5b5b5b);
|
||||
const Color faqTitlesColor = const Color(0xff404040);
|
||||
|
||||
const Color inputFieldBackground = const Color(0xffefefef);
|
||||
// Dimens
|
||||
const double verticalMargin = 28.0;
|
||||
const double buttonHeight = 48.0;
|
||||
|
||||
@@ -35,7 +35,7 @@ class _RegistrationScreenState extends BaseState<FinishRegistrationScreen> {
|
||||
return new Column(children: <Widget>[
|
||||
getLogo(),
|
||||
getHintLabel(),
|
||||
getDecoratedTextWidget(),
|
||||
getInputField(),
|
||||
getMessage(),
|
||||
buildRaisedButton(context, _tokenActive
|
||||
? Strings.of(context).completeRegistration()
|
||||
@@ -3,29 +3,22 @@ import 'splash.dart';
|
||||
import 'consts.dart';
|
||||
import 'strings.dart';
|
||||
import 'dart:async';
|
||||
import 'i18n/messages_all.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
Future<LocaleQueryData> _onLocaleChanged(Locale locale) async {
|
||||
final String localeString = locale.toString();
|
||||
await initializeMessages(localeString);
|
||||
Intl.defaultLocale = localeString;
|
||||
return Strings.instance;
|
||||
}
|
||||
|
||||
/// Точка входа в приложение.
|
||||
void main() {
|
||||
runApp(new Checker());
|
||||
}
|
||||
|
||||
class Checker extends StatelessWidget {
|
||||
class Checker extends StatefulWidget {
|
||||
@override CheckerState createState() => new CheckerState();
|
||||
}
|
||||
|
||||
class CheckerState extends State<Checker> {
|
||||
|
||||
@override Widget build(BuildContext context) {
|
||||
return new MaterialApp(title: appName,
|
||||
home: new SplashScreen(),
|
||||
onLocaleChanged: _onLocaleChanged,
|
||||
theme: new ThemeData(
|
||||
primaryColor: primaryColor,
|
||||
accentColor: primaryColor
|
||||
));
|
||||
return new MaterialApp(
|
||||
title: appName,
|
||||
home: new SplashScreen()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import 'package:checker/common.dart';
|
||||
import 'package:checker/consts.dart';
|
||||
import 'package:checker/network.dart';
|
||||
import 'package:checker/base_state.dart';
|
||||
import 'purchase_success.dart';
|
||||
import 'package:checker/purchase_success.dart';
|
||||
|
||||
/// Экран проведения покупки.
|
||||
class PurchaseScreen extends StatefulWidget {
|
||||
@@ -23,6 +23,11 @@ class PurchaseScreen extends StatefulWidget {
|
||||
|
||||
class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
|
||||
|
||||
/// Объект, помогающий вручную изменять введенный пользователем текст.
|
||||
/// Используется для форматирования введенных пользователем данных
|
||||
/// (удаляет запрещенные символы до их отображаения).
|
||||
TextEditingController controller = new TextEditingController();
|
||||
|
||||
PurchaseScreenState(String userString, String card) {
|
||||
this.user = JSON.decode(userString);
|
||||
this.card = card;
|
||||
@@ -37,13 +42,13 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
|
||||
@override Widget getScreenContent() {
|
||||
return new Column(
|
||||
children: <Widget>[new Expanded(child: new ListView(children: <Widget>[
|
||||
getValueWithTitle(Strings.of(context).userName(), user['first_name'] == null ? '' : user['first_name']),
|
||||
getValueWithTitle(Strings.of(context).card(), card),
|
||||
getValueWithTitle(Strings.of(context).reward(), loyality),
|
||||
getValueWithDescription(Strings.of(context).userName(), user['first_name'] == null ? '' : user['first_name']),
|
||||
getValueWithDescription(Strings.of(context).card(), card),
|
||||
getValueWithDescription(Strings.of(context).reward(), loyality),
|
||||
getHintLabel(),
|
||||
getDecoratedTextWidget(),
|
||||
getInputField(),
|
||||
buildButton(getScreenMargins(36.0), getCompleteButton()),
|
||||
buildButton(getScreenMargins(24.0), getScanButton())
|
||||
buildButton(getScreenMargins(24.0), getScanButton(context, Strings.of(context).scan(), primaryColor))
|
||||
]))]);
|
||||
}
|
||||
|
||||
@@ -57,8 +62,17 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
|
||||
return buildRaisedButton(context, title, () => onPurchaseClick(context));
|
||||
}
|
||||
|
||||
getScanButton() {
|
||||
return buildFlatButton(context, Strings.of(context).scan(), primaryColor);
|
||||
Widget getScanButton(BuildContext context, String title, Color textColor) {
|
||||
return new Container(height: buttonHeight, child: new FlatButton(child: new Text(title,
|
||||
style: new TextStyle(color: textColor)),
|
||||
onPressed: () => startScanner(context)),
|
||||
decoration: getDecorationForScanButton());
|
||||
}
|
||||
|
||||
getDecorationForScanButton() {
|
||||
return new BoxDecoration(
|
||||
border: new Border.all(color: primaryColor, width: 1.0),
|
||||
borderRadius: new BorderRadius.all(new Radius.circular(4.0)));
|
||||
}
|
||||
|
||||
@override String getTitle() {
|
||||
@@ -183,7 +197,7 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
|
||||
}
|
||||
|
||||
getContentMessage(String val) {
|
||||
return Strings.of(context).confirmPurchase(val);
|
||||
return Strings.of(context).confirmPurchase();
|
||||
}
|
||||
|
||||
purchase(String sumTotal) async {
|
||||
@@ -36,7 +36,7 @@ class PurchaseSuccessScreenState<T> extends BaseState<PurchaseSuccessScreen> {
|
||||
|
||||
@override Widget getScreenContent() {
|
||||
return new Column(children: <Widget>[
|
||||
getValueWithTitle(Strings.of(context).buyer(), username),
|
||||
getValueWithDescription(Strings.of(context).buyer(), username),
|
||||
getSuccessMessage(),
|
||||
new Expanded(child: new Center()),
|
||||
buildButton(getScreenMargins(74.0), getScanButton())
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:checker/finish_registration.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:convert'; // Пакет для обработки json с ответом от сервера.
|
||||
|
||||
@@ -5,7 +6,6 @@ import 'package:checker/common.dart';
|
||||
import 'package:checker/network.dart';
|
||||
import 'package:checker/base_state.dart';
|
||||
import 'package:checker/strings.dart';
|
||||
import 'activate_token.dart';
|
||||
|
||||
/// Экран регистрации магазина и кассы.
|
||||
class RegistrationScreen extends StatefulWidget {
|
||||
@@ -14,35 +14,36 @@ class RegistrationScreen extends StatefulWidget {
|
||||
|
||||
class _RegistrationScreenState extends BaseState<RegistrationScreen> {
|
||||
|
||||
@override String getTitle() {
|
||||
return Strings.of(context).registration();
|
||||
@override String getTitle(BuildContext ctx) {
|
||||
return "registration";
|
||||
}
|
||||
|
||||
@override getHint() {
|
||||
return Strings.of(context).idStore();
|
||||
@override getHint(BuildContext ctx) {
|
||||
return "idStore()";
|
||||
}
|
||||
|
||||
// Список виджетов, автоматически прокручиваемый вверх при открытии клавиатуры.
|
||||
@override Widget getScreenContent() {
|
||||
@override Widget getScreenContent(BuildContext ctx) {
|
||||
print(new Strings().registration());
|
||||
return new Container(
|
||||
child: new ListView(children: <Widget>[
|
||||
new Column(children: <Widget>[
|
||||
getLogo(),
|
||||
getHintLabel(),
|
||||
getDecoratedTextWidget(),
|
||||
getButton()])
|
||||
getHintLabel(ctx),
|
||||
getInputField(ctx),
|
||||
getButton(ctx)])
|
||||
]));
|
||||
}
|
||||
|
||||
// Возвращает кнопку регистрации.
|
||||
getButton() {
|
||||
/// Возвращает кнопку регистрации.
|
||||
getButton(BuildContext ctx) {
|
||||
return new Container(margin: new EdgeInsets.only(top: 36.0), child:
|
||||
buildRaisedButton(context, Strings.of(context).signUp(), getOnPressed()));
|
||||
buildRaisedButton(ctx, "signUp()", getOnPressed(ctx)));
|
||||
}
|
||||
|
||||
// Возвращает обработчик нажатий на кнопку регистрации.
|
||||
getOnPressed() {
|
||||
return _isValidMerchantID() && !loading ? () => _registerShop(context) : null;
|
||||
getOnPressed(BuildContext ctx) {
|
||||
return _isValidMerchantID() && !loading ? () => _registerShop(ctx) : null;
|
||||
}
|
||||
|
||||
/// Токен кассы - это DIN код. DIN код - это специальный код динекта, максимальная его длина - 25 символов.
|
||||
@@ -52,15 +53,15 @@ class _RegistrationScreenState extends BaseState<RegistrationScreen> {
|
||||
}
|
||||
|
||||
/// Показать progressBar, запросить токен.
|
||||
_registerShop(BuildContext context) {
|
||||
_registerShop(BuildContext ctx) {
|
||||
setState(() {
|
||||
loading = true;
|
||||
_register(context);
|
||||
_register(ctx);
|
||||
});
|
||||
}
|
||||
|
||||
/// Получение от платформы id установки, формирование запроса на получение токена, сохранение токена.
|
||||
_register(BuildContext context) async {
|
||||
_register(BuildContext ctx) async {
|
||||
if (await platform.invokeMethod('isOnline')) {
|
||||
createToken(textFieldValue, await platform.invokeMethod('getPosID')).then((response) {
|
||||
|
||||
@@ -75,7 +76,7 @@ class _RegistrationScreenState extends BaseState<RegistrationScreen> {
|
||||
token = parsedMap['token'];
|
||||
platform.invokeMethod('saveToken', {'token' : token});
|
||||
platform.invokeMethod('saveMerchantID', {'merchantID' : textFieldValue});
|
||||
pushRoute(context, new FinishRegistrationScreen());
|
||||
pushRoute(ctx, new FinishRegistrationScreen());
|
||||
} else {
|
||||
setState(() {
|
||||
error = parsedMap['errors'][0];
|
||||
@@ -1,49 +1,54 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'common.dart';
|
||||
import 'network.dart';
|
||||
import 'consts.dart';
|
||||
import 'package:checker/registration/registration.dart';
|
||||
import 'package:checker/registration/activate_token.dart';
|
||||
import 'registration.dart';
|
||||
import 'finish_registration.dart';
|
||||
import 'strings.dart';
|
||||
|
||||
class SplashScreen extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
// Появляется splash screen, проверяется токен.
|
||||
new Future.delayed(const Duration(milliseconds: 500), () {
|
||||
|
||||
Strings s = new Strings();
|
||||
s.load("ru").then((_) {
|
||||
showNextScreen(context);
|
||||
});
|
||||
|
||||
// new Future.delayed(const Duration(milliseconds: 500), () {
|
||||
// });
|
||||
|
||||
return new Stack(children: <Widget>[getSplashBackground(), 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)))]);
|
||||
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: <Widget>[new Image.asset(logo_png, height: 112.0, width: 252.0),
|
||||
new Image.asset(splash_text_png, height: 40.0, width: 240.0)]));
|
||||
children: <Widget>[new Image.asset(logo_png, height: 112.0, width: 252.0),
|
||||
new Image.asset(splash_text_png, height: 40.0, width: 240.0)]));
|
||||
}
|
||||
|
||||
// Возвращает контейнер, который содержит decoration с фоновым изображением.
|
||||
/// Возвращает контейнер, который содержит decoration с фоновым изображением.
|
||||
getSplashBackground() {
|
||||
return new Container(decoration:
|
||||
new BoxDecoration(image:
|
||||
new DecorationImage(image: new ExactAssetImage(splash_png), fit: BoxFit.cover)));
|
||||
new BoxDecoration(image:
|
||||
new DecorationImage(image: new ExactAssetImage(splash_png), fit: BoxFit.cover)));
|
||||
}
|
||||
|
||||
// Запуск следующего экрана приложения.
|
||||
/// Запуск следующего экрана приложения.
|
||||
showNextScreen(BuildContext context) async {
|
||||
|
||||
token = await platform.invokeMethod('getToken');
|
||||
print('token: $token');
|
||||
|
||||
// В случае, если в приложении отсутствует токен,
|
||||
// необходимо запустить регистрацию кассы.
|
||||
@@ -61,9 +66,9 @@ class SplashScreen extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
// Обработка ответа.
|
||||
// В случае, если токен был удален может прийти active: false, либо 404.
|
||||
// Если токен не активен, попробовать создать его еще раз. В случае успешного создания токена удалить его и перейти на экран регистрации
|
||||
/// Обработка ответа.
|
||||
/// В случае, если токен был удален может прийти active: false, либо 404.
|
||||
/// Если токен не активен, попробовать создать его еще раз.
|
||||
handleStatusResponse(BuildContext context, var statusResponse) async {
|
||||
int code = statusResponse.statusCode;
|
||||
print('resp: ${code}');
|
||||
@@ -75,32 +80,44 @@ class SplashScreen extends StatelessWidget {
|
||||
});
|
||||
} else {
|
||||
|
||||
Map statusResponseMap = JSON.decode(statusResponse.body);
|
||||
bool active = statusResponseMap['active'] == null ? false : statusResponseMap['active'];
|
||||
Map status = JSON.decode(statusResponse.body);
|
||||
bool active = status['active'] == null ? false : status['active'];
|
||||
|
||||
if (active) {
|
||||
startScanner(context);
|
||||
} else {
|
||||
if (await platform.invokeMethod('isOnline')) {
|
||||
createToken(await platform.invokeMethod('getMerchantID'), await platform.invokeMethod('getPosID')).then((response) {
|
||||
if (response.statusCode == 409) {
|
||||
pushRoute(context, new FinishRegistrationScreen());
|
||||
} else if (response.statusCode == 201) {
|
||||
platform.invokeMethod('removeKeys').then((result) {
|
||||
Map parsedMap = JSON.decode(result);
|
||||
String t = parsedMap['token'];
|
||||
deleteToken(t).then((response) {
|
||||
print(response.body);
|
||||
Navigator.of(context).pop(); // Убираем текущий route
|
||||
pushRoute(context, new RegistrationScreen()); // Запускаем регистрацию
|
||||
}).catchError((error) {
|
||||
print(error.toString());
|
||||
});
|
||||
});
|
||||
}
|
||||
}).catchError((error) => print(error.toString()));
|
||||
_createToken(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Отправляется запрос на создание токена.
|
||||
///
|
||||
/// Если вернулся код 409, значит такой токен уже существует и активирован.
|
||||
/// Нужно направить пользователя на экран подтверждения активации.
|
||||
///
|
||||
/// Если вернулся код 200, значит токен был ранее удален и только что снова создался.
|
||||
/// Нужно удалить его и направить пользователя на экран регистрации.
|
||||
_createToken(BuildContext ctx) async {
|
||||
String merchantID = await platform.invokeMethod('getMerchantID');
|
||||
String posID = await platform.invokeMethod('getPosID');
|
||||
createToken(merchantID, posID).then((response) {
|
||||
if (response.statusCode == 409) {
|
||||
pushRoute(ctx, new FinishRegistrationScreen());
|
||||
} else if (response.statusCode == 201) {
|
||||
platform.invokeMethod('removeKeys').then((result) {
|
||||
Map parsedMap = JSON.decode(result);
|
||||
deleteToken(parsedMap['token']).then((response) {
|
||||
print(response.body);
|
||||
Navigator.of(ctx).pop(); // Убираем текущий route
|
||||
pushRoute(ctx, new RegistrationScreen()); // Запускаем регистрацию
|
||||
}).catchError((error) {
|
||||
print(error.toString());
|
||||
});
|
||||
});
|
||||
}
|
||||
}).catchError((error) => print(error.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,45 @@
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:sprintf/sprintf.dart';
|
||||
import 'i18n/messages_all.dart';
|
||||
import 'dart:async';
|
||||
|
||||
class Strings extends LocaleQueryData {
|
||||
class Strings {
|
||||
|
||||
static Strings of(BuildContext context) {
|
||||
return LocaleQuery.of(context);
|
||||
static final Strings _singleton = new Strings._internal();
|
||||
|
||||
String _localeName;
|
||||
|
||||
factory Strings(){
|
||||
return _singleton;
|
||||
}
|
||||
|
||||
static final Strings instance = new Strings();
|
||||
Strings._internal();
|
||||
|
||||
String confirmPurchase(String val) {
|
||||
return sprintf(Intl.message('confirm_purchase'), val);
|
||||
Future load(String locale) async {
|
||||
_localeName = locale;
|
||||
return initializeMessages(locale);
|
||||
}
|
||||
|
||||
String purchaseCompleted(String val) {
|
||||
return sprintf(Intl.message('purchase_complite'), val);
|
||||
}
|
||||
|
||||
String idStore() => Intl.message('ID_Store');
|
||||
String signUp() => Intl.message('sign_up');
|
||||
String registration() => Intl.message('registration');
|
||||
String specifyDinStore() => Intl.message('specify_din_store');
|
||||
String confirmation() => Intl.message('confirmation');
|
||||
String askChangeStore() => Intl.message('ask_change_store');
|
||||
String yes() => Intl.message('yes');
|
||||
String no() => Intl.message('no');
|
||||
String requestSentWaitActivation() => Intl.message('request_sent_wait_activ');
|
||||
String refreshActivationStatus() => Intl.message('update_activ_status');
|
||||
String appActivated() => Intl.message('app_activ');
|
||||
String completeRegistration() => Intl.message('complite_activ');
|
||||
String cardScanner() => Intl.message('card_scaner');
|
||||
String userName() => Intl.message('user_name');
|
||||
String card() => Intl.message('card');
|
||||
String reward() => Intl.message('reward');
|
||||
String sum() => Intl.message('sum');
|
||||
String carryingPurchase() => Intl.message('carry_purchase');
|
||||
String completePurchase() => Intl.message('complite_purchase');
|
||||
String scan() => Intl.message('scan');
|
||||
String buyer() => Intl.message('buyer');
|
||||
String idNotFound() => Intl.message('ID_not_found');
|
||||
String registration() => Intl.message('registration', name: 'registration', locale: _localeName);
|
||||
String idStore() => Intl.message('ID_Store', name: 'ID_Store', locale: _localeName);
|
||||
String signUp() => Intl.message('sign_up', name: 'sign_up', locale: _localeName);
|
||||
String specifyDinStore() => Intl.message('specify_din_store', name: 'specify_din_store', locale: _localeName);
|
||||
String confirmation() => Intl.message('confirmation', name: 'confirmation', locale: _localeName);
|
||||
String askChangeStore() => Intl.message('ask_change_store', name: 'ask_change_store', locale: _localeName);
|
||||
String yes() => Intl.message('yes', name: 'yes', locale: _localeName);
|
||||
String no() => Intl.message('no', name: 'no', locale: _localeName);
|
||||
String requestSentWaitActivation() => Intl.message('request_sent_wait_activ', name: 'request_sent_wait_activ', locale: _localeName);
|
||||
String refreshActivationStatus() => Intl.message('update_activ_status', name: 'update_activ_status', locale: _localeName);
|
||||
String appActivated() => Intl.message('app_activ', name: 'app_activ', locale: _localeName);
|
||||
String completeRegistration() => Intl.message('complite_activ', name: 'complite_activ', locale: _localeName);
|
||||
String cardScanner() => Intl.message('card_scaner', name: 'card_scaner', locale: _localeName);
|
||||
String userName() => Intl.message('user_name', name: 'user_name', locale: _localeName);
|
||||
String card() => Intl.message('card', name: 'card', locale: _localeName);
|
||||
String reward() => Intl.message('reward', name: 'reward', locale: _localeName);
|
||||
String sum() => Intl.message('sum', name: 'sum', locale: _localeName);
|
||||
String carryingPurchase() => Intl.message('carry_purchase', name: 'carry_purchase', locale: _localeName);
|
||||
String completePurchase() => Intl.message('complite_purchase', name: 'complite_purchase', locale: _localeName);
|
||||
String scan() => Intl.message('scan', name: 'scan', locale: _localeName);
|
||||
String buyer() => Intl.message('buyer', name: 'buyer', locale: _localeName);
|
||||
String confirmPurchase() => Intl.message('confirm_purchase', name: 'confirm_purchase', locale: _localeName);
|
||||
String idNotFound() => Intl.message('ID_not_found', name: 'ID_not_found', locale: _localeName);
|
||||
}
|
||||
Reference in New Issue
Block a user