From 60090ea4377410d930f1a861cb687ef352c92100 Mon Sep 17 00:00:00 2001 From: Ivan Murashov Date: Wed, 6 Sep 2017 14:01:12 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9B=D0=BE=D0=BA=D0=B0=D0=BB=D1=8C=20=D0=BC?= =?UTF-8?q?=D0=BE=D0=B6=D0=BD=D0=BE=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=82=D1=8C?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=8D=D1=82=D0=B0=D0=BF=D0=B5=20=D1=81=D0=B1?= =?UTF-8?q?=D0=BE=D1=80=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/AndroidManifest.sublime-workspace | 217 ------------------ android/app/src/main/AndroidManifest.xml | 2 +- .../checker/AbstractScannerActivity.java | 2 +- .../java/com/dinect/checker/MainActivity.java | 11 +- .../com/dinect/checker/NetworkThread.java | 4 +- .../main/java/com/dinect/checker/Utils.java | 1 + .../dinect/{ => checker}/net/ApiClient.java | 12 +- .../net/DinectAuthorizationInterceptor.java | 2 +- .../app/src/main/res/values-ru/strings.xml | 12 + .../app/src/main/res/values-ua/strings.xml | 12 + android/app/src/main/res/values/strings.xml | 15 +- lib/base_state.dart | 47 ++-- lib/common.dart | 18 +- lib/faq.dart | 2 +- lib/finish_registration.dart | 27 ++- lib/i18n/messages_en.dart | 2 +- lib/i18n/messages_es.dart | 2 +- lib/i18n/messages_ru.dart | 2 +- lib/i18n/messages_ua.dart | 2 +- lib/main.dart | 22 +- lib/purchase.dart | 51 ++-- lib/purchase_success.dart | 14 +- lib/registration.dart | 48 ++-- lib/splash.dart | 15 +- lib/strings.dart | 69 +++--- 25 files changed, 226 insertions(+), 385 deletions(-) delete mode 100644 android/app/src/main/AndroidManifest.sublime-workspace rename android/app/src/main/java/com/dinect/{ => checker}/net/ApiClient.java (91%) rename android/app/src/main/java/com/dinect/{ => checker}/net/DinectAuthorizationInterceptor.java (98%) create mode 100644 android/app/src/main/res/values-ru/strings.xml create mode 100644 android/app/src/main/res/values-ua/strings.xml diff --git a/android/app/src/main/AndroidManifest.sublime-workspace b/android/app/src/main/AndroidManifest.sublime-workspace deleted file mode 100644 index 6c13090..0000000 --- a/android/app/src/main/AndroidManifest.sublime-workspace +++ /dev/null @@ -1,217 +0,0 @@ -{ - "auto_complete": - { - "selected_items": - [ - [ - "e", - "else" - ], - [ - "pre", - "previewing" - ], - [ - "purc", - "_purchase" - ] - ] - }, - "buffers": - [ - ], - "build_system": "", - "build_system_choices": - [ - ], - "build_varint": "", - "command_palette": - { - "height": 359.0, - "last_filter": "packa", - "selected_items": - [ - [ - "packa", - "Package Control: Install Package" - ], - [ - "pac", - "Install Package Control" - ] - ], - "width": 485.0 - }, - "console": - { - "height": 0.0, - "history": - [ - ] - }, - "distraction_free": - { - "menu_visible": true, - "show_minimap": false, - "show_open_files": false, - "show_tabs": false, - "side_bar_visible": false, - "status_bar_visible": false - }, - "file_history": - [ - "/Users/kifio/FlutterProjects/checker/lib/consts.dart", - "/Users/kifio/FlutterProjects/checker/lib/activate_token.dart", - "/Users/kifio/FlutterProjects/checker/lib/registration.dart", - "/Users/kifio/FlutterProjects/checker/lib/purchase_success.dart", - "/Users/kifio/FlutterProjects/checker/lib/purchase.dart", - "/Users/kifio/FlutterProjects/checker/lib/main.dart", - "/Users/kifio/FlutterProjects/checker/lib/faq.dart", - "/home/kifio/ShitCoding/checker/lib/main.dart", - "/home/kifio/ShitCoding/checker/lib/base_state.dart", - "/home/kifio/ShitCoding/checker/lib/splash.dart", - "/home/kifio/ShitCoding/checker/lib/registration.dart", - "/home/kifio/ShitCoding/checker/lib/activate_token.dart" - ], - "find": - { - "height": 23.0 - }, - "find_in_files": - { - "height": 93.0, - "where_history": - [ - "" - ] - }, - "find_state": - { - "case_sensitive": true, - "find_history": - [ - "intToken", - "http://pos-api-autoclub.dinect.com/20130701/", - "intUrl", - "async", - "common", - " \treturn new Text('Покупка на сумму 1234.00 руб. проведена', style: new TextStyle(color: tokenActiveTextColor, decorationColor: const Color(0x8ae28aff)));\n", - "getProgressIndicator", - "direc", - "_loading", - "_merchantID", - " \n", - "getPaddingForTextField", - "horiz", - "horizontaMargin", - "28.0", - "merchantID" - ], - "highlight": true, - "in_selection": false, - "preserve_case": false, - "regex": false, - "replace_history": - [ - "loading", - "textFieldValue", - "verticalMargin", - "_merchantID" - ], - "reverse": false, - "show_context": true, - "use_buffer2": true, - "whole_word": false, - "wrap": true - }, - "groups": - [ - { - "sheets": - [ - ] - } - ], - "incremental_find": - { - "height": 23.0 - }, - "input": - { - "height": 33.0 - }, - "layout": - { - "cells": - [ - [ - 0, - 0, - 1, - 1 - ] - ], - "cols": - [ - 0.0, - 1.0 - ], - "rows": - [ - 0.0, - 1.0 - ] - }, - "menu_visible": true, - "output.find_results": - { - "height": 0.0 - }, - "pinned_build_system": "", - "project": "AndroidManifest.sublime-project", - "replace": - { - "height": 42.0 - }, - "save_all_on_build": true, - "select_file": - { - "height": 0.0, - "last_filter": "", - "selected_items": - [ - ], - "width": 0.0 - }, - "select_project": - { - "height": 0.0, - "last_filter": "", - "selected_items": - [ - ], - "width": 0.0 - }, - "select_symbol": - { - "height": 0.0, - "last_filter": "", - "selected_items": - [ - ], - "width": 0.0 - }, - "selected_group": 0, - "settings": - { - }, - "show_minimap": true, - "show_open_files": false, - "show_tabs": true, - "side_bar_visible": true, - "side_bar_width": 241.0, - "status_bar_visible": true, - "template_settings": - { - } -} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a664487..cda80be 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -2,7 +2,7 @@ + android:versionName="1.0.1"> response = client.findUser(card); + final Pair response = client.findUser(activity, card); Log.d(TAG, "network request done with result: " + response.first); activity.runOnUiThread(new Runnable() { @Override diff --git a/android/app/src/main/java/com/dinect/checker/Utils.java b/android/app/src/main/java/com/dinect/checker/Utils.java index 32d94a2..b4987f2 100644 --- a/android/app/src/main/java/com/dinect/checker/Utils.java +++ b/android/app/src/main/java/com/dinect/checker/Utils.java @@ -7,6 +7,7 @@ import android.net.NetworkInfo; public class Utils { private Utils() { + } public static boolean isOnline(Context context) { diff --git a/android/app/src/main/java/com/dinect/net/ApiClient.java b/android/app/src/main/java/com/dinect/checker/net/ApiClient.java similarity index 91% rename from android/app/src/main/java/com/dinect/net/ApiClient.java rename to android/app/src/main/java/com/dinect/checker/net/ApiClient.java index f9b680f..3ea5cbb 100644 --- a/android/app/src/main/java/com/dinect/net/ApiClient.java +++ b/android/app/src/main/java/com/dinect/checker/net/ApiClient.java @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.dinect.net; +package com.dinect.checker.net; +import android.content.Context; import android.support.annotation.NonNull; import android.util.Log; import android.util.Pair; @@ -22,6 +23,7 @@ import android.util.Pair; import org.json.JSONArray; import org.json.JSONException; +import java.lang.String; import java.io.IOException; import java.util.concurrent.TimeUnit; @@ -30,6 +32,8 @@ import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import com.dinect.checker.R; + /** * Created by anonymous */ @@ -41,8 +45,6 @@ public final class ApiClient { private static final int TIMEOUT_CONNECTION = 3; private static final int TIMEOUT_READ = 3; private static final int TIMEOUT_WRITE = 3; - private static final String IDENTIFIER_NOT_FOUND = "Идентификатор {card} не найден."; - public final String endpoint; public final String appToken; @@ -76,7 +78,7 @@ public final class ApiClient { * @param card card/foreigncarf number * @return (null, error) on fail or (card, user) info on success */ - public Pair findUser(final @NonNull String card) { + public Pair findUser(Context ctx, final @NonNull String card) { final Request.Builder builder = new Request.Builder(); final Request request; @@ -91,7 +93,7 @@ public final class ApiClient { try { final Response response = http.newCall(request).execute(); final String body = response.body().string(); - final String NOT_FOUND_MESSAGE = IDENTIFIER_NOT_FOUND.replace("{card}", card); + final String NOT_FOUND_MESSAGE = String.format(ctx.getString(R.string.identifier_not_found, card)); switch (response.code()) { case 200: final JSONArray users = new JSONArray(body); diff --git a/android/app/src/main/java/com/dinect/net/DinectAuthorizationInterceptor.java b/android/app/src/main/java/com/dinect/checker/net/DinectAuthorizationInterceptor.java similarity index 98% rename from android/app/src/main/java/com/dinect/net/DinectAuthorizationInterceptor.java rename to android/app/src/main/java/com/dinect/checker/net/DinectAuthorizationInterceptor.java index 2d4a312..9d39896 100644 --- a/android/app/src/main/java/com/dinect/net/DinectAuthorizationInterceptor.java +++ b/android/app/src/main/java/com/dinect/checker/net/DinectAuthorizationInterceptor.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.dinect.net; +package com.dinect.checker.net; import java.io.IOException; diff --git a/android/app/src/main/res/values-ru/strings.xml b/android/app/src/main/res/values-ru/strings.xml new file mode 100644 index 0000000..d203e90 --- /dev/null +++ b/android/app/src/main/res/values-ru/strings.xml @@ -0,0 +1,12 @@ + + AutoBonus + Сканер карты + Сканировать + FAQ + Выход + Подтверждение + Вы действительно хотите выйти и ввести другой номер магазина? + Да + Нет + "Идентификатор %s не найден" + diff --git a/android/app/src/main/res/values-ua/strings.xml b/android/app/src/main/res/values-ua/strings.xml new file mode 100644 index 0000000..bd673a5 --- /dev/null +++ b/android/app/src/main/res/values-ua/strings.xml @@ -0,0 +1,12 @@ + + AutoBonus + Сканер карти + Сканувати + FAQ + Вихід + Підтвердження + Ви дійсно хочете вийти і ввести інший номер магазину? + Так + Ні + "Ідентифікатор %s не знайден" + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index d55053c..bc190eb 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -1,11 +1,12 @@ AutoBonus - Сканнер карты - Сканировать + Card Scanner + Scan FAQ - Выход - Подтверждение - Вы действительно хотите выйти и ввести другой номер магазина? - Да - Нет + Logout + Сonfirmation + Do you really want to log out and enter a different store number? + Yes + No + "Identifier %s is not found" diff --git a/lib/base_state.dart b/lib/base_state.dart index 297931b..9e23923 100644 --- a/lib/base_state.dart +++ b/lib/base_state.dart @@ -18,28 +18,26 @@ abstract class BaseState extends State { /// Введенное пользователем значение. String textFieldValue = ''; - Strings s; - @override Widget build(BuildContext ctx) { - return new Scaffold(appBar: getAppBar(ctx), + return new Scaffold(appBar: getAppBar(), body: new Stack(children: [ - getScreenContent(ctx), + getScreenContent(), new Center(child: loading ? new CircularProgressIndicator() : null) ])); } /// Возвращает контейнер с всеми виджетами экрана. - Widget getScreenContent(BuildContext ctx); + Widget getScreenContent(); /// Возвращает заголовок для AppBar - String getTitle(BuildContext ctx); + String getTitle(); - AppBar getAppBar(BuildContext ctx) { - return new AppBar(title: new Text(getTitle(ctx), style: new TextStyle(fontSize: 18.0)), - backgroundColor: primaryColor, actions: getMenuButtons(ctx)); + AppBar getAppBar() { + return new AppBar(title: new Text(getTitle(), style: new TextStyle(fontSize: 18.0)), + backgroundColor: primaryColor, actions: getMenuButtons()); } - List getMenuButtons(BuildContext context) { + List getMenuButtons() { return [getFaqButton()]; } @@ -52,28 +50,28 @@ abstract class BaseState extends State { } /// Возврвщает контейнер, внутри которого Text с подсказкой. - Widget getHintLabel(BuildContext ctx) { + Widget getHintLabel() { 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: [new Text(getHintString(ctx), textAlign: TextAlign.left, + children: [new Text(getHintString(), textAlign: TextAlign.left, style: new TextStyle(fontWeight: FontWeight.w300, color: error == null ? greyTextColor : primaryColor, fontSize: 14.0))])); } /// Возвращает подсказку, либо ошибку, если введенные в поле ввода данные неверны. - String getHintString(BuildContext ctx) { + String getHintString() { if (textFieldValue.length == 0 && error == null) { return ' '; } else if (error != null) { return error; } else { - return getHint(ctx); + return getHint(); } } /// Возвращает текст подсказки для поля ввода. /// Должен быть переопределен на экранах, на которых есть поле ввода. - String getHint(BuildContext ctx) { + String getHint() { return null; } @@ -85,14 +83,17 @@ abstract class BaseState extends State { } /// Метод возвращает контейнер с полем ввода внутри. - Widget getInputField(BuildContext ctx) { + Widget getInputField() { return new Container(margin: new EdgeInsets.only(left: verticalMargin, right: verticalMargin), 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))); + child: getTextWidget()); + } + + /// Возвращает поле ввода. + /// Переопределяется для использования на экранах регистрации и проведения покупки. + Widget getTextWidget() { + return null; } /// Возвращат паддинги для поля ввода. @@ -113,7 +114,7 @@ abstract class BaseState extends State { } /// Возвращает выпуклую залитую фирменным цветом кнопку - Widget buildRaisedButton(BuildContext context, String text, VoidCallback onPressed) { + Widget buildRaisedButton(String text, VoidCallback onPressed) { return new RaisedButton(child: new Text(text, style: new TextStyle(color: Colors.white)), onPressed: onPressed, @@ -138,7 +139,7 @@ abstract class BaseState extends State { /// Возвращает список, единственный элемент которого - Text с заголовком для текстового поля. List getDescriptionWidget(String title) { - return [new Text(title, textAlign: TextAlign.left, style: new TextStyle(color: greyTextColor, fontSize: 14.0))] + return [new Text(title, textAlign: TextAlign.left, style: new TextStyle(color: greyTextColor, fontSize: 14.0))]; } /// Возвращает список, единственный элемент которого - Text с информацией (размер скидки, сумма проведенной покупки). @@ -147,7 +148,7 @@ abstract class BaseState extends State { } /// Возвращает кнопку, обернутую набором специфичных контейнеров. - Widget buildButton(EdgeInsets margin, Widget widget) { + Widget wrapButton(EdgeInsets margin, Widget widget) { return new Container(margin: margin, height: buttonHeight, child: new Row(children: [new Expanded(child: widget)])); } diff --git a/lib/common.dart b/lib/common.dart index d87b03d..78c0075 100644 --- a/lib/common.dart +++ b/lib/common.dart @@ -11,9 +11,6 @@ import 'strings.dart'; // Канал для взаимодействия с кодом платформы. const platform = const MethodChannel('com.dinect.checker/instance_id'); -/// Токен кассы. Инициализируется при регистрации. -String token; - // Метод обеспечивает замену текущего объекта route новым. pushRoute(BuildContext context, Widget widget) { var route = new MaterialPageRoute(builder: (BuildContext context) => widget); @@ -27,8 +24,8 @@ faq(BuildContext context, bool returnToScanner) { } // В методе отправляется запрос на удаление токена кассы, очищаются SharedPreferences приложения. -logout(BuildContext context) { - +logout(BuildContext context) async { + String token = await platform.invokeMethod('getToken'); VoidCallback positiveCalback = () { if (token != null) { deleteToken(token).then((response) { @@ -47,11 +44,11 @@ logout(BuildContext context) { } }; - showYesNoDialog(context, Strings.of(context).confirmation(), Strings.of(context).askChangeStore(), positiveCalback); + showYesNoDialog(context, StringsLocalization.confirmation(), StringsLocalization.askChangeStore(), positiveCalback); } -forceLogout(BuildContext context) { - +forceLogout(BuildContext context) async { + String token = await platform.invokeMethod('getToken'); deleteToken(token).then((response) { print(response.body); platform.invokeMethod('removeKeys').then((result) { @@ -67,6 +64,7 @@ forceLogout(BuildContext context) { /// Может производиться с нескольких экранов (splash, finish_registration). startScanner(BuildContext context) async { + String token = await platform.invokeMethod('getToken'); // Канал ловит вызовы методов из "нативной" части приложения. // Могут быть вызваны либо logaut либо faq, либо purchase. if (token != null) { @@ -101,12 +99,12 @@ showYesNoDialog(BuildContext context, String title, String content, VoidCallback content: new Text(content), actions: [ new FlatButton( - child: new Text(Strings.of(context).no()), + child: new Text(StringsLocalization.no()), onPressed: () { Navigator.of(context).pop(); } ), new FlatButton( - child: new Text(Strings.of(context).yes()), + child: new Text(StringsLocalization.yes()), onPressed: positiveCallback)])); } diff --git a/lib/faq.dart b/lib/faq.dart index a3b53ed..f7885bf 100644 --- a/lib/faq.dart +++ b/lib/faq.dart @@ -51,7 +51,7 @@ class FAQScreenState extends BaseState { return "FAQ"; } - @override getMenuButtons(BuildContext context) { + @override getMenuButtons() { return [getLogoutButton()]; } diff --git a/lib/finish_registration.dart b/lib/finish_registration.dart index 38199cf..30b2351 100644 --- a/lib/finish_registration.dart +++ b/lib/finish_registration.dart @@ -24,11 +24,11 @@ class _RegistrationScreenState extends BaseState { } @override String getTitle() { - return Strings.of(context).registration(); + return StringsLocalization.registration(); } @override getHint() { - return Strings.of(context).idStore(); + return StringsLocalization.idStore(); } @override Widget getScreenContent() { @@ -37,9 +37,9 @@ class _RegistrationScreenState extends BaseState { getHintLabel(), getInputField(), getMessage(), - buildRaisedButton(context, _tokenActive - ? Strings.of(context).completeRegistration() - : Strings.of(context).refreshActivationStatus(), () => handleTap()) + buildRaisedButton(_tokenActive + ? StringsLocalization.completeRegistration() + : StringsLocalization.refreshActivationStatus(), () => handleTap()) ]); } @@ -50,6 +50,7 @@ class _RegistrationScreenState extends BaseState { startScanner(context); } else { if (await platform.invokeMethod('isOnline')) { + String token = await platform.invokeMethod('getToken'); checkTokenStatus(token).then((response) { print(response.body); @@ -68,8 +69,9 @@ class _RegistrationScreenState extends BaseState { } } - @override Widget getTextWidget() { - return new Row(children: [new Text(_merchantID != null ? _merchantID : '', style: new TextStyle(color: Colors.black, fontSize: 16.0))]); + @override getTextWidget() { + return new Row(children: [new Text(_merchantID != null ? _merchantID : '', + style: new TextStyle(color: Colors.black, fontSize: 16.0))]); } /// Достаем сохраненный в SharedPreferences merchantID. @@ -84,7 +86,7 @@ class _RegistrationScreenState extends BaseState { /// Метод возвращает контейнер с текстом сообщения и бэкграундом. getMessage() { - return new Container(height: _tokenActive ? 72.0 : 108.0, decoration: _getDecoraionForMessageField(), + return new Container(height: _tokenActive ? 72.0 : 108.0, decoration: _getDecorationForMessageField(), margin: new EdgeInsets.only(top: 20.0, left: 12.0, right: 12.0), padding: new EdgeInsets.only(bottom: 22.0, left: 14.0, right: 14.0), child: new Center(child: getMessageTextWidget())); @@ -100,13 +102,14 @@ class _RegistrationScreenState extends BaseState { /// Получаем текст сообщения, в зависимости от статуса активации. getMessageString() { return _tokenActive - ? Strings.of(context).completeRegistration() - : Strings.of(context).refreshActivationStatus(); + ? StringsLocalization.completeRegistration() + : StringsLocalization.refreshActivationStatus(); } /// Фоновое изображение для сообщения. - Decoration _getDecoraionForMessageField() { + Decoration _getDecorationForMessageField() { return new BoxDecoration(image: new DecorationImage( - image: new ExactAssetImage(_tokenActive ? active_token_bg_png : activate_token_bg_png), fit: _tokenActive ? BoxFit.fitWidth : BoxFit.fill)); + image: new ExactAssetImage(_tokenActive ? active_token_bg_png : activate_token_bg_png), + fit: _tokenActive ? BoxFit.fitWidth : BoxFit.fill)); } } \ No newline at end of file diff --git a/lib/i18n/messages_en.dart b/lib/i18n/messages_en.dart index 048896b..846e453 100644 --- a/lib/i18n/messages_en.dart +++ b/lib/i18n/messages_en.dart @@ -16,7 +16,7 @@ class MessageLookup extends MessageLookupByLibrary { final messages = _notInlinedMessages(_notInlinedMessages); static _notInlinedMessages(_) => { "ID_Store" : MessageLookupByLibrary.simpleMessage("DIN Store"), - "ID_not_found" : MessageLookupByLibrary.simpleMessage("Identifier N is not found"), + "ID_not_found" : MessageLookupByLibrary.simpleMessage("Identifier %s is not found"), "app_activ" : MessageLookupByLibrary.simpleMessage("The application is activated"), "ask_change_store" : MessageLookupByLibrary.simpleMessage("Do you really want to log out and enter a different store number?"), "buyer" : MessageLookupByLibrary.simpleMessage("Buyer"), diff --git a/lib/i18n/messages_es.dart b/lib/i18n/messages_es.dart index bbf243b..0faa5d9 100644 --- a/lib/i18n/messages_es.dart +++ b/lib/i18n/messages_es.dart @@ -16,7 +16,7 @@ class MessageLookup extends MessageLookupByLibrary { final messages = _notInlinedMessages(_notInlinedMessages); static _notInlinedMessages(_) => { "ID_Store" : MessageLookupByLibrary.simpleMessage("DIN del negocio "), - "ID_not_found" : MessageLookupByLibrary.simpleMessage("ID N no está encontrado"), + "ID_not_found" : MessageLookupByLibrary.simpleMessage("ID %s no está encontrado"), "app_activ" : MessageLookupByLibrary.simpleMessage("Aplicación está activada"), "ask_change_store" : MessageLookupByLibrary.simpleMessage("¿Os realmente quiereis acabarse una sesión y dar otro DIN del negocio?"), "buyer" : MessageLookupByLibrary.simpleMessage("El comprador"), diff --git a/lib/i18n/messages_ru.dart b/lib/i18n/messages_ru.dart index 3bd155b..bce5b66 100644 --- a/lib/i18n/messages_ru.dart +++ b/lib/i18n/messages_ru.dart @@ -16,7 +16,7 @@ class MessageLookup extends MessageLookupByLibrary { final messages = _notInlinedMessages(_notInlinedMessages); static _notInlinedMessages(_) => { "ID_Store" : MessageLookupByLibrary.simpleMessage("DIN магазина"), - "ID_not_found" : MessageLookupByLibrary.simpleMessage("Идентификатор N не найден"), + "ID_not_found" : MessageLookupByLibrary.simpleMessage("Идентификатор %s не найден"), "app_activ" : MessageLookupByLibrary.simpleMessage("Приложение активировано"), "ask_change_store" : MessageLookupByLibrary.simpleMessage("Вы действительно хотите выйти и ввести другой номер магазина?"), "buyer" : MessageLookupByLibrary.simpleMessage("Покупатель"), diff --git a/lib/i18n/messages_ua.dart b/lib/i18n/messages_ua.dart index 7bb9dbc..ac058c6 100644 --- a/lib/i18n/messages_ua.dart +++ b/lib/i18n/messages_ua.dart @@ -16,7 +16,7 @@ class MessageLookup extends MessageLookupByLibrary { final messages = _notInlinedMessages(_notInlinedMessages); static _notInlinedMessages(_) => { "ID_Store" : MessageLookupByLibrary.simpleMessage("DIN магазину"), - "ID_not_found" : MessageLookupByLibrary.simpleMessage("Ідентифікатор N не знайден"), + "ID_not_found" : MessageLookupByLibrary.simpleMessage("Ідентифікатор %s не знайден"), "app_activ" : MessageLookupByLibrary.simpleMessage("Додаток активований"), "ask_change_store" : MessageLookupByLibrary.simpleMessage("Ви дійсно хочете вийти і ввести інший номер магазину"), "buyer" : MessageLookupByLibrary.simpleMessage("Покупець"), diff --git a/lib/main.dart b/lib/main.dart index 677587e..d0d13ae 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,8 +2,23 @@ import 'package:flutter/material.dart'; import 'splash.dart'; import 'consts.dart'; import 'strings.dart'; +import 'common.dart'; import 'dart:async'; +class StringsLocalizationDelegate extends LocalizationsDelegate { + + @override + Future load(Locale locale) async { + return StringsLocalization.load(await platform.invokeMethod("getLocale")); + } + + @override + bool shouldReload(LocalizationsDelegate old) { + return false; + } + +} + /// Точка входа в приложение. void main() { runApp(new Checker()); @@ -18,7 +33,12 @@ class CheckerState extends State { @override Widget build(BuildContext context) { return new MaterialApp( title: appName, - home: new SplashScreen() + home: new SplashScreen(), + localizationsDelegates: getLocalizationsDelegate() ); } + + getLocalizationsDelegate() { + return [new StringsLocalizationDelegate()]; + } } diff --git a/lib/purchase.dart b/lib/purchase.dart index b71fd87..6922afc 100644 --- a/lib/purchase.dart +++ b/lib/purchase.dart @@ -31,24 +31,24 @@ class PurchaseScreenState extends BaseState { PurchaseScreenState(String userString, String card) { this.user = JSON.decode(userString); this.card = card; - getLoyality(user['loyalty_url']); + getLoyalty(user['loyalty_url']); } bool purchaseInProgress = false; Map user; String card = ''; - String loyality = ''; + String loyalty = ''; @override Widget getScreenContent() { return new Column( children: [new Expanded(child: new ListView(children: [ - getValueWithDescription(Strings.of(context).userName(), user['first_name'] == null ? '' : user['first_name']), - getValueWithDescription(Strings.of(context).card(), card), - getValueWithDescription(Strings.of(context).reward(), loyality), + getValueWithDescription(StringsLocalization.userName(), user['first_name'] == null ? '' : user['first_name']), + getValueWithDescription(StringsLocalization.card(), card), + getValueWithDescription(StringsLocalization.reward(), loyalty), getHintLabel(), getInputField(), - buildButton(getScreenMargins(36.0), getCompleteButton()), - buildButton(getScreenMargins(24.0), getScanButton(context, Strings.of(context).scan(), primaryColor)) + wrapButton(getScreenMargins(36.0), getCompleteButton()), + wrapButton(getScreenMargins(24.0), getScanButton(context, StringsLocalization.scan(), primaryColor)) ]))]); } @@ -58,8 +58,7 @@ class PurchaseScreenState extends BaseState { } getCompleteButton() { - String title = Strings.of(context).completePurchase(); - return buildRaisedButton(context, title, () => onPurchaseClick(context)); + return buildRaisedButton(StringsLocalization.completePurchase(), () => onPurchaseClick()); } Widget getScanButton(BuildContext context, String title, Color textColor) { @@ -76,21 +75,17 @@ class PurchaseScreenState extends BaseState { } @override String getTitle() { - return Strings.of(context).carryingPurchase(); + return StringsLocalization.carryingPurchase(); } @override getHint() { - return Strings.of(context).sum(); + return StringsLocalization.sum(); } - @override getMenuButtons(BuildContext context) { + @override getMenuButtons() { return [getFaqButton(), getLogoutButton()]; } - @override Color getTextFilledBackground() { - return Colors.white; - } - @override getTextWidget() { return new TextField( keyboardType: TextInputType.number, @@ -109,10 +104,12 @@ class PurchaseScreenState extends BaseState { ); } - getLoyality(String url) async { + getLoyalty(String url) async { if (await platform.invokeMethod('isOnline')) { + String token = await platform.invokeMethod('getToken'); + var headers = { 'DM-Authorization': 'dmapptoken $appToken', 'Authorization': 'dmtoken ${token}' @@ -126,11 +123,11 @@ class PurchaseScreenState extends BaseState { String type = bonuses['type']; setState(() { if (type == 'amount') { - this.loyality = '${user['discount']}%'; + this.loyalty = '${user['discount']}%'; } else { List amountToBonus = bonuses['amount_to_bonus']; double loyalityVal = (double.parse(amountToBonus[1]) / amountToBonus[0]) * 100; - this.loyality = '${loyalityVal.toStringAsFixed(0)}%'; + this.loyalty = '${loyalityVal.toStringAsFixed(0)}%'; } }); }).catchError((error) { @@ -175,20 +172,20 @@ class PurchaseScreenState extends BaseState { return sumTotal.toStringAsFixed(2); } - onPurchaseClick(BuildContext context) { + onPurchaseClick() { String val = _parseSum(controller.text); showDialog(context: context, child: new AlertDialog( - title: new Text(Strings.of(context).confirmation()), - content: new Text(getContentMessage(val)), + title: new Text(StringsLocalization.confirmation()), + content: new Text(StringsLocalization.confirmPurchase(val)), actions: [ new FlatButton( - child: new Text(Strings.of(context).no()), + child: new Text(StringsLocalization.no()), onPressed: () { Navigator.of(context).pop(); }, ), new FlatButton( - child: new Text(Strings.of(context).yes()), + child: new Text(StringsLocalization.yes()), onPressed: () { purchase(val); }, @@ -196,14 +193,12 @@ class PurchaseScreenState extends BaseState { ])); } - getContentMessage(String val) { - return Strings.of(context).confirmPurchase(); - } - purchase(String sumTotal) async { if (await platform.invokeMethod('isOnline')) { if (!purchaseInProgress) { purchaseInProgress = true; + + String token = await platform.invokeMethod('getToken'); platform.invokeMethod('getDocID').then((result) { String url = user['purchases_url']; diff --git a/lib/purchase_success.dart b/lib/purchase_success.dart index 25fff7e..f257fec 100644 --- a/lib/purchase_success.dart +++ b/lib/purchase_success.dart @@ -22,12 +22,12 @@ class PurchaseSuccessScreenState extends BaseState { String sum; String username; - @override getMenuButtons(BuildContext context) { + @override getMenuButtons() { return [getFaqButton(), getLogoutButton()]; } @override String getTitle() { - return Strings.of(context).carryingPurchase(); + return StringsLocalization.carryingPurchase(); } @override String getHint() { @@ -36,10 +36,10 @@ class PurchaseSuccessScreenState extends BaseState { @override Widget getScreenContent() { return new Column(children: [ - getValueWithDescription(Strings.of(context).buyer(), username), + getValueWithDescription(StringsLocalization.buyer(), username), getSuccessMessage(), new Expanded(child: new Center()), - buildButton(getScreenMargins(74.0), getScanButton()) + wrapButton(getScreenMargins(74.0), getScanButton()) ]); } @@ -49,8 +49,8 @@ class PurchaseSuccessScreenState extends BaseState { } getScanButton() { - String title = Strings.of(context).scan(); - return buildRaisedButton(context, title, () => startScanner(context)); + String title = StringsLocalization.scan(); + return buildRaisedButton(title, () => startScanner(context)); } getSuccessMessage() { @@ -61,7 +61,7 @@ class PurchaseSuccessScreenState extends BaseState { } getMessageTitle() { - return Strings.of(context).purchaseCompleted(sum); + return StringsLocalization.purchaseCompleted(sum); } } \ No newline at end of file diff --git a/lib/registration.dart b/lib/registration.dart index 9f1e945..0213c8b 100644 --- a/lib/registration.dart +++ b/lib/registration.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'dart:convert'; // Пакет для обработки json с ответом от сервера. import 'package:checker/common.dart'; +import 'package:checker/consts.dart'; import 'package:checker/network.dart'; import 'package:checker/base_state.dart'; import 'package:checker/strings.dart'; @@ -14,36 +15,42 @@ class RegistrationScreen extends StatefulWidget { class _RegistrationScreenState extends BaseState { - @override String getTitle(BuildContext ctx) { - return "registration"; + @override String getTitle() { + return StringsLocalization.registration(); } - @override getHint(BuildContext ctx) { - return "idStore()"; + @override getHint() { + return StringsLocalization.idStore(); } - // Список виджетов, автоматически прокручиваемый вверх при открытии клавиатуры. - @override Widget getScreenContent(BuildContext ctx) { - print(new Strings().registration()); + /// Список виджетов, автоматически прокручиваемый вверх при открытии клавиатуры. + @override Widget getScreenContent() { return new Container( child: new ListView(children: [ new Column(children: [ getLogo(), - getHintLabel(ctx), - getInputField(ctx), - getButton(ctx)]) + getHintLabel(), + getInputField(), + getButton()]) ])); } + @override 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)); + } + /// Возвращает кнопку регистрации. - getButton(BuildContext ctx) { + getButton() { return new Container(margin: new EdgeInsets.only(top: 36.0), child: - buildRaisedButton(ctx, "signUp()", getOnPressed(ctx))); + buildRaisedButton(StringsLocalization.signUp(), getOnPressed())); } // Возвращает обработчик нажатий на кнопку регистрации. - getOnPressed(BuildContext ctx) { - return _isValidMerchantID() && !loading ? () => _registerShop(ctx) : null; + getOnPressed() { + return _isValidMerchantID() && !loading ? () => _registerShop() : null; } /// Токен кассы - это DIN код. DIN код - это специальный код динекта, максимальная его длина - 25 символов. @@ -53,15 +60,15 @@ class _RegistrationScreenState extends BaseState { } /// Показать progressBar, запросить токен. - _registerShop(BuildContext ctx) { + _registerShop() { setState(() { loading = true; - _register(ctx); + _register(); }); } /// Получение от платформы id установки, формирование запроса на получение токена, сохранение токена. - _register(BuildContext ctx) async { + _register() async { if (await platform.invokeMethod('isOnline')) { createToken(textFieldValue, await platform.invokeMethod('getPosID')).then((response) { @@ -69,14 +76,15 @@ class _RegistrationScreenState extends BaseState { error = null; loading = false; }); - + print(response.body); + Map parsedMap = JSON.decode(response.body); if (response.statusCode == 201) { - token = parsedMap['token']; + String token = parsedMap['token']; platform.invokeMethod('saveToken', {'token' : token}); platform.invokeMethod('saveMerchantID', {'merchantID' : textFieldValue}); - pushRoute(ctx, new FinishRegistrationScreen()); + pushRoute(context, new FinishRegistrationScreen()); } else { setState(() { error = parsedMap['errors'][0]; diff --git a/lib/splash.dart b/lib/splash.dart index bf33796..16cef33 100644 --- a/lib/splash.dart +++ b/lib/splash.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; import 'dart:async'; import 'dart:convert'; @@ -16,14 +17,14 @@ class SplashScreen extends StatelessWidget { Widget build(BuildContext context) { // Появляется splash screen, проверяется токен. - Strings s = new Strings(); - s.load("ru").then((_) { - showNextScreen(context); + new Future.delayed(const Duration(milliseconds: 500), () { + platform.invokeMethod("getLocale").then((locale) { + Intl.defaultLocale = locale; + print(Intl.defaultLocale); + showNextScreen(context); + }); }); -// new Future.delayed(const Duration(milliseconds: 500), () { -// }); - return new Stack(children: [getSplashBackground(), getLogo(), new Align(alignment: FractionalOffset.bottomRight, child: new Container(margin: new EdgeInsets.only(right: 11.0, bottom: 5.0), child: @@ -48,7 +49,7 @@ class SplashScreen extends StatelessWidget { /// Запуск следующего экрана приложения. showNextScreen(BuildContext context) async { - token = await platform.invokeMethod('getToken'); + String token = await platform.invokeMethod('getToken'); // В случае, если в приложении отсутствует токен, // необходимо запустить регистрацию кассы. diff --git a/lib/strings.dart b/lib/strings.dart index 8f1eae0..8b030f7 100644 --- a/lib/strings.dart +++ b/lib/strings.dart @@ -1,45 +1,42 @@ import 'package:intl/intl.dart'; import 'i18n/messages_all.dart'; +import 'package:sprintf/sprintf.dart'; import 'dart:async'; -class Strings { +class StringsLocalization { - static final Strings _singleton = new Strings._internal(); - - String _localeName; - - factory Strings(){ - return _singleton; - } - - Strings._internal(); - - Future load(String locale) async { - _localeName = locale; + static Future load(String locale) async { return initializeMessages(locale); } - 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); + static String confirmPurchase(String val) { + return sprintf(Intl.message('confirm_purchase', name: 'confirm_purchase', locale: Intl.defaultLocale), [val]); + } + + static String purchaseCompleted(String val) { + return sprintf(Intl.message('purchase_complite', name: 'purchase_complite', locale: Intl.defaultLocale), [val]); + } + + static String registration() => Intl.message('registration', name: 'registration', locale: Intl.defaultLocale); + static String idStore() => Intl.message('ID_Store', name: 'ID_Store', locale: Intl.defaultLocale); + static String signUp() => Intl.message('sign_up', name: 'sign_up', locale: Intl.defaultLocale); + static String specifyDinStore() => Intl.message('specify_din_store', name: 'specify_din_store', locale: Intl.defaultLocale); + static String confirmation() => Intl.message('confirmation', name: 'confirmation', locale: Intl.defaultLocale); + static String askChangeStore() => Intl.message('ask_change_store', name: 'ask_change_store', locale: Intl.defaultLocale); + static String yes() => Intl.message('yes', name: 'yes', locale: Intl.defaultLocale); + static String no() => Intl.message('no', name: 'no', locale: Intl.defaultLocale); + static String requestSentWaitActivation() => Intl.message('request_sent_wait_activ', name: 'request_sent_wait_activ', locale: Intl.defaultLocale); + static String refreshActivationStatus() => Intl.message('update_activ_status', name: 'update_activ_status', locale: Intl.defaultLocale); + static String appActivated() => Intl.message('app_activ', name: 'app_activ', locale: Intl.defaultLocale); + static String completeRegistration() => Intl.message('complite_activ', name: 'complite_activ', locale: Intl.defaultLocale); + static String cardScanner() => Intl.message('card_scaner', name: 'card_scaner', locale: Intl.defaultLocale); + static String userName() => Intl.message('user_name', name: 'user_name', locale: Intl.defaultLocale); + static String card() => Intl.message('card', name: 'card', locale: Intl.defaultLocale); + static String reward() => Intl.message('reward', name: 'reward', locale: Intl.defaultLocale); + static String sum() => Intl.message('sum', name: 'sum', locale: Intl.defaultLocale); + static String carryingPurchase() => Intl.message('carry_purchase', name: 'carry_purchase', locale: Intl.defaultLocale); + static String completePurchase() => Intl.message('complite_purchase', name: 'complite_purchase', locale: Intl.defaultLocale); + static String scan() => Intl.message('scan', name: 'scan', locale: Intl.defaultLocale); + static String buyer() => Intl.message('buyer', name: 'buyer', locale: Intl.defaultLocale); + static String idNotFound() => Intl.message('ID_not_found', name: 'ID_not_found', locale: Intl.defaultLocale); } \ No newline at end of file