import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; import 'package:get_it/get_it.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:sport/application.dart'; import 'package:sport/bean/hardware.dart'; import 'package:sport/pages/home/guide_page.dart'; import 'package:sport/pages/my/dfu_update_page.dart'; import 'package:sport/pages/web/data_test_page.dart'; import 'package:sport/pages/web/game_test_page.dart'; import 'package:sport/provider/bluetooth.dart'; import 'package:sport/provider/user_model.dart'; import 'package:sport/router/navigator_util.dart'; import 'package:sport/services/Converter.dart'; import 'package:sport/utils/toast.dart'; import 'package:sport/widgets/appbar.dart'; import 'package:sport/widgets/button_primary.dart'; import 'package:sport/widgets/decoration.dart'; import 'package:sport/widgets/dialog/alert_dialog.dart'; import 'package:sport/widgets/dialog/request_dialog.dart'; import 'package:sport/widgets/dialog/search_device.dart'; import 'package:sport/widgets/image.dart'; import 'package:sport/widgets/loading.dart'; import 'package:umeng_common_sdk/umeng_common_sdk.dart'; class DeviceInfoPage extends StatefulWidget { @override State createState() => _PageState(); } class _PageState extends State { var labelPadding = const EdgeInsets.symmetric(horizontal: 12.0, vertical: 10.0); var contentPadding = const EdgeInsets.symmetric(horizontal: 0.0); late Bluetooth _bluetooth; @override void initState() { super.initState(); _bluetooth = GetIt.I(); _bluetooth.queryDeviceInfo(); _bluetooth.stepTotalTestNotifier.value = 1; UmengCommonSdk.onEvent("shoe_detail", {}); // // ByteDataReader r = ByteDataReader(); // r.add([0,0,1,128,33,184,201,128]); // int i = r.readUint64(); // print("1111111111 ${i } ${DateTime.fromMillisecondsSinceEpoch(i)}"); // r = ByteDataReader(); // r.add([0,0,1,128,33,19,254,0]); // i = r.readUint64(); // print("1111111111 ${i } ${DateTime.fromMillisecondsSinceEpoch(i)}"); // r = ByteDataReader(); // r.add([0,0,1,128,27,182,179,128 ]); // print("1111111111 ${r.readUint64()}"); // r = ByteDataReader(); // r.add([0,0,84,135]); // print("1111111111 ${r.readUint32()}"); // r = ByteDataReader(); // r.add([0,0,84,136]); // print("1111111111 ${r.readUint32()}"); } @override void dispose() { _bluetooth.stepTotalTestNotifier.value = 0; super.dispose(); } @override Widget build(BuildContext context) { var _padding = EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0); return Scaffold( appBar: buildAppBar(context, backgroundColor: Colors.transparent, brightness: Brightness.light, actions: [ TextButton( onPressed: () { NavigatorUtil.goPage(context, (context) => GuidePage()); }, child: Row( children: [ Image.asset("lib/assets/img/mine_icon_novice.png"), const SizedBox( width: 6, ), Text( "新手指引", style: Theme.of(context).textTheme.subtitle1, ), const SizedBox( width: 6, ), ], )), ]), body: ValueListenableBuilder( valueListenable: GetIt.I().deviceNotifier, builder: (BuildContext context, DiscoveredDevice? d, Widget? child) { if (d == null) return RequestLoadingWidget(); final device = d; return CustomScrollView( slivers: [ SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ Padding( padding: const EdgeInsets.fromLTRB(0, 20, 0, 30.0), child: ValueListenableBuilder( valueListenable: GetIt.I().deviceNameNotifier, builder: (context, data, _) { return Row( mainAxisSize: MainAxisSize.min, children: [ SizedBox( width: 32, ), Text( "当前鞋子:$data", style: Theme.of(context).textTheme.headline1, ), IconButton( icon: Image.asset("lib/assets/img/modify_pen.png"), onPressed: () { TextEditingController controller = TextEditingController(text: data); showDialog( context: context, builder: (context) => CustomAlertDialog( title: '修改昵称', child: Column( children: [ Padding( padding: const EdgeInsets.fromLTRB(16.0, 0, 16.0, 12.0), child: TextField( textAlign: TextAlign.center, controller: controller, autofocus: true, maxLength: 100, // inputFormatters: [ // FilteringTextInputFormatter(RegExp( // "[a-zA-Z]|[\u4e00-\u9fa5]|[0-9]"), allow: true),//最大长度 // ], onChanged: (str) {}, decoration: InputDecoration( counterText: '', // helperText: '用户名长度为2-10个字母,数字,中文', // hintText: name, helperMaxLines: 1, focusedBorder: UnderlineInputBorder( borderSide: BorderSide(color: Color(0xffF1F1F1)), ))), ), Text( "给你的鞋子起一个容易记住的名称", style: Theme.of(context).textTheme.bodyText1, ), ], ), ok: () { String str = controller.text; int length = 0; for (int i = 0; i < str.length; i++) { length++; if (str.codeUnitAt(i) > 122) { length++; } } if (length <= 10) { Navigator.of(context).pop(true); } else { ToastUtil.show("昵称长度不能大于5个中文字或10个英文字母"); } }), ).then((value) { if (value == true) { String name = controller.value.text; _bluetooth.updateName(name); } }); }, ), ], ); }), ), Row( children: [ Expanded( child: PrimaryButton( height: 44.0, callback: () { openSearchDeviceDialog(context); }, content: '', child: Center( child: Row( mainAxisSize: MainAxisSize.min, children: [ Image.asset("lib/assets/img/icon_change.png"), SizedBox( width: 5, ), Text("更换鞋子", style: Theme.of(context).textTheme.subtitle1!.copyWith(color: Colors.white, fontSize: 16.0)) ], ), ), ), ), const SizedBox( width: 20.0, ), Expanded( child: PrimaryButton( height: 44.0, callback: () async { if (await showDialog( context: context, builder: (context) => CustomAlertDialog(title: '断开当前已连接鞋子', ok: () => Navigator.of(context).pop(true)), ) == true) { await request(context, () async { await GetIt.I().clearDevice(deleteStep: true); await Future.delayed(Duration(seconds: 2)); return 1; }); Navigator.of(context).pop(true); } }, content: '', child: Center( child: Row( mainAxisSize: MainAxisSize.min, children: [ Image.asset("lib/assets/img/icon_disconnect.png"), SizedBox( width: 5, ), Text("断开连接", style: Theme.of(context).textTheme.subtitle1!.copyWith(color: Colors.white, fontSize: 16.0)) ], ), ))), ], ) ], ), ), ), SliverToBoxAdapter( child: Container( decoration: circular(), margin: _padding, child: ListView( padding: _padding, physics: NeverScrollableScrollPhysics(), shrinkWrap: true, children: ListTile.divideTiles(context: context, tiles: [ ListTile( title: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "鞋子电量", style: Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 16.0), ), ValueListenableBuilder( valueListenable: _bluetooth.dataNotifier, builder: (context, data, _) => Column( children: [ Text( isDebugShoe == true ? "${Converter.toInt(data['0_electricity'])}%\t\t/\t\t${Converter.toInt(data['1_electricity'])}%" : "${min(Converter.toInt(data['0_electricity']), Converter.toInt(data['1_electricity']))}%", style: Theme.of(context).textTheme.bodyText2!, ), if (isDebugShoe) Text( "${Converter.toInt(data['0_adc'])}\t\t/\t\t${Converter.toInt(data['1_adc'])}", style: Theme.of(context).textTheme.bodyText2!, ), ], ), ), ], ), contentPadding: contentPadding, onTap: () { _bluetooth.queryDeviceData(); }, ), ListTile( title: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "鞋子编号", style: Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 16.0), ), Text( "${device.name}", style: Theme.of(context).textTheme.bodyText2!, ), ], ), contentPadding: contentPadding, ), if (isDebugShoe == true) ListTile( title: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "鞋子测试", style: Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 16.0), ), ], ), contentPadding: contentPadding, trailing: arrowRight5(), onTap: () { NavigatorUtil.goPage( context, (context) => DeviceScreen( device: device, )); }, ), if (isDebugShoe == true) ListTile( title: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "鞋子数据测试", style: Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 16.0), ), ], ), contentPadding: contentPadding, trailing: arrowRight5(), onTap: () { NavigatorUtil.goPage(context, (context) => DataTestPage()); }, ), if (isDebugShoe == true) ListTile( title: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "游戏数据测试", style: Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 16.0), ), ], ), contentPadding: contentPadding, trailing: arrowRight5(), onTap: () { NavigatorUtil.goPage(context, (context) => GameTestPage()); }, ), ]).toList()), ), ), SliverToBoxAdapter( child: Container( decoration: circular(), margin: _padding, child: ListView( padding: _padding, physics: NeverScrollableScrollPhysics(), shrinkWrap: true, children: ListTile.divideTiles(context: context, tiles: [ ListTile( title: StreamBuilder( stream: SharedPreferences.getInstance().asStream().asyncMap((event) => event.getBool("vibrate") ?? true), builder: (context, snapshot) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "游戏震动反馈开关", style: Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 16.0), ), Switch( value: snapshot.data ?? true, onChanged: (bool value) { SharedPreferences.getInstance().then((prefs) { prefs.setBool("vibrate", value); setState(() {}); }); }, ) ], ); }), subtitle: Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Text("开启后,游戏过程中使用鞋子做某些动作时,鞋子会震动提示", style: Theme.of(context).textTheme.bodyText1), ), contentPadding: contentPadding, ), ]).toList()), )), if (isDebugShoe == true) SliverToBoxAdapter( child: Container( decoration: circular(), margin: _padding, child: ListView( padding: _padding, physics: NeverScrollableScrollPhysics(), shrinkWrap: true, children: ListTile.divideTiles(context: context, tiles: [ ListTile( title: StreamBuilder( stream: SharedPreferences.getInstance().asStream().asyncMap((event) => event.getBool("debug_game") ?? true), builder: (context, snapshot) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "原生游戏界面调试开关", style: Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 16.0), ), Switch( value: snapshot.data ?? true, onChanged: (bool value) { SharedPreferences.getInstance().then((prefs) { prefs.setBool("debug_game", value); setState(() {}); }); }, ) ], ); }), subtitle: Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Text("开启后,原生游戏界面会打印调试数据和保存数据日志", style: Theme.of(context).textTheme.bodyText1), ), contentPadding: contentPadding, ), ]).toList()), )), SliverToBoxAdapter( child: ValueListenableBuilder( valueListenable: _bluetooth.infoNotifier, builder: (_, data, ___) { return ValueListenableBuilder( valueListenable: _bluetooth.verNotifier, builder: (_, version, __) { return Column( children: [ Padding( padding: _padding.copyWith(bottom: 0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("设备信息", style: Theme.of(context).textTheme.bodyText1), ElevatedButton( style: ButtonStyle(shape: MaterialStateProperty.all(StadiumBorder(side: BorderSide(color: const Color(0xffdcdcdc)))), elevation: MaterialStateProperty.all(0), backgroundColor: MaterialStateProperty.all(Colors.transparent)), child: Text('复制信息', style: Theme.of(context).textTheme.bodyText1), onPressed: () { var user = Provider.of(context, listen: false); Clipboard.setData(ClipboardData(text: '用户ID:${user.user.id}\n型号:${data['name']?.toString().trim() ?? 'SHOES'}\n固件:${data['softwareVer'] ?? 0}\n硬件:${data['hardwareVer'] ?? 0}')); ToastUtil.show("已复制至粘贴板"); }, ), ], ), ), Container( decoration: circular(), margin: _padding, child: ListView( padding: _padding, physics: NeverScrollableScrollPhysics(), shrinkWrap: true, children: ListTile.divideTiles(context: context, tiles: [ ListTile( title: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "鞋子型号", style: Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 16.0), ), Text( "${data['name']?.toString().trim() ?? 'SHOES'}", style: Theme.of(context).textTheme.bodyText2!, maxLines: 1, ) ], ), contentPadding: contentPadding, onTap: () { if (isDebugShoe) { _bluetooth.testDfu++; if (_bluetooth.testDfu > 5) { ToastUtil.showBottom("进入DFU模式"); _bluetooth.infoNotifier.value = {}; final oldVersion = _bluetooth.versionNotifier.value; _bluetooth.versionNotifier.value = ""; _bluetooth.verNotifier.value = null; _bluetooth.queryDeviceInfo(); } } }, ), // ListTile( // title: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, // children: [ // Text("鞋码"), // Text( // "42码", // style: Theme.of(context).textTheme.bodyText2!, // ) // ], // ), // contentPadding: contentPadding, // ), ListTile( title: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "鞋子固件版本", style: Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 16.0), ), Text( "V ${data['softwareVer'] ?? 0}", style: Theme.of(context).textTheme.bodyText2!, ), ], ), contentPadding: contentPadding, trailing: version?.devices?.isNotEmpty == true ? Container( padding: EdgeInsets.symmetric(horizontal: 10, vertical: 6), decoration: BoxDecoration(borderRadius: BorderRadius.circular(50.0), color: Color(0xffFF5B1D)), child: Text( "点击更新", style: Theme.of(context).textTheme.subtitle2!.copyWith(fontSize: 12.0, color: Colors.white), ), ) : null, onTap: () async { if (version == null) return; if (version.devices?.isNotEmpty != true) return; var result = await showDialog( context: context, builder: (context) => CustomAlertDialog( title: '发现新的鞋子固件', child: Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Text( "${version.name}\n${version.localVer} -> ${version.ver}\n${version.msg}", style: TextStyle(fontSize: 14, color: Color(0xff333333), height: 1.4), )), textOk: '立即升级', ok: () => Navigator.of(context).pop(true)), ); if (result != true) return; result = await showDialog( context: context, barrierDismissible: false, builder: (context) => SimpleDialog( children: [DfuUpdatePage(hardware: version, version: "${version.ver}")], )); }, ), ListTile( title: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "鞋子硬件版本", style: Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 16.0), ), Text( "V ${data['hardwareVer'] ?? 0}", style: Theme.of(context).textTheme.bodyText2!, ) ], ), onTap: () { _bluetooth.checkUpdate(); }, contentPadding: contentPadding, ), if (isDebugShoe) ListTile( title: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "蓝牙地址", style: Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 16.0), ), SizedBox( width: 10, ), Expanded( child: Align( alignment: Alignment.centerRight, child: Text( "${_bluetooth.deviceId}", style: Theme.of(context).textTheme.bodyText2!, maxLines: 1, ), )), ], ), contentPadding: contentPadding, ), ]).toList())), ], ); }); })), ], ); })); } }