From 40fed84275ab90fad702bd0d638584d4a7409ad4 Mon Sep 17 00:00:00 2001 From: kifio Date: Sat, 23 Sep 2017 23:19:32 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=BF=D1=80=D0=BE=D1=89=D0=B5=D0=BD?= =?UTF-8?q?=D0=B0=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20=D1=81=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=BA=D0=B0=D0=BB=D1=8C=D1=8E,=20=D0=B1=D0=B0=D0=B7?= =?UTF-8?q?=D0=BE=D0=B2=D1=8B=D0=B9=20url=20=D0=B8=20=D1=82=D0=BE=D0=BA?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=BF=D1=80=D0=B8=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B2=D1=8B=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=D1=8B?= =?UTF-8?q?=20=D0=B2=20build.gradle,=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D1=80=D0=B0=D0=B7=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B8=20=D0=B8=20=D1=82=D0=B5=D1=81=D1=82=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F,=20=D0=B8=D1=81?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B1=D0=BB=D0=B5=D0=BC=D0=B0=20=D1=81=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D1=85=D0=BE=D0=B4=D0=BE=D0=BC=20=D0=BD=D0=B0=20?= =?UTF-8?q?=D1=8D=D0=BA=D1=80=D0=B0=D0=BD=20=D1=81=D0=BA=D0=B0=D0=BD=D0=B5?= =?UTF-8?q?=D1=80=D0=B0=20=D0=B5=D1=81=D0=BB=D0=B8=20=D0=BB=D0=BE=D0=BA?= =?UTF-8?q?=D0=B0=D0=BB=D1=8C=20=D0=BD=D0=B5=20=D0=B2=D1=8B=D0=B1=D0=B8?= =?UTF-8?q?=D1=80=D0=B0=D0=BB=D0=B0=D1=81=D1=8C=20=D0=B2=20=D0=BD=D0=B0?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA=D0=B0=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 +- android/app/build.gradle | 17 +- .../java/com/dinect/checker/MainActivity.java | 50 ++--- lib/base/base_state.dart | 6 +- lib/common.dart | 31 ++-- lib/consts.dart | 9 - lib/db.dart | 2 +- lib/main.dart | 7 +- lib/network.dart | 67 +++++-- lib/screens/finish_registration.dart | 4 +- lib/screens/languages.dart | 14 +- lib/screens/purchase.dart | 175 +++++++++--------- lib/screens/registration.dart | 64 ++++--- lib/screens/splash.dart | 72 +++---- settings.gradle | 2 + 15 files changed, 277 insertions(+), 255 deletions(-) create mode 100644 settings.gradle diff --git a/README.md b/README.md index 284ed3f..37c8c80 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ Для запуска необходимо установить [Dart](https://www.dartlang.org/install) - язык программирования и [flutter](https://flutter.io/setup/) - фреймворк для создания кроссплатформенных мобильных приложений на этом языке. - Для сборки и запуска приложения используются команды flutter run (собирает debug apk, устанавливает его на устройство) и flutter build (собирает release apk, не устанавливает на устройство). @@ -20,11 +19,9 @@ flutter build (собирает release apk, не устанавливает н 2) В файл pubscpec.yaml в раздел assets/ добавить пути этих изображений. 3) В файл lib/resources.dart в методы ```getPrimaryColor``` и ```getButtonsColor``` - добавить цвета необходимые цвета.* - -4) В файле consts.dart изменить значения переменных appName, url, appToken на правильные для сборки значения.* + добавить цвета необходимые цвета. -5) В файл android/app/build.gradle в раздел productFlavors добавить блок следующего вида: +4) В файл android/app/build.gradle в раздел productFlavors добавить блок следующего вида: ``` %name% { applicationId 'com.dinect.autobonus' @@ -33,6 +30,8 @@ flutter build (собирает release apk, не устанавливает н buildConfigField "int", "currency", "643" buildConfigField "String", "supportPhone", "\"8-800-234-6064\"" buildConfigField "String", "supportUrl", "\"https://www.auto-club.biz\"" + buildConfigField "String", "endpoint", "\"https://pos-api-int.dinect.com/20130701/\"" + buildConfigField "String", "appToken", "\"9fec83cdca38c357e6b65dbb17514cdd36bf2a08\"" } ``` @@ -46,7 +45,6 @@ flutter build (собирает release apk, не устанавливает н ``` - Иконки проще всего нарезать тут: https://romannurik.github.io/AndroidAssetStudio/icons-launcher.html @@ -55,8 +53,6 @@ https://romannurik.github.io/AndroidAssetStudio/icons-launcher.html После выполнения всех этих пунктов появится возможность собирать приложение как описано выше(flutter run --flavor %name% либо flutter build apk --flavor %name%). -\* - параметры из этих пунктов будут при первой же возможности перенесены в пункт 5, чтобы менять их из одного места. - #Добавление локализации приложения 1) В каталог lib/i18n добавить файл messages_%locale%.dart. diff --git a/android/app/build.gradle b/android/app/build.gradle index b1031b6..c50c395 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -49,6 +49,8 @@ android { buildConfigField "int", "currency", "643" buildConfigField "String", "supportPhone", "\"8-800-234-6064\"" buildConfigField "String", "supportUrl", "\"https://www.auto-club.biz\"" + buildConfigField "String", "endpoint", "\"https://pos-api-autoclub.dinect.com/20130701/\"" + buildConfigField "String", "appToken", "\"bdea0f3ba9034b688019a7cac753d1209e2b227f\"" } pip { @@ -58,6 +60,19 @@ android { buildConfigField "int", "currency", "980" buildConfigField "String", "supportPhone", "\"+38 080 030 9997\\n+38 044 390 1697\"" buildConfigField "String", "supportUrl", "\"http://discount.kiev.ua/\"" + buildConfigField "String", "endpoint", "\"https://pos-api.discount.kiev.ua/20130701/\"" + buildConfigField "String", "appToken", "\"bdea0f3ba9034b688019a7cac753d1209e2b227f\"" + } + + develop { + applicationId 'com.dinect.develop' + buildConfigField "String", "locale", "\"ru\"" + buildConfigField "String", "flavor", "\"autobonus\"" + buildConfigField "int", "currency", "643" + buildConfigField "String", "supportPhone", "\"8 800 555 35 35\"" + buildConfigField "String", "supportUrl", "\"http://yandex.ru/\"" + buildConfigField "String", "endpoint", "\"https://pos-api-int.dinect.com/20130701/\"" + buildConfigField "String", "appToken", "\"9fec83cdca38c357e6b65dbb17514cdd36bf2a08\"" } } @@ -79,7 +94,7 @@ flutter { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) + compile fileTree(include: ['*.jar'], dir: 'libs') compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.squareup.okhttp3:okhttp:3.8.1' compile 'com.squareup.okio:okio:1.13.0' diff --git a/android/app/src/main/java/com/dinect/checker/MainActivity.java b/android/app/src/main/java/com/dinect/checker/MainActivity.java index 11cf72a..66118fe 100644 --- a/android/app/src/main/java/com/dinect/checker/MainActivity.java +++ b/android/app/src/main/java/com/dinect/checker/MainActivity.java @@ -4,50 +4,37 @@ import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; import android.os.Bundle; -import android.util.Log; import android.widget.Toast; - -import com.dinect.checker.net.ApiClient; import com.dinect.checker.zbar.CameraActivity; import com.dinect.checker.zxing.ScannerActivity; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; -import java.util.Map; - import io.flutter.app.FlutterActivity; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugins.GeneratedPluginRegistrant; +import java.util.*; + public class MainActivity extends FlutterActivity { - static final String TAG = "Checker.MainActivity"; - private static final int START_SCANNER_REQUEST_CODE = 2017; + private static final String FLUTTER_CHANNEL_NAME = "com.dinect.checker/instance_id"; - public static final String PREF_API_URL = "prefs_api_token"; - public static final String PREF_APP_TOKEN = "pres_app_token"; - public static final String PREF_POS_TOKEN = "pref_pos_token"; + static final String PREF_API_URL = "prefs_api_token"; + static final String PREF_APP_TOKEN = "pres_app_token"; + static final String PREF_POS_TOKEN = "pref_pos_token"; static final String PREF_APP_BAR_COLOR = "pref_app_bar_color"; + static final String SCANNER_BACKEND_KEY = "scanner_backend_idx"; - public static final int ZXING = 0; - public static final int ZBAR = 1; + static final int ZXING = 0; + static final int ZBAR = 1; static final Class[] SCANNER_BACKEND = { ScannerActivity.class, CameraActivity.class, }; - static final String SCANNER_BACKEND_KEY = "scanner_backend_idx"; - private MethodChannel mChannel; private Map mScannerArgs; @@ -55,9 +42,9 @@ public class MainActivity extends FlutterActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); GeneratedPluginRegistrant.registerWith(this); - mChannel = new MethodChannel(getFlutterView(), "com.dinect.checker/instance_id"); + mChannel = new MethodChannel(getFlutterView(), FLUTTER_CHANNEL_NAME); mChannel.setMethodCallHandler( - new MethodCallHandler() { + new MethodChannel.MethodCallHandler() { @Override public void onMethodCall(MethodCall call, Result result) { callMethod(call, result); @@ -89,6 +76,12 @@ public class MainActivity extends FlutterActivity { case "getSupportUrl": result.success(BuildConfig.supportUrl); break; + case "getEndpoint": + result.success(BuildConfig.endpoint); + break; + case "getAppToken": + result.success(BuildConfig.appToken); + break; default: result.notImplemented(); break; @@ -112,6 +105,7 @@ public class MainActivity extends FlutterActivity { } private void setLocale(String locale) { + locale = locale != null ? locale : getLanguage(); Resources res = getResources(); Configuration configuration = new Configuration(res.getConfiguration()); configuration.locale = new Locale(locale); @@ -146,7 +140,6 @@ public class MainActivity extends FlutterActivity { mChannel.invokeMethod("purchase", args); } else { String menuItem = data.getExtras().getString("item", null); - Log.d(TAG, menuItem); if (menuItem != null) { mChannel.invokeMethod(menuItem, null); } @@ -190,4 +183,11 @@ public class MainActivity extends FlutterActivity { } + public void getEndpoint() { + + } + + public void getAppToken() { + + } } diff --git a/lib/base/base_state.dart b/lib/base/base_state.dart index 43356ad..272b6f1 100644 --- a/lib/base/base_state.dart +++ b/lib/base/base_state.dart @@ -24,7 +24,7 @@ abstract class BaseState extends State { String error; /// Введенное пользователем значение. - String dinCode = ''; + String merchantID = ''; Widget getMainWidget() { return app == null ? getBackground() : new Scaffold(appBar: getAppBar(), @@ -112,7 +112,7 @@ abstract class BaseState extends State { /// Возвращает подсказку, либо ошибку, если введенные в поле ввода данные неверны. String getHintOrError() { - if (dinCode.length == 0 && error == null) { + if (merchantID.length == 0 && error == null) { return ' '; } else if (error != null) { return error; @@ -130,7 +130,7 @@ abstract class BaseState extends State { /// Смена состояния экрана при изменении текста в поле ввода. void handleUserInput(String text) { setState(() { - dinCode = text; + merchantID = text; }); } diff --git a/lib/common.dart b/lib/common.dart index 3a64b8d..7d63043 100644 --- a/lib/common.dart +++ b/lib/common.dart @@ -4,8 +4,8 @@ import 'package:checker/screens/settings.dart'; import 'package:checker/screens/splash.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:intl/intl.dart'; -import 'consts.dart'; import 'db.dart'; import 'network.dart'; import 'resources.dart'; @@ -34,11 +34,11 @@ faq(BuildContext context, bool returnToScanner) { logout(BuildContext context, SqliteHelper helper) async { String token = await helper.getToken(); - String locale = await helper.getLocale(); +// String locale = await helper.getLocale(); VoidCallback positiveCallback = () { if (token != null) { - deleteToken(token, locale).then((response) { + getDeleteTokenRequest(token).then((response) { helper.clear().then((result) { helper.close().then((_) { Navigator.of(context).pop(); @@ -59,8 +59,7 @@ logout(BuildContext context, SqliteHelper helper) async { } forceLogout(String token , BuildContext context) async { - - deleteToken(token, 'ru').then((response) { + getDeleteTokenRequest(token).then((response) { SqliteHelper helper = new SqliteHelper(); helper.open().then((_) { helper.clear().then((_) { @@ -87,7 +86,6 @@ startScanner(BuildContext context, String app, SqliteHelper helper) async { }); } else { String token = await helper.getToken(); - String locale = await helper.getLocale(); helper.close(); // Канал ловит вызовы методов из "нативной" части приложения. // Могут быть вызваны либо logout либо faq, либо purchase. @@ -116,15 +114,20 @@ startScanner(BuildContext context, String app, SqliteHelper helper) async { } }); - await platform.invokeMethod('startScanner', { - 'token': token, - 'url': url, - 'appToken': appToken, - 'locale': locale, - 'color': Resources - .getPrimaryColor(app) - .value + platform.invokeMethod('getEndpoint').then((endpoint) { + platform.invokeMethod('getAppToken').then((appToken) async { + platform.invokeMethod('startScanner', { + 'token': token, + 'url': endpoint, + 'appToken': appToken, + 'locale': Intl.defaultLocale, + 'color': Resources + .getPrimaryColor(app) + .value + }); + }); }); + } } } diff --git a/lib/consts.dart b/lib/consts.dart index 9156fca..da76715 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -1,14 +1,5 @@ import 'package:flutter/material.dart'; -// Serious constants -const String appName = "Autobonus"; - -const String url = 'https://pos-api-autoclub.dinect.com/20130701/'; -const String appToken = 'bdea0f3ba9034b688019a7cac753d1209e2b227f'; - -//const String url = 'https://pos-api-int.dinect.com/20130701/'; -//const String appToken = '9fec83cdca38c357e6b65dbb17514cdd36bf2a08'; - // Assets const String logout_png = 'assets/logout.png'; const String help_png = 'assets/help.png'; diff --git a/lib/db.dart b/lib/db.dart index 925f774..afaf00e 100644 --- a/lib/db.dart +++ b/lib/db.dart @@ -64,7 +64,7 @@ class SqliteHelper { } /// Создается запись в таблице, содержащая данные, которые не зависят от сессии. - Future createAppInfo(String locale, int currency) async { + Future createAppInfo(int currency) async { List appInfo = await db.query(tableSettings); if (appInfo.length > 0) { return null; diff --git a/lib/main.dart b/lib/main.dart index 53fbbca..123bdf3 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,17 +1,14 @@ import 'package:flutter/material.dart'; import 'package:checker/screens/splash.dart'; -import 'consts.dart'; /// Точка входа в приложение. void main() { runApp(new Checker()); } -// TODO: Запрашивать appName у платформы class Checker extends StatelessWidget { + @override Widget build(BuildContext context) { - return new MaterialApp( - title: appName, - home: new SplashScreen()); + return new MaterialApp(home: new SplashScreen()); } } \ No newline at end of file diff --git a/lib/network.dart b/lib/network.dart index fc74466..9e3a238 100644 --- a/lib/network.dart +++ b/lib/network.dart @@ -1,6 +1,8 @@ +import 'package:checker/db.dart'; import 'package:flutter/services.dart'; +import 'package:intl/intl.dart'; -import 'consts.dart'; +import 'common.dart'; // Клиент http приложения final httpClient = createHttpClient(); @@ -8,23 +10,58 @@ final httpClient = createHttpClient(); // Попытка создать токен для кассы. // В случае если токен для кассы уже существует, вернется ошибка 409. // На сервере есть ограничение в 40 токенов. -createToken(String merchantId, String posID, String locale) async { - - // Поле description - необязательное. - var body = { - 'merchant_shop': merchantId, - 'pos': posID, - }; - - return httpClient.post(url + 'tokens/?_dmapptoken=' + appToken, body: body, headers: {'Accept-Language': locale}); +getCreateTokenRequest(Map httpBody) async { + return httpClient.post( + await getEndpoint() + 'tokens/?_dmapptoken=' + await getToken(), + body: httpBody, + headers: {'Accept-Language': Intl.defaultLocale}); } // Проверка статуса токена. В ответе приходит параметр active, который может быть либо true, либо false,. -checkTokenStatus(String token, String locale) async { - return httpClient.get(url + 'tokens/' + token + '?_dmapptoken=' + appToken, headers: {'Accept-Language': locale}); +getCheckTokenStatusRequest(String token) async { + return httpClient.get( + await getEndpoint() + + 'tokens/' + + token + + '?_dmapptoken=' + + await getToken(), + headers: {'Accept-Language': Intl.defaultLocale}); } // Удаление токена на сервере. -deleteToken(String token, String locale) async { - return httpClient.delete(url + 'tokens/' + token + '?_dmapptoken=' + appToken, headers: {'Accept-Language': locale}); -} \ No newline at end of file +getDeleteTokenRequest(String token) async { + return httpClient.delete( + await getEndpoint() + 'tokens/' + token + '?_dmapptoken=' + + await getToken(), headers: {'Accept-Language': Intl.defaultLocale}); +} + +getLoyaltyRequest(String endpoint, SqliteHelper helper) async { + String token = await helper.getToken(); + + var headers = { + 'DM-Authorization': 'dmapptoken ${await getToken()}', + 'Authorization': 'dmtoken ${token}', + 'Accept-Language': Intl.defaultLocale + }; + + return httpClient.get(endpoint, headers: headers); +} + +getPurchaseRequest(String endpoint, Map body, String token) async { + + var headers = { + 'DM-Authorization': 'dmapptoken ${await getToken()}', + 'Authorization': 'dmtoken ${token}', + 'Accept-Language': Intl.defaultLocale + }; + + return httpClient.post(endpoint, body: body, headers: headers); +} + +getEndpoint() async { + return await platform.invokeMethod('getEndpoint'); +} + +getToken() async { + return await platform.invokeMethod('getAppToken'); +} diff --git a/lib/screens/finish_registration.dart b/lib/screens/finish_registration.dart index 7e35bd2..977a985 100644 --- a/lib/screens/finish_registration.dart +++ b/lib/screens/finish_registration.dart @@ -9,6 +9,7 @@ import 'package:checker/network.dart'; import 'package:checker/strings.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:intl/intl.dart'; class FinishRegistrationScreen extends BaseScreen { @@ -66,8 +67,7 @@ class RegistrationScreenState extends BaseState { } else { if (await platform.invokeMethod('isOnline')) { String token = await helper.getToken(); - String locale = await helper.getLocale(); - checkTokenStatus(token, locale).then((response) { + getCheckTokenStatusRequest(token).then((response) { Map parsedMap = JSON.decode(response.body); // Обновить экран, заменить сообщение о необходимости активации токена, на сообщние о том, что токен активен. diff --git a/lib/screens/languages.dart b/lib/screens/languages.dart index e58a5a9..4f101b9 100644 --- a/lib/screens/languages.dart +++ b/lib/screens/languages.dart @@ -45,18 +45,8 @@ class LanguagesState extends SettingsBaseState { @override void getSelectedValue() { - helper.getLocale().then((locale) { - if (locale == null) { - platform.invokeMethod('getLocale').then((locale) { - setState(() { - selectedItem == locale; - }); - }); - } else { - setState(() { - selectedItem = getOptions().indexOf(getLocaleTitle(locale)); - }); - } + setState(() { + selectedItem = getOptions().indexOf(getLocaleTitle(Intl.defaultLocale)); }); } } \ No newline at end of file diff --git a/lib/screens/purchase.dart b/lib/screens/purchase.dart index 01952c6..328413e 100644 --- a/lib/screens/purchase.dart +++ b/lib/screens/purchase.dart @@ -14,17 +14,16 @@ import 'package:checker/screens/purchase_success.dart'; /// Экран проведения покупки. class PurchaseScreen extends StatefulWidget { - PurchaseScreen(this.user, this.card); final String user; final String card; - @override State createState() => new PurchaseScreenState(user, card); + @override + State createState() => new PurchaseScreenState(user, card); } class PurchaseScreenState extends BaseState { - /// Объект, помогающий вручную изменять введенный пользователем текст. /// Используется для форматирования введенных пользователем данных /// (удаляет запрещенные символы до их отображаения). @@ -35,7 +34,8 @@ class PurchaseScreenState extends BaseState { this.card = card; } - @override Widget build(BuildContext ctx) { + @override + Widget build(BuildContext ctx) { if (helper == null) { helper = new SqliteHelper(); helper.open().then((_) { @@ -43,7 +43,7 @@ class PurchaseScreenState extends BaseState { platform.invokeMethod('getFlavor').then((flavor) { app = flavor; setState(() { - getLoyalty(user['loyalty_url']); + requestLoyalty(user['loyalty_url']); }); }); } @@ -57,17 +57,24 @@ class PurchaseScreenState extends BaseState { String card = ''; String loyalty = ''; - @override Widget getScreenContent() { - return new Column( - children: [new Expanded(child: new ListView(children: [ - getValueWithDescription(StringsLocalization.buyer(), user['first_name'] == null ? '' : user['first_name']), - getValueWithDescription(StringsLocalization.card(), card), - getValueWithDescription(StringsLocalization.reward(), loyalty), - getHintLabel(), - getInputField(), - wrapButton(getScreenMargins(36.0), getCompleteButton()), - wrapButton(getScreenMargins(24.0), getScanButton(context, StringsLocalization.scan(), Resources.getPrimaryColor(app))) - ]))]); + @override + Widget getScreenContent() { + return new Column(children: [ + new Expanded( + child: new ListView(children: [ + getValueWithDescription(StringsLocalization.buyer(), + user['first_name'] == null ? '' : user['first_name']), + getValueWithDescription(StringsLocalization.card(), card), + getValueWithDescription(StringsLocalization.reward(), loyalty), + getHintLabel(), + getInputField(), + wrapButton(getScreenMargins(36.0), getCompleteButton()), + wrapButton( + getScreenMargins(24.0), + getScanButton(context, StringsLocalization.scan(), + Resources.getPrimaryColor(app))) + ])) + ]); } getScreenMargins(double top) { @@ -76,37 +83,39 @@ class PurchaseScreenState extends BaseState { } getCompleteButton() { - return buildRaisedButton(StringsLocalization.completePurchase(), () => onPurchaseClick()); + return buildRaisedButton( + StringsLocalization.completePurchase(), () => onPurchaseClick()); } 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)), + child: new Text(title, style: new TextStyle(color: textColor)), onPressed: () => startScanner(context, app, helper)), decoration: new BoxDecoration( - border: new Border.all(color: Resources.getButtonColor(app), width: 1.0), + border: new Border.all( + color: Resources.getButtonColor(app), width: 1.0), borderRadius: new BorderRadius.all(new Radius.circular(4.0)))); } - @override String getTitle() { + @override + String getTitle() { return StringsLocalization.carryingPurchase(); } - @override getHintString() { + @override + getHintString() { return StringsLocalization.sum(); } - @override getTextWidget() { + @override + getTextWidget() { return new TextField( keyboardType: TextInputType.number, decoration: new InputDecoration.collapsed( hintText: getHintString(), - hintStyle: new TextStyle(color: greyTextColor, fontSize: 16.0) - ), + hintStyle: new TextStyle(color: greyTextColor, fontSize: 16.0)), controller: controller, onSubmitted: (String text) { setState(() { @@ -118,33 +127,11 @@ class PurchaseScreenState extends BaseState { ); } - getLoyalty(String url) async { - + requestLoyalty(String url) async { if (await platform.invokeMethod('isOnline')) { - - String token = await helper.getToken(); - String locale = await helper.getLocale(); - - var headers = { - 'DM-Authorization': 'dmapptoken $appToken', - 'Authorization': 'dmtoken ${token}', - 'Accept-Language': locale - }; - - httpClient.get(url, headers: headers).then((response) { - - print(response.body); - - Map bonuses = JSON.decode(response.body); - String type = bonuses['type']; + getLoyaltyRequest(url, helper).then((response) { setState(() { - if (type == 'amount') { - this.loyalty = '${user['discount']}%'; - } else { - List amountToBonus = bonuses['amount_to_bonus']; - double loyaltyVal = (double.parse(amountToBonus[1]) / amountToBonus[0]) * 100; - this.loyalty = '${loyaltyVal.toStringAsFixed(0)}%'; - } + setBonuses(JSON.decode(response.body)); }); }).catchError((error) { print(error.toString()); @@ -152,15 +139,15 @@ class PurchaseScreenState extends BaseState { } } - // TODO: Переделать? чтобы работало хорошо - String _cleanupNumber(String text){ + // TODO: Переделать, если потребуется + String _cleanupNumber(String text) { String tmp = text .replaceAll(' ', '') .replaceAll('-', '') .replaceAll(',', '.') .replaceAll('..', '.'); - while(tmp.indexOf('..') != -1){ + while (tmp.indexOf('..') != -1) { tmp = tmp.replaceAll('..', '.'); } return tmp; @@ -172,17 +159,17 @@ class PurchaseScreenState extends BaseState { try { sumTotal = num.parse(text); - } catch(exception) { + } catch (exception) { print(exception); try { int idx = text.indexOf('.'); String integerPart = text.substring(0, idx); String fractionalPart = text.substring(idx + 1, text.length); - if(fractionalPart.length > 2) { + if (fractionalPart.length > 2) { fractionalPart = fractionalPart.substring(0, 2); } return '${integerPart}.${fractionalPart}'; - } catch(exception){ + } catch (exception) { print(exception); } } @@ -193,23 +180,26 @@ class PurchaseScreenState extends BaseState { String val = _parseSum(controller.text); helper.getCurrency().then((currency) { print(currency.toString()); - showDialog(context: context, child: new AlertDialog( - title: new Text(StringsLocalization.confirmation()), - content: new Text(StringsLocalization.confirmPurchase(val, currency)), - actions: [ - new FlatButton( - child: new Text(StringsLocalization.no()), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - new FlatButton( - child: new Text(StringsLocalization.yes()), - onPressed: () { - purchase(val); - }, - ) - ])); + showDialog( + context: context, + child: new AlertDialog( + title: new Text(StringsLocalization.confirmation()), + content: + new Text(StringsLocalization.confirmPurchase(val, currency)), + actions: [ + new FlatButton( + child: new Text(StringsLocalization.no()), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + new FlatButton( + child: new Text(StringsLocalization.yes()), + onPressed: () { + purchase(val); + }, + ) + ])); }); } @@ -219,11 +209,7 @@ class PurchaseScreenState extends BaseState { purchaseInProgress = true; String token = await helper.getToken(); - String locale = await helper.getLocale(); helper.getMerchantID().then((result) { - - String url = user['purchases_url']; - helper.getCurrency().then((currency) { var body = { 'doc_id': result, @@ -232,14 +218,8 @@ class PurchaseScreenState extends BaseState { 'sum_total': sumTotal }; - var headers = { - 'DM-Authorization': 'dmapptoken $appToken', - 'Authorization': 'dmtoken ${token}', - 'Accept-Language': locale - }; - - httpClient.post(url, body: body, headers: headers).then((response) { - + getPurchaseRequest(user['purchases_url'], body, token) + .then((response) { print(response.body); Map parsedMap = JSON.decode(response.body); @@ -247,11 +227,18 @@ class PurchaseScreenState extends BaseState { if (parsedMap.containsKey('errors')) { List errors = parsedMap['errors']; - Scaffold.of(context).showSnackBar(new SnackBar(content: new Text(errors[0]))); + Scaffold + .of(context) + .showSnackBar(new SnackBar(content: new Text(errors[0]))); } else { - pushRouteReplacement(context, new PurchaseSuccessScreen(sumTotal, user['first_name'] == null ? '' : user['first_name'], helper, app)); + pushRouteReplacement( + context, + new PurchaseSuccessScreen( + sumTotal, + user['first_name'] == null ? '' : user['first_name'], + helper, + app)); } - }).catchError((error) { purchaseInProgress = false; print(error.toString()); @@ -261,4 +248,14 @@ class PurchaseScreenState extends BaseState { } } } + + void setBonuses(Map bonuses) { + if (bonuses['type'] == 'amount') { + this.loyalty = '${user['discount']}%'; + } else { + double loyaltyVal = (double.parse(bonuses['amount_to_bonus'][1]) / + bonuses['amount_to_bonus'][0]) * 100; + this.loyalty = '${loyaltyVal.toStringAsFixed(0)}%'; + } + } } diff --git a/lib/screens/registration.dart b/lib/screens/registration.dart index 12996c9..cf395f6 100644 --- a/lib/screens/registration.dart +++ b/lib/screens/registration.dart @@ -11,58 +11,64 @@ import 'package:checker/strings.dart'; import 'package:flutter/material.dart'; // Пакет для обработки json с ответом от сервера. - /// Экран регистрации магазина и кассы. class RegistrationScreen extends BaseScreen { - RegistrationScreen(helper, app) : super(helper, app); - @override State createState() => new RegistrationScreenState(helper, app); + @override + State createState() => new RegistrationScreenState(helper, app); } class RegistrationScreenState extends BaseState { - RegistrationScreenState(SqliteHelper helper, String app) { this.helper = helper; this.app = app; } - @override Widget build(BuildContext ctx) { + @override + Widget build(BuildContext ctx) { return getMainWidget(); } - @override String getTitle() { + @override + String getTitle() { return StringsLocalization.registration(); } - @override getHintString() { + @override + getHintString() { return StringsLocalization.idStore(); } /// Список виджетов, автоматически прокручиваемый вверх при открытии клавиатуры. - @override Widget getScreenContent() { + @override + Widget getScreenContent() { return new Container( child: new ListView(children: [ - new Column(children: [ - getLogo(), - getHintLabel(), - getInputField(), - getButton() - ]) - ])); + new Column(children: [ + getLogo(), + getHintLabel(), + getInputField(), + getButton() + ]) + ])); } - @override getTextWidget() { - return new TextField(keyboardType: TextInputType.number, - decoration: new InputDecoration.collapsed(hintText: getHintString(), + @override + getTextWidget() { + return new TextField( + keyboardType: TextInputType.number, + decoration: new InputDecoration.collapsed( + hintText: getHintString(), hintStyle: new TextStyle(color: greyTextColor, fontSize: 16.0)), onChanged: (text) => handleUserInput(text)); } /// Возвращает кнопку регистрации. getButton() { - return new Container(margin: new EdgeInsets.only(top: 36.0), child: - buildRaisedButton(StringsLocalization.signUp(), getOnPressed())); + return new Container( + margin: new EdgeInsets.only(top: 36.0), + child: buildRaisedButton(StringsLocalization.signUp(), getOnPressed())); } // Возвращает обработчик нажатий на кнопку регистрации. @@ -70,10 +76,10 @@ class RegistrationScreenState extends BaseState { return _isValidMerchantID() && !loading ? () => _registerShop() : null; } - /// Токен кассы - это DIN код. DIN код - это специальный код динекта, максимальная его длина - 25 символов. + /// Токен кассы - это DIN код. DIN код - это специальный код динекта, максимальная его длина - 25 символов. _isValidMerchantID() { - print("${dinCode.length}"); - return dinCode.length > 0 && dinCode.length < 25; + print("${merchantID.length}"); + return merchantID.length > 0 && merchantID.length < 25; } /// Показать progressBar, запросить токен. @@ -88,8 +94,9 @@ class RegistrationScreenState extends BaseState { _register() async { if (await platform.invokeMethod('isOnline')) { String posID = await helper.getPosID(); - String locale = await helper.getLocale(); - createToken(dinCode, posID, locale).then((response) { + + getCreateTokenRequest({'merchant_shop': merchantID, 'pos': posID}) + .then((response) { setState(() { error = null; loading = false; @@ -100,8 +107,9 @@ class RegistrationScreenState extends BaseState { Map parsedMap = JSON.decode(response.body); if (response.statusCode == 201) { - helper.createSession(dinCode, posID, parsedMap['token']).then((_) { - pushRouteReplacement(context, new FinishRegistrationScreen(helper, app)); + helper.createSession(merchantID, posID, parsedMap['token']).then((_) { + pushRouteReplacement( + context, new FinishRegistrationScreen(helper, app)); }); } else { setState(() { @@ -113,4 +121,4 @@ class RegistrationScreenState extends BaseState { }); } } -} \ No newline at end of file +} diff --git a/lib/screens/splash.dart b/lib/screens/splash.dart index aa29824..d77b1ed 100644 --- a/lib/screens/splash.dart +++ b/lib/screens/splash.dart @@ -15,12 +15,13 @@ import 'package:http/http.dart'; import 'package:intl/intl.dart'; class SplashScreen extends StatefulWidget { - @override State createState() => new _SplashScreenState(); + @override + State createState() => new _SplashScreenState(); } class _SplashScreenState extends BaseState { - - @override Widget build(BuildContext ctx) { + @override + Widget build(BuildContext ctx) { if (helper == null) { helper = new SqliteHelper(); helper.open().then((_) { @@ -42,7 +43,7 @@ class _SplashScreenState extends BaseState { if (locale == null) { initWithSystemValue(); } else { - initWithSavedValue(); + initWithSavedValue(locale); } }); } @@ -61,17 +62,15 @@ class _SplashScreenState extends BaseState { }); } - void initWithSavedValue() { - helper.getLocale().then((locale) { - initLocale(locale, () { - showNext(); - }); + void initWithSavedValue(String locale) { + initLocale(locale, () { + showNext(); }); } void createSettingsTable(String locale) { platform.invokeMethod('getCurrency').then((currency) { - helper.createAppInfo(locale, currency); + helper.createAppInfo(currency); initLocale(locale, () { showNext(); }); @@ -95,44 +94,31 @@ class _SplashScreenState extends BaseState { Widget getScreenContent() { return app == null ? getBackground() - : 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))) - ]); + : 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) - ])); + 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() async { String token = await helper.getToken(); - String locale = await helper.getLocale(); // В случае, если в приложении отсутствует токен, // необходимо запустить регистрацию кассы. @@ -140,7 +126,7 @@ class _SplashScreenState extends BaseState { pushRouteReplacement(context, new RegistrationScreen(helper, app)); } else { if (await platform.invokeMethod('isOnline')) { - checkTokenStatus(token, locale).then((statusResponse) { + getCheckTokenStatusRequest(token).then((statusResponse) { handleStatusResponse(statusResponse, helper); }).catchError((error) { handleError(error.toString()); @@ -183,11 +169,12 @@ class _SplashScreenState extends BaseState { _createToken(SqliteHelper helper) async { String merchantID = await helper.getMerchantID(); String posID = await helper.getPosID(); - String locale = await helper.getLocale(); - createToken(merchantID, posID, locale).then((response) { + getCreateTokenRequest({'merchant_shop': merchantID, 'pos': posID}) + .then((response) { if (response.statusCode == 409) { - pushRouteReplacement(context, new FinishRegistrationScreen(helper, app)); + pushRouteReplacement( + context, new FinishRegistrationScreen(helper, app)); } else if (response.statusCode == 201) { clearToken(response, helper); } @@ -198,10 +185,9 @@ class _SplashScreenState extends BaseState { /// Очищаем бд, делаем запрос на удаление токена. Future clearToken(Response response, SqliteHelper helper) async { - String locale = await helper.getLocale(); helper.clear().then((_) { Map parsedMap = JSON.decode(response.body); - deleteToken(parsedMap['token'], locale).then((_) { + getDeleteTokenRequest(parsedMap['token']).then((_) { Navigator.of(context).pop(); pushRouteReplacement(context, new RegistrationScreen(helper, app)); }).catchError((error) { diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..a6d5325 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +include ':app' +project(':app').projectDir = new File('android/app') \ No newline at end of file