Merge branch 'master' into nfc-android

# Conflicts:
#	lib/views/login/login_view.dart
#	pubspec.yaml
backend_nfc
Serik.Uvaissov 2020-07-15 13:57:14 +06:00
commit ce8f20b7b0
14 changed files with 150 additions and 86 deletions

View File

@ -30,6 +30,8 @@ PODS:
- SwiftProtobuf (1.9.0) - SwiftProtobuf (1.9.0)
- url_launcher (0.0.1): - url_launcher (0.0.1):
- Flutter - Flutter
- url_launcher_linux (0.0.1):
- Flutter
- url_launcher_macos (0.0.1): - url_launcher_macos (0.0.1):
- Flutter - Flutter
- url_launcher_web (0.0.1): - url_launcher_web (0.0.1):
@ -48,6 +50,7 @@ DEPENDENCIES:
- shared_preferences_web (from `.symlinks/plugins/shared_preferences_web/ios`) - shared_preferences_web (from `.symlinks/plugins/shared_preferences_web/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`) - sqflite (from `.symlinks/plugins/sqflite/ios`)
- url_launcher (from `.symlinks/plugins/url_launcher/ios`) - url_launcher (from `.symlinks/plugins/url_launcher/ios`)
- url_launcher_linux (from `.symlinks/plugins/url_launcher_linux/ios`)
- url_launcher_macos (from `.symlinks/plugins/url_launcher_macos/ios`) - url_launcher_macos (from `.symlinks/plugins/url_launcher_macos/ios`)
- url_launcher_web (from `.symlinks/plugins/url_launcher_web/ios`) - url_launcher_web (from `.symlinks/plugins/url_launcher_web/ios`)
@ -82,6 +85,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/sqflite/ios" :path: ".symlinks/plugins/sqflite/ios"
url_launcher: url_launcher:
:path: ".symlinks/plugins/url_launcher/ios" :path: ".symlinks/plugins/url_launcher/ios"
url_launcher_linux:
:path: ".symlinks/plugins/url_launcher_linux/ios"
url_launcher_macos: url_launcher_macos:
:path: ".symlinks/plugins/url_launcher_macos/ios" :path: ".symlinks/plugins/url_launcher_macos/ios"
url_launcher_web: url_launcher_web:
@ -103,6 +108,7 @@ SPEC CHECKSUMS:
sqflite: 4001a31ff81d210346b500c55b17f4d6c7589dd0 sqflite: 4001a31ff81d210346b500c55b17f4d6c7589dd0
SwiftProtobuf: ecbec1be9036d15655f6b3443a1c4ea693c97932 SwiftProtobuf: ecbec1be9036d15655f6b3443a1c4ea693c97932
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
url_launcher_linux: ac237cb7a8058736e4aae38bdbcc748a4b394cc0
url_launcher_macos: fd7894421cd39320dce5f292fc99ea9270b2a313 url_launcher_macos: fd7894421cd39320dce5f292fc99ea9270b2a313
url_launcher_web: e5527357f037c87560776e36436bf2b0288b965c url_launcher_web: e5527357f037c87560776e36436bf2b0288b965c

View File

@ -392,7 +392,7 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 10; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 94BM6VL7L8; DEVELOPMENT_TEAM = 94BM6VL7L8;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
@ -531,7 +531,7 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 10; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 94BM6VL7L8; DEVELOPMENT_TEAM = 94BM6VL7L8;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
@ -563,7 +563,7 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 10; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 94BM6VL7L8; DEVELOPMENT_TEAM = 94BM6VL7L8;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (

View File

@ -5,12 +5,14 @@ class DialogRequest {
final String description; final String description;
final String buttonTitle; final String buttonTitle;
final String cancelTitle; final String cancelTitle;
final String formatType;
DialogRequest( DialogRequest(
{@required this.title, {@required this.title,
@required this.description, @required this.description,
@required this.buttonTitle, @required this.buttonTitle,
this.cancelTitle}); this.cancelTitle,
this.formatType});
} }
class DialogResponse { class DialogResponse {

View File

@ -132,10 +132,12 @@ class ApiService extends BaseService {
HttpHeaders.contentTypeHeader: "multipart/form-data", HttpHeaders.contentTypeHeader: "multipart/form-data",
HttpHeaders.cacheControlHeader: "no-cache" HttpHeaders.cacheControlHeader: "no-cache"
}; };
if(Platform.isAndroid) { if(Platform.isAndroid) {
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
headers.addAll(<String, String>{ headers.addAll(<String, String>{
HttpHeaders.userAgentHeader: androidInfo.model, HttpHeaders.userAgentHeader: androidInfo.model,
"mob_agent" : "e40c519e7a24d0c93530fd362023afa0",
}); });
} }
@ -143,8 +145,10 @@ class ApiService extends BaseService {
IosDeviceInfo iosInfo = await deviceInfo.iosInfo; IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
headers.addAll(<String, String>{ headers.addAll(<String, String>{
HttpHeaders.userAgentHeader: iosInfo.utsname.machine, HttpHeaders.userAgentHeader: iosInfo.utsname.machine,
"mob_agent" : "fbd69e994b6251837ba82a08c6f68307",
}); });
} }
String url = '$endpoint$point'; String url = '$endpoint$point';
if(this._test) { if(this._test) {
url = '$test_endpoint$point'; url = '$test_endpoint$point';
@ -161,7 +165,7 @@ class ApiService extends BaseService {
Response check = Response.fromJsonDynamic(json.decode(body)); Response check = Response.fromJsonDynamic(json.decode(body));
if (!check.operation && ( [401,402,403,412].contains(check.status) ) ) { if (!check.operation && ( [401,402,403,412].contains(check.status) ) ) {
var future = new Future.delayed(const Duration(milliseconds: 1000), (){ new Future.delayed(const Duration(milliseconds: 1000), (){
_dialogService.showDialog(description: 'Необходимо пройти повторную авторизацию'); _dialogService.showDialog(description: 'Необходимо пройти повторную авторизацию');
UserState state = Redux.store.state.userState; UserState state = Redux.store.state.userState;
_navigatorService.replace(LoginViewRoute, arguments: LoginModel(authType: state.authenticateType, login: state.login, password: state.password )); _navigatorService.replace(LoginViewRoute, arguments: LoginModel(authType: state.authenticateType, login: state.login, password: state.password ));

View File

@ -14,7 +14,8 @@ class DialogService {
GlobalKey<NavigatorState> get dialogNavigationKey => _dialogNavigationKey; GlobalKey<NavigatorState> get dialogNavigationKey => _dialogNavigationKey;
/// Registers a callback function. Typically to show the dialog /// Registers a callback function. Typically to show the dialog
void registerDialogListener(Function(DialogRequest) showDialogListener, Function(DialogRequest) showDialogInputListener) { void registerDialogListener(Function(DialogRequest) showDialogListener,
Function(DialogRequest) showDialogInputListener) {
_showDialogListener = showDialogListener; _showDialogListener = showDialogListener;
_showDialogInputListener = showDialogInputListener; _showDialogInputListener = showDialogInputListener;
} }
@ -50,16 +51,18 @@ class DialogService {
} }
Future<DialogResponse> showConfirmationDialogInput( Future<DialogResponse> showConfirmationDialogInput(
{String title =' Aman Касса', {String title = ' Aman Касса',
String description, String description,
String confirmationTitle = 'Ok', String confirmationTitle = 'Ok',
String cancelTitle = 'Cancel'}) { String cancelTitle = 'Cancel',
String formatType}) {
_dialogCompleter = Completer<DialogResponse>(); _dialogCompleter = Completer<DialogResponse>();
_showDialogInputListener(DialogRequest( _showDialogInputListener(DialogRequest(
title: title, title: title,
description: description, description: description,
buttonTitle: confirmationTitle, buttonTitle: confirmationTitle,
cancelTitle: cancelTitle)); cancelTitle: cancelTitle,
formatType: formatType));
return _dialogCompleter.future; return _dialogCompleter.future;
} }
@ -69,6 +72,4 @@ class DialogService {
_dialogCompleter.complete(response); _dialogCompleter.complete(response);
_dialogCompleter = null; _dialogCompleter = null;
} }
} }

View File

@ -186,3 +186,7 @@ Future<void> openSmena(Store<AppState> store) async {
store.dispatch(checkMoney); store.dispatch(checkMoney);
} }
} }
Future<void> openSmenaPseudo(Store<AppState> store) async {
store.dispatch(SetUserStateAction(UserState(smena: Smena(startedAt: DateTime.now() ))));
}

View File

@ -128,6 +128,7 @@ class _MyFloatingActionButtonState extends State<MyFloatingActionButton> {
description: 'Номер телефона', description: 'Номер телефона',
cancelTitle: 'Отмена', cancelTitle: 'Отмена',
confirmationTitle: 'Отправить', confirmationTitle: 'Отправить',
formatType: 'phone'
); );
if (response.confirmed) { if (response.confirmed) {
String phoneNumber = response.responseText; String phoneNumber = response.responseText;

View File

@ -11,36 +11,56 @@ class HeaderTitle extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return StoreConnector<AppState, UserState>( return StoreConnector<AppState, UserState>(
converter: (store) => store.state.userState, converter: (store) => store.state.userState,
builder: (context, vm) { builder: (context, vm) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Container( Container(
width: 75, width: 75,
child: Image( child: Image(
image: AssetImage('assets/images/logo.png'), image: AssetImage('assets/images/logo.png'),
fit: BoxFit.fitWidth, fit: BoxFit.fitWidth,
),
margin: const EdgeInsets.only(right: 15),
), ),
margin: const EdgeInsets.only(right: 15), Expanded(
), child: Column(
Expanded( crossAxisAlignment: CrossAxisAlignment.start,
child: Column( children: <Widget>[
crossAxisAlignment: CrossAxisAlignment.start, Text(
children: <Widget>[ 'Пользователь: ${vm.user.email}',
Text('Пользователь: ${vm.user.email}', overflow: TextOverflow.fade, maxLines: 1, softWrap: false, style: TextStyle(fontSize: 13, color: Colors.black, ),), overflow: TextOverflow.fade,
vm.smena.message !=null maxLines: 1,
? Text(vm.smena.message, style: TextStyle(fontSize: 13, color: redColor) ) softWrap: false,
: vm.smena.startedAt !=null style: TextStyle(
? Text('Смена от: ${dateFormat.format(vm.smena.startedAt)}', overflow: TextOverflow.fade, maxLines: 1, softWrap: false , style: TextStyle(fontSize: 13, color: Colors.black),) fontSize: 13,
: Text('Смена от:', style: TextStyle(fontSize: 13, color: Colors.black),), color: Colors.black,
], ),
), ),
) vm.smena.message != null
], ? Text(vm.smena.message,
); style: TextStyle(fontSize: 13, color: redColor))
} : vm.smena.startedAt != null
); ? Text(
'Смена открыта',
overflow: TextOverflow.fade,
maxLines: 1,
softWrap: false,
style: TextStyle(
fontSize: 13, color: Colors.black),
)
: Text(
'',
style: TextStyle(
fontSize: 13, color: Colors.black),
),
],
),
)
],
);
});
} }
} }

View File

@ -104,19 +104,21 @@ class _LoginViewState extends State<LoginView> {
), ),
verticalSpaceSmall, verticalSpaceSmall,
InputField( InputField(
placeholder: 'Пароль', placeholder: 'Пароль',
password: true, password: true,
controller: passwordController, controller: passwordController,
fieldFocusNode: passwordNode, fieldFocusNode: passwordNode,
additionalNote: vm.loginFormMessage.password, additionalNote: vm.loginFormMessage.password,
enterPressed: _pressBtnEnter), enterPressed: _pressBtnEnter,
textInputAction: TextInputAction.done,
),
verticalSpaceMedium, verticalSpaceMedium,
Row( Row(
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
SizedBox( SizedBox(
width: 100, width: 150,
child: BusyButton( child: BusyButton(
title: 'Войти', title: 'Войти',
busy: vm.isLoading, busy: vm.isLoading,

View File

@ -203,6 +203,7 @@ class _PaymentViewState extends State<PaymentView> {
Redux.store.dispatch(cleanKassaItems); Redux.store.dispatch(cleanKassaItems);
} }
Redux.store.dispatch(checkMoney); Redux.store.dispatch(checkMoney);
Redux.store.dispatch(openSmenaPseudo);
Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop();
_navigatorService.pop(); _navigatorService.pop();
_navigatorService.push(ImageShowRoute, _navigatorService.push(ImageShowRoute,

View File

@ -4,6 +4,7 @@ import 'package:aman_kassa_flutter/core/services/dialog_service.dart';
import 'package:aman_kassa_flutter/shared/app_colors.dart'; import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:mask_text_input_formatter/mask_text_input_formatter.dart';
class DialogManager extends StatefulWidget { class DialogManager extends StatefulWidget {
final Widget child; final Widget child;
@ -15,18 +16,18 @@ class DialogManager extends StatefulWidget {
class _DialogManagerState extends State<DialogManager> { class _DialogManagerState extends State<DialogManager> {
final DialogService _dialogService = locator<DialogService>(); final DialogService _dialogService = locator<DialogService>();
TextEditingController controller; TextEditingController _controller;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
controller = new TextEditingController(); _controller = new TextEditingController();
_dialogService.registerDialogListener(_showDialog, _showDialogInput); _dialogService.registerDialogListener(_showDialog, _showDialogInput);
} }
@override @override
void dispose() { void dispose() {
controller.dispose(); _controller.dispose();
super.dispose(); super.dispose();
} }
@ -77,7 +78,13 @@ class _DialogManagerState extends State<DialogManager> {
void _showDialogInput(DialogRequest request) { void _showDialogInput(DialogRequest request) {
var isConfirmationDialog = request.cancelTitle != null; var isConfirmationDialog = request.cancelTitle != null;
controller.clear();
_controller.clear();
var maskFormatter = new MaskTextInputFormatter(
mask: '+% (###) ###-##-##',
filter: {"#": RegExp(r'[0-9]'), "%": RegExp(r'[7]')});
var dialogController = showDialog( var dialogController = showDialog(
context: context, context: context,
builder: (context) => AlertDialog( builder: (context) => AlertDialog(
@ -101,15 +108,21 @@ class _DialogManagerState extends State<DialogManager> {
//Text(request.description), //Text(request.description),
TextField( TextField(
autofocus: true, autofocus: true,
decoration: InputDecoration(labelText: request.description), decoration: InputDecoration(
controller: controller, labelText: request.description,
hintText: request.formatType == "phone"
? "+7 (123) 456-78-90"
: ""),
controller: _controller,
onSubmitted: (value) { onSubmitted: (value) {
_dialogService _dialogService
.dialogComplete(DialogResponse(confirmed: false)); .dialogComplete(DialogResponse(confirmed: false));
}, },
keyboardType: TextInputType.phone, keyboardType: TextInputType.phone,
inputFormatters: <TextInputFormatter>[ inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter(RegExp("^[0-9.]*")), if (request.formatType == "phone") maskFormatter,
if (request.formatType == null)
WhitelistingTextInputFormatter(RegExp("^[0-9.]*")),
], ],
) )
], ],
@ -137,8 +150,12 @@ class _DialogManagerState extends State<DialogManager> {
style: TextStyle(fontSize: 18), style: TextStyle(fontSize: 18),
), ),
onPressed: () { onPressed: () {
_dialogService.dialogComplete(DialogResponse( String _result = _controller.text;
confirmed: true, responseText: controller.text)); if (request.formatType == "phone") {
_result = maskFormatter.getUnmaskedText();
}
_dialogService.dialogComplete(
DialogResponse(confirmed: true, responseText: _result));
}, },
), ),
], ],

View File

@ -41,40 +41,46 @@ class _BusyButtonState extends State<BusyButton> {
child: InkWell( child: InkWell(
onTap: widget.busy || !widget.enabled ? null : widget.onPressed, onTap: widget.busy || !widget.enabled ? null : widget.onPressed,
child: AnimatedContainer( child: AnimatedContainer(
height: widget.busy ? 40 : 40, height: widget.busy ? 45 : 45,
//width: widget.busy ? 40 : 40, //width: widget.busy ? 40 : 40,
duration: const Duration(milliseconds: 300), duration: const Duration(milliseconds: 300),
alignment: Alignment.center, alignment: Alignment.center,
margin: EdgeInsets.symmetric( margin: EdgeInsets.symmetric(
horizontal: widget.busy ? 10 : 25, horizontal: widget.busy ? 10 : 25,
vertical: widget.busy ? 10 : 15), vertical: widget.busy ? 10 : 10),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
!widget.busy !widget.busy
? Row( ? Expanded(
mainAxisAlignment: MainAxisAlignment.center, child: Row(
children: <Widget>[ mainAxisAlignment: MainAxisAlignment.center,
widget.icon != null children: <Widget>[
? Container( widget.icon != null
child: (Icon( ? Container(
widget.icon, child: (Icon(
color: whiteColor, widget.icon,
)), color: whiteColor,
margin: const EdgeInsets.only(right: 10.0), )),
) margin: const EdgeInsets.only(right: 10.0),
: (Container()), )
AutoSizeText( : (Container()),
widget.title, AutoSizeText(
textAlign: TextAlign.center, widget.title,
style: buttonTitleTextStyle, textAlign: TextAlign.center,
), style: buttonTitleTextStyle,
], ),
],
),
) )
: CircularProgressIndicator( : SizedBox(
strokeWidth: 2, width: 30,
valueColor: height: 30,
AlwaysStoppedAnimation<Color>(Colors.white)), child: CircularProgressIndicator(
strokeWidth: 2,
valueColor:
AlwaysStoppedAnimation<Color>(Colors.white)),
),
], ],
), ),
), ),

View File

@ -91,7 +91,7 @@ packages:
name: equatable name: equatable
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.2"
esys_flutter_share: esys_flutter_share:
dependency: "direct main" dependency: "direct main"
description: description:
@ -309,7 +309,7 @@ packages:
name: provider name: provider
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.3.0" version: "4.3.1"
pub_semver: pub_semver:
dependency: transitive dependency: transitive
description: description:

View File

@ -1,6 +1,6 @@
name: aman_kassa_flutter name: aman_kassa_flutter
description: A new Flutter project. description: A new Flutter project.
version: 1.0.1+22 version: 1.0.1+21
environment: environment:
sdk: '>=2.3.0 <3.0.0' sdk: '>=2.3.0 <3.0.0'
dependencies: dependencies: