voice command changes

merge-update-with-lab-changes
Sultan Khan 5 years ago
parent d33918c932
commit b3e6c4efda

@ -94,6 +94,6 @@ dependencies {
implementation 'com.github.kittinunf.fuel:fuel:2.3.0' //for JVM
implementation 'com.github.kittinunf.fuel:fuel-android:2.3.0'
implementation 'com.google.android.gms:play-services-location:17.1.0'//for Android
implementation 'com.google.android.gms:play-services-basement:17.5.0'
}

@ -289,7 +289,7 @@ const GET_PATIENT_HEALTH_STATS =
const CHANNEL = 3;
const GENERAL_ID = 'Cs2020@2016\$2958';
const IP_ADDRESS = '10.20.10.20';
const VERSION_ID = 5.8;
const VERSION_ID = 8.4;
const SETUP_ID = '91877';
const LANGUAGE = 2;
const PATIENT_OUT_SA = 0;
@ -298,6 +298,8 @@ const IS_DENTAL_ALLOWED_BACKEND = false;
const PATIENT_TYPE = 1;
const PATIENT_TYPE_ID = 1;
var DEVICE_TOKEN = "";
var IS_VOICE_COMMAND_CLOSED = false;
var IS_TEXT_COMPLETED = false;
var DeviceTypeID = Platform.isIOS ? 1 : 2;
const LANGUAGE_ID = 1;
const GET_PHARMCY_ITEMS = "Services/Lists.svc/REST/GetPharmcyItems_Region";

@ -1784,5 +1784,6 @@ const Map localizedValues = {
"en": "Select the preferred unit",
"ar": "اختر الوحدة المفضلة"
},
"select-unit": {"en": "Select unit", "ar": "اختر وحدة القياس"}
"select-unit": {"en": "Select unit", "ar": "اختر وحدة القياس"},
"try-saying": {"en": "Try saying something", "ar": 'حاول قول شيء ما'}
};

@ -86,7 +86,12 @@ class _LandingPageState extends State<LandingPage> with WidgetsBindingObserver {
_changeCurrentTab(int tab) {
setState(() {
currentTab = tab;
if (tab != 0) pageController.jumpToPage(tab);
if (tab != 0)
pageController.jumpToPage(tab);
else {
IS_VOICE_COMMAND_CLOSED = false;
pageController.jumpToPage(tab);
}
});
}
@ -627,7 +632,7 @@ class _LandingPageState extends State<LandingPage> with WidgetsBindingObserver {
authService
.selectDeviceImei(token)
.then((SelectDeviceIMEIRES value) => setUserValues(value));
if (await sharedPref.getObject(USER_PROFILE) != null) {
if (projectViewModel.isLoading == true) {
var data =
AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE));
if (data != null) {
@ -636,9 +641,11 @@ class _LandingPageState extends State<LandingPage> with WidgetsBindingObserver {
.then((res) => {print(res)});
authService.getDashboard().then((value) => {
setState(() {
if (value != null) {
notificationCount = value['List_PatientDashboard'][0]
['UnreadPatientNotificationCount']
.toString();
}
})
});
}

@ -71,7 +71,7 @@ class _MedicalProfilePageState extends State<MedicalProfilePage> {
builder: (_, model, widget) => AppScaffold(
isShowDecPage: false,
baseViewModel: model,
// isHelp: true,
isHelp: true,
body: Container(
child: SingleChildScrollView(
child: Column(

@ -33,7 +33,6 @@ class _GeneralSettings extends State<GeneralSettings>
super.initState();
}
Widget build(BuildContext context) {
mediaQueryData = MediaQuery.of(context);
themeNotifier = Provider.of<ThemeNotifier>(context);
@ -59,7 +58,6 @@ class _GeneralSettings extends State<GeneralSettings>
onChanged: (value) {
setState(() {
vibration = value;
});
setVibration(value);
},
@ -239,7 +237,7 @@ class _GeneralSettings extends State<GeneralSettings>
case 1:
{
themeNotifier.setTheme(ThemeData(
fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans',
//fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans',
primarySwatch: Colors.grey,
visualDensity: VisualDensity.adaptivePlatformDensity,
brightness: Brightness.light,
@ -262,7 +260,8 @@ class _GeneralSettings extends State<GeneralSettings>
highlightColor: Colors.grey[100].withOpacity(0.4),
splashColor: Colors.transparent,
primaryColor: Colors.grey,
bottomSheetTheme: BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)),
bottomSheetTheme:
BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)),
cursorColor: Colors.grey,
iconTheme: IconThemeData(),
@ -296,27 +295,30 @@ class _GeneralSettings extends State<GeneralSettings>
break;
}
//permission.setTheme(value);
}
setVibration(value) {
permission.setVibrationPermission(value);
}
setAccisibility() {
if(!accsibility){
}
if (!accsibility) {}
// permission.setVibrationPermission(value);
}
getValues() async {
blindValue= permission.isThemeEnabled() == null ? 0 : permission.isThemeEnabled();
vibration = permission.isVibrationEnabled() ==null ? false : permission.isVibrationEnabled();
blindValue =
permission.isThemeEnabled() == null ? 0 : permission.isThemeEnabled();
vibration = permission.isVibrationEnabled() == null
? false
: permission.isVibrationEnabled();
accsibility = mediaQueryData.accessibleNavigation;
}
getTheme(value) async {
if (value == 1) {
return ThemeData(
fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans',
// fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans',
primarySwatch: Colors.grey,
visualDensity: VisualDensity.adaptivePlatformDensity,
brightness: Brightness.light,
@ -339,7 +341,8 @@ class _GeneralSettings extends State<GeneralSettings>
highlightColor: Colors.grey[100].withOpacity(0.4),
splashColor: Colors.transparent,
primaryColor: Colors.grey,
bottomSheetTheme: BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)),
bottomSheetTheme:
BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)),
cursorColor: Colors.grey,
iconTheme: IconThemeData(),
@ -352,10 +355,9 @@ class _GeneralSettings extends State<GeneralSettings>
),
),
);
} else if (value == 3) {
return ThemeData(
fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans',
// fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans',
primarySwatch: Colors.grey,
visualDensity: VisualDensity.adaptivePlatformDensity,
brightness: Brightness.light,
@ -378,7 +380,8 @@ class _GeneralSettings extends State<GeneralSettings>
highlightColor: Colors.grey[100].withOpacity(0.4),
splashColor: Colors.transparent,
primaryColor: Colors.grey,
bottomSheetTheme: BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)),
bottomSheetTheme:
BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)),
cursorColor: Colors.grey,
iconTheme: IconThemeData(),
@ -391,10 +394,9 @@ class _GeneralSettings extends State<GeneralSettings>
),
),
);
} else {
return ThemeData(
fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans',
//fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans',
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
brightness: Brightness.light,
@ -415,7 +417,8 @@ class _GeneralSettings extends State<GeneralSettings>
highlightColor: Colors.grey[100].withOpacity(0.4),
splashColor: Colors.transparent,
primaryColor: Color(0xff40ACC9),
bottomSheetTheme: BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)),
bottomSheetTheme:
BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)),
cursorColor: Colors.grey,
cardColor: Colors.white,
iconTheme: IconThemeData(),
@ -428,7 +431,6 @@ class _GeneralSettings extends State<GeneralSettings>
),
),
);
}
}
}

@ -39,7 +39,6 @@ class _SplashScreenState extends State<SplashScreen> {
),
);
});
},
);
}
@ -47,14 +46,19 @@ class _SplashScreenState extends State<SplashScreen> {
/// load the Privilege from service
Future loadPrivilege() async {
await _privilegeService.getPrivilege();
Provider.of<ProjectViewModel>(context, listen: false).setPrivilegeModelList(privilege: _privilegeService.privilegeModelList);
Provider.of<ProjectViewModel>(context, listen: false)
.setPrivilegeModelList(privilege: _privilegeService.privilegeModelList);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Image.asset('assets/images/powerd-by.jpg',fit: BoxFit.fitWidth,width: MediaQuery.of(context).size.width,),
body: Image.asset(
'assets/images/powerd-by.jpg',
fit: BoxFit.fitWidth,
width: MediaQuery.of(context).size.width,
),
);
}
}

@ -1468,6 +1468,7 @@ class TranslationBase {
String get areyousure => localizedValues["areyousure"][locale.languageCode];
String get preferredunit =>
localizedValues["preferredunit"][locale.languageCode];
String get trySaying => localizedValues["try-saying"][locale.languageCode];
}
class TranslationBaseDelegate extends LocalizationsDelegate<TranslationBase> {

@ -51,7 +51,6 @@ class AppScaffold extends StatelessWidget {
final List<Widget> appBarIcons;
final List<ImagesInfo> imagesInfo;
final bool isHelp;
bool isAnimation = false;
AuthenticatedUserObject authenticatedUserObject =
locator<AuthenticatedUserObject>();
@ -206,17 +205,20 @@ class _RobotIcon extends State<RobotIcon> {
void initState() {
event.controller.stream.listen((p) {
if (p['animationEnable'] == 'false') {
//setState(() {
// if (this.mounted) {
if (this.mounted) {
setState(() {
this.isAnimation = false;
//}
// });
}
});
}
} else if (p['animationEnable'] == 'true') {
if (this.mounted) {
setState(() {
setAnimation();
this.isAnimation = true;
});
}
}
});
super.initState();
}
@ -277,13 +279,10 @@ class _RobotIcon extends State<RobotIcon> {
bottom: 50);
}
setAnimation() async {
//await sharedPref.getBool(IS_ROBOT_VISIBLE) ||
var animation =
await sharedPref.getBool(IS_ROBOT_INIT) == null ? true : false;
// setAnimation() async {
// /// await sharedPref.getBool(IS_ROBOT_VISIBLE) ||
// // var animation =
// // IS_TEXT_COMPLETED == ? true : false;
setState(() {
this.isAnimation = animation;
});
}
// }
}

@ -59,8 +59,7 @@ import 'package:flutter_tts/flutter_tts.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'package:speech_to_text/speech_recognition_error.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:speech_to_text/speech_to_text.dart';
import 'package:speech_to_text/speech_to_text.dart' as stt;
import 'package:diplomaticquarterapp/pages/BookAppointment/DoctorProfile.dart';
import 'package:diplomaticquarterapp/pages/BookAppointment/Search.dart';
import 'package:flutter/cupertino.dart';
@ -82,7 +81,7 @@ class _FloatingSearchButton extends State<FloatingSearchButton>
RobotProvider eventProvider = RobotProvider();
bool isLoading = false;
bool isError = false;
final SpeechToText speech = SpeechToText();
stt.SpeechToText speech = stt.SpeechToText();
String error = '';
String _currentLocaleId = "";
String lastError;
@ -102,28 +101,40 @@ class _FloatingSearchButton extends State<FloatingSearchButton>
var sharedPref = new AppSharedPreferences();
bool _hasSpeech = false;
ProjectViewModel projectProvider;
bool isAnimationEnable = false;
bool isAnimationEnable = true;
AnimationController controller;
Animation<Offset> offset;
String networkImage;
bool isArabic;
@override
void initState() {
controller =
AnimationController(vsync: this, duration: Duration(seconds: 1));
offset = Tween<Offset>(begin: Offset.zero, end: Offset(0.0, 1.0))
offset = Tween<Offset>(begin: Offset(0.0, 1.0), end: Offset(0.0, 0.0))
.animate(controller);
initialSpeak();
Future.delayed(const Duration(seconds: 2), () {
if (IS_VOICE_COMMAND_CLOSED == true) {
controller.reverse(from: -1);
}
if (mounted) {
//Future.delayed(const Duration(seconds: 2), () {
isArabic = Provider.of<ProjectViewModel>(context, listen: false).isArabic;
requestPermissions();
getUserData();
initialSpeak();
setState(() {
if (IS_TEXT_COMPLETED) {
isAnimationEnable = false;
}
});
}
event.controller.stream.listen((p) {
if (p['isRobotVisible'] == 'true') {
if (this.mounted) {
setState(() {
sharedPref.setBool(IS_ROBOT_VISIBLE, true);
controller.reverse();
if (IS_VOICE_COMMAND_CLOSED == false) {
controller.forward();
}
});
}
}
@ -141,21 +152,25 @@ class _FloatingSearchButton extends State<FloatingSearchButton>
}
@override
void didUpdateWidget(FloatingSearchButton oldWidget) {
// super.didUpdateWidget(oldWidget);
// event.controller.stream.listen((p) {
// if (p['animationEnable'] != 'false') {
// initialSpeak();
void dispose() {
controller.dispose();
super.dispose();
}
// @override
// void didUpdateWidget(FloatingSearchButton oldWidget) {
// // super.didUpdateWidget(oldWidget);
// // event.controller.stream.listen((p) {
// // if (p['animationEnable'] != 'false') {
// // initialSpeak();
// // }
// // });
// }
// });
}
AuthenticatedUserObject authenticatedUserObject =
locator<AuthenticatedUserObject>();
VitalSignService _vitalSignService = locator<VitalSignService>();
@override
Widget build(BuildContext context) {
projectProvider = Provider.of(context);
return Container(
child: SlideTransition(position: offset, child: getStack()));
}
@ -180,7 +195,6 @@ class _FloatingSearchButton extends State<FloatingSearchButton>
: 'assets/images/gif/robot-idle.gif'),
),
onTap: () {
RoboSearch.isClosed = false;
new RoboSearch(context: context).showAlertDialog(context);
initSpeechState().then((value) => {startVoiceSearch()});
},
@ -192,8 +206,8 @@ class _FloatingSearchButton extends State<FloatingSearchButton>
onTap: () {
setState(() {
if (this.mounted) {
controller.forward();
sharedPref.setBool(IS_ROBOT_VISIBLE, false);
controller.reverse();
IS_VOICE_COMMAND_CLOSED = true;
}
});
},
@ -213,25 +227,38 @@ class _FloatingSearchButton extends State<FloatingSearchButton>
startVoiceSearch() async {
_currentLocaleId =
TranslationBase.of(AppGlobal.context).locale.languageCode;
bool available = await speech.initialize(
onStatus: statusListener, onError: errorListener);
if (available) {
speech.listen(
onResult: resultListener,
listenFor: Duration(seconds: 10),
// listenMode: ListenMode.confirmation,
localeId: _currentLocaleId == 'en' ? 'en-US' : 'ar-SA',
onSoundLevelChange: soundLevelListener,
cancelOnError: true,
partialResults: true,
onDevice: true,
listenMode: ListenMode.deviceDefault);
);
} else {
print("The user has denied the use of speech recognition.");
}
// some time later...
//speech.stop();
// speech.listen(
// onResult: resultListener,
// listenFor: Duration(seconds: 10),
// localeId: _currentLocaleId == 'en' ? 'en-US' : 'ar-SA',
// onSoundLevelChange: soundLevelListener,
// cancelOnError: true,
// partialResults: true,
// onDevice: true,
// listenMode: ListenMode.deviceDefault);
}
void resultListener(SpeechRecognitionResult result) {
// lastWords = "${result.recognizedWords} - ${result.finalResult}";
void resultListener(result) {
reconizedWord = result.recognizedWords;
event.setValue({"searchText": reconizedWord});
if (result.finalResult == true) {
Future.delayed(const Duration(seconds: 1), () {
_speak(reconizedWord);
RoboSearch.closeAlertDialog(context);
//Navigator.of(context).pop();
});
}
}
@ -250,10 +277,13 @@ class _FloatingSearchButton extends State<FloatingSearchButton>
}
void requestPermissions() async {
if (await Permission.microphone.isDenied ||
await Permission.microphone.isUndetermined) {
Map<Permission, PermissionStatus> statuses = await [
Permission.microphone,
].request();
}
}
Future<void> initSpeechState() async {
bool hasSpeech = await speech.initialize(
@ -274,9 +304,7 @@ class _FloatingSearchButton extends State<FloatingSearchButton>
void errorListener(SpeechRecognitionError error) {
event.setValue({"searchText": 'null'});
//setState(() {
// reconizedWord = "${error.errorMsg} - ${error.permanent}";
//});
RoboSearch.closeAlertDialog(context);
}
void statusListener(String status) {
@ -298,9 +326,7 @@ class _FloatingSearchButton extends State<FloatingSearchButton>
}
getCommands(result) async {
print(result);
results = result;
switch (result["CommandNumber"]) {
case '100':
{
@ -797,14 +823,16 @@ class _FloatingSearchButton extends State<FloatingSearchButton>
}
speak({isInit}) async {
//if (mounted) {
setState(() {
this.networkImage = results['AnimationURL'];
this.isAnimationEnable = true;
});
if (Provider.of<ProjectViewModel>(context, listen: false).isArabic ==
false &&
results['ReturnMessage'] != null) {
//}
if (isInit == true) {
event.setValue({"animationEnable": 'true'});
}
if (isArabic == false && results['ReturnMessage'] != null) {
await flutterTts
.setVoice({"name": "en-au-x-aub-network", "locale": "en-AU"});
await flutterTts.speak(results['ReturnMessage']);
@ -840,44 +868,32 @@ class _FloatingSearchButton extends State<FloatingSearchButton>
}
initialSpeak() async {
await flutterTts.awaitSpeakCompletion(true);
results = {
'ReturnMessage_Ar':
"هذه الخدمة تم تصميمها لتتمكن من ربط الملفات الطبية للعائلة بملفك الطبي حتى تتمكن من إدارة سجلاتهم عن طريق تسجيل الدخول إلى ملفك الطبي.",
'ReturnMessage':
"Through this service, you will be able to link your family medical files to your medical file so that you can manage their records by login to your medical file."
};
if (await sharedPref.getBool(IS_ROBOT_INIT) == null) {
if (IS_VOICE_COMMAND_CLOSED == false) {
if (IS_TEXT_COMPLETED == false) {
this.speak(isInit: true);
controller.reverse();
} else {
controller.forward();
}
// if (Provider.of<ProjectViewModel>(context, listen: false).isArabic ==
// false &&
// results['ReturnMessage'] != null) {
// await flutterTts
// .setVoice({"name": "en-au-x-aub-network", "locale": "en-AU"});
// await flutterTts.speak(results['ReturnMessage']);
// } else if (results['ReturnMessage_Ar'] != null) {
// await flutterTts
// .setVoice({"name": "ar-xa-x-ard-network", "locale": "ar"});
// await flutterTts.speak(results['ReturnMessage_Ar']);
// }
//this.isAnimationEnable = true;
//stopAnimation();
controller.forward();
}
}
stopAnimation({isInit}) async {
if (isInit && (await sharedPref.getBool(IS_ROBOT_INIT) == null)) {
sharedPref.setBool(IS_ROBOT_INIT, isInit);
if (isInit == true) {
IS_TEXT_COMPLETED = true;
}
flutterTts.setCompletionHandler(() => {
event.setValue({"animationEnable": 'false'}),
flutterTts.setCompletionHandler(() async {
event.setValue({"animationEnable": 'false'});
setState(() {
this.networkImage = null;
this.isAnimationEnable = false;
})
});
});
}
@ -895,30 +911,81 @@ class _FloatingSearchButton extends State<FloatingSearchButton>
class RoboSearch {
final BuildContext context;
var event = RobotProvider();
var searchText;
static StreamSubscription<dynamic> streamSubscription;
static var isClosed = false;
static var dialog;
RoboSearch({
@required this.context,
});
showAlertDialog(BuildContext context) {
AlertDialog alert = AlertDialog(
content: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
//AlertDialog alert = AlertDialog
// AlertDialog alert = AlertDialog(content: MyStatefulBuilder(dispose: () {
// print('dispose!!!!!!!!!!!!');
// })
// isClosed = true;
// streamSubscription.cancel();
// }, builder: (BuildContext context, StateSetter setState) {
// //print(streamSubscription);
// }),
// );
// show the dialog
showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
dialog = context;
return MyStatefulBuilder(
dispose: () {},
);
},
);
print(dialog);
}
static closeAlertDialog(BuildContext context) {
Navigator.of(dialog).pop();
}
}
typedef Disposer = void Function();
class MyStatefulBuilder extends StatefulWidget {
const MyStatefulBuilder({
// @required this.builder,
@required this.dispose,
});
//final StatefulWidgetBuilder builder;
final Disposer dispose;
@override
_MyStatefulBuilderState createState() => _MyStatefulBuilderState();
}
class _MyStatefulBuilderState extends State<MyStatefulBuilder> {
var event = RobotProvider();
var searchText;
static StreamSubscription<dynamic> streamSubscription;
static var isClosed = false;
@override
void initState() {
streamSubscription = event.controller.stream.listen((p) {
if (p['searchText'] != 'null' &&
if ((p['searchText'] != 'null' &&
p['searchText'] != null &&
p['searchText'] != "" &&
isClosed == false) {
isClosed == false) &&
mounted) {
setState(() {
searchText = p['searchText'];
});
}
});
print(streamSubscription);
return Container(
super.initState();
}
@override
Widget build(BuildContext context) => AlertDialog(
content: Container(
color: Colors.white,
height: SizeConfig.realScreenHeight * 0.5,
width: SizeConfig.realScreenWidth * 0.8,
@ -952,7 +1019,7 @@ class RoboSearch {
child: Center(
child: Text(searchText != null && searchText != 'null'
? searchText
: 'Try saying something'))),
: TranslationBase.of(context).trySaying))),
searchText == 'null'
? Center(
child: RaisedButton(
@ -964,22 +1031,11 @@ class RoboSearch {
))
: SizedBox()
]),
));
}),
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
).then((value) => {});
}
)));
static closeAlertDialog(BuildContext context) {
isClosed = true;
streamSubscription.cancel();
Navigator.of(context).pop();
@override
void dispose() {
super.dispose();
widget.dispose();
}
}

@ -24,8 +24,8 @@ class _TyperState extends State<TyperAnimatedTextKit>
setState(() {
_stringIndex = _stringIndex == null ? 0 : _stringIndex + 1;
_characterCount = new StepTween(begin: 0, end: widget.textLength)
.animate(new CurvedAnimation(parent: _controller, curve: Curves.easeIn));
.animate(
new CurvedAnimation(parent: _controller, curve: Curves.easeIn));
});
_controller.forward();
});
@ -43,9 +43,8 @@ class _TyperState extends State<TyperAnimatedTextKit>
setState(() {
_stringIndex = _stringIndex == null ? 0 : _stringIndex + 1;
_characterCount = new StepTween(begin: 0, end: widget.textLength)
.animate(new CurvedAnimation(parent: _controller, curve: Curves.easeIn));
_characterCount = new StepTween(begin: 0, end: widget.textLength).animate(
new CurvedAnimation(parent: _controller, curve: Curves.easeIn));
});
_controller.forward();
}
@ -55,16 +54,20 @@ class _TyperState extends State<TyperAnimatedTextKit>
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
child: _characterCount == null ? null : new AnimatedBuilder(
child: _characterCount == null
? null
: new AnimatedBuilder(
animation: _characterCount,
builder: (BuildContext context, Widget child) {
String text = widget.text.substring(0, _characterCount.value);
return Text(text, style: TextStyle(color:Colors.black, fontSize: 12), textAlign: TextAlign.start,
return Text(
text,
style: TextStyle(color: Colors.black, fontSize: 12),
textAlign: TextAlign.start,
);
},
));

@ -21,7 +21,7 @@ dependencies:
# http client
http: ^0.12.1
connectivity: ^0.4.9+3
audio_wave: ^0.0.3
# State Management
provider: ^4.3.2+2

Loading…
Cancel
Save