Вынес работу с сетью и общие методы в отдельные файлы
This commit is contained in:
@@ -47,6 +47,10 @@ import android.view.SurfaceView;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.Exception;
|
import java.lang.Exception;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
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 com.dinect.checker.R;
|
import com.dinect.checker.R;
|
||||||
|
|
||||||
public class CameraActivity extends AppCompatActivity implements SurfaceHolder.Callback {
|
public class CameraActivity extends AppCompatActivity implements SurfaceHolder.Callback {
|
||||||
@@ -57,7 +61,7 @@ public class CameraActivity extends AppCompatActivity implements SurfaceHolder.C
|
|||||||
private HashMap<String, Integer> mContours = new HashMap<>();
|
private HashMap<String, Integer> mContours = new HashMap<>();
|
||||||
|
|
||||||
private boolean mBarcodeScanned = false;
|
private boolean mBarcodeScanned = false;
|
||||||
private boolean previewing = true;
|
private boolean previewing = false;
|
||||||
private Handler autoFocusHandler;
|
private Handler autoFocusHandler;
|
||||||
private int mOffset;
|
private int mOffset;
|
||||||
|
|
||||||
@@ -117,12 +121,14 @@ public class CameraActivity extends AppCompatActivity implements SurfaceHolder.C
|
|||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
mCamera.startPreview();
|
mCamera.startPreview();
|
||||||
|
previewing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
mCamera.stopPreview();
|
mCamera.stopPreview();
|
||||||
|
previewing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -138,6 +144,7 @@ public class CameraActivity extends AppCompatActivity implements SurfaceHolder.C
|
|||||||
try {
|
try {
|
||||||
mCamera.setPreviewDisplay(holder);
|
mCamera.setPreviewDisplay(holder);
|
||||||
mCamera.startPreview();
|
mCamera.startPreview();
|
||||||
|
previewing = true;
|
||||||
try {
|
try {
|
||||||
mCamera.autoFocus(autoFocusCallback);
|
mCamera.autoFocus(autoFocusCallback);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
@@ -207,8 +214,15 @@ public class CameraActivity extends AppCompatActivity implements SurfaceHolder.C
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
Intent intent = new Intent();
|
||||||
if (item.getItemId() == R.id.logout) {
|
if (item.getItemId() == R.id.logout) {
|
||||||
setResult(RESULT_OK);
|
intent.putExtra("item", "logout");
|
||||||
|
setResult(RESULT_OK, intent);
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
} else if (item.getItemId() == R.id.faq) {
|
||||||
|
intent.putExtra("item", "faq");
|
||||||
|
setResult(RESULT_OK, intent);
|
||||||
finish();
|
finish();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -253,8 +267,9 @@ public class CameraActivity extends AppCompatActivity implements SurfaceHolder.C
|
|||||||
|
|
||||||
private Runnable doAutoFocus = new Runnable() {
|
private Runnable doAutoFocus = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (previewing)
|
if (previewing) {
|
||||||
mCamera.autoFocus(autoFocusCallback);
|
mCamera.autoFocus(autoFocusCallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -108,19 +108,25 @@ public class MainActivity extends FlutterActivity {
|
|||||||
if (requestCode == START_SCANNER_REQUEST_CODE && resultCode == RESULT_CANCELED) {
|
if (requestCode == START_SCANNER_REQUEST_CODE && resultCode == RESULT_CANCELED) {
|
||||||
finish();
|
finish();
|
||||||
} else if (requestCode == START_SCANNER_REQUEST_CODE && resultCode == RESULT_OK) {
|
} else if (requestCode == START_SCANNER_REQUEST_CODE && resultCode == RESULT_OK) {
|
||||||
if (data == null) {
|
if (data != null) {
|
||||||
mChannel.invokeMethod("foo", null);
|
|
||||||
} else {
|
|
||||||
String code = data.getExtras().getString("code", null);
|
String code = data.getExtras().getString("code", null);
|
||||||
if (code == null) {
|
if (code != null) {
|
||||||
mChannel.invokeMethod("foo", null);
|
mChannel.invokeMethod("purchase", code);
|
||||||
} else {
|
} else {
|
||||||
mChannel.invokeMethod("purchase", code);
|
String menuItem = data.getExtras().getString("item", null);
|
||||||
|
Log.d("item", menuItem);
|
||||||
|
if (menuItem != null) {
|
||||||
|
mChannel.invokeMethod(menuItem, null);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleItemClick() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void getDocID() {
|
private void getDocID() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import 'main.dart';
|
import 'common.dart';
|
||||||
|
import 'consts.dart';
|
||||||
|
import 'network.dart';
|
||||||
import 'dart:convert'; // Пакет для обработки json с ответом от сервера.
|
import 'dart:convert'; // Пакет для обработки json с ответом от сервера.
|
||||||
import 'base_state.dart';
|
import 'base_state.dart';
|
||||||
|
|
||||||
@@ -40,7 +42,7 @@ class _RegistrationScreenState extends BaseState<FinishRegistrationScreen> {
|
|||||||
|
|
||||||
handleTap() {
|
handleTap() {
|
||||||
if (_tokenActive) {
|
if (_tokenActive) {
|
||||||
startScanner(context);
|
startScanner(context);
|
||||||
} else {
|
} else {
|
||||||
checkTokenStatus(context).then((response) {
|
checkTokenStatus(context).then((response) {
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'main.dart';
|
import 'common.dart';
|
||||||
import 'faq.dart';
|
import 'network.dart';
|
||||||
|
import 'consts.dart';
|
||||||
|
|
||||||
abstract class BaseState<T> extends State<T> {
|
abstract class BaseState<T> extends State<T> {
|
||||||
|
|
||||||
bool loading = false;
|
bool loading = false;
|
||||||
String error = null;
|
String error = null;
|
||||||
String textFieldValue = "";
|
String textFieldValue = '';
|
||||||
|
|
||||||
TextEditingController controller = new TextEditingController();
|
TextEditingController controller = new TextEditingController();
|
||||||
|
|
||||||
@@ -28,7 +27,7 @@ abstract class BaseState<T> extends State<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getFaqButton() {
|
getFaqButton() {
|
||||||
return new IconButton(icon: new Icon(Icons.help_outline), onPressed: () => faq());
|
return new IconButton(icon: new Icon(Icons.help_outline), onPressed: () => faq(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
getLogoutButton() {
|
getLogoutButton() {
|
||||||
@@ -45,11 +44,6 @@ abstract class BaseState<T> extends State<T> {
|
|||||||
|
|
||||||
String getHint();
|
String getHint();
|
||||||
|
|
||||||
faq() {
|
|
||||||
var route = new MaterialPageRoute<Null>(builder: (BuildContext context) => new FAQScreen());
|
|
||||||
Navigator.of(context).push(route);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Метод возвращает контейнер с отступами, который содержит картинку с логотипом.
|
/// Метод возвращает контейнер с отступами, который содержит картинку с логотипом.
|
||||||
getLogo() {
|
getLogo() {
|
||||||
double containerHeight = 92.0;
|
double containerHeight = 92.0;
|
||||||
|
|||||||
111
lib/common.dart
Normal file
111
lib/common.dart
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'network.dart';
|
||||||
|
import 'purchase.dart';
|
||||||
|
import 'faq.dart';
|
||||||
|
|
||||||
|
// Канал для взаимодействия с кодом платформы.
|
||||||
|
const platform = const MethodChannel('com.dinect.checker/instance_id');
|
||||||
|
|
||||||
|
/// Токен кассы. Инициализируется при регистрации.
|
||||||
|
String token;
|
||||||
|
|
||||||
|
// Метод обеспечивает замену текущего объекта route новым.
|
||||||
|
pushRoute(BuildContext context, Widget widget) {
|
||||||
|
var route = new MaterialPageRoute<Null>(builder: (BuildContext context) => widget);
|
||||||
|
Navigator.of(context).pushReplacement(route);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Добавление route, с возможностью вернуться к предыдущему экрану.
|
||||||
|
faq(BuildContext context) {
|
||||||
|
var route = new MaterialPageRoute<Null>(builder: (BuildContext context) => new FAQScreen());
|
||||||
|
Navigator.of(context).push(route);
|
||||||
|
}
|
||||||
|
|
||||||
|
// В методе отправляется запрос на удаление токена кассы, очищаются SharedPreferences приложения.
|
||||||
|
logout(BuildContext context) {
|
||||||
|
|
||||||
|
VoidCallback positiveCalback = () {
|
||||||
|
if (token != null) {
|
||||||
|
deleteToken(token).then((response) async {
|
||||||
|
print(response.body);
|
||||||
|
await platform.invokeMethod('removeKeys');
|
||||||
|
pushRoute(context, new RegistrationScreen()); // Запускаем регистрацию
|
||||||
|
}).catchError((error) {
|
||||||
|
print(error.toString());
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
showYesNoDialog(context, 'Подтверждение', 'Вы действительно хотите выйти и ввести другой номер магазина?', positiveCalback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Запуск спецефичной для каждой платформы части приложения - сканера.
|
||||||
|
/// Может производиться с нескольких экранов (splash, finish_registration).
|
||||||
|
startScanner(BuildContext context) async {
|
||||||
|
|
||||||
|
// Канал ловит вызовы методов из "нативной" части приложения.
|
||||||
|
// Могут быть вызваны либо logaut либо faq, либо purchase.
|
||||||
|
if (token != null) {
|
||||||
|
platform.setMethodCallHandler((MethodCall call) async {
|
||||||
|
|
||||||
|
print('call.method: ${call.method}');
|
||||||
|
if (call.method == 'logout') {
|
||||||
|
logout(context);
|
||||||
|
} else if (call.method == 'faq') {
|
||||||
|
faq(context);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
List usersList = JSON.decode(call.arguments);
|
||||||
|
print('usersList.length: ${usersList.length}');
|
||||||
|
if (usersList.length > 0) {
|
||||||
|
pushRoute(context, new PurchaseScreen(usersList[0], card));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// var card = ;
|
||||||
|
|
||||||
|
// String url = 'http://pos-api-int.dinect.com/20130701/users/?auto=${card}';
|
||||||
|
// print('url: ' + url);
|
||||||
|
|
||||||
|
// var headers = {
|
||||||
|
// 'DM-Authorization': 'dmapptoken 9fec83cdca38c357e6b65dbb17514cdd36bf2a08',
|
||||||
|
// 'Authorization': 'dmtoken ${token}'
|
||||||
|
// };
|
||||||
|
|
||||||
|
// httpClient.get(url, headers: headers).then((response) {
|
||||||
|
|
||||||
|
// print(response.body);
|
||||||
|
|
||||||
|
|
||||||
|
// }).catchError((error) {
|
||||||
|
// print(error.toString());
|
||||||
|
// });
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await platform.invokeMethod('startScanner');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запуск диалога с двумя кнопками
|
||||||
|
showYesNoDialog(BuildContext context, String title, String content, VoidCallback positiveCallback) {
|
||||||
|
showDialog(context: context, child: new AlertDialog(
|
||||||
|
title: new Text(title),
|
||||||
|
content: new Text(content),
|
||||||
|
actions: <Widget>[
|
||||||
|
new FlatButton(
|
||||||
|
child: new Text('Нет'),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
),
|
||||||
|
new FlatButton(
|
||||||
|
child: new Text('Да'),
|
||||||
|
onPressed: positiveCallback)]));
|
||||||
|
}
|
||||||
35
lib/consts.dart
Normal file
35
lib/consts.dart
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
// Serious constants
|
||||||
|
const String intUrl = 'https://pos-api-int.dinect.com/20130701/';
|
||||||
|
const String intToken = '9fec83cdca38c357e6b65dbb17514cdd36bf2a08';
|
||||||
|
|
||||||
|
// Hints
|
||||||
|
const String merchantIDHint = 'ID магазина';
|
||||||
|
const String posIDHint = 'Номер кассы';
|
||||||
|
|
||||||
|
// Assets
|
||||||
|
const String logo_png = 'assets/registration_logo.png';
|
||||||
|
const String splash_png = 'assets/splash.png';
|
||||||
|
const String logout_png = 'assets/logout.png';
|
||||||
|
const String activate_token_bg_png = 'assets/activate_token_message_background.png';
|
||||||
|
const String active_token_bg_png = 'assets/active_token_message_background.png';
|
||||||
|
const String expansion_icon_png = 'assets/expansion_icon.png';
|
||||||
|
const String powered_by_dinect_splash_png = 'assets/powered_by_dinect_splash.png';
|
||||||
|
const String powered_by_dinect_png = 'assets/powered_by_dinect.png';
|
||||||
|
|
||||||
|
// Colors
|
||||||
|
const Color primaryColor = const Color(0xffeb0004);
|
||||||
|
const Color greyTextColor = const Color(0xffa5a5a5);
|
||||||
|
const Color textBorderColor = const Color(0xffcfd8dc);
|
||||||
|
const Color tokenActiveTextColor = const Color(0xff1f5a1f);
|
||||||
|
const Color tokenActivateTextColor = const Color(0xff4e3a19);
|
||||||
|
const Color greenBackground = const Color(0xff8ae28a);
|
||||||
|
const Color faqGrey = const Color(0xff5b5b5b);
|
||||||
|
const Color faqTitlesColor = const Color(0xff404040);
|
||||||
|
|
||||||
|
// Dimens
|
||||||
|
const double verticalMargin = 28.0;
|
||||||
|
const double buttonVerticalMargin = 42.0;
|
||||||
|
const double buttonHeight = 48.0;
|
||||||
|
const double iconHeight = 20.0;
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import 'main.dart';
|
|
||||||
import 'base_state.dart';
|
import 'base_state.dart';
|
||||||
|
import 'consts.dart';
|
||||||
|
|
||||||
/// Класс содержит заголовки и текст блоков FAQ.
|
/// Класс содержит заголовки и текст блоков FAQ.
|
||||||
class Entry {
|
class Entry {
|
||||||
|
|||||||
161
lib/main.dart
161
lib/main.dart
@@ -1,169 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'splash.dart';
|
import 'splash.dart';
|
||||||
import 'registration.dart';
|
import 'consts.dart';
|
||||||
import 'dart:async';
|
|
||||||
import 'dart:convert';
|
|
||||||
import 'purchase.dart';
|
|
||||||
|
|
||||||
/// Главный класс приложения.
|
|
||||||
/// Здесь распоосложены константы и некоторые методы, которые могут вызываться с разных экранов приложения.
|
|
||||||
|
|
||||||
// Serious constants
|
|
||||||
const String intUrl = 'https://pos-api-int.dinect.com/20130701/';
|
|
||||||
const String intToken = '9fec83cdca38c357e6b65dbb17514cdd36bf2a08';
|
|
||||||
|
|
||||||
// Hints
|
|
||||||
const String merchantIDHint = 'ID магазина';
|
|
||||||
const String posIDHint = 'Номер кассы';
|
|
||||||
|
|
||||||
// Assets
|
|
||||||
const String logo_png = 'assets/registration_logo.png';
|
|
||||||
const String splash_png = 'assets/splash.png';
|
|
||||||
const String logout_png = 'assets/logout.png';
|
|
||||||
const String activate_token_bg_png = 'assets/activate_token_message_background.png';
|
|
||||||
const String active_token_bg_png = 'assets/active_token_message_background.png';
|
|
||||||
const String expansion_icon_png = 'assets/expansion_icon.png';
|
|
||||||
const String powered_by_dinect_splash_png = 'assets/powered_by_dinect_splash.png';
|
|
||||||
const String powered_by_dinect_png = 'assets/powered_by_dinect.png';
|
|
||||||
// Colors
|
|
||||||
const Color primaryColor = const Color(0xffeb0004);
|
|
||||||
const Color greyTextColor = const Color(0xffa5a5a5);
|
|
||||||
const Color textBorderColor = const Color(0xffcfd8dc);
|
|
||||||
const Color tokenActiveTextColor = const Color(0xff1f5a1f);
|
|
||||||
const Color tokenActivateTextColor = const Color(0xff4e3a19);
|
|
||||||
const Color greenBackground = const Color(0xff8ae28a);
|
|
||||||
const Color faqGrey = const Color(0xff5b5b5b);
|
|
||||||
const Color faqTitlesColor = const Color(0xff404040);
|
|
||||||
// Dimens
|
|
||||||
const double verticalMargin = 28.0;
|
|
||||||
const double buttonVerticalMargin = 42.0;
|
|
||||||
const double buttonHeight = 48.0;
|
|
||||||
const double iconHeight = 20.0;
|
|
||||||
|
|
||||||
const platform = const MethodChannel('com.dinect.checker/instance_id');
|
|
||||||
|
|
||||||
// HttpClient
|
|
||||||
final httpClient = createHttpClient();
|
|
||||||
|
|
||||||
/// Токен кассы. Инициализируется при регистрации.
|
|
||||||
String token;
|
|
||||||
|
|
||||||
/// Точка входа в приложение.
|
/// Точка входа в приложение.
|
||||||
void main() {
|
void main() {
|
||||||
runApp(new Checker());
|
runApp(new Checker());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Проверка статуса токена. Токен может быть активирован, либо не активирован.
|
|
||||||
checkTokenStatus(BuildContext context) async {
|
|
||||||
return httpClient.get(intUrl + 'tokens/' + token + '?_dmapptoken=' + intToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
createToken(String merchantId) async {
|
|
||||||
|
|
||||||
String url = intUrl + 'tokens/?_dmapptoken=' + intToken;
|
|
||||||
|
|
||||||
String posID = await platform.invokeMethod('getPosID');
|
|
||||||
print('posID: ${posID}');
|
|
||||||
|
|
||||||
print('merchantId: ${merchantId}');
|
|
||||||
|
|
||||||
// Поле description - необязательное.
|
|
||||||
var body = {
|
|
||||||
'merchant_shop': merchantId,
|
|
||||||
'pos': posID,
|
|
||||||
};
|
|
||||||
|
|
||||||
return httpClient.post(url, body: body);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Запуск спецефичной для каждой платформы части приложения - сканера.
|
|
||||||
/// Может производиться с нескольких экранов (splash, finish_registration).
|
|
||||||
startScanner(BuildContext context) async {
|
|
||||||
|
|
||||||
// Канал ловит вызовы методов из "нативной" части приложения.
|
|
||||||
// Могут быть вызваны либо logaut либо faq, либо purchase.
|
|
||||||
if (token != null) {
|
|
||||||
platform.setMethodCallHandler((MethodCall call) async {
|
|
||||||
|
|
||||||
if (call.method == 'foo') {
|
|
||||||
logout(context);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
var card = call.arguments;
|
|
||||||
|
|
||||||
print('card: ' + card);
|
|
||||||
String url = 'http://pos-api-int.dinect.com/20130701/users/?auto=${card}';
|
|
||||||
print('url: ' + url);
|
|
||||||
|
|
||||||
var headers = {
|
|
||||||
'DM-Authorization': 'dmapptoken 9fec83cdca38c357e6b65dbb17514cdd36bf2a08',
|
|
||||||
'Authorization': 'dmtoken ${token}'
|
|
||||||
};
|
|
||||||
|
|
||||||
httpClient.get(url, headers: headers).then((response) {
|
|
||||||
|
|
||||||
print(response.body);
|
|
||||||
|
|
||||||
List usersList = JSON.decode(response.body);
|
|
||||||
print('usersList.length: ${usersList.length}');
|
|
||||||
if (usersList.length > 0) {
|
|
||||||
pushRoute(context, new PurchaseScreen(usersList[0], card));
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catchError((error) {
|
|
||||||
print(error.toString());
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await platform.invokeMethod('startScanner');
|
|
||||||
}
|
|
||||||
|
|
||||||
logout(BuildContext context) {
|
|
||||||
showDialog(context: context, child: new AlertDialog(
|
|
||||||
title: new Text('Подтверждение'),
|
|
||||||
content: new Text('Вы действительно хотите выйти и ввести другой номер магазина?'),
|
|
||||||
actions: <Widget>[
|
|
||||||
new FlatButton(
|
|
||||||
child: new Text('Нет'),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
}
|
|
||||||
),
|
|
||||||
new FlatButton(
|
|
||||||
child: new Text('Да'),
|
|
||||||
onPressed: () {
|
|
||||||
if (token != null) {
|
|
||||||
String url = intUrl + 'tokens/' + token + '?_dmapptoken=' + intToken;
|
|
||||||
print(url);
|
|
||||||
httpClient.delete(url).then((response) async {
|
|
||||||
print(response.body);
|
|
||||||
await platform.invokeMethod('removeKeys');
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
pushRoute(context, new RegistrationScreen());
|
|
||||||
}).catchError((error) {
|
|
||||||
print(error.toString());
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)]));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Навигация по приложению.
|
|
||||||
/// widget - следующий экран приложения.
|
|
||||||
pushRoute(BuildContext context, Widget widget) {
|
|
||||||
var route = new MaterialPageRoute<Null>(builder: (BuildContext context) => widget);
|
|
||||||
Navigator.of(context).pushReplacement(route);
|
|
||||||
}
|
|
||||||
|
|
||||||
class Checker extends StatelessWidget {
|
class Checker extends StatelessWidget {
|
||||||
@override Widget build(BuildContext context) {
|
@override Widget build(BuildContext context) {
|
||||||
return new MaterialApp(title: "AutoClub",
|
return new MaterialApp(title: "AutoClub",
|
||||||
@@ -174,5 +17,3 @@ class Checker extends StatelessWidget {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
39
lib/network.dart
Normal file
39
lib/network.dart
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'consts.dart';
|
||||||
|
|
||||||
|
// Клиент http приложения
|
||||||
|
final httpClient = createHttpClient();
|
||||||
|
|
||||||
|
// Попытка создать токен для кассы.
|
||||||
|
// В случае если токен для кассы уже существует, вернется ошибка 409.
|
||||||
|
// На сервере есть ограничение в 40 токенов.
|
||||||
|
createToken(String merchantId, String posID) async {
|
||||||
|
|
||||||
|
String url = intUrl + 'tokens/?_dmapptoken=' + intToken;
|
||||||
|
|
||||||
|
// Поле description - необязательное.
|
||||||
|
var body = {
|
||||||
|
'merchant_shop': merchantId,
|
||||||
|
'pos': posID,
|
||||||
|
};
|
||||||
|
|
||||||
|
return httpClient.post(url, body: body);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверка статуса токена. В ответе приходит параметр active, который может быть либо true, либо false,.
|
||||||
|
checkTokenStatus(String token) async {
|
||||||
|
return httpClient.get(intUrl + 'tokens/' + token + '?_dmapptoken=' + intToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Удаление токена на сервере.
|
||||||
|
deleteToken(String token) async {
|
||||||
|
String url = intUrl + 'tokens/' + token + '?_dmapptoken=' + intToken;
|
||||||
|
print(url);
|
||||||
|
return httpClient.delete(url).then();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Удалить токены
|
||||||
|
// 57e0d09aa935252d2a3463ebc1d61501608a6af9
|
||||||
|
// f1355ea87375c173695b57afa72f78fedbe5b6c3
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'dart:convert'; // Пакет для обработки json с ответом от сервера.
|
import 'dart:convert'; // Пакет для обработки json с ответом от сервера.
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'main.dart';
|
import 'common.dart';
|
||||||
|
import 'network.dart';
|
||||||
|
import 'consts.dart';
|
||||||
import 'activate_token.dart';
|
import 'activate_token.dart';
|
||||||
import 'base_state.dart';
|
import 'base_state.dart';
|
||||||
|
|
||||||
/// На фото мой сын, большой любитель голых констант.
|
|
||||||
|
|
||||||
/// Экран регистрации магазина и кассы.
|
/// Экран регистрации магазина и кассы.
|
||||||
class RegistrationScreen extends StatefulWidget {
|
class RegistrationScreen extends StatefulWidget {
|
||||||
@override State createState() => new _RegistrationScreenState();
|
@override State createState() => new _RegistrationScreenState();
|
||||||
@@ -54,7 +52,7 @@ class _RegistrationScreenState extends BaseState<RegistrationScreen> {
|
|||||||
/// Получение от платформы id установки, формирование запроса на получение токена, сохранение токена.
|
/// Получение от платформы id установки, формирование запроса на получение токена, сохранение токена.
|
||||||
_register(BuildContext context) async {
|
_register(BuildContext context) async {
|
||||||
|
|
||||||
createToken(textFieldValue).then((response) {
|
createToken(textFieldValue, await platform.invokeMethod('getPosID')).then((response) {
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
error = null;
|
error = null;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'main.dart';
|
import 'common.dart';
|
||||||
|
import 'network.dart';
|
||||||
|
import 'consts.dart';
|
||||||
import 'registration.dart';
|
import 'registration.dart';
|
||||||
import 'activate_token.dart';
|
import 'activate_token.dart';
|
||||||
import 'purchase.dart';
|
|
||||||
|
|
||||||
class SplashScreen extends StatelessWidget {
|
class SplashScreen extends StatelessWidget {
|
||||||
|
|
||||||
@@ -20,14 +20,18 @@ class SplashScreen extends StatelessWidget {
|
|||||||
// pushRoute(context, new PurchaseScreen(null));
|
// pushRoute(context, new PurchaseScreen(null));
|
||||||
});
|
});
|
||||||
|
|
||||||
return new Stack(children: <Widget>[new Container(padding: new EdgeInsets.only(left: 48.0, right: 48.0), decoration: getSplashBg()),
|
return new Stack(children: <Widget>[getBackgroundContainer(),
|
||||||
new Align(alignment: FractionalOffset.bottomRight, child:
|
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 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)))]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Decoration getSplashBg() {
|
getBackgroundContainer() {
|
||||||
return new BoxDecoration(image: new DecorationImage(
|
const margin = 48.0;
|
||||||
image: new ExactAssetImage(splash_png), fit: BoxFit.cover));
|
return new Container(padding: new EdgeInsets.only(left: margin, right: margin), decoration: getSplashBackground());
|
||||||
|
}
|
||||||
|
|
||||||
|
getSplashBackground() {
|
||||||
|
return new BoxDecoration(image: new DecorationImage(image: new ExactAssetImage(splash_png), fit: BoxFit.cover));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Запуск следующего экрана приложения.
|
/// Запуск следующего экрана приложения.
|
||||||
@@ -42,20 +46,18 @@ class SplashScreen extends StatelessWidget {
|
|||||||
pushRoute(context, new RegistrationScreen());
|
pushRoute(context, new RegistrationScreen());
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
checkTokenStatus(context).then((statusResponse) {
|
checkTokenStatus(token).then((statusResponse) {
|
||||||
handleStatusResponse(context, statusResponse);
|
handleStatusResponse(context, statusResponse);
|
||||||
}).catchError((error) {
|
}).catchError((error) {
|
||||||
print('Handle exception!');
|
|
||||||
print(error.toString());
|
print(error.toString());
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startRegistration() async {
|
// Обработка ответа.
|
||||||
|
// В случае, если токен был удален может прийти active: false, либо 404.
|
||||||
}
|
// Если токен не активен, попробовать создать его еще раз. В случае успешного создания токена удалить его и перейти на экран регистрации
|
||||||
|
|
||||||
handleStatusResponse(BuildContext context, var statusResponse) async {
|
handleStatusResponse(BuildContext context, var statusResponse) async {
|
||||||
int code = statusResponse.statusCode;
|
int code = statusResponse.statusCode;
|
||||||
print('resp: ${code}');
|
print('resp: ${code}');
|
||||||
@@ -73,13 +75,20 @@ class SplashScreen extends StatelessWidget {
|
|||||||
if (active) {
|
if (active) {
|
||||||
startScanner(context);
|
startScanner(context);
|
||||||
} else {
|
} else {
|
||||||
createToken(await platform.invokeMethod('getMerchantID')).then((response) {
|
createToken(await platform.invokeMethod('getMerchantID'), await platform.invokeMethod('getPosID')).then((response) {
|
||||||
print('response.body: ${response.body}');
|
print('response.body: ${response.body}');
|
||||||
|
|
||||||
if (response.statusCode == 409) {
|
if (response.statusCode == 409) {
|
||||||
pushRoute(context, new FinishRegistrationScreen());
|
pushRoute(context, new FinishRegistrationScreen());
|
||||||
} else {
|
} else {
|
||||||
startRegistration();
|
deleteToken(token).then((response) async {
|
||||||
|
print(response.body);
|
||||||
|
await platform.invokeMethod('removeKeys');
|
||||||
|
Navigator.of(context).pop(); // Убираем текущий route
|
||||||
|
pushRoute(context, new RegistrationScreen()); // Запускаем регистрацию
|
||||||
|
}).catchError((error) {
|
||||||
|
print(error.toString());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}).catchError((error) {
|
}).catchError((error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user