slang_retail_assistant 8.4.0
slang_retail_assistant: ^8.4.0 copied to clipboard
The client library for adding and interacting with Slang CONVA's Retail In-App Voice Assistant.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:slang_retail_assistant/slang_retail_assistant.dart';
import 'dart:convert';
void main() {
runApp(new MaterialApp(
home: new MyApp(),
debugShowCheckedModeBanner: false,
));
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp>
implements
RetailAssistantAction,
RetailAssistantLifeCycleObserver,
RetailAssistantVoiceAssistListener {
String _searchText = '';
SearchUserJourney _searchUserJourney;
NavigationUserJourney _navigationUserJourney;
OrderManagementUserJourney _orderManagementUserJourney;
String stringSearchAppState;
Condition appStateCondition;
String stringNavigationAppState;
String stringOrderManagementAppState;
int mOrderIndex = -1;
@override
void initState() {
super.initState();
initSlangRetailAssistant();
}
void initSlangRetailAssistant() {
var positionConfig = new AssistantUIPosition()
..baseUIPosition = BaseUIPosition.BOTTOM_CENTER
..offsetY = -56
..isForced = true
..isDraggable = true;
var assistantConfig = new AssistantConfiguration()
..assistantId = "AssistantId"
..apiKey = "APIKey"
..triggerStyle = AssistantTriggerStyle.FLAT
..surfaceStyle = AssistantSurfaceStyle.MINIMAL_CARD
..uiPosition = positionConfig;
SlangRetailAssistant.initialize(assistantConfig);
SlangRetailAssistant.setAction(this);
SlangRetailAssistant.setLifecycleObserver(this);
SearchUserJourney.getContext().clear();
SearchUserJourney.disablePreserveContext();
OrderManagementUserJourney.getContext().clear();
OrderManagementUserJourney.disablePreserveContext();
NavigationUserJourney.getContext().clear();
NavigationUserJourney.disablePreserveContext();
}
@override
void onAssistantError(Map<String, String> assistantError) {
print("AssistantError main.dart" + assistantError.toString());
}
@override
SearchAppState onSearch(
SearchInfo searchInfo, SearchUserJourney searchUserJourney) {
_searchUserJourney = searchUserJourney;
setState(() {
try {
JsonEncoder encoder = new JsonEncoder.withIndent(' ');
String searchMapString = encoder.convert(searchInfo);
_searchText = searchMapString;
} catch (e) {
print(e);
}
});
_showAppStateDialogForSearch().then((value) => (stringSearchAppState !=
'unsupported')
? _showAppStateConditionDialogForSearch().then((value) =>
(stringSearchAppState == 'search_results')
? _searchUserJourney
.notifyAppState(new SearchResultAppState(appStateCondition))
: _searchUserJourney
.notifyAppState(new AddToCartAppState(appStateCondition)))
: _searchUserJourney.notifyAppState(new UnSupportedAppState()));
return new WaitingAppState();
}
@override
NavigationAppState onNavigation(
navigationInfo, NavigationUserJourney navigationUserJourney) {
_navigationUserJourney = navigationUserJourney;
_showAppStateDialogForNavigation().then((value) =>
stringNavigationAppState != 'unsupported'
? _showAppStateConditionDialogForNavigation().then((value) =>
_navigationUserJourney.notifyAppState(
new NavigationCompleteAppState(appStateCondition)))
: _navigationUserJourney.notifyAppState(new UnSupportedAppState()));
return new WaitingAppState();
}
@override
OrderManagementAppState onOrderManagement(OrderInfo orderInfo,
OrderManagementUserJourney orderManagementUserJourney) {
_orderManagementUserJourney = orderManagementUserJourney;
if (orderInfo.index != null) {
setState(() {
mOrderIndex = orderInfo.index;
});
}
_showAppStateDialogForOrderManagement().then((value) =>
(stringOrderManagementAppState != 'unsupported')
? _showAppStateConditionDialogForOrderManagement().then((value) =>
(stringOrderManagementAppState == 'view_order')
? _orderManagementUserJourney.notifyAppState(
new OrderViewAppState(appStateCondition))
: _orderManagementUserJourney.notifyAppState(
new OrderCancelAppState(appStateCondition)))
: _orderManagementUserJourney
.notifyAppState(new UnSupportedAppState()));
return new WaitingAppState();
}
@override
Widget build(BuildContext context) {
SlangRetailAssistant.getUI().showTrigger();
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Slang Retail PlayGround App'),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Container(height: 16), // set height
TextButton(
child: Text(
'Show Trigger',
style: TextStyle(fontSize: 20.0),
),
onPressed: () {
SlangRetailAssistant.getUI().showTrigger();
},
),
Container(height: 16), // set height
TextButton(
child: Text(
'Hide Trigger',
style: TextStyle(fontSize: 20.0),
),
onPressed: () {
SlangRetailAssistant.getUI().hideTrigger();
},
),
Container(height: 16), // set height
TextButton(
child: Text(
'Clear UJ Context',
style: TextStyle(fontSize: 20.0),
),
onPressed: () {
SearchUserJourney.getContext().clear();
OrderManagementUserJourney.getContext().clear();
NavigationUserJourney.getContext().clear();
},
),
Container(height: 16), // set height
TextButton(
child: Text(
'Notify Non-Voice Search',
style: TextStyle(fontSize: 20.0),
),
onPressed: () {
SlangRetailAssistant.notifyNonVoiceSearch("potato");
},
),
Container(height: 16), // set height
Flexible(
child: FractionallySizedBox(
widthFactor: 0.9,
heightFactor: 0.98,
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Container(
height: MediaQuery.of(context).size.height,
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.black,
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'$_searchText\n',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
color: Colors.white),
),
),
))))
],
))));
}
Future<void> _showAppStateDialogForSearch() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
elevation: 24.0,
title: Text('Search App State'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('Please select the search App state'),
],
),
),
actions: <Widget>[
TextButton(
child: Text('ADD_TO_CART'),
onPressed: () {
setState(() {
stringSearchAppState = 'add_to_cart';
});
Navigator.of(context).pop();
},
),
TextButton(
child: Text('SEARCH_RESULTS'),
onPressed: () {
setState(() {
stringSearchAppState = 'search_results';
});
Navigator.of(context).pop();
},
),
TextButton(
child: Text('UNSUPPORTED'),
onPressed: () {
setState(() {
stringSearchAppState = 'unsupported';
});
Navigator.of(context).pop();
},
)
],
);
},
);
}
Future<void> _showAppStateConditionDialogForSearch() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
elevation: 24.0,
title: Text('Search App State'),
content: Column(
children: <Widget>[..._widgetListForSearchAppStateCondition],
),
);
},
);
}
List<Widget> get _widgetListForSearchAppStateCondition {
List<Widget> list = [];
list.addAll([
TextButton(
child: Text('Success'),
onPressed: () {
appStateCondition = SearchResultAppState.success;
Navigator.of(context).pop();
},
),
TextButton(
child: Text('Failure'),
onPressed: () {
appStateCondition = SearchResultAppState.failure;
Navigator.of(context).pop();
},
),
TextButton(
child: Text('Item Not Found'),
onPressed: () {
appStateCondition = SearchResultAppState.itemNotFound;
Navigator.of(context).pop();
},
),
TextButton(
child: Text('Item Not Specified'),
onPressed: () {
appStateCondition = SearchResultAppState.itemNotSpecified;
Navigator.of(context).pop();
},
),
TextButton(
child: Text('Item Out of Stock'),
onPressed: () {
appStateCondition = SearchResultAppState.itemOutOfStock;
Navigator.of(context).pop();
},
)
]);
if (stringSearchAppState != null && stringSearchAppState == 'add_to_cart') {
list.addAll([
TextButton(
child: Text('Item Ambiguous'),
onPressed: () {
appStateCondition = AddToCartAppState.itemAmbiguous;
Navigator.of(context).pop();
},
),
TextButton(
child: Text('Item Ambiguous Force UI'),
onPressed: () {
appStateCondition = AddToCartAppState.itemAmbiguousForceUI;
Navigator.of(context).pop();
},
),
TextButton(
child: Text('Item Quantity Required'),
onPressed: () {
appStateCondition = AddToCartAppState.itemQuantityRequired;
Navigator.of(context).pop();
},
)
]);
}
return list;
}
Future<void> _showAppStateDialogForNavigation() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
elevation: 24.0,
title: Text('Navigation App State'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('Please select the Navigation App state'),
],
),
),
actions: <Widget>[
TextButton(
child: Text('NAVIGATION'),
onPressed: () {
setState(() {
stringNavigationAppState = 'navigation';
});
Navigator.of(context).pop();
},
),
TextButton(
child: Text('UNSUPPORTED'),
onPressed: () {
setState(() {
stringNavigationAppState = 'unsupported';
});
Navigator.of(context).pop();
},
)
],
);
},
);
}
Future<void> _showAppStateConditionDialogForNavigation() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
elevation: 24.0,
title: Text('Navigation AppState Condition'),
actions: [
TextButton(
child: Text('Success'),
onPressed: () {
appStateCondition = NavigationCompleteAppState.success;
Navigator.of(context).pop();
},
),
TextButton(
child: Text('Failure'),
onPressed: () {
appStateCondition = NavigationCompleteAppState.failure;
Navigator.of(context).pop();
},
),
],
);
},
);
}
Future<void> _showAppStateDialogForOrderManagement() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
elevation: 24.0,
title: Text('OrderManagement App State'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('Please select the OrderManagement App state'),
],
),
),
actions: <Widget>[
TextButton(
child: Text('VIEW_ORDER'),
onPressed: () {
setState(() {
stringOrderManagementAppState = 'view_order';
});
Navigator.of(context).pop();
},
),
TextButton(
child: Text('CANCEL_ORDER'),
onPressed: () {
setState(() {
stringOrderManagementAppState = 'cancel_order';
});
Navigator.of(context).pop();
},
),
TextButton(
child: Text('UNSUPPORTED'),
onPressed: () {
setState(() {
stringOrderManagementAppState = 'unsupported';
});
Navigator.of(context).pop();
},
)
],
);
},
);
}
Future<void> _showAppStateConditionDialogForOrderManagement() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
elevation: 24.0,
title: Text('OrderManagement App State'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
..._widgetListForOrderManagementAppStateCondition
],
)),
);
},
);
}
List<Widget> get _widgetListForOrderManagementAppStateCondition {
List<Widget> list = [];
list.addAll([
TextButton(
child: Text('Success'),
onPressed: () {
appStateCondition = OrderViewAppState.success;
Navigator.of(context).pop();
},
),
TextButton(
child: Text('Failure'),
onPressed: () {
appStateCondition = OrderViewAppState.failure;
Navigator.of(context).pop();
},
),
TextButton(
child: Text('Order Not Found'),
onPressed: () {
appStateCondition = OrderViewAppState.orderNotFound;
Navigator.of(context).pop();
},
)
]);
if (stringOrderManagementAppState != null &&
stringOrderManagementAppState == 'view_order') {
list.addAll([
TextButton(
child: Text('Empty Order'),
onPressed: () {
appStateCondition = OrderViewAppState.orderHistoryEmpty;
Navigator.of(context).pop();
},
)
]);
}
if (stringOrderManagementAppState != null &&
stringOrderManagementAppState == 'cancel_order') {
list.addAll([
TextButton(
child: Text('Cancel Confirmation Required'),
onPressed: () {
appStateCondition =
OrderCancelAppState.orderCancelConfirmationRequired;
Navigator.of(context).pop();
},
),
TextButton(
child: Text('User Confirmed Cancel'),
onPressed: () {
appStateCondition = OrderCancelAppState.orderCancelUserConfirmed;
Navigator.of(context).pop();
},
),
TextButton(
child: Text('User Denied Cancel'),
onPressed: () {
appStateCondition = OrderCancelAppState.orderCancelUserDenied;
Navigator.of(context).pop();
},
),
]);
}
return list;
}
@override
void onAssistantClosed(bool isCancelled) {
print("onAssistantClosed " + isCancelled.toString());
}
@override
void onAssistantInitFailure(String description) {
print("onAssistantInitFailure " + description);
}
@override
void onAssistantInitSuccess() {
print("onAssistantInitSuccess");
}
@override
void onAssistantInvoked() {
print("onAssistantInvoked");
}
@override
void onAssistantLocaleChanged(Map<String, String> locale) {
print("onAssistantLocaleChanged " + locale.toString());
}
@override
void onOnboardingFailure() {
print("onOnboardingFailure");
}
@override
void onOnboardingSuccess() {
print("onOnboardingSuccess");
}
@override
void onUnrecognisedUtterance(String utterance) {
print("onUnrecognisedUtterance " + utterance);
}
@override
void onUtteranceDetected(String utterance) {
print("onUtteranceDetected " + utterance);
}
@override
void onMicPermissionDenied() {
print("onMicPermissionDenied");
}
@override
void onMicPermissionGranted() {
print("onMicPermissionDenied");
}
@override
void onCoachmarkAction(AssistantCoachmarkType coachmarkType,
AssistantCoachmarkAction coachmarkAction) {
print(
"onCoachmarkAction CoachmarkType=$coachmarkType CoachmarkAction=$coachmarkAction");
}
@override
void onVoiceAssistEnd(String promptId, String promptText, bool b) {
print("onVoiceAssistEnd promptId " +
promptId +
" promptText " +
promptText +
" boolean " +
b.toString());
}
@override
void onVoiceAssistStart(String promptId, String promptText) {
print("onVoiceAssistStart promptId " +
promptId +
" promptText " +
promptText);
}
}