Compare commits

..

12 Commits

48 changed files with 1765 additions and 2263 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -1185,6 +1185,5 @@
"这是单次密码,只能使用一次": "这是单次密码,只能使用一次", "这是单次密码,只能使用一次": "这是单次密码,只能使用一次",
"您好": "您好", "您好": "您好",
"您的开门密码是": "您的开门密码是", "您的开门密码是": "您的开门密码是",
"开锁时,先激活锁键盘,再输入密码,以#号结束,#号键在键盘右下角,有可能是其他图标": "开锁时,先激活锁键盘,再输入密码,以#号结束,#号键在键盘右下角,有可能是其他图标", "开锁时,先激活锁键盘,再输入密码,以#号结束,#号键在键盘右下角,有可能是其他图标": "开锁时,先激活锁键盘,再输入密码,以#号结束,#号键在键盘右下角,有可能是其他图标"
"锁博士": "锁博士"
} }

View File

@ -150,7 +150,6 @@ class AppColors {
static Color openPassageModeColor = const Color(0xFFEB2A3B); // () static Color openPassageModeColor = const Color(0xFFEB2A3B); // ()
static Color listTimeYellowColor = const Color(0xFFF3BA37); // () static Color listTimeYellowColor = const Color(0xFFF3BA37); // ()
static Color messageTipsColor = const Color.fromRGBO(202, 220, 247, 1); //
static Color get lockDetailBottomBtnUneable => static Color get lockDetailBottomBtnUneable =>
const Color(0xFF808080); // () const Color(0xFF808080); // ()

View File

@ -46,7 +46,7 @@ class BlueManage {
StreamSubscription<BluetoothConnectionState>? _connectionStateSubscription; StreamSubscription<BluetoothConnectionState>? _connectionStateSubscription;
StreamSubscription<int>? _mtuSubscription; StreamSubscription<int>? _mtuSubscription;
int? _mtuSize = 20; int? _mtuSize = 30;
// //
String connectDeviceName = ''; String connectDeviceName = '';
@ -119,8 +119,7 @@ class BlueManage {
_connectionStateSubscription?.cancel(); _connectionStateSubscription?.cancel();
_connectionStateSubscription = null; _connectionStateSubscription = null;
_connectionStateSubscription = _connectionStateSubscription = bluetoothConnectDevice!.connectionState.listen((BluetoothConnectionState state) async {
bluetoothConnectDevice!.connectionState.listen((BluetoothConnectionState state) async {
bluetoothConnectionState = state; bluetoothConnectionState = state;
AppLog.log('蓝牙连接回调状态:$state'); AppLog.log('蓝牙连接回调状态:$state');
}); });
@ -159,26 +158,20 @@ class BlueManage {
// AppLog.log('startScanSingle 蓝牙状态 系统蓝牙状态:$_adapterState 蓝牙连接状态:$bluetoothConnectionState'); // AppLog.log('startScanSingle 蓝牙状态 系统蓝牙状态:$_adapterState 蓝牙连接状态:$bluetoothConnectionState');
if (_adapterState == BluetoothAdapterState.on) { if (_adapterState == BluetoothAdapterState.on) {
try { try {
BuglyTool.uploadException( BuglyTool.uploadException(message: '开始指定设备名称的扫描蓝牙设备', detail: '调用方法是:startScanSingle 指定设备名称是:$deviceName', upload: false);
message: '开始指定设备名称的扫描蓝牙设备', detail: '调用方法是:startScanSingle 指定设备名称是:$deviceName', upload: false);
//android 3 //android 3
final int divisor = Platform.isAndroid ? 3 : 1; final int divisor = Platform.isAndroid ? 3 : 1;
FlutterBluePlus.startScan( FlutterBluePlus.startScan(
continuousDivisor: divisor, continuousDivisor: divisor, continuousUpdates: true, withKeywords: <String>[deviceName], timeout: Duration(seconds: timeout));
continuousUpdates: true,
withKeywords: <String>[deviceName],
timeout: Duration(seconds: timeout));
final Completer<dynamic> completer = Completer<dynamic>(); final Completer<dynamic> completer = Completer<dynamic>();
final StreamSubscription<List<ScanResult>> subscription = final StreamSubscription<List<ScanResult>> subscription = FlutterBluePlus.scanResults.listen((List<ScanResult> results) {
FlutterBluePlus.scanResults.listen((List<ScanResult> results) { final bool isExit = results
final bool isExit = results.any((ScanResult element) => .any((ScanResult element) => (element.device.platformName == deviceName) || (element.advertisementData.advName == deviceName));
(element.device.platformName == deviceName) || (element.advertisementData.advName == deviceName));
final int milliseconds = DateTime.now().millisecondsSinceEpoch - start.millisecondsSinceEpoch; final int milliseconds = DateTime.now().millisecondsSinceEpoch - start.millisecondsSinceEpoch;
AppLog.log('扫描到的设备数:${results.length} 是否查找到 $isExit 以查找$milliseconds毫秒'); AppLog.log('扫描到的设备数:${results.length} 是否查找到 $isExit 以查找$milliseconds毫秒');
BuglyTool.uploadException( BuglyTool.uploadException(
message: '指定设备名称的扫描蓝牙设备 监听扫描结果', message: '指定设备名称的扫描蓝牙设备 监听扫描结果',
detail: detail: 'startScanSingle$deviceName 监听扫描结果 是否查找到 $isExit 以查找$milliseconds毫秒 扫描到的设备数:${results.length} results:$results',
'startScanSingle$deviceName 监听扫描结果 是否查找到 $isExit 以查找$milliseconds毫秒 扫描到的设备数:${results.length} results:$results',
upload: false); upload: false);
if (isExit) { if (isExit) {
for (final ScanResult scanResult in results) { for (final ScanResult scanResult in results) {
@ -215,8 +208,7 @@ class BlueManage {
completer.complete(); completer.complete();
} }
}, onError: (e) { }, onError: (e) {
BuglyTool.uploadException( BuglyTool.uploadException(message: '指定设备名称的扫描蓝牙设备 监听扫描结果失败', detail: '打印失败问题 e${e.toString()}', upload: false);
message: '指定设备名称的扫描蓝牙设备 监听扫描结果失败', detail: '打印失败问题 e${e.toString()}', upload: false);
AppLog.log('扫描失败:$e'); AppLog.log('扫描失败:$e');
}); });
FlutterBluePlus.cancelWhenScanComplete(subscription); FlutterBluePlus.cancelWhenScanComplete(subscription);
@ -224,8 +216,7 @@ class BlueManage {
scanDevicesCallBack(scanDevices); scanDevicesCallBack(scanDevices);
subscription.cancel(); subscription.cancel();
} catch (e) { } catch (e) {
BuglyTool.uploadException( BuglyTool.uploadException(message: '指定设备名称的扫描蓝牙设备 内部逻辑整形失败', detail: 'tartScanSingle内部逻辑整形失败 e:${e.toString()}', upload: false);
message: '指定设备名称的扫描蓝牙设备 内部逻辑整形失败', detail: 'tartScanSingle内部逻辑整形失败 e:${e.toString()}', upload: false);
AppLog.log('扫描失败'); AppLog.log('扫描失败');
} }
} else { } else {
@ -242,16 +233,14 @@ class BlueManage {
} }
/// ///
Future<void> startScan(int timeout, DeviceType deviceType, ScanDevicesCallBack scanDevicesCallBack, Future<void> startScan(int timeout, DeviceType deviceType, ScanDevicesCallBack scanDevicesCallBack, {List<Guid>? idList}) async {
{List<Guid>? idList}) async {
FlutterBluePlus.isSupported.then((bool isAvailable) async { FlutterBluePlus.isSupported.then((bool isAvailable) async {
if (isAvailable) { if (isAvailable) {
AppLog.log('startScan 蓝牙状态 系统蓝牙状态:$_adapterState 蓝牙连接状态:$bluetoothConnectionState'); AppLog.log('startScan 蓝牙状态 系统蓝牙状态:$_adapterState 蓝牙连接状态:$bluetoothConnectionState');
if (_adapterState == BluetoothAdapterState.on) { if (_adapterState == BluetoothAdapterState.on) {
try { try {
FlutterBluePlus.startScan(timeout: Duration(seconds: timeout)); FlutterBluePlus.startScan(timeout: Duration(seconds: timeout));
final StreamSubscription<List<ScanResult>> subscription = final StreamSubscription<List<ScanResult>> subscription = FlutterBluePlus.scanResults.listen((List<ScanResult> results) {
FlutterBluePlus.scanResults.listen((List<ScanResult> results) {
scanDevices.clear(); scanDevices.clear();
for (final ScanResult scanResult in results) { for (final ScanResult scanResult in results) {
if (scanResult.advertisementData.serviceUuids.isNotEmpty) { if (scanResult.advertisementData.serviceUuids.isNotEmpty) {
@ -420,16 +409,13 @@ class BlueManage {
} else { } else {
BuglyTool.uploadException( BuglyTool.uploadException(
message: '点击按钮 蓝牙已经连接 下一步扫描连接蓝牙', message: '点击按钮 蓝牙已经连接 下一步扫描连接蓝牙',
detail: detail: 'blueSendData 直接回调状态 蓝牙连接状态bluetoothConnectionState$bluetoothConnectionState deviceName:$deviceName',
'blueSendData 直接回调状态 蓝牙连接状态bluetoothConnectionState$bluetoothConnectionState deviceName:$deviceName',
upload: false); upload: false);
stateCallBack(bluetoothConnectionState!); stateCallBack(bluetoothConnectionState!);
} }
} else { } else {
BuglyTool.uploadException( BuglyTool.uploadException(
message: '点击按钮 蓝牙未打开', message: '点击按钮 蓝牙未打开', detail: 'blueSendData 蓝牙未打开--_adapterState:${BluetoothAdapterState.on} deviceName:$deviceName', upload: false);
detail: 'blueSendData 蓝牙未打开--_adapterState:${BluetoothAdapterState.on} deviceName:$deviceName',
upload: false);
try { try {
stateCallBack(BluetoothConnectionState.disconnected); stateCallBack(BluetoothConnectionState.disconnected);
openBlue(); openBlue();
@ -442,8 +428,7 @@ class BlueManage {
} }
} }
} else { } else {
BuglyTool.uploadException( BuglyTool.uploadException(message: '点击按钮 蓝牙状态不可用', detail: 'blueSendData 蓝牙状态不可用--isAvailable:$isAvailable', upload: false);
message: '点击按钮 蓝牙状态不可用', detail: 'blueSendData 蓝牙状态不可用--isAvailable:$isAvailable', upload: false);
stateCallBack(BluetoothConnectionState.disconnected); stateCallBack(BluetoothConnectionState.disconnected);
AppLog.log('开始扫描 蓝牙不可用,不能进行蓝牙操作'); AppLog.log('开始扫描 蓝牙不可用,不能进行蓝牙操作');
} }
@ -451,8 +436,7 @@ class BlueManage {
} }
/// ///
Future<void> _connect(String deviceName, ConnectStateCallBack connectStateCallBack, Future<void> _connect(String deviceName, ConnectStateCallBack connectStateCallBack, {bool isAddEquipment = false}) async {
{bool isAddEquipment = false}) async {
connectDeviceName = deviceName; connectDeviceName = deviceName;
// //
final List<ScanResult> devicesList = scanDevices; final List<ScanResult> devicesList = scanDevices;
@ -533,8 +517,8 @@ class BlueManage {
// //
bool isExistScanDevices(String connectDeviceName) { bool isExistScanDevices(String connectDeviceName) {
final bool isExistDevice = scanDevices.any((ScanResult element) => final bool isExistDevice = scanDevices
element.device.platformName == connectDeviceName || element.advertisementData.advName == connectDeviceName); .any((ScanResult element) => element.device.platformName == connectDeviceName || element.advertisementData.advName == connectDeviceName);
return isExistDevice; return isExistDevice;
} }
@ -545,11 +529,8 @@ class BlueManage {
bool isAddEquipment = false, // bool isAddEquipment = false, //
bool isReconnect = true, // bool isReconnect = true, //
}) async { }) async {
// final int knownDeviceIndex =
// AppLog.log("devicesList:$devicesList"); devicesList.indexWhere((ScanResult d) => (d.device.platformName == deviceName) || (d.advertisementData.advName == deviceName));
final int knownDeviceIndex = devicesList.indexWhere(
(ScanResult d) => (d.device.platformName == deviceName) || (d.advertisementData.advName == deviceName));
ScanResult? scanResult; //使 ScanResult? scanResult; //使
if (knownDeviceIndex >= 0) { if (knownDeviceIndex >= 0) {
@ -560,7 +541,6 @@ class BlueManage {
bluetoothConnectDevice = devicesList[knownDeviceIndex].device; bluetoothConnectDevice = devicesList[knownDeviceIndex].device;
scanResult = devicesList[knownDeviceIndex]; scanResult = devicesList[knownDeviceIndex];
// AppLog.log('bluetoothConnectDevice: $bluetoothConnectDevice scanResult:$scanResult');
_initGetMtuSubscription(); _initGetMtuSubscription();
_initListenConnectionState(); _initListenConnectionState();
@ -572,87 +552,13 @@ class BlueManage {
upload: false); upload: false);
return; return;
} }
AppLog.log('调用了停止扫描的方法');
await stopScan();
if (scanResult.advertisementData.serviceUuids[0].toString().length >= 5 &&
(scanResult.advertisementData.serviceUuids[0].toString()[5] == '0') &&
isAddEquipment == false) {
//
if (isReconnect == true) {
AppLog.log('该锁已被重置, 重新发送扫描命令');
BuglyTool.uploadException(
message: '该锁已被重置, 重新发送扫描命令startScanSingle 上传记录当前方法是_connectDevice',
detail:
'添加这个判断是因为有些苹果设备或者安卓等性能比较好的设备时,添加完锁之后,锁板未改变为已添加状态之前,就进行了蓝牙连接,导致添加完锁就失败,这里进行了判断,如果第一次连接失败,就清除缓存重新扫描连接 该锁已被重置, 重新发送扫描命令 serviceUuids:${scanResult.advertisementData.serviceUuids[0].toString()}',
upload: false);
scanDevices.clear();
startScanSingle(deviceName, 15, (List<ScanResult> scanDevices) {
_connectDevice(scanDevices, deviceName, connectStateCallBack,
isAddEquipment: isAddEquipment, isReconnect: false);
});
} else {
connectStateCallBack(BluetoothConnectionState.disconnected);
if (!F.isSKY) {
EasyLoading.showToast('该锁已被重置'.tr, duration: 2000.milliseconds);
}
scanDevices.clear();
BuglyTool.uploadException(
message: '提示该锁已被重置, 回调断开连接, 清除缓存上传记录当前方法是_connectDevice',
detail: 'isReconnect:$isReconnect serviceUuids:${scanResult.advertisementData.serviceUuids[0].toString()}',
upload: false);
}
return;
}
if (scanResult.advertisementData.serviceUuids[0].toString().length >= 30 &&
(scanResult.advertisementData.serviceUuids[0].toString()[31] == '0') &&
isAddEquipment == false) {
//
if (isReconnect == true) {
AppLog.log('该锁已被重置, 重新发送扫描命令');
BuglyTool.uploadException(
message: '该锁已被重置, 重新发送扫描命令startScanSingle 上传记录当前方法是_connectDevice',
detail:
'添加这个判断是因为有些苹果设备或者安卓等性能比较好的设备时,添加完锁之后,锁板未改变为已添加状态之前,就进行了蓝牙连接,导致添加完锁就失败,这里进行了判断,如果第一次连接失败,就清除缓存重新扫描连接 该锁已被重置, 重新发送扫描命令 serviceUuids:${scanResult.advertisementData.serviceUuids[0].toString()}',
upload: false);
scanDevices.clear();
startScanSingle(deviceName, 15, (List<ScanResult> scanDevices) {
_connectDevice(scanDevices, deviceName, connectStateCallBack,
isAddEquipment: isAddEquipment, isReconnect: true);
});
} else {
connectStateCallBack(BluetoothConnectionState.disconnected);
if (!F.isSKY) {
EasyLoading.showToast('该锁已被重置'.tr, duration: 2000.milliseconds);
}
scanDevices.clear();
BuglyTool.uploadException(
message: '提示该锁已被重置, 回调断开连接, 清除缓存上传记录当前方法是_connectDevice',
detail: 'isReconnect:$isReconnect serviceUuids:${scanResult.advertisementData.serviceUuids[0].toString()}',
upload: false);
}
return;
}
BuglyTool.uploadException(
message: '从devicesList里面查到了设备 下一步连接设备 上传记录当前方法是_connectDevice',
detail:
'devicesList:$devicesList scanResult:${scanResult.toString()} bluetoothConnectDevice${bluetoothConnectDevice.toString()} connectDeviceMacAddress$connectDeviceMacAddress',
upload: false);
// //
await bluetoothDeviceConnect(bluetoothConnectDevice!, connectStateCallBack); await bluetoothDeviceConnect(bluetoothConnectDevice!, connectStateCallBack);
} }
// //
Future<void> doNotSearchBLE(String masAdds, ConnectStateCallBack connectStateCallBack, Future<void> doNotSearchBLE(String masAdds, ConnectStateCallBack connectStateCallBack, {bool isAddEquipment = false}) async {
{bool isAddEquipment = false}) async {
await FlutterBluePlus.stopScan(); await FlutterBluePlus.stopScan();
if (bluetoothConnectDevice == null || bluetoothConnectDevice?.remoteId.str != masAdds) { if (bluetoothConnectDevice == null || bluetoothConnectDevice?.remoteId.str != masAdds) {
@ -660,9 +566,7 @@ class BlueManage {
_initGetMtuSubscription(); _initGetMtuSubscription();
_initListenConnectionState(); _initListenConnectionState();
BuglyTool.uploadException( BuglyTool.uploadException(
message: '直接给蓝牙设备写入 上传记录当前方法是doNotSearchBLE', message: '直接给蓝牙设备写入 上传记录当前方法是doNotSearchBLE', detail: '直接给蓝牙设备写入 通过fromId方法创建一个BluetoothDevice masAdds$masAdds', upload: false);
detail: '直接给蓝牙设备写入 通过fromId方法创建一个BluetoothDevice masAdds$masAdds',
upload: false);
} else { } else {
BuglyTool.uploadException( BuglyTool.uploadException(
message: '直接给蓝牙设备写入 上传记录当前方法是doNotSearchBLE', message: '直接给蓝牙设备写入 上传记录当前方法是doNotSearchBLE',
@ -747,9 +651,7 @@ class BlueManage {
connectStateCallBack(bluetoothConnectionState!); connectStateCallBack(bluetoothConnectionState!);
AppLog.log('发现设备时失败 e:$e bluetoothConnectionState:$bluetoothConnectionState'); AppLog.log('发现设备时失败 e:$e bluetoothConnectionState:$bluetoothConnectionState');
BuglyTool.uploadException( BuglyTool.uploadException(
message: '发现服务时失败', message: '发现服务时失败', detail: '发现服务时报错原因e$e bluetoothDeviceConnect:${bluetoothConnectDevice.toString()}', upload: false);
detail: '发现服务时报错原因e$e bluetoothDeviceConnect:${bluetoothConnectDevice.toString()}',
upload: false);
rethrow; rethrow;
} }
} }
@ -819,12 +721,24 @@ class BlueManage {
for (final BluetoothCharacteristic characteristic in service.characteristics) { for (final BluetoothCharacteristic characteristic in service.characteristics) {
if (characteristic.characteristicUuid == _characteristicIdWrite) { if (characteristic.characteristicUuid == _characteristicIdWrite) {
try { try {
_initGetMtuSubscription();
// MTU还是默认值
if ((_mtuSize == 23 || _mtuSize == 20) && bluetoothConnectDevice != null) {
try {
if (Platform.isAndroid) {
await bluetoothConnectDevice!.requestMtu(512);
}
} catch (e) {
AppLog.log('重新请求MTU失败: $e');
}
}
// //
int retryCount = 0; int retryCount = 0;
const int maxRetries = 3; const int maxRetries = 3;
const int retryDelayMs = 500; const int retryDelayMs = 500;
final List<int> valueList = value; final List<int> valueList = value;
AppLog.log('发送数据时当前的mtuSize是:${_mtuSize}');
final List subData = splitList(valueList, _mtuSize!); final List subData = splitList(valueList, _mtuSize!);
for (int i = 0; i < subData.length; i++) { for (int i = 0; i < subData.length; i++) {

View File

@ -1,4 +1,3 @@
import 'dart:async'; import 'dart:async';
import 'package:star_lock/blue/entity/lock_user_no_list_entity.dart'; import 'package:star_lock/blue/entity/lock_user_no_list_entity.dart';
@ -22,10 +21,10 @@ import 'io_tool/manager_event_bus.dart';
import 'sender_data.dart'; import 'sender_data.dart';
class SenderBeforeDataManage { class SenderBeforeDataManage {
factory SenderBeforeDataManage() => shareManager()!; factory SenderBeforeDataManage() => shareManager()!;
SenderBeforeDataManage._init(); SenderBeforeDataManage._init();
static SenderBeforeDataManage? _manager; static SenderBeforeDataManage? _manager;
static SenderBeforeDataManage? shareManager() { static SenderBeforeDataManage? shareManager() {
@ -42,6 +41,7 @@ class SenderBeforeDataManage {
// //
StreamSubscription<Reply>? _replySubscription; StreamSubscription<Reply>? _replySubscription;
// //
bool isBeforeAddUser = true; bool isBeforeAddUser = true;
@ -146,10 +146,8 @@ class SenderBeforeDataManage {
// //
Future<List<int>> getCleanUpUsers({List<int>? tokenList}) async { Future<List<int>> getCleanUpUsers({List<int>? tokenList}) async {
final LockUserNoListEntity entity = await ApiRepository.to final LockUserNoListEntity entity = await ApiRepository.to.getLockUserNoList(lockId: CommonDataManage().currentKeyInfo.lockId!);
.getLockUserNoList(lockId: CommonDataManage().currentKeyInfo.lockId!); if (!entity.errorCode!.codeIsSuccessful || (entity.data?.userNos ?? <int>[]).isEmpty) {
if (!entity.errorCode!.codeIsSuccessful ||
(entity.data?.userNos ?? <int>[]).isEmpty) {
throw Exception('ApiRepository.to.getLockUserNoList 访问失败'); throw Exception('ApiRepository.to.getLockUserNoList 访问失败');
} }
final List<String>? privateKey = await Storage.getStringList(saveBluePrivateKey); final List<String>? privateKey = await Storage.getStringList(saveBluePrivateKey);
@ -208,7 +206,8 @@ class SenderBeforeDataManage {
endTime = DateTime.fromMillisecondsSinceEpoch(currentKeyInfo.endDate!); endTime = DateTime.fromMillisecondsSinceEpoch(currentKeyInfo.endDate!);
startDateTime = DateTool().dateToTimestamp(DateTool().dateToYMDString(currentKeyInfo.startDate!.toString()), 1) ~/ 1000; startDateTime = DateTool().dateToTimestamp(DateTool().dateToYMDString(currentKeyInfo.startDate!.toString()), 1) ~/ 1000;
endDateTime = (DateTool().dateToTimestamp(DateTool().dateToYMDString(currentKeyInfo.endDate!.toString()), 1) + CommonDataManage().dayLatestTime) ~/ 1000; endDateTime =
(DateTool().dateToTimestamp(DateTool().dateToYMDString(currentKeyInfo.endDate!.toString()), 1) + CommonDataManage().dayLatestTime) ~/ 1000;
} else if (currentKeyInfo.keyType == XSConstantMacro.keyTypeOnce) { } else if (currentKeyInfo.keyType == XSConstantMacro.keyTypeOnce) {
// //
useCountLimit = 1; useCountLimit = 1;
@ -217,7 +216,7 @@ class SenderBeforeDataManage {
// AppLog.log("startTime.hour:${startTime!.hour} startTime.minute:${startTime!.minute} endTime.hour:${endTime!.hour} endTime.minute:${endTime!.minute}}"); // AppLog.log("startTime.hour:${startTime!.hour} startTime.minute:${startTime!.minute} endTime.hour:${endTime!.hour} endTime.minute:${endTime!.minute}}");
final AddUserCommand addUserData = AddUserCommand( final AddUserCommand addUserData = AddUserCommand(
lockID: BlueManage().connectDeviceName, lockID: BlueManage().connectDeviceName,
authUserID: currentKeyInfo.senderUserId!.toString(), authUserID: currentKeyInfo.senderUserId?.toString() ?? '1',
keyID: currentKeyInfo.keyId.toString(), keyID: currentKeyInfo.keyId.toString(),
userID: await Storage.getUid(), userID: await Storage.getUid(),
openMode: 1, openMode: 1,
@ -226,10 +225,7 @@ class SenderBeforeDataManage {
expireDate: endDateTime, expireDate: endDateTime,
useCountLimit: useCountLimit, useCountLimit: useCountLimit,
isRound: isRound ? 1 : 0, isRound: isRound ? 1 : 0,
weekRound: isRound weekRound: isRound ? DateTool().accordingTheCycleIntoTheCorrespondingNumber(currentKeyInfo.weekDays!) : 0,
? DateTool().accordingTheCycleIntoTheCorrespondingNumber(
currentKeyInfo.weekDays!)
: 0,
startHour: isRound ? startTime!.hour : 0, startHour: isRound ? startTime!.hour : 0,
startMin: isRound ? startTime!.minute : 0, startMin: isRound ? startTime!.minute : 0,
endHour: isRound ? endTime!.hour : 0, endHour: isRound ? endTime!.hour : 0,
@ -271,8 +267,7 @@ class SenderBeforeDataManage {
// NO // NO
Future<void> _updateLockUserNo(List<int> dataList) async { Future<void> _updateLockUserNo(List<int> dataList) async {
final LockNetTokenEntity entity = await ApiRepository.to.updateLockUserNo( final LockNetTokenEntity entity = await ApiRepository.to.updateLockUserNo(
keyId: CommonDataManage().currentKeyInfo.keyId.toString(), keyId: CommonDataManage().currentKeyInfo.keyId.toString(), lockUserNo: CommonDataManage().currentKeyInfo.lockUserNo.toString());
lockUserNo: CommonDataManage().currentKeyInfo.lockUserNo.toString());
if (entity.errorCode!.codeIsSuccessful) { if (entity.errorCode!.codeIsSuccessful) {
eventBus.fire(RefreshLockListInfoDataEvent()); eventBus.fire(RefreshLockListInfoDataEvent());
eventBus.fire(LockAddUserSucceedEvent(<int>[0], 0)); eventBus.fire(LockAddUserSucceedEvent(<int>[0], 0));
@ -281,9 +276,8 @@ class SenderBeforeDataManage {
// InitUserNo // InitUserNo
Future<void> _updateLockInitUserNo() async { Future<void> _updateLockInitUserNo() async {
final LockNetTokenEntity entity = await ApiRepository.to.updateLockInitUserNo( final LockNetTokenEntity entity = await ApiRepository.to
lockId: CommonDataManage().currentKeyInfo.lockId ?? 0, .updateLockInitUserNo(lockId: CommonDataManage().currentKeyInfo.lockId ?? 0, initUserNo: CommonDataManage().currentKeyInfo.initUserNo ?? 0);
initUserNo: CommonDataManage().currentKeyInfo.initUserNo ?? 0);
if (entity.errorCode!.codeIsSuccessful) { if (entity.errorCode!.codeIsSuccessful) {
eventBus.fire(RefreshLockListInfoDataEvent()); eventBus.fire(RefreshLockListInfoDataEvent());
eventBus.fire(LockInitUserNoEvent()); eventBus.fire(LockInitUserNoEvent());

View File

@ -97,7 +97,7 @@ class F {
case Flavor.sky: case Flavor.sky:
case Flavor.sky_dev: case Flavor.sky_dev:
case Flavor.sky_pre: case Flavor.sky_pre:
return '博士'.tr; return '通通'.tr;
case Flavor.xhj: case Flavor.xhj:
case Flavor.xhj_bundle: case Flavor.xhj_bundle:
case Flavor.xhj_dev: case Flavor.xhj_dev:
@ -119,7 +119,7 @@ class F {
case Flavor.sky: case Flavor.sky:
case Flavor.sky_dev: case Flavor.sky_dev:
case Flavor.sky_pre: case Flavor.sky_pre:
return '博士'.tr; return '通通'.tr;
case Flavor.xhj: case Flavor.xhj:
case Flavor.xhj_bundle: case Flavor.xhj_bundle:
case Flavor.xhj_dev: case Flavor.xhj_dev:

View File

@ -52,13 +52,6 @@ class StarLockLoginLogic extends BaseGetXController {
Future<void> login() async { Future<void> login() async {
FocusScope.of(Get.context!).requestFocus(FocusNode()); // FocusScope.of(Get.context!).requestFocus(FocusNode()); //
//
if (!GetUtils.isEmail(state.emailOrPhone.value)) {
showToast('请输入有效的邮箱地址');
return;
}
final LoginEntity entity = await ApiRepository.to.login( final LoginEntity entity = await ApiRepository.to.login(
loginType: '1', loginType: '1',
password: state.pwd.value, password: state.pwd.value,

View File

@ -88,31 +88,30 @@ class _StarLockLoginPageState extends State<StarLockLoginPage> {
children: <Widget>[ children: <Widget>[
Container( Container(
padding: EdgeInsets.all(10.w), padding: EdgeInsets.all(10.w),
child: Center(child: Image.asset('images/icon_main_drlock_1024.png', width: 110.w, height: 110.w))), child: Center(child: Image.asset('images/icon_main_sky_1024.png', width: 110.w, height: 110.w))),
SizedBox(height: 50.w), SizedBox(height: 50.w),
// Obx(() => Obx(() => CommonItem(
// CommonItem( leftTitel: '你所在的国家/地区'.tr,
// leftTitel: '你所在的国家/地区'.tr, rightTitle: '',
// rightTitle: '', isHaveLine: true,
// isHaveLine: true, isPadding: false,
// isPadding: false, isHaveRightWidget: true,
// isHaveRightWidget: true, isHaveDirection: true,
// isHaveDirection: true, rightWidget: Text(
// rightWidget: Text( '${state.countryName} +${state.countryCode.value}',
// '${state.countryName} +${state.countryCode.value}', textAlign: TextAlign.end,
// textAlign: TextAlign.end, style: TextStyle(fontSize: 22.sp, color: AppColors.darkGrayTextColor),
// style: TextStyle(fontSize: 22.sp, color: AppColors.darkGrayTextColor), ),
// ), action: () async {
// action: () async { final result = await Get.toNamed(Routers.selectCountryRegionPage);
// final result = await Get.toNamed(Routers.selectCountryRegionPage); if (result != null) {
// if (result != null) { result as Map<String, dynamic>;
// result as Map<String, dynamic>; state.countryCode.value = result['code'];
// state.countryCode.value = result['code']; state.countryKey.value = result['countryName'];
// state.countryKey.value = result['countryName']; logic.checkIpAction();
// logic.checkIpAction(); }
// } },
// }, )),
// )),
LoginInput( LoginInput(
focusNode: logic.state.emailOrPhoneFocusNode, focusNode: logic.state.emailOrPhoneFocusNode,
controller: state.emailOrPhoneController, controller: state.emailOrPhoneController,
@ -127,16 +126,12 @@ class _StarLockLoginPageState extends State<StarLockLoginPage> {
height: 36.w, height: 36.w,
), ),
), ),
// hintText: '请输入手机号或者邮箱'.tr, hintText: '请输入手机号或者邮箱'.tr,
hintText: '请输入邮箱'.tr,
// keyboardType: TextInputType.number, // keyboardType: TextInputType.number,
keyboardType: TextInputType.emailAddress,
inputFormatters: <TextInputFormatter>[ inputFormatters: <TextInputFormatter>[
// FilteringTextInputFormatter.allow(RegExp('[0-9]')), // FilteringTextInputFormatter.allow(RegExp('[0-9]')),
LengthLimitingTextInputFormatter(30), LengthLimitingTextInputFormatter(30),
FilteringTextInputFormatter.singleLineFormatter, FilteringTextInputFormatter.singleLineFormatter
//
FilteringTextInputFormatter.allow(RegExp(r'^[a-zA-Z0-9@._-]+$')),
]), ]),
SizedBox(height: 10.h), SizedBox(height: 10.h),
LoginInput( LoginInput(

View File

@ -30,8 +30,7 @@ class StarLockLoginState {
RxString emailOrPhone = ''.obs; RxString emailOrPhone = ''.obs;
RxString pwd = ''.obs; RxString pwd = ''.obs;
RxBool canNext = false.obs; RxBool canNext = false.obs;
// bool get isEmailOrPhone => emailOrPhone.value.isNotEmpty; bool get isEmailOrPhone => emailOrPhone.value.isNotEmpty;
bool get isEmailOrPhone => GetUtils.isEmail(emailOrPhone.value);
bool get pwdIsOK => pwd.value.isNotEmpty; bool get pwdIsOK => pwd.value.isNotEmpty;
TextEditingController emailOrPhoneController = TextEditingController(); TextEditingController emailOrPhoneController = TextEditingController();

View File

@ -41,7 +41,7 @@ class _StarLockRegisterPageState extends State<StarLockRegisterPage> {
child: ListView( child: ListView(
padding: EdgeInsets.only(top: 40.h, left: 40.w, right: 40.w), padding: EdgeInsets.only(top: 40.h, left: 40.w, right: 40.w),
children: <Widget>[ children: <Widget>[
// topSelectCountryAndRegionWidget(), topSelectCountryAndRegionWidget(),
middleTFWidget(), middleTFWidget(),
Obx(() { Obx(() {
return SubmitBtn( return SubmitBtn(

View File

@ -6,7 +6,7 @@ class StarLockRegisterState {
StarLockRegisterState() { StarLockRegisterState() {
// tab // tab
final Locale? systemLocale = Get.deviceLocale; final Locale? systemLocale = Get.deviceLocale;
//isIphoneType.value = systemLocale?.languageCode == 'zh'; isIphoneType.value = systemLocale?.languageCode == 'zh';
resetResend(); resetResend();
} }
@ -24,7 +24,7 @@ class StarLockRegisterState {
RxString surePwd = ''.obs; RxString surePwd = ''.obs;
RxString verificationCode = ''.obs; RxString verificationCode = ''.obs;
RxString xWidth = ''.obs; // RxString xWidth = ''.obs; //
RxBool isIphoneType = false.obs; RxBool isIphoneType = true.obs;
RxBool canSub = false.obs; // RxBool canSub = false.obs; //
RxBool agree = false.obs; RxBool agree = false.obs;
RxBool canSendCode = false.obs; // RxBool canSendCode = false.obs; //

View File

@ -69,14 +69,6 @@ FutureOr<void> main() async {
String? token = await CallKitHandler.getVoipToken(); String? token = await CallKitHandler.getVoipToken();
print('获取到的VoIP Token: $token'); print('获取到的VoIP Token: $token');
} }
// runApp
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(
statusBarColor: Colors.transparent, //
statusBarIconBrightness: Brightness.dark, // Android:
statusBarBrightness: Brightness.dark, // iOS:
),
);
runApp(MyApp(isLogin: isLogin)); runApp(MyApp(isLogin: isLogin));
}); });

View File

@ -658,6 +658,7 @@ class LockDetailLogic extends BaseGetXController {
if (list.isEmpty) { if (list.isEmpty) {
return; return;
} }
AppLog.log('list:${list}');
final KeyOperationRecordEntity entity = final KeyOperationRecordEntity entity =
await ApiRepository.to.lockRecordUploadData(lockId: state.keyInfos.value.lockId.toString(), records: list); await ApiRepository.to.lockRecordUploadData(lockId: state.keyInfos.value.lockId.toString(), records: list);
if (entity.errorCode!.codeIsSuccessful) { if (entity.errorCode!.codeIsSuccessful) {

View File

@ -1,3 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@ -36,23 +37,25 @@ class _LockDetailMainPageState extends State<LockDetailMainPage> {
appBar: TitleAppBar( appBar: TitleAppBar(
barTitle: F.navTitle, barTitle: F.navTitle,
haveBack: true, haveBack: true,
backgroundColor: Colors.white, backgroundColor: AppColors.mainColor),
titleColor: Colors.black, body: LockDetailPage(
iconColor: Colors.black, isOnlyOneData: isOnlyOneData,
), lockListInfoItemEntity: keyInfos),
body: LockDetailPage(isOnlyOneData: isOnlyOneData, lockListInfoItemEntity: keyInfos),
// body: Container(), // body: Container(),
), ),
xhjCall: () => Scaffold( xhjCall: () => Scaffold(
backgroundColor: Colors.white, backgroundColor: Colors.white,
appBar: TitleAppBar( appBar: TitleAppBar(
barTitle: F.sw(xhjCall: () => '星星锁'.tr, skyCall: () => keyInfos.lockAlias), barTitle: F.sw(
xhjCall: () => '星星锁'.tr, skyCall: () => keyInfos.lockAlias),
haveBack: true, haveBack: true,
backgroundColor: Colors.white, backgroundColor: Colors.white,
titleColor: AppColors.blackColor, titleColor: AppColors.blackColor,
iconColor: AppColors.blackColor, iconColor: AppColors.blackColor,
), ),
body: LockDetailPage(isOnlyOneData: isOnlyOneData, lockListInfoItemEntity: keyInfos), body: LockDetailPage(
isOnlyOneData: isOnlyOneData,
lockListInfoItemEntity: keyInfos),
// body: Container(), // body: Container(),
)); ));
} }

View File

@ -464,44 +464,6 @@ class _LockDetailPageState extends State<LockDetailPage> with TickerProviderStat
Widget skWidget() { Widget skWidget() {
return ListView( return ListView(
children: <Widget>[ children: <Widget>[
Visibility(
visible: widget.isOnlyOneData,
child: Row(
children: [
SizedBox(
width: 20.w,
),
Image.asset('images/icon_main_drlock_1024.png', width: 68.w, height: 68.w),
SizedBox(
width: 20.w,
),
Text(
F.title,
style: TextStyle(
fontSize: 28.sp,
fontWeight: FontWeight.w600,
),
),
Spacer(),
IconButton(
onPressed: () {
//
Navigator.pushNamed(
context,
Routers.selectLockTypePage,
);
},
icon: Icon(
Icons.add_circle_outline_rounded,
size: 48.sp,
),
),
SizedBox(
width: 20.w,
),
],
),
),
Visibility( Visibility(
visible: (state.keyInfos.value.keyType == XSConstantMacro.keyTypeTime || visible: (state.keyInfos.value.keyType == XSConstantMacro.keyTypeTime ||
state.keyInfos.value.keyType == XSConstantMacro.keyTypeLoop) && // state.keyInfos.value.keyType == XSConstantMacro.keyTypeLoop) && //

View File

@ -29,7 +29,24 @@ class ThirdPartyPlatformLogic extends BaseGetXController {
super.onReady(); super.onReady();
await getActivateInfo(); await getActivateInfo();
_initReplySubscription(); _initReplySubscription();
getServerDatetime(); await getServerDatetime();
showEasyLoading();
showBlueConnetctToastTimer(action: () {
dismissEasyLoading();
});
BlueManage().blueSendData(
BlueManage().connectDeviceName,
(BluetoothConnectionState connectionState) async {
if (connectionState == BluetoothConnectionState.connected) {
IoSenderManage.readRegisterKey(
lockID: BlueManage().connectDeviceName,
);
} else if (connectionState == BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
}
},
);
} }
@override @override
@ -57,6 +74,7 @@ class ThirdPartyPlatformLogic extends BaseGetXController {
Future<void> getServerDatetime() async { Future<void> getServerDatetime() async {
final GetServerDatetimeEntity entity = await ApiRepository.to.getServerDatetimeData(isUnShowLoading: true); final GetServerDatetimeEntity entity = await ApiRepository.to.getServerDatetimeData(isUnShowLoading: true);
if (entity.errorCode!.codeIsSuccessful) { if (entity.errorCode!.codeIsSuccessful) {
state.serverTime = entity.data!.date! ~/ 1000;
state.differentialTime = entity.data!.date! ~/ 1000 - DateTime.now().millisecondsSinceEpoch ~/ 1000; state.differentialTime = entity.data!.date! ~/ 1000 - DateTime.now().millisecondsSinceEpoch ~/ 1000;
} }
} }
@ -72,7 +90,6 @@ class ThirdPartyPlatformLogic extends BaseGetXController {
return; return;
} }
_replySubscription = EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async { _replySubscription = EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async {
AppLog.log('输出了listen${_replySubscription.hashCode}');
if (reply is SenderReadRegisterKeyCommandReply) { if (reply is SenderReadRegisterKeyCommandReply) {
_handleReadRegisterKeyReply(reply); _handleReadRegisterKeyReply(reply);
} }
@ -158,7 +175,7 @@ class ThirdPartyPlatformLogic extends BaseGetXController {
uuid: response.data?.extraParams?['uuid'], uuid: response.data?.extraParams?['uuid'],
key: response.data?.authCode, key: response.data?.authCode,
mac: response.data?.extraParams?['mac'], mac: response.data?.extraParams?['mac'],
platform: 1, platform: state.selectPlatFormIndex.value,
utcTimeStamp: getUTCNetTime(), utcTimeStamp: getUTCNetTime(),
); );
} else if (connectionState == BluetoothConnectionState.disconnected) { } else if (connectionState == BluetoothConnectionState.disconnected) {
@ -190,26 +207,12 @@ class ThirdPartyPlatformLogic extends BaseGetXController {
} }
void savePlatFormSetting() { void savePlatFormSetting() {
if (state.selectPlatFormIndex.value == 1) { if (state.selectPlatFormIndex.value == 1 || state.selectPlatFormIndex.value == 0) {
showEasyLoading(); if (state.registerKey.isNotEmpty) {
showBlueConnetctToastTimer(action: () { _requestAuthorizationCode();
dismissEasyLoading();
});
BlueManage().blueSendData(
BlueManage().connectDeviceName,
(BluetoothConnectionState connectionState) async {
if (connectionState == BluetoothConnectionState.connected) {
IoSenderManage.readRegisterKey(
lockID: BlueManage().connectDeviceName,
);
} else if (connectionState == BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
} }
},
);
} else { } else {
showToast('目前只支持切换至涂鸦智能协议'.tr); showToast('目前只支持切换至涂鸦智能、锁通通协议'.tr);
} }
} }
@ -232,15 +235,14 @@ class ThirdPartyPlatformLogic extends BaseGetXController {
switch (status) { switch (status) {
case 0x00: case 0x00:
final platform = reply.data[7];
// RegisterKey (740) // RegisterKey (740)
final List<int> registerKeyBytes = reply.data.sublist(7, 47); final List<int> registerKeyBytes = reply.data.sublist(8, 48);
final String registerKey = String.fromCharCodes(registerKeyBytes); final String registerKey = String.fromCharCodes(registerKeyBytes);
state.selectPlatFormIndex.value = platform;
print('platform: $platform');
print('Register Key: $registerKey'); print('Register Key: $registerKey');
state.registerKey.value = registerKey; state.registerKey.value = registerKey;
if (registerKey.isNotEmpty) {
_requestAuthorizationCode();
}
// //
cancelBlueConnetctToastTimer(); cancelBlueConnetctToastTimer();
dismissEasyLoading(); dismissEasyLoading();
@ -265,8 +267,8 @@ class ThirdPartyPlatformLogic extends BaseGetXController {
IoSenderManage.senderGetStarLockStatuInfo( IoSenderManage.senderGetStarLockStatuInfo(
lockID: BlueManage().connectDeviceName, lockID: BlueManage().connectDeviceName,
userID: await Storage.getUid(), userID: await Storage.getUid(),
utcTimeStamp: 0, utcTimeStamp: state.serverTime,
unixTimeStamp: 0, unixTimeStamp: getLocalTime2(),
isBeforeAddUser: false, isBeforeAddUser: false,
privateKey: getPrivateKeyList, privateKey: getPrivateKeyList,
); );
@ -278,6 +280,18 @@ class ThirdPartyPlatformLogic extends BaseGetXController {
}); });
} }
int getLocalTime() {
final DateTime now = DateTime.now();
final Duration timeZoneOffset = now.timeZoneOffset;
return state.differentialTime + timeZoneOffset.inSeconds;
}
int getLocalTime2() {
final DateTime now = DateTime.now();
final Duration timeZoneOffset = now.timeZoneOffset;
return state.serverTime + timeZoneOffset.inSeconds;
}
void _handleAuthorizationCodeReply(SenderAuthorizationCodeCommandReply reply) { void _handleAuthorizationCodeReply(SenderAuthorizationCodeCommandReply reply) {
final int status = reply.data[6]; final int status = reply.data[6];
switch (status) { switch (status) {
@ -285,7 +299,12 @@ class ThirdPartyPlatformLogic extends BaseGetXController {
// //
cancelBlueConnetctToastTimer(); cancelBlueConnetctToastTimer();
dismissEasyLoading(); dismissEasyLoading();
showToast('操作成功请在24小时内用涂鸦APP添加门锁否则将过期'.tr); if (state.selectPlatFormIndex.value == 1) {
showSuccess('操作成功,请尽快用"涂鸦”APP配置如不使用请关闭该设置支持'.tr);
} else if (state.selectPlatFormIndex.value == 0) {
showSuccess('操作成功'.tr);
}
break; break;
default: default:
// //

View File

@ -128,7 +128,8 @@ class _ThirdPartyPlatformPageState extends State<ThirdPartyPlatformPage> {
// 线 // 线
isHaveDirection: false, isHaveDirection: false,
isHaveRightWidget: true, isHaveRightWidget: true,
rightWidget: Radio<String>( rightWidget: Obx(
() => Radio<String>(
// Radio 使 id // Radio 使 id
value: platform, value: platform,
// selectPlatFormIndex id // selectPlatFormIndex id
@ -148,6 +149,7 @@ class _ThirdPartyPlatformPageState extends State<ThirdPartyPlatformPage> {
} }
}, },
), ),
),
action: () { action: () {
setState(() { setState(() {
state.selectPlatFormIndex.value = index; state.selectPlatFormIndex.value = index;

View File

@ -25,8 +25,11 @@ class ThirdPartyPlatformState {
// UI // UI
final RxList<TppSupportInfo> tppSupportList = RxList<TppSupportInfo>([]); final RxList<TppSupportInfo> tppSupportList = RxList<TppSupportInfo>([]);
RxInt selectPlatFormIndex = 1.obs; RxInt selectPlatFormIndex = 0.obs;
RxBool openNumber = false.obs;
RxString registerKey = ''.obs; RxString registerKey = ''.obs;
Map lockInfo = {}; Map lockInfo = {};
int serverTime = 0; // UTC+0
} }

View File

@ -300,7 +300,7 @@ class PasswordKeyDetailLogic extends BaseGetXController {
'\n' + '\n' +
'有效期'.tr + '有效期'.tr +
':${startDateStr.toLocal().toString().substring(0, 16)} -- ${endDateStr.toLocal().toString().substring(0, 16)}\n\n' + ':${startDateStr.toLocal().toString().substring(0, 16)} -- ${endDateStr.toLocal().toString().substring(0, 16)}\n\n' +
'${'这是单次密码,只能使用一次'.tr}\n'; '这是单次密码,只能使用一次\n';
break; break;
case 2: case 2:
// 2 24使 // 2 24使
@ -309,8 +309,8 @@ class PasswordKeyDetailLogic extends BaseGetXController {
':' + ':' +
'永久'.tr + '永久'.tr +
'\n' + '\n' +
'\n${'注:'.tr}\n' + '\n注:\n' +
'${'必需在开始时间24小时内使用一次否则将失效'.tr}\n'; '必需在开始时间24小时内使用一次否则将失效\n';
break; break;
case 3: case 3:
// 3 24使 // 3 24使
@ -324,7 +324,7 @@ class PasswordKeyDetailLogic extends BaseGetXController {
':${startDateStr.toLocal().toString().substring(0, 16)}-${endDateStr.toLocal().toString().substring(0, 16)}' + ':${startDateStr.toLocal().toString().substring(0, 16)}-${endDateStr.toLocal().toString().substring(0, 16)}' +
'\n' + '\n' +
'\n注:\n' + '\n注:\n' +
'${'必需在开始时间24小时内使用一次否则将失效'.tr}\n'; '必需在开始时间24小时内使用一次否则将失效\n';
break; break;
case 4: case 4:
// 4 使使 // 4 使使
@ -453,10 +453,9 @@ class PasswordKeyDetailLogic extends BaseGetXController {
default: default:
} }
// return '您好,您的密码是'.tr + ':${state.itemData.value.keyboardPwd}\n$useDateStr\n${'密码名字'.tr}:${state.itemData.value.keyboardPwdName}'; // return '您好,您的密码是'.tr + ':${state.itemData.value.keyboardPwd}\n$useDateStr\n${'密码名字'.tr}:${state.itemData.value.keyboardPwdName}';
return '您好'.tr + return '您好' +
',\n${'您的开门密码是'.tr}' + ',\n您的开门密码是' +
':${state.itemData.value.keyboardPwd}\n$useDateStr\n${'密码名字'.tr}:${state.itemData.value.keyboardPwdName}\n' ':${state.itemData.value.keyboardPwd}\n$useDateStr\n${'密码名字'.tr}:${state.itemData.value.keyboardPwdName}\n\n开锁时,先激活锁键盘,再输入密码,以#号结束,#号键在键盘右下角,有可能是其他图标';
'\n${'开锁时,先激活锁键盘,再输入密码,以#号结束,#号键在键盘右下角,有可能是其他图标'.tr}';
} }
@override @override

View File

@ -46,24 +46,32 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
} else if (state.widgetType.value == 1) { } else if (state.widgetType.value == 1) {
// //
// 鸿 // 鸿
if (CommonDataManage().currentKeyInfo.vendor == IoModelVendor.vendor_XHJ && if (CommonDataManage().currentKeyInfo.vendor ==
(CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XHJ_SYD || IoModelVendor.vendor_XHJ &&
CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XHJ_JL)) { (CommonDataManage().currentKeyInfo.model ==
if (endDate <= DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { IoModelVendor.model_XHJ_SYD ||
CommonDataManage().currentKeyInfo.model ==
IoModelVendor.model_XHJ_JL)) {
if (endDate <=
DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) {
showToast('失效时间要大于当前时间'.tr); showToast('失效时间要大于当前时间'.tr);
return; return;
} }
//endDate 0 //endDate 0
final DateTime now = DateTime.now(); final DateTime now = DateTime.now();
startDate = DateTime(now.year, now.month, now.day).millisecondsSinceEpoch; startDate =
DateTime(now.year, now.month, now.day).millisecondsSinceEpoch;
} }
// //
if (CommonDataManage().currentKeyInfo.vendor == IoModelVendor.vendor_XL && if (CommonDataManage().currentKeyInfo.vendor == IoModelVendor.vendor_XL &&
(CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_BLE || (CommonDataManage().currentKeyInfo.model ==
CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_WIFI)) { IoModelVendor.model_XL_BLE ||
CommonDataManage().currentKeyInfo.model ==
IoModelVendor.model_XL_WIFI)) {
// //
if (startDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { if (startDate <
DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) {
showToast('生效时间不能小于当前时间'.tr); showToast('生效时间不能小于当前时间'.tr);
return; return;
} }
@ -83,9 +91,12 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
// //
// //
if (CommonDataManage().currentKeyInfo.vendor == IoModelVendor.vendor_XL && if (CommonDataManage().currentKeyInfo.vendor == IoModelVendor.vendor_XL &&
(CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_BLE || (CommonDataManage().currentKeyInfo.model ==
CommonDataManage().currentKeyInfo.model == IoModelVendor.model_XL_WIFI)) { IoModelVendor.model_XL_BLE ||
if (endDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) { CommonDataManage().currentKeyInfo.model ==
IoModelVendor.model_XL_WIFI)) {
if (endDate <
DateTool().dateToTimestamp(DateTool().getNowDateWithType(3), 1)) {
showToast('结束时间不能小于当前时间'.tr); showToast('结束时间不能小于当前时间'.tr);
return; return;
} }
@ -155,8 +166,10 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
// //
if (state.isPermanent.value == false) { if (state.isPermanent.value == false) {
getKeyType = '3'; getKeyType = '3';
getEffectiveDateTime = DateTool().dateToTimestamp(state.customBeginTime.value, 1).toString(); getEffectiveDateTime =
getFailureDateTime = DateTool().dateToTimestamp(state.customEndTime.value, 1).toString(); DateTool().dateToTimestamp(state.customBeginTime.value, 1).toString();
getFailureDateTime =
DateTool().dateToTimestamp(state.customEndTime.value, 1).toString();
} }
final PasswordKeyEntity entity = await ApiRepository.to.addPasswordKey( final PasswordKeyEntity entity = await ApiRepository.to.addPasswordKey(
lockId: lockId, lockId: lockId,
@ -171,7 +184,8 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
if (entity.errorCode!.codeIsSuccessful) { if (entity.errorCode!.codeIsSuccessful) {
ApmHelper.instance.trackEvent('add_password', { ApmHelper.instance.trackEvent('add_password', {
'lock_name': BlueManage().connectDeviceName, 'lock_name': BlueManage().connectDeviceName,
'account': getMobile.isNotEmpty ? getMobile : (await Storage.getEmail())!, 'account':
getMobile.isNotEmpty ? getMobile : (await Storage.getEmail())!,
'date': DateTool().getNowDateWithType(1), 'date': DateTool().getNowDateWithType(1),
'add_password_result': '成功', 'add_password_result': '成功',
}); });
@ -188,7 +202,8 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
} else { } else {
ApmHelper.instance.trackEvent('add_password', { ApmHelper.instance.trackEvent('add_password', {
'lock_name': BlueManage().connectDeviceName, 'lock_name': BlueManage().connectDeviceName,
'account': getMobile.isNotEmpty ? getMobile : (await Storage.getEmail())!, 'account':
getMobile.isNotEmpty ? getMobile : (await Storage.getEmail())!,
'date': DateTool().getNowDateWithType(1), 'date': DateTool().getNowDateWithType(1),
'add_password_result': '${entity.errorMsg}', 'add_password_result': '${entity.errorMsg}',
}); });
@ -215,7 +230,8 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
showToast('请输入密码'.tr); showToast('请输入密码'.tr);
return; return;
} }
final PasswordKeyEntity entity = await ApiRepository.to.checkKeyboardpwdName( final PasswordKeyEntity entity =
await ApiRepository.to.checkKeyboardpwdName(
lockId: state.keyInfo.value.lockId.toString(), lockId: state.keyInfo.value.lockId.toString(),
keyboardPwdName: state.nameController.text, keyboardPwdName: state.nameController.text,
keyboardPwd: state.pwdController.text, keyboardPwd: state.pwdController.text,
@ -230,11 +246,16 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
late StreamSubscription<Reply> _replySubscription; late StreamSubscription<Reply> _replySubscription;
void _initReplySubscription() { void _initReplySubscription() {
_replySubscription = EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async { _replySubscription =
EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async {
// //
if ((reply is SenderCustomPasswordsReply) && (state.ifCurrentScreen.value == true)) { if ((reply is SenderCustomPasswordsReply) &&
(state.ifCurrentScreen.value == true)) {
BuglyTool.uploadException( BuglyTool.uploadException(
message: '添加密码结果,解析数据', detail: '添加密码结果,解析数据:${reply.data}', eventStr: '添加密码事件结果', upload: true); message: '添加密码结果,解析数据',
detail: '添加密码结果,解析数据:${reply.data}',
eventStr: '添加密码事件结果',
upload: true);
final int status = reply.data[2]; final int status = reply.data[2];
switch (status) { switch (status) {
@ -284,14 +305,20 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
final List<String> saveStrList = changeIntListToStringList(token); final List<String> saveStrList = changeIntListToStringList(token);
Storage.setStringList(saveBlueToken, saveStrList); Storage.setStringList(saveBlueToken, saveStrList);
final List<String>? privateKey = await Storage.getStringList(saveBluePrivateKey); final List<String>? privateKey =
final List<int> getPrivateKeyList = changeStringListToIntList(privateKey!); await Storage.getStringList(saveBluePrivateKey);
final List<int> getPrivateKeyList =
changeStringListToIntList(privateKey!);
final List<String>? signKey = await Storage.getStringList(saveBlueSignKey); final List<String>? signKey =
final List<int> signKeyDataList = changeStringListToIntList(signKey!); await Storage.getStringList(saveBlueSignKey);
final List<int> signKeyDataList =
changeStringListToIntList(signKey!);
int startDate = DateTool().dateToTimestamp(state.customBeginTime.value, 1); int startDate =
int endDate = DateTool().dateToTimestamp(state.customEndTime.value, 1); DateTool().dateToTimestamp(state.customBeginTime.value, 1);
int endDate =
DateTool().dateToTimestamp(state.customEndTime.value, 1);
// //
if (state.isPermanent.value == true) { if (state.isPermanent.value == true) {
startDate = 0; startDate = 0;
@ -340,7 +367,8 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
int endDate = DateTool().dateToTimestamp(state.customEndTime.value, 1); int endDate = DateTool().dateToTimestamp(state.customEndTime.value, 1);
// //
if (state.isPermanent.value == false) { if (state.isPermanent.value == false) {
if (startDate < DateTool().dateToTimestamp(DateTool().getNowDateWithType(2), 1)) { if (startDate <
DateTool().dateToTimestamp(DateTool().getNowDateWithType(2), 1)) {
showToast('生效时间需晚于当前时间'.tr); showToast('生效时间需晚于当前时间'.tr);
return; return;
} }
@ -354,7 +382,8 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
endDate = 0; endDate = 0;
} }
if (state.pwdController.text.length < 6 || state.pwdController.text.length > 9) { if (state.pwdController.text.length < 6 ||
state.pwdController.text.length > 9) {
showToast('请输入6-9位数字'.tr); showToast('请输入6-9位数字'.tr);
return; return;
} }
@ -367,7 +396,8 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
final List<String>? signKey = await Storage.getStringList(saveBlueSignKey); final List<String>? signKey = await Storage.getStringList(saveBlueSignKey);
final List<int> signKeyDataList = changeStringListToIntList(signKey!); final List<int> signKeyDataList = changeStringListToIntList(signKey!);
final List<String>? privateKey = await Storage.getStringList(saveBluePrivateKey); final List<String>? privateKey =
await Storage.getStringList(saveBluePrivateKey);
final List<int> getPrivateKeyList = changeStringListToIntList(privateKey!); final List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
final List<String>? token = await Storage.getStringList(saveBlueToken); final List<String>? token = await Storage.getStringList(saveBlueToken);
@ -394,7 +424,8 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
final String getMobile = (await Storage.getMobile())!; final String getMobile = (await Storage.getMobile())!;
ApmHelper.instance.trackEvent('add_password', { ApmHelper.instance.trackEvent('add_password', {
'lock_name': BlueManage().connectDeviceName, 'lock_name': BlueManage().connectDeviceName,
'account': getMobile.isNotEmpty ? getMobile : (await Storage.getEmail())!, 'account':
getMobile.isNotEmpty ? getMobile : (await Storage.getEmail())!,
'date': DateTool().getNowDateWithType(1), 'date': DateTool().getNowDateWithType(1),
'add_password_result': '添加自定义密码超时', 'add_password_result': '添加自定义密码超时',
}); });
@ -408,13 +439,17 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
dismissEasyLoading(); dismissEasyLoading();
state.sureBtnState.value = 0; state.sureBtnState.value = 0;
}); });
BlueManage().blueSendData(BlueManage().connectDeviceName, (BluetoothConnectionState deviceConnectionState) async { BlueManage().blueSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState deviceConnectionState) async {
if (deviceConnectionState == BluetoothConnectionState.connected) { if (deviceConnectionState == BluetoothConnectionState.connected) {
final List<String>? signKey = await Storage.getStringList(saveBlueSignKey); final List<String>? signKey =
await Storage.getStringList(saveBlueSignKey);
final List<int> signKeyDataList = changeStringListToIntList(signKey!); final List<int> signKeyDataList = changeStringListToIntList(signKey!);
final List<String>? privateKey = await Storage.getStringList(saveBluePrivateKey); final List<String>? privateKey =
final List<int> getPrivateKeyList = changeStringListToIntList(privateKey!); await Storage.getStringList(saveBluePrivateKey);
final List<int> getPrivateKeyList =
changeStringListToIntList(privateKey!);
final List<String>? token = await Storage.getStringList(saveBlueToken); final List<String>? token = await Storage.getStringList(saveBlueToken);
final List<int> getTokenList = changeStringListToIntList(token!); final List<int> getTokenList = changeStringListToIntList(token!);
@ -434,11 +469,13 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
signKey: signKeyDataList, signKey: signKeyDataList,
privateKey: getPrivateKeyList, privateKey: getPrivateKeyList,
token: getTokenList); token: getTokenList);
} else if (deviceConnectionState == BluetoothConnectionState.disconnected) { } else if (deviceConnectionState ==
BluetoothConnectionState.disconnected) {
final String getMobile = (await Storage.getMobile())!; final String getMobile = (await Storage.getMobile())!;
ApmHelper.instance.trackEvent('add_password', { ApmHelper.instance.trackEvent('add_password', {
'lock_name': BlueManage().connectDeviceName, 'lock_name': BlueManage().connectDeviceName,
'account': getMobile.isNotEmpty ? getMobile : (await Storage.getEmail())!, 'account':
getMobile.isNotEmpty ? getMobile : (await Storage.getEmail())!,
'date': DateTool().getNowDateWithType(1), 'date': DateTool().getNowDateWithType(1),
'add_password_result': '添加自定义密码断开', 'add_password_result': '添加自定义密码断开',
}); });
@ -480,11 +517,17 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
'\n' + '\n' +
'有效期'.tr + '有效期'.tr +
':${startDateStr.toLocal().toString().substring(0, 16)} -- ${endDateStr.toLocal().toString().substring(0, 16)}\n\n' + ':${startDateStr.toLocal().toString().substring(0, 16)} -- ${endDateStr.toLocal().toString().substring(0, 16)}\n\n' +
'${'这是单次密码,只能使用一次'.tr}\n'; '这是单次密码,只能使用一次\n';
break; break;
case 0: case 0:
// 2 24使 // 2 24使
useDateStr = '\n' + '类型'.tr + ':' + '永久'.tr + '\n' + '\n注:\n' + '${'必需在开始时间24小时内使用一次否则将失效'.tr}\n'; useDateStr = '\n' +
'类型'.tr +
':' +
'永久'.tr +
'\n' +
'\n注:\n' +
'必需在开始时间24小时内使用一次否则将失效\n';
break; break;
case 1: case 1:
// 3 24使 // 3 24使
@ -497,14 +540,15 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
'有效期'.tr + '有效期'.tr +
':${startDateStr.toLocal().toString().substring(0, 16)}-${endDateStr.toLocal().toString().substring(0, 16)}' + ':${startDateStr.toLocal().toString().substring(0, 16)}-${endDateStr.toLocal().toString().substring(0, 16)}' +
'\n' + '\n' +
'\n${'注:'.tr}\n' + '\n注:\n' +
'${'必需在开始时间24小时内使用一次否则将失效'.tr}\n'; '必需在开始时间24小时内使用一次否则将失效\n';
break; break;
case 3: case 3:
// //
if (state.isPermanent.value == false) { if (state.isPermanent.value == false) {
useDateStr = useDateStr = '类型'.tr +
'类型'.tr + ':' + '自定义-限时\n${'有效期'.tr}:${state.customBeginTime.value} -- ${state.customEndTime.value}'; ':' +
'自定义-限时\n${'有效期'.tr}:${state.customBeginTime.value} -- ${state.customEndTime.value}';
} else { } else {
useDateStr = '类型:自定义-永久'.tr; useDateStr = '类型:自定义-永久'.tr;
} }
@ -515,51 +559,171 @@ class PasswordKeyPerpetualLogic extends BaseGetXController {
break; break;
case 4: case 4:
// 5 // 5
useDateStr = '\n' + '类型'.tr + ':' + '循环'.tr + '\n' + '\n' + '周末'.tr + ' $starHour:00-$endHour:00' + '\n'; useDateStr = '\n' +
'类型'.tr +
':' +
'循环'.tr +
'\n' +
'\n' +
'周末'.tr +
' $starHour:00-$endHour:00' +
'\n';
break; break;
case 6: case 6:
// 6 // 6
useDateStr = '\n' + '类型'.tr + ':' + '循环'.tr + '\n' + '\n' + '每日'.tr + ' $starHour:00-$endHour:00' + '\n'; useDateStr = '\n' +
'类型'.tr +
':' +
'循环'.tr +
'\n' +
'\n' +
'每日'.tr +
' $starHour:00-$endHour:00' +
'\n';
break; break;
case 7: case 7:
// 7 // 7
useDateStr = '\n' + '类型'.tr + ':' + '循环'.tr + '\n' + '\n' + '工作日'.tr + ' $starHour:00-$endHour:00' + '\n'; useDateStr = '\n' +
'类型'.tr +
':' +
'循环'.tr +
'\n' +
'\n' +
'工作日'.tr +
' $starHour:00-$endHour:00' +
'\n';
break; break;
case 8: case 8:
// 8 // 8
useDateStr = '\n' + '类型'.tr + ':' + '循环'.tr + '\n' + '\n' + '周一'.tr + ' $starHour:00-$endHour:00' + '\n'; useDateStr = '\n' +
'类型'.tr +
':' +
'循环'.tr +
'\n' +
'\n' +
'周一'.tr +
' $starHour:00-$endHour:00' +
'\n';
break; break;
case 9: case 9:
// 9 // 9
useDateStr = '\n' + '类型'.tr + ':' + '循环'.tr + '\n' + '\n' + '周二'.tr + ' $starHour:00-$endHour:00' + '\n'; useDateStr = '\n' +
'类型'.tr +
':' +
'循环'.tr +
'\n' +
'\n' +
'周二'.tr +
' $starHour:00-$endHour:00' +
'\n';
break; break;
case 10: case 10:
// 10 // 10
useDateStr = '\n' + '类型'.tr + ':' + '循环'.tr + '\n' + '\n' + '周三'.tr + ' $starHour:00-$endHour:00' + '\n'; useDateStr = '\n' +
'类型'.tr +
':' +
'循环'.tr +
'\n' +
'\n' +
'周三'.tr +
' $starHour:00-$endHour:00' +
'\n';
break; break;
case 11: case 11:
// 11 // 11
useDateStr = '\n' + '类型'.tr + ':' + '循环'.tr + '\n' + '\n' + '周四'.tr + ' $starHour:00 -$endHour:00' + '\n'; useDateStr = '\n' +
'类型'.tr +
':' +
'循环'.tr +
'\n' +
'\n' +
'周四'.tr +
' $starHour:00 -$endHour:00' +
'\n';
break; break;
case 12: case 12:
// 12 // 12
useDateStr = '\n' + '类型'.tr + ':' + '循环'.tr + '\n' + '\n' + '周五'.tr + ' $starHour:00-$endHour:00' + '\n'; useDateStr = '\n' +
'类型'.tr +
':' +
'循环'.tr +
'\n' +
'\n' +
'周五'.tr +
' $starHour:00-$endHour:00' +
'\n';
break; break;
case 13: case 13:
// 13 // 13
useDateStr = '\n' + '类型'.tr + ':' + '循环'.tr + '\n' + '\n' + '周六'.tr + ' $starHour:00-$endHour:00' + '\n'; useDateStr = '\n' +
'类型'.tr +
':' +
'循环'.tr +
'\n' +
'\n' +
'周六'.tr +
' $starHour:00-$endHour:00' +
'\n';
break; break;
case 14: case 14:
// 14 // 14
useDateStr = '\n' + '类型'.tr + ':' + '循环'.tr + '\n' + '\n' + '周日'.tr + ' $starHour:00-$endHour:00' + '\n'; useDateStr = '\n' +
'类型'.tr +
':' +
'循环'.tr +
'\n' +
'\n' +
'周日'.tr +
' $starHour:00-$endHour:00' +
'\n';
break; break;
default: default:
} }
// return '您好,您的密码是'.tr + ':${state.itemData.value.keyboardPwd}\n$useDateStr\n${'密码名字'.tr}:${state.itemData.value.keyboardPwdName}';
return '您好'.tr + return '您好' +
',\n${'您的开门密码是'.tr}' + ',\n您的开门密码是' +
':${state.getPwdStr.value}\n$useDateStr\n${'密码名字'.tr}:${state.pwdNameStr}\n' ':${state.getPwdStr.value}\n$useDateStr\n${'密码名字'.tr}:${state.pwdNameStr}\n\n开锁时,先激活锁键盘,再输入密码,以#号结束,#号键在键盘右下角,有可能是其他图标';
'\n${'开锁时,先激活锁键盘,再输入密码,以#号结束,#号键在键盘右下角,有可能是其他图标'.tr}'; // switch (getPwdType) {
// case 0:
// // 24使
// useDateStr = '类型'.tr + ':' + '永久';
// break;
// case 1:
// // 24使
// useDateStr = '类型'.tr +
// ':' +
// '限时\n${'有效期'.tr}:${state.beginTime.value} -- ${state.endTime.value}';
// break;
// case 2:
// // 6使
// useDateStr = '类型'.tr +
// ':' +
// '单次\n${'有效期'.tr}:${state.beginTime.value} -- ${state.endTime.value}';
// break;
// case 3:
// //
// if (state.isPermanent.value == false) {
// useDateStr = '类型'.tr +
// ':' +
// '自定义-限时\n${'有效期'.tr}:${state.customBeginTime.value} -- ${state.customEndTime.value}';
// } else {
// useDateStr = '类型:自定义-永久'.tr;
// }
// break;
// case 4:
// //
// useDateStr = '类型'.tr +
// ':' +
// '循环\n${state.loopModeStr.value} ${state.loopEffectiveDate.value}:00-${state.loopFailureDate.value}';
// break;
// case 5:
// // 4 使使
// useDateStr = '类型:清空';
// break;
//
// default:
// }
// return '${'您好,您的密码是'.tr}:${state.getPwdStr.value}\n$useDateStr\n${'密码名字'.tr}:${state.pwdNameStr}';
} }
String addSpaces(String input) { String addSpaces(String input) {

View File

@ -36,13 +36,13 @@ class _LockListGroupViewState extends State<LockListGroupView> {
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
// Container( Container(
// color: widget.backgroundColor ?? Colors.white, color: widget.backgroundColor ?? Colors.white,
// height: 80.h, height: 80.h,
// child: Row( child: Row(
// children: _buildExpandRowList(), children: _buildExpandRowList(),
// ), ),
// ), ),
ClipRect( ClipRect(
child: AnimatedAlign( child: AnimatedAlign(
heightFactor: _isExpanded ? 1.0 : 0.0, heightFactor: _isExpanded ? 1.0 : 0.0,

View File

@ -32,12 +32,10 @@ class LockListLogic extends BaseGetXController {
final ShowTipView showTipView = ShowTipView(); final ShowTipView showTipView = ShowTipView();
List<GroupList> get groupDataListFiltered { List<GroupList> get groupDataListFiltered {
final List<GroupList> list = final List<GroupList> list = groupDataList.map((GroupList e) => e.copy()).toList();
groupDataList.map((GroupList e) => e.copy()).toList();
if (state.searchStr.value != '' && state.showSearch.value) { if (state.searchStr.value != '' && state.showSearch.value) {
list.forEach((GroupList element) { list.forEach((GroupList element) {
element.lockList?.removeWhere((LockListInfoItemEntity element) => element.lockList?.removeWhere((LockListInfoItemEntity element) => !(element.lockAlias?.contains(state.searchStr.value) ?? true));
!(element.lockAlias?.contains(state.searchStr.value) ?? true));
}); });
} }
if (list.length > 0) { if (list.length > 0) {
@ -46,8 +44,7 @@ class LockListLogic extends BaseGetXController {
final lockList = element.lockList; final lockList = element.lockList;
if (lockList != null && lockList.length > 0) { if (lockList != null && lockList.length > 0) {
lockList.forEach((element) { lockList.forEach((element) {
if (element.network?.peerId != null && if (element.network?.peerId != null && element.network?.peerId != '') {
element.network?.peerId != '') {
StartChartManage().lockListPeerId.add(element); StartChartManage().lockListPeerId.add(element);
} }
}); });
@ -68,11 +65,9 @@ class LockListLogic extends BaseGetXController {
late StreamSubscription _setLockListInfoGroupEntity; late StreamSubscription _setLockListInfoGroupEntity;
void _initReplySubscription() { void _initReplySubscription() {
_replySubscription = _replySubscription = EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async {
EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async {
// //
if ((reply is FactoryDataResetReply) && if ((reply is FactoryDataResetReply)) {
(state.ifCurrentScreen.value == true)) {
_replyFactoryDataResetKey(reply); _replyFactoryDataResetKey(reply);
} }
}); });
@ -93,19 +88,18 @@ class LockListLogic extends BaseGetXController {
break; break;
case 0x06: case 0x06:
// //
final List<String>? token = await Storage.getStringList(saveBlueToken); final List<int> tokenData = reply.data.sublist(2, 6);
final List<int> getTokenList = changeStringListToIntList(token!); final List<String> saveStrList = changeIntListToStringList(tokenData);
Storage.setStringList(saveBlueToken, saveStrList);
IoSenderManage.senderFactoryDataReset( IoSenderManage.senderFactoryDataReset(
lockID: BlueManage().connectDeviceName, lockID: BlueManage().connectDeviceName,
userID: await Storage.getUid(), userID: await Storage.getUid(),
keyID: '1', keyID: '1',
needAuthor: 1, needAuthor: 1,
publicKey: publicKey: state.publicKey,
state.lockListInfoItemEntity.bluetooth!.publicKey!.cast<int>(), privateKey: state.privateKey,
privateKey: token: tokenData,
state.lockListInfoItemEntity.bluetooth!.privateKey!.cast<int>(), );
token: getTokenList);
break; break;
case 0x07: case 0x07:
// //
@ -146,8 +140,7 @@ class LockListLogic extends BaseGetXController {
keyInfo.keyType == XSConstantMacro.keyTypeLong || keyInfo.keyType == XSConstantMacro.keyTypeLong ||
keyInfo.keyType == XSConstantMacro.keyTypeLoop) { keyInfo.keyType == XSConstantMacro.keyTypeLoop) {
// 使 // 使
if (keyInfo.keyStatus == XSConstantMacro.keyStatusNormalUse || if (keyInfo.keyStatus == XSConstantMacro.keyStatusNormalUse || keyInfo.keyStatus == XSConstantMacro.keyStatusWaitReceive) {
keyInfo.keyStatus == XSConstantMacro.keyStatusWaitReceive) {
return "${"".tr}${DateTool().compareTimeGetDaysFromNow(keyInfo.endDate!)}${"".tr}"; return "${"".tr}${DateTool().compareTimeGetDaysFromNow(keyInfo.endDate!)}${"".tr}";
} else { } else {
return XSConstantMacro.getKeyStatusStr(keyInfo.keyStatus!); return XSConstantMacro.getKeyStatusStr(keyInfo.keyStatus!);
@ -160,11 +153,7 @@ class LockListLogic extends BaseGetXController {
// //
bool getShowType(LockListInfoItemEntity keyInfo) { bool getShowType(LockListInfoItemEntity keyInfo) {
final List<int> keyTypes = <int>[ final List<int> keyTypes = <int>[XSConstantMacro.keyTypeTime, XSConstantMacro.keyTypeOnce, XSConstantMacro.keyTypeLoop];
XSConstantMacro.keyTypeTime,
XSConstantMacro.keyTypeOnce,
XSConstantMacro.keyTypeLoop
];
final List<int> keyStatus = <int>[ final List<int> keyStatus = <int>[
XSConstantMacro.keyStatusWaitIneffective, XSConstantMacro.keyStatusWaitIneffective,
XSConstantMacro.keyStatusFrozen, XSConstantMacro.keyStatusFrozen,
@ -172,36 +161,30 @@ class LockListLogic extends BaseGetXController {
]; ];
//--&& //--&&
final bool isLongFrozenStatus = final bool isLongFrozenStatus = keyInfo.keyType == XSConstantMacro.keyTypeLong && keyInfo.keyStatus == XSConstantMacro.keyStatusFrozen;
keyInfo.keyType == XSConstantMacro.keyTypeLong && final DateTime endDate = DateTime.fromMillisecondsSinceEpoch(keyInfo.endDate ?? 0);
keyInfo.keyStatus == XSConstantMacro.keyStatusFrozen;
final DateTime endDate =
DateTime.fromMillisecondsSinceEpoch(keyInfo.endDate ?? 0);
final DateTime now = DateTime.now(); final DateTime now = DateTime.now();
final bool isKeyType = keyTypes.contains(keyInfo.keyType); final bool isKeyType = keyTypes.contains(keyInfo.keyType);
final bool isKeyStatus = keyStatus.contains(keyInfo.keyStatus); final bool isKeyStatus = keyStatus.contains(keyInfo.keyStatus);
final Duration difference = endDate.difference(now); final Duration difference = endDate.difference(now);
final bool isExpirationSoon = isKeyType && difference.inDays <= 15; final bool isExpirationSoon = isKeyType && difference.inDays <= 15;
final bool isShow = final bool isShow = isKeyType && isKeyStatus || isExpirationSoon || isLongFrozenStatus;
isKeyType && isKeyStatus || isExpirationSoon || isLongFrozenStatus;
return isShow; return isShow;
} }
/// ///
void deleyLockLogicOfRoles() { void deleyLockLogicOfRoles(LockListInfoItemEntity keyInfo) {
if (state.lockListInfoItemEntity.isLockOwner == 1) { if (state.lockListInfoItemEntity.value.isLockOwner == 1) {
// //
showTipView.showIosTipWithContentDialog('删除锁后,所有信息都会一起删除,确定删除锁吗?'.tr, () { showTipView.showIosTipWithContentDialog('删除锁后,所有信息都会一起删除,确定删除锁吗?'.tr, () {
// //
AppLog.log('调用了删除锁'); AppLog.log('调用了删除锁');
showTipView.resetGetController(); showTipView.resetGetController();
showTipView.showTFViewAlertDialog( showTipView.showTFViewAlertDialog(state.passwordTF, '请输入登录密码'.tr, '请输入登录密码'.tr, () => checkLoginPassword(keyInfo));
state.passwordTF, '请输入登录密码'.tr, '请输入登录密码'.tr, checkLoginPassword);
}); });
} else if (state.lockListInfoItemEntity.keyRight == 1) { } else if (state.lockListInfoItemEntity.value.keyRight == 1) {
// //
showTipView.showDeleteAdministratorIsHaveAllDataDialog( showTipView.showDeleteAdministratorIsHaveAllDataDialog('同时删除其发送的所有钥匙,钥匙删除后不能恢复'.tr, (bool a) {
'同时删除其发送的所有钥匙,钥匙删除后不能恢复'.tr, (bool a) {
// //
state.deleteAdministratorIsHaveAllData.value = a; state.deleteAdministratorIsHaveAllData.value = a;
deletKeyData(); deletKeyData();
@ -213,20 +196,20 @@ class LockListLogic extends BaseGetXController {
} }
// //
Future<void> checkLoginPassword() async { Future<void> checkLoginPassword(LockListInfoItemEntity keyInfo) async {
final LockListInfoEntity entity = await ApiRepository.to.checkLoginPassword( final LockListInfoEntity entity = await ApiRepository.to.checkLoginPassword(
password: state.passwordTF.text, password: state.passwordTF.text,
); );
if (entity.errorCode!.codeIsSuccessful) { if (entity.errorCode!.codeIsSuccessful) {
Get.back(); Get.back();
factoryDataResetAction(); factoryDataResetAction(keyInfo);
} }
} }
// //
Future<void> deletLockInfoData() async { Future<void> deletLockInfoData() async {
final LockListInfoEntity entity = await ApiRepository.to.deletOwnerLockData( final LockListInfoEntity entity = await ApiRepository.to.deletOwnerLockData(
lockId: state.lockListInfoItemEntity.lockId!, lockId: state.lockListInfoItemEntity.value.lockId!,
); );
if (entity.errorCode!.codeIsSuccessful) { if (entity.errorCode!.codeIsSuccessful) {
BlueManage().connectDeviceMacAddress = ''; BlueManage().connectDeviceMacAddress = '';
@ -239,10 +222,9 @@ class LockListLogic extends BaseGetXController {
// //
Future<void> deletKeyData() async { Future<void> deletKeyData() async {
final LockListInfoEntity entity = await ApiRepository.to.deletOwnerKeyData( final LockListInfoEntity entity = await ApiRepository.to.deletOwnerKeyData(
lockId: state.lockListInfoItemEntity.lockId.toString(), lockId: state.lockListInfoItemEntity.value.lockId.toString(),
keyId: state.lockListInfoItemEntity.keyId.toString(), keyId: state.lockListInfoItemEntity.value.keyId.toString(),
includeUnderlings: includeUnderlings: state.deleteAdministratorIsHaveAllData.value == true ? 1 : 0);
state.deleteAdministratorIsHaveAllData.value == true ? 1 : 0);
if (entity.errorCode!.codeIsSuccessful) { if (entity.errorCode!.codeIsSuccessful) {
BlueManage().connectDeviceMacAddress = ''; BlueManage().connectDeviceMacAddress = '';
SchedulerBinding.instance.addPostFrameCallback((_) { SchedulerBinding.instance.addPostFrameCallback((_) {
@ -252,7 +234,7 @@ class LockListLogic extends BaseGetXController {
} }
// //
Future<void> factoryDataResetAction() async { Future<void> factoryDataResetAction(LockListInfoItemEntity keyInfo) async {
showEasyLoading(); showEasyLoading();
showBlueConnetctToastTimer( showBlueConnetctToastTimer(
isShowBlueConnetctToast: false, isShowBlueConnetctToast: false,
@ -260,31 +242,23 @@ class LockListLogic extends BaseGetXController {
dismissEasyLoading(); dismissEasyLoading();
showDeletAlertTipDialog(); showDeletAlertTipDialog();
}); });
BlueManage().blueSendData(state.lockListInfoItemEntity.lockName!, BlueManage().blueSendData(state.lockListInfoItemEntity.value.lockName!, (BluetoothConnectionState connectionState) async {
(BluetoothConnectionState connectionState) async {
if (connectionState == BluetoothConnectionState.connected) { if (connectionState == BluetoothConnectionState.connected) {
final List<int> publicKeyData = final List<int> publicKeyData = state.lockListInfoItemEntity.value.bluetooth!.publicKey!.cast<int>();
state.lockListInfoItemEntity.bluetooth!.publicKey!.cast<int>(); final List<String> saveStrList = changeIntListToStringList(publicKeyData);
final List<String> saveStrList =
changeIntListToStringList(publicKeyData);
await Storage.setStringList(saveBluePublicKey, saveStrList); await Storage.setStringList(saveBluePublicKey, saveStrList);
// //
final List<int> privateKeyData = final List<int> privateKeyData = state.lockListInfoItemEntity.value.bluetooth!.privateKey!.cast<int>();
state.lockListInfoItemEntity.bluetooth!.privateKey!.cast<int>(); final List<String> savePrivateKeyList = changeIntListToStringList(privateKeyData);
final List<String> savePrivateKeyList =
changeIntListToStringList(privateKeyData);
await Storage.setStringList(saveBluePrivateKey, savePrivateKeyList); await Storage.setStringList(saveBluePrivateKey, savePrivateKeyList);
// signKey // signKey
final List<int> signKeyData = final List<int> signKeyData = state.lockListInfoItemEntity.value.bluetooth!.signKey!.cast<int>();
state.lockListInfoItemEntity.bluetooth!.signKey!.cast<int>(); final List<String> saveSignKeyList = changeIntListToStringList(signKeyData);
final List<String> saveSignKeyList =
changeIntListToStringList(signKeyData);
await Storage.setStringList(saveBlueSignKey, saveSignKeyList); await Storage.setStringList(saveBlueSignKey, saveSignKeyList);
final List<String> saveTokenList = final List<String> saveTokenList = changeIntListToStringList(<int>[0, 0, 0, 0]);
changeIntListToStringList(<int>[0, 0, 0, 0]);
await Storage.setStringList(saveBlueToken, saveTokenList); await Storage.setStringList(saveBlueToken, saveTokenList);
IoSenderManage.senderFactoryDataReset( IoSenderManage.senderFactoryDataReset(
@ -292,11 +266,13 @@ class LockListLogic extends BaseGetXController {
userID: await Storage.getUid(), userID: await Storage.getUid(),
keyID: '1', keyID: '1',
needAuthor: 1, needAuthor: 1,
publicKey: publicKey: keyInfo.bluetooth?.publicKey ?? [],
state.lockListInfoItemEntity.bluetooth!.publicKey!.cast<int>(), privateKey: keyInfo.bluetooth?.privateKey ?? [],
privateKey:
state.lockListInfoItemEntity.bluetooth!.privateKey!.cast<int>(),
token: <int>[0, 0, 0, 0]); token: <int>[0, 0, 0, 0]);
state.publicKey.value = keyInfo.bluetooth?.publicKey ?? [];
state.privateKey.value = keyInfo.bluetooth?.privateKey ?? [];
state.publicKey.refresh();
state.privateKey.refresh();
} else if (connectionState == BluetoothConnectionState.disconnected) { } else if (connectionState == BluetoothConnectionState.disconnected) {
dismissEasyLoading(); dismissEasyLoading();
cancelBlueConnetctToastTimer(); cancelBlueConnetctToastTimer();
@ -353,9 +329,7 @@ class LockListLogic extends BaseGetXController {
} }
void _initEventHandler() { void _initEventHandler() {
_setLockListInfoGroupEntity = eventBus _setLockListInfoGroupEntity = eventBus.on<SetLockListInfoGroupEntity>().listen((SetLockListInfoGroupEntity event) async {
.on<SetLockListInfoGroupEntity>()
.listen((SetLockListInfoGroupEntity event) async {
setLockListInfoGroupEntity(event.lockListInfoGroupEntity); setLockListInfoGroupEntity(event.lockListInfoGroupEntity);
}); });
} }

View File

@ -1,9 +1,8 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:star_lock/flavors.dart'; import 'package:star_lock/app_settings/app_settings.dart';
import 'package:star_lock/main/lockMian/lockList/lockList_state.dart'; import 'package:star_lock/main/lockMian/lockList/lockList_state.dart';
import '../../../appRouters.dart'; import '../../../appRouters.dart';
@ -38,47 +37,8 @@ class _LockListPageState extends State<LockListPage> with RouteAware {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Obx( return Obx(
() => Scaffold( () => Scaffold(
body: SafeArea( body: ListView.separated(
child: Column( itemCount: logic.groupDataList.length,
children: [
Row(
children: [
SizedBox(
width: 20.w,
),
Image.asset('images/icon_main_drlock_1024.png', width: 68.w, height: 68.w),
SizedBox(
width: 20.w,
),
Text(
F.title,
style: TextStyle(
fontSize: 28.sp,
fontWeight: FontWeight.w600,
),
),
Spacer(),
IconButton(
onPressed: () {
//
Navigator.pushNamed(
context,
Routers.selectLockTypePage,
);
},
icon: Icon(
Icons.add_circle_outline_rounded,
size: 48.sp,
),
),
SizedBox(
width: 20.w,
),
],
),
Expanded(
child: ListView.separated(
itemCount: logic.groupDataListFiltered.length,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
final GroupList itemData = logic.groupDataListFiltered[index]; final GroupList itemData = logic.groupDataListFiltered[index];
return _buildLockExpandedList(context, index, itemData, key: ValueKey(itemData.groupId)); return _buildLockExpandedList(context, index, itemData, key: ValueKey(itemData.groupId));
@ -93,10 +53,6 @@ class _LockListPageState extends State<LockListPage> with RouteAware {
}, },
), ),
), ),
],
),
),
),
); );
} }
@ -135,8 +91,12 @@ class _LockListPageState extends State<LockListPage> with RouteAware {
children: <Widget>[ children: <Widget>[
SlidableAction( SlidableAction(
onPressed: (BuildContext context) { onPressed: (BuildContext context) {
state.lockListInfoItemEntity = keyInfo; state.publicKey.value = keyInfo.bluetooth?.publicKey ?? [];
logic.deleyLockLogicOfRoles(); state.privateKey.value = keyInfo.bluetooth?.privateKey ?? [];
state.lockListInfoItemEntity.value = keyInfo;
state.lockListInfoItemEntity.refresh();
AppLog.log('msg=================:${state.lockListInfoItemEntity.value}');
logic.deleyLockLogicOfRoles(keyInfo);
}, },
backgroundColor: Colors.red, backgroundColor: Colors.red,
foregroundColor: Colors.white, foregroundColor: Colors.white,
@ -146,8 +106,7 @@ class _LockListPageState extends State<LockListPage> with RouteAware {
], ],
), ),
child: lockInfoListItem(keyInfo, isLast, () { child: lockInfoListItem(keyInfo, isLast, () {
if ((keyInfo.keyType == XSConstantMacro.keyTypeTime || if ((keyInfo.keyType == XSConstantMacro.keyTypeTime || keyInfo.keyType == XSConstantMacro.keyTypeLoop) &&
keyInfo.keyType == XSConstantMacro.keyTypeLoop) &&
(keyInfo.keyStatus == XSConstantMacro.keyStatusWaitIneffective)) { (keyInfo.keyStatus == XSConstantMacro.keyStatusWaitIneffective)) {
logic.showToast('您的钥匙未生效'.tr); logic.showToast('您的钥匙未生效'.tr);
return; return;
@ -159,8 +118,7 @@ class _LockListPageState extends State<LockListPage> with RouteAware {
logic.showToast('您的钥匙已冻结'.tr); logic.showToast('您的钥匙已冻结'.tr);
return; return;
} }
if ((keyInfo.keyType == XSConstantMacro.keyTypeTime || if ((keyInfo.keyType == XSConstantMacro.keyTypeTime || keyInfo.keyType == XSConstantMacro.keyTypeLoop) &&
keyInfo.keyType == XSConstantMacro.keyTypeLoop) &&
(keyInfo.keyStatus == XSConstantMacro.keyStatusExpired)) { (keyInfo.keyStatus == XSConstantMacro.keyStatusExpired)) {
logic.showToast('您的钥匙已过期'.tr); logic.showToast('您的钥匙已过期'.tr);
return; return;
@ -181,16 +139,13 @@ class _LockListPageState extends State<LockListPage> with RouteAware {
onTap: action, onTap: action,
child: Container( child: Container(
// height: 122.h, // height: 122.h,
margin: isLast margin: isLast ? EdgeInsets.only(left: 20.w, right: 20.w, top: 20.w, bottom: 20.w) : EdgeInsets.only(left: 20.w, right: 20.w, top: 20.w),
? EdgeInsets.only(left: 20.w, right: 20.w, top: 20.w, bottom: 20.w)
: EdgeInsets.only(left: 20.w, right: 20.w, top: 20.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: (((keyInfo.keyType == XSConstantMacro.keyTypeTime || keyInfo.keyType == XSConstantMacro.keyTypeLoop) && color: (((keyInfo.keyType == XSConstantMacro.keyTypeTime || keyInfo.keyType == XSConstantMacro.keyTypeLoop) &&
(keyInfo.keyStatus == XSConstantMacro.keyStatusWaitIneffective || (keyInfo.keyStatus == XSConstantMacro.keyStatusWaitIneffective ||
keyInfo.keyStatus == XSConstantMacro.keyStatusFrozen || keyInfo.keyStatus == XSConstantMacro.keyStatusFrozen ||
keyInfo.keyStatus == XSConstantMacro.keyStatusExpired)) || keyInfo.keyStatus == XSConstantMacro.keyStatusExpired)) ||
(keyInfo.keyType == XSConstantMacro.keyTypeLong && (keyInfo.keyType == XSConstantMacro.keyTypeLong && keyInfo.keyStatus == XSConstantMacro.keyStatusFrozen))
keyInfo.keyStatus == XSConstantMacro.keyStatusFrozen))
? AppColors.greyBackgroundColor ? AppColors.greyBackgroundColor
: Colors.white, : Colors.white,
borderRadius: BorderRadius.circular(20.w), borderRadius: BorderRadius.circular(20.w),
@ -214,9 +169,7 @@ class _LockListPageState extends State<LockListPage> with RouteAware {
style: TextStyle( style: TextStyle(
fontSize: 24.sp, fontSize: 24.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: keyInfo.passageMode == 1 color: keyInfo.passageMode == 1 ? AppColors.openPassageModeColor : AppColors.darkGrayTextColor),
? AppColors.openPassageModeColor
: AppColors.darkGrayTextColor),
), ),
], ],
), ),
@ -273,9 +226,7 @@ class _LockListPageState extends State<LockListPage> with RouteAware {
padding: EdgeInsets.only(right: 5.w, left: 5.w), padding: EdgeInsets.only(right: 5.w, left: 5.w),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.w), borderRadius: BorderRadius.circular(5.w),
color: DateTool().compareTimeIsOvertime(keyInfo.endDate!) color: DateTool().compareTimeIsOvertime(keyInfo.endDate!) ? AppColors.listTimeYellowColor : AppColors.mainColor,
? AppColors.listTimeYellowColor
: AppColors.mainColor,
), ),
child: Text(logic.getKeyEffective(keyInfo), style: TextStyle(fontSize: 18.sp, color: Colors.white) child: Text(logic.getKeyEffective(keyInfo), style: TextStyle(fontSize: 18.sp, color: Colors.white)
// child: Text(logic.compareTimeIsOvertime(keyInfo.endDate!) ? "已过期" : "${logic.compareTimeGetDaysFromNow(keyInfo.endDate!)}", style: TextStyle(fontSize: 18.sp, color: Colors.white) // child: Text(logic.compareTimeIsOvertime(keyInfo.endDate!) ? "已过期" : "${logic.compareTimeGetDaysFromNow(keyInfo.endDate!)}", style: TextStyle(fontSize: 18.sp, color: Colors.white)

View File

@ -7,11 +7,14 @@ import '../entity/lockListInfo_entity.dart';
class LockListState{ class LockListState{
RxBool itemStatusIsEable = false.obs; // item是否能点击 RxBool itemStatusIsEable = false.obs; // item是否能点击
LockListInfoItemEntity lockListInfoItemEntity = LockListInfoItemEntity(); // item //
Rx<LockListInfoItemEntity> lockListInfoItemEntity = LockListInfoItemEntity().obs; // item
TextEditingController passwordTF = TextEditingController(); TextEditingController passwordTF = TextEditingController();
RxBool deleteAdministratorIsHaveAllData = false.obs; // RxBool deleteAdministratorIsHaveAllData = false.obs; //
RxBool ifCurrentScreen = true.obs; // , RxBool ifCurrentScreen = true.obs; // ,
RxBool showSearch = false.obs; // , RxBool showSearch = false.obs; // ,
RxString searchStr = ''.obs; // , RxString searchStr = ''.obs; // ,
RxList<int> publicKey=<int>[].obs;
RxList<int> privateKey=<int>[].obs;
} }

View File

@ -192,8 +192,9 @@ class _LockListXHJPageState extends State<LockListXHJPage> with RouteAware {
children: <Widget>[ children: <Widget>[
SlidableAction( SlidableAction(
onPressed: (BuildContext context) { onPressed: (BuildContext context) {
state.lockListInfoItemEntity = keyInfo; state.lockListInfoItemEntity.value = keyInfo;
logic.deleyLockLogicOfRoles(); state.lockListInfoItemEntity.refresh();
logic.deleyLockLogicOfRoles(keyInfo);
}, },
backgroundColor: Colors.red, backgroundColor: Colors.red,
foregroundColor: Colors.white, foregroundColor: Colors.white,

View File

@ -23,11 +23,8 @@ import 'package:star_lock/tools/submitBtn.dart';
import '../../../appRouters.dart'; import '../../../appRouters.dart';
import '../../../baseWidget.dart'; import '../../../baseWidget.dart';
import '../../../flavors.dart'; import '../../../flavors.dart';
import '../../../mine/addLock/selectLockType/selectLockType_logic.dart';
import '../../../mine/message/messageList/messageList_page.dart';
import '../../../mine/mine/starLockMine_page.dart'; import '../../../mine/mine/starLockMine_page.dart';
import '../../../tools/EasyRefreshTool.dart'; import '../../../tools/EasyRefreshTool.dart';
import '../../../tools/commonDataManage.dart';
import '../../../tools/eventBusEventManage.dart'; import '../../../tools/eventBusEventManage.dart';
import '../../../tools/storage.dart'; import '../../../tools/storage.dart';
import '../../../tools/titleAppBar.dart'; import '../../../tools/titleAppBar.dart';
@ -37,7 +34,8 @@ import '../lockList/lockList_page.dart';
import 'lockMain_logic.dart'; import 'lockMain_logic.dart';
class StarLockMainPage extends StatefulWidget { class StarLockMainPage extends StatefulWidget {
StarLockMainPage({Key? key, this.showAppBar = true, this.showDrawer = true}) : super(key: key); StarLockMainPage({Key? key, this.showAppBar = true, this.showDrawer = true})
: super(key: key);
bool showAppBar; bool showAppBar;
bool showDrawer; bool showDrawer;
@ -50,15 +48,16 @@ class _StarLockMainPageState extends State<StarLockMainPage>
final LockMainLogic logic = Get.put(LockMainLogic()); final LockMainLogic logic = Get.put(LockMainLogic());
final LockMainState state = Get.find<LockMainLogic>().state; final LockMainState state = Get.find<LockMainLogic>().state;
final SelectLockTypeLogic logicType = Get.put(SelectLockTypeLogic()); Future<void> getHttpData(
{bool clearScanDevices = false, bool isUnShowLoading = false}) async {
Future<void> getHttpData({bool clearScanDevices = false, bool isUnShowLoading = false}) async { LockListInfoGroupEntity? lockListInfoGroupEntity =
LockListInfoGroupEntity? lockListInfoGroupEntity = await Storage.getLockMainListData(); await Storage.getLockMainListData();
if (lockListInfoGroupEntity != null) { if (lockListInfoGroupEntity != null) {
await logic.loadMainDataLogic(lockListInfoGroupEntity); await logic.loadMainDataLogic(lockListInfoGroupEntity);
setState(() {}); setState(() {});
} }
lockListInfoGroupEntity = (await logic.getStarLockInfo(isUnShowLoading: isUnShowLoading)).data; lockListInfoGroupEntity =
(await logic.getStarLockInfo(isUnShowLoading: isUnShowLoading)).data;
if (lockListInfoGroupEntity != null) { if (lockListInfoGroupEntity != null) {
await logic.loadMainDataLogic(lockListInfoGroupEntity); await logic.loadMainDataLogic(lockListInfoGroupEntity);
setState(() {}); setState(() {});
@ -90,8 +89,7 @@ class _StarLockMainPageState extends State<StarLockMainPage>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetBuilder<LockMainLogic>(builder: (LockMainLogic logic) { return GetBuilder<LockMainLogic>(builder: (LockMainLogic logic) {
Widget child = Obx( Widget child = EasyRefreshTool(
() => EasyRefreshTool(
onRefresh: () { onRefresh: () {
SchedulerBinding.instance.addPostFrameCallback((_) { SchedulerBinding.instance.addPostFrameCallback((_) {
// //
@ -100,44 +98,37 @@ class _StarLockMainPageState extends State<StarLockMainPage>
}); });
}, },
// child: getDataReturnUI(state.dataLength.value)); // child: getDataReturnUI(state.dataLength.value));
child: getDataReturnUI(state.dataLength.value), child: getDataReturnUI(state.dataLength.value));
),
);
if (widget.showAppBar || widget.showDrawer) { if (widget.showAppBar || widget.showDrawer) {
child = Scaffold( child = Scaffold(
backgroundColor: Colors.white, backgroundColor: const Color(0xFFF5F5F5),
body: child, appBar: widget.showAppBar
bottomNavigationBar: Obx( ? TitleAppBar(
() => BottomNavigationBar( barTitle: F.navTitle,
backgroundColor: Colors.white, haveBack: false,
items: <BottomNavigationBarItem>[ haveOtherLeftWidget: true,
BottomNavigationBarItem( leftWidget: Builder(
icon: ImageIcon( builder: (BuildContext context) => IconButton(
AssetImage(state.selectedIndex.value == 0 icon: Image.asset(
? 'images/icon_device_selected' 'images/main/mainLeft_menu_icon.png',
'.png' color: Colors.white,
: 'images/icon_device_not_selected.png'), width: 44.w,
), // 使 height: 44.w,
label: '设备',
), ),
const BottomNavigationBarItem( onPressed: () {
icon: Icon(Icons.notifications), Scaffold.of(context).openDrawer();
label: '消息',
),
const BottomNavigationBarItem(
icon: Icon(Icons.person),
label: '我的',
),
],
onTap: (index) {
state.selectedIndex.value = index;
}, },
currentIndex: state.selectedIndex.value, )),
selectedItemColor: AppColors.mainColor, backgroundColor: AppColors.mainColor,
unselectedItemColor: Colors.grey, )
showUnselectedLabels: true, // : null,
), drawer: widget.showDrawer
), ? Drawer(
width: 1.sw / 3 * 2,
child: const StarLockMinePage(),
)
: null,
body: child,
); );
} }
child = F.sw( child = F.sw(
@ -158,52 +149,41 @@ class _StarLockMainPageState extends State<StarLockMainPage>
Widget getDataReturnUI(int type) { Widget getDataReturnUI(int type) {
Widget returnWidget; Widget returnWidget;
if (state.selectedIndex.value == 0) {
if (type == 1) { if (type == 1) {
type = F.sw(skyCall: () => 1, xhjCall: () => 2); type = F.sw(skyCall: () => 1, xhjCall: () => 2);
} }
switch (type) { switch (type) {
case 0: case 0:
// //
returnWidget = MainBg(child: unHaveData()); returnWidget = unHaveData();
break; break;
case 1: case 1:
// //
Storage.setBool(ifIsDemoModeOrNot, false); Storage.setBool(ifIsDemoModeOrNot, false);
returnWidget = MainBg(child: LockDetailPage( returnWidget = LockDetailPage(
isOnlyOneData: true, isOnlyOneData: true,
lockListInfoItemEntity: state.lockListInfoGroupEntity.value.groupList![0].lockList![0])); lockListInfoItemEntity:
state.lockListInfoGroupEntity.value.groupList![0].lockList![0]);
break; break;
case 2: case 2:
// //
Storage.setBool(ifIsDemoModeOrNot, false); Storage.setBool(ifIsDemoModeOrNot, false);
returnWidget = F.sw( returnWidget = F.sw(
skyCall: () => MainBg(child: LockListPage(lockListInfoGroupEntity: state.lockListInfoGroupEntity.value)), skyCall: () => LockListPage(
xhjCall: () => MainBg(child: LockListXHJPage(lockListInfoGroupEntity: state.lockListInfoGroupEntity.value))); lockListInfoGroupEntity: state.lockListInfoGroupEntity.value),
xhjCall: () => LockListXHJPage(
lockListInfoGroupEntity: state.lockListInfoGroupEntity.value));
break; break;
default: default:
returnWidget = MainBg(child: NoData()); returnWidget = NoData();
break; break;
} }
} else if (state.selectedIndex.value == 1) {
returnWidget = MainBg(child: MessageListPage());
} else {
returnWidget = MainBg(child: StarLockMinePage());
}
return returnWidget; return returnWidget;
} }
// //
Widget MainBg({required Widget child}) { Widget XHJBg({required Widget child}) {
return Container( return Container();
child: child,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('images/lockMain_bg.jpg'),
fit: BoxFit.cover,
),
),
);
} }
Widget unHaveData() { Widget unHaveData() {
@ -212,48 +192,6 @@ class _StarLockMainPageState extends State<StarLockMainPage>
Column( Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
SizedBox(
height: 10.h,
),
Row(
children: [
SizedBox(
width: 20.w,
),
Image.asset('images/icon_main_drlock_1024.png', width: 68.w, height: 68.w),
SizedBox(
width: 20.w,
),
Text(
F.title,
style: TextStyle(
fontSize: 28.sp,
fontWeight: FontWeight.w600,
),
),
Spacer(),
IconButton(
onPressed: () {
//
// Navigator.pushNamed(
// context,
// Routers.selectLockTypePage,
// );
//
CommonDataManage().seletLockType = 0;
logicType.getNearByLimits();
},
icon: Icon(
Icons.add_circle_outline_rounded,
size: 48.sp,
),
),
SizedBox(
width: 20.w,
),
],
),
SizedBox( SizedBox(
height: 160.h, height: 160.h,
), ),
@ -273,14 +211,10 @@ class _StarLockMainPageState extends State<StarLockMainPage>
), ),
onTap: () { onTap: () {
// //
// Navigator.pushNamed( Navigator.pushNamed(
// context, context,
// Routers.selectLockTypePage, Routers.selectLockTypePage,
// ); );
//
CommonDataManage().seletLockType = 0;
logicType.getNearByLimits();
}, },
)), )),
], ],
@ -354,9 +288,13 @@ class _StarLockMainPageState extends State<StarLockMainPage>
late StreamSubscription _teamEvent; late StreamSubscription _teamEvent;
void _initLoadDataAction() { void _initLoadDataAction() {
_teamEvent = eventBus.on<RefreshLockListInfoDataEvent>().listen((RefreshLockListInfoDataEvent event) { _teamEvent = eventBus
.on<RefreshLockListInfoDataEvent>()
.listen((RefreshLockListInfoDataEvent event) {
logic.pageNo = 1; logic.pageNo = 1;
getHttpData(clearScanDevices: event.clearScanDevices, isUnShowLoading: event.isUnShowLoading); getHttpData(
clearScanDevices: event.clearScanDevices,
isUnShowLoading: event.isUnShowLoading);
}); });
} }
@ -366,7 +304,8 @@ class _StarLockMainPageState extends State<StarLockMainPage>
ByteData byteData = await rootBundle.load(assetPath); ByteData byteData = await rootBundle.load(assetPath);
// ByteData Uint8List // ByteData Uint8List
Uint8List uint8List = Uint8List.sublistView(byteData); //byteData.buffer.asUint8List(); Uint8List uint8List =
Uint8List.sublistView(byteData); //byteData.buffer.asUint8List();
// //
return uint8List.toList(); return uint8List.toList();

View File

@ -1,9 +1,11 @@
import 'dart:async'; import 'dart:async';
import 'package:get/get.dart'; import 'package:get/get.dart';
import '../entity/lockListInfo_entity.dart'; import '../entity/lockListInfo_entity.dart';
class LockMainState { class LockMainState {
// 0 1 2 // 0 1 2
RxInt dataLength = 100.obs; RxInt dataLength = 100.obs;
Rx<LockListInfoGroupEntity> lockListInfoGroupEntity = LockListInfoGroupEntity().obs; Rx<LockListInfoGroupEntity> lockListInfoGroupEntity = LockListInfoGroupEntity().obs;
@ -11,6 +13,5 @@ class LockMainState {
// 0 1 // 0 1
RxInt networkConnectionStatus = 0.obs; RxInt networkConnectionStatus = 0.obs;
RxInt selectedIndex = 0.obs;
// late Timer timer; // late Timer timer;
} }

View File

@ -31,8 +31,7 @@ class SaveLockLogic extends BaseGetXController {
late StreamSubscription<Reply> _replySubscription; late StreamSubscription<Reply> _replySubscription;
void _initReplySubscription() { void _initReplySubscription() {
_replySubscription = _replySubscription = EventBusManager().eventBus!.on<Reply>().listen((Reply reply) {
EventBusManager().eventBus!.on<Reply>().listen((Reply reply) {
if (reply is AddUserReply && state.ifCurrentScreen.value == true) { if (reply is AddUserReply && state.ifCurrentScreen.value == true) {
_replyAddUserKey(reply); _replyAddUserKey(reply);
} }
@ -66,15 +65,11 @@ class SaveLockLogic extends BaseGetXController {
break; break;
case 0x06: case 0x06:
// //
final List<String>? privateKey = final List<String>? privateKey = await Storage.getStringList(saveBluePrivateKey);
await Storage.getStringList(saveBluePrivateKey); final List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
final List<int> getPrivateKeyList =
changeStringListToIntList(privateKey!);
final List<String>? publicKey = final List<String>? publicKey = await Storage.getStringList(saveBluePublicKey);
await Storage.getStringList(saveBluePublicKey); final List<int> publicKeyDataList = changeStringListToIntList(publicKey!);
final List<int> publicKeyDataList =
changeStringListToIntList(publicKey!);
IoSenderManage.senderAddUser( IoSenderManage.senderAddUser(
lockID: BlueManage().connectDeviceName, lockID: BlueManage().connectDeviceName,
@ -215,19 +210,14 @@ class SaveLockLogic extends BaseGetXController {
showBlueConnetctToast(); showBlueConnetctToast();
} }
}); });
BlueManage().blueSendData(BlueManage().connectDeviceName, BlueManage().blueSendData(BlueManage().connectDeviceName, (BluetoothConnectionState deviceConnectionState) async {
(BluetoothConnectionState deviceConnectionState) async {
if (deviceConnectionState == BluetoothConnectionState.connected) { if (deviceConnectionState == BluetoothConnectionState.connected) {
// //
final List<String>? privateKey = final List<String>? privateKey = await Storage.getStringList(saveBluePrivateKey);
await Storage.getStringList(saveBluePrivateKey); final List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
final List<int> getPrivateKeyList =
changeStringListToIntList(privateKey!);
final List<String>? publicKey = final List<String>? publicKey = await Storage.getStringList(saveBluePublicKey);
await Storage.getStringList(saveBluePublicKey); final List<int> publicKeyDataList = changeStringListToIntList(publicKey!);
final List<int> publicKeyDataList =
changeStringListToIntList(publicKey!);
final List<String>? token = await Storage.getStringList(saveBlueToken); final List<String>? token = await Storage.getStringList(saveBlueToken);
List<int> getTokenList = <int>[0, 0, 0, 0]; List<int> getTokenList = <int>[0, 0, 0, 0];
@ -257,8 +247,7 @@ class SaveLockLogic extends BaseGetXController {
privateKey: getPrivateKeyList, privateKey: getPrivateKeyList,
token: getTokenList, token: getTokenList,
isBeforeAddUser: true); isBeforeAddUser: true);
} else if (deviceConnectionState == } else if (deviceConnectionState == BluetoothConnectionState.disconnected) {
BluetoothConnectionState.disconnected) {
dismissEasyLoading(); dismissEasyLoading();
cancelBlueConnetctToastTimer(); cancelBlueConnetctToastTimer();
state.sureBtnState.value = 0; state.sureBtnState.value = 0;
@ -376,16 +365,14 @@ class SaveLockLogic extends BaseGetXController {
// positionMap['address'] = state.addressInfo['address']; // positionMap['address'] = state.addressInfo['address'];
final Map<String, dynamic> bluetooth = <String, dynamic>{}; final Map<String, dynamic> bluetooth = <String, dynamic>{};
bluetooth['bluetoothDeviceId'] = BlueManage().connectDeviceMacAddress; bluetooth['bluetoothDeviceId'] = state.lockInfo['mac'];
bluetooth['bluetoothDeviceName'] = BlueManage().connectDeviceName; bluetooth['bluetoothDeviceName'] = BlueManage().connectDeviceName;
final List<String>? publicKey = final List<String>? publicKey = await Storage.getStringList(saveBluePublicKey);
await Storage.getStringList(saveBluePublicKey);
final List<int> publicKeyDataList = changeStringListToIntList(publicKey!); final List<int> publicKeyDataList = changeStringListToIntList(publicKey!);
bluetooth['publicKey'] = publicKeyDataList; bluetooth['publicKey'] = publicKeyDataList;
final List<String>? privateKey = final List<String>? privateKey = await Storage.getStringList(saveBluePrivateKey);
await Storage.getStringList(saveBluePrivateKey);
final List<int> getPrivateKeyList = changeStringListToIntList(privateKey!); final List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
bluetooth['privateKey'] = getPrivateKeyList; bluetooth['privateKey'] = getPrivateKeyList;
@ -410,8 +397,7 @@ class SaveLockLogic extends BaseGetXController {
final String getMobile = (await Storage.getMobile())!; final String getMobile = (await Storage.getMobile())!;
ApmHelper.instance.trackEvent('save_lock_result', { ApmHelper.instance.trackEvent('save_lock_result', {
'lock_name': BlueManage().connectDeviceName, 'lock_name': BlueManage().connectDeviceName,
'account': 'account': getMobile.isNotEmpty ? getMobile : (await Storage.getEmail())!,
getMobile.isNotEmpty ? getMobile : (await Storage.getEmail())!,
'date': DateTool().getNowDateWithType(1), 'date': DateTool().getNowDateWithType(1),
'save_lock_result': '成功', 'save_lock_result': '成功',
}); });
@ -427,8 +413,7 @@ class SaveLockLogic extends BaseGetXController {
final String getMobile = (await Storage.getMobile())!; final String getMobile = (await Storage.getMobile())!;
ApmHelper.instance.trackEvent('save_lock_result', { ApmHelper.instance.trackEvent('save_lock_result', {
'lock_name': BlueManage().connectDeviceName, 'lock_name': BlueManage().connectDeviceName,
'account': 'account': getMobile.isNotEmpty ? getMobile : (await Storage.getEmail())!,
getMobile.isNotEmpty ? getMobile : (await Storage.getEmail())!,
'date': DateTool().getNowDateWithType(1), 'date': DateTool().getNowDateWithType(1),
'save_lock_result': '${entity.errorCode}--${entity.errorMsg}', 'save_lock_result': '${entity.errorCode}--${entity.errorMsg}',
}); });
@ -489,26 +474,18 @@ class SaveLockLogic extends BaseGetXController {
// BlueManage().disconnect(); // BlueManage().disconnect();
// //
final LockSetInfoEntity entity = final LockSetInfoEntity entity = await ApiRepository.to.getLockSettingInfoData(
await ApiRepository.to.getLockSettingInfoData(
lockId: state.lockId.toString(), lockId: state.lockId.toString(),
); );
if (entity.errorCode!.codeIsSuccessful) { if (entity.errorCode!.codeIsSuccessful) {
state.lockSetInfoData.value = entity.data!; state.lockSetInfoData.value = entity.data!;
if (state.lockSetInfoData.value.lockFeature?.wifi == 1) { if (state.lockSetInfoData.value.lockFeature?.wifi == 1) {
// wifi锁WIFI // wifi锁WIFI
Get.toNamed(Routers.wifiListPage, arguments: { Get.toNamed(Routers.wifiListPage, arguments: {'lockSetInfoData': state.lockSetInfoData.value, 'pageName': 'saveLock'});
'lockSetInfoData': state.lockSetInfoData.value,
'pageName': 'saveLock'
});
} else if (state.lockSetInfoData.value.lockFeature?.languageSpeech == 1) { } else if (state.lockSetInfoData.value.lockFeature?.languageSpeech == 1) {
Get.toNamed(Routers.lockVoiceSettingPage, arguments: { Get.toNamed(Routers.lockVoiceSettingPage, arguments: {'lockSetInfoData': state.lockSetInfoData.value, 'pageName': 'saveLock'});
'lockSetInfoData': state.lockSetInfoData.value,
'pageName': 'saveLock'
});
} else { } else {
eventBus.fire(RefreshLockListInfoDataEvent( eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true, isUnShowLoading: true));
clearScanDevices: true, isUnShowLoading: true));
Future<void>.delayed(const Duration(seconds: 1), () { Future<void>.delayed(const Duration(seconds: 1), () {
// Get.close(state.isFromMap == 1 // Get.close(state.isFromMap == 1
// ? (CommonDataManage().seletLockType == 0 ? 4 : 5) // ? (CommonDataManage().seletLockType == 0 ? 4 : 5)
@ -518,15 +495,12 @@ class SaveLockLogic extends BaseGetXController {
// 2 // 2
Future<void>.delayed(const Duration(milliseconds: 200), () { Future<void>.delayed(const Duration(milliseconds: 200), () {
if (Get.isRegistered<LockDetailLogic>()) { if (Get.isRegistered<LockDetailLogic>()) {
Get.find<LockDetailLogic>() Get.find<LockDetailLogic>().functionBlocker.countdownProhibited(duration: const Duration(seconds: 2));
.functionBlocker
.countdownProhibited(duration: const Duration(seconds: 2));
} }
}); });
} }
} else { } else {
eventBus.fire(RefreshLockListInfoDataEvent( eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true, isUnShowLoading: true));
clearScanDevices: true, isUnShowLoading: true));
Future<void>.delayed(const Duration(seconds: 1), () { Future<void>.delayed(const Duration(seconds: 1), () {
// Get.close(state.isFromMap == 1 // Get.close(state.isFromMap == 1
// ? (CommonDataManage().seletLockType == 0 ? 4 : 5) // ? (CommonDataManage().seletLockType == 0 ? 4 : 5)
@ -536,9 +510,7 @@ class SaveLockLogic extends BaseGetXController {
// 2 // 2
Future<void>.delayed(const Duration(milliseconds: 200), () { Future<void>.delayed(const Duration(milliseconds: 200), () {
if (Get.isRegistered<LockDetailLogic>()) { if (Get.isRegistered<LockDetailLogic>()) {
Get.find<LockDetailLogic>() Get.find<LockDetailLogic>().functionBlocker.countdownProhibited(duration: const Duration(seconds: 2));
.functionBlocker
.countdownProhibited(duration: const Duration(seconds: 2));
} }
}); });
} }

View File

@ -22,8 +22,7 @@ class GatewayConfigurationWifiLogic extends BaseGetXController {
final GatewayConfigurationWifiState state = GatewayConfigurationWifiState(); final GatewayConfigurationWifiState state = GatewayConfigurationWifiState();
Future<void> gatewayDistributionNetwork() async { Future<void> gatewayDistributionNetwork() async {
final LoginEntity entity = await ApiRepository.to final LoginEntity entity = await ApiRepository.to.gatewayDistributionNetwork(
.gatewayDistributionNetwork(
gatewayName: state.gatewayNameTF.text, gatewayName: state.gatewayNameTF.text,
gatewayMac: state.gatewayModel.mac, gatewayMac: state.gatewayModel.mac,
serialNumber: state.gatewayModel.serialNum, serialNumber: state.gatewayModel.serialNum,
@ -42,8 +41,7 @@ class GatewayConfigurationWifiLogic extends BaseGetXController {
} }
Future<void> getGatewayConfiguration() async { Future<void> getGatewayConfiguration() async {
final GetGatewayConfigurationEntity entity = final GetGatewayConfigurationEntity entity = await ApiRepository.to.getGatewayConfiguration(timeout: 60);
await ApiRepository.to.getGatewayConfiguration(timeout: 60);
if (entity.errorCode!.codeIsSuccessful) { if (entity.errorCode!.codeIsSuccessful) {
String configStr = entity.data ?? ''; String configStr = entity.data ?? '';
@ -52,6 +50,7 @@ class GatewayConfigurationWifiLogic extends BaseGetXController {
try { try {
Map<String, dynamic> config = jsonDecode(configStr); Map<String, dynamic> config = jsonDecode(configStr);
config['timeZoneOffset'] = DateTime.now().timeZoneOffset.inSeconds; config['timeZoneOffset'] = DateTime.now().timeZoneOffset.inSeconds;
AppLog.log('state.config:$config');
state.getGatewayConfigurationStr = jsonEncode(config); state.getGatewayConfigurationStr = jsonEncode(config);
} catch (e) { } catch (e) {
AppLog.log('处理网关配置时区信息失败: $e'); AppLog.log('处理网关配置时区信息失败: $e');
@ -68,9 +67,9 @@ class GatewayConfigurationWifiLogic extends BaseGetXController {
// //
late StreamSubscription<Reply> _replySubscription; late StreamSubscription<Reply> _replySubscription;
void _initReplySubscription() { void _initReplySubscription() {
_replySubscription = _replySubscription = EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async {
EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async {
// WIFI配网 // WIFI配网
// if(reply is GatewayConfiguringWifiReply) { // if(reply is GatewayConfiguringWifiReply) {
// _replySenderConfiguringWifi(reply); // _replySenderConfiguringWifi(reply);
@ -112,8 +111,7 @@ class GatewayConfigurationWifiLogic extends BaseGetXController {
cancelBlueConnetctToastTimer(); cancelBlueConnetctToastTimer();
dismissEasyLoading(); dismissEasyLoading();
final int secretKeyJsonLength = (reply.data[3] << 8) + reply.data[4]; final int secretKeyJsonLength = (reply.data[3] << 8) + reply.data[4];
final List<int> secretKeyList = final List<int> secretKeyList = reply.data.sublist(5, 5 + secretKeyJsonLength);
reply.data.sublist(5, 5 + secretKeyJsonLength);
state.gatewayJson = utf8String(secretKeyList); state.gatewayJson = utf8String(secretKeyList);
gatewayDistributionNetwork(); gatewayDistributionNetwork();
@ -129,8 +127,7 @@ class GatewayConfigurationWifiLogic extends BaseGetXController {
// wifi // wifi
Future<void> senderConfiguringWifiAction() async { Future<void> senderConfiguringWifiAction() async {
AppLog.log( AppLog.log('state.getGatewayConfigurationStr:${state.getGatewayConfigurationStr}');
'state.getGatewayConfigurationStr:${state.getGatewayConfigurationStr}');
if (state.wifiNameTF.text.isEmpty) { if (state.wifiNameTF.text.isEmpty) {
showToast('请输入wifi名称'.tr); showToast('请输入wifi名称'.tr);
return; return;
@ -158,8 +155,7 @@ class GatewayConfigurationWifiLogic extends BaseGetXController {
dismissEasyLoading(); dismissEasyLoading();
state.sureBtnState.value = 0; state.sureBtnState.value = 0;
}); });
BlueManage().blueSendData(BlueManage().connectDeviceName, BlueManage().blueSendData(BlueManage().connectDeviceName, (BluetoothConnectionState connectionState) async {
(BluetoothConnectionState connectionState) async {
if (connectionState == BluetoothConnectionState.connected) { if (connectionState == BluetoothConnectionState.connected) {
IoSenderManage.gatewayConfiguringWifiCommand( IoSenderManage.gatewayConfiguringWifiCommand(
ssid: state.wifiNameTF.text, ssid: state.wifiNameTF.text,
@ -178,6 +174,7 @@ class GatewayConfigurationWifiLogic extends BaseGetXController {
} }
final NetworkInfo _networkInfo = NetworkInfo(); final NetworkInfo _networkInfo = NetworkInfo();
Future<String> getWifiName() async { Future<String> getWifiName() async {
String ssid = ''; String ssid = '';
ssid = (await _networkInfo.getWifiName())!; ssid = (await _networkInfo.getWifiName())!;

View File

@ -29,38 +29,6 @@ class _MessageListPageState extends State<MessageListPage>
final MessageListLogic logic = Get.put(MessageListLogic()); final MessageListLogic logic = Get.put(MessageListLogic());
final MessageListState state = Get.find<MessageListLogic>().state; final MessageListState state = Get.find<MessageListLogic>().state;
// _showCheckboxes
final RxBool _showCheckboxes = false.obs;
//
final RxList<bool> _selectedItems = <bool>[].obs;
//
bool showNotificationBanner = true;
//
final RxBool _pushNotificationEnabled = false.obs;
//
void deleteSelectedMessages() {
final List<MessageItemEntity> selectedMessages = [];
for (int i = 0; i < state.itemDataList.value.length; i++) {
if (_selectedItems[i]) {
selectedMessages.add(state.itemDataList.value[i]);
}
}
//
//logic.deletMessageDataRequest(selectedMessages);
//
_selectedItems.clear();
_selectedItems.addAll(
List.generate(state.itemDataList.value.length, (index) => false));
_showCheckboxes.value = false;
setState(() {});
}
void getHttpData() { void getHttpData() {
logic.messageListDataRequest().then((MessageListEntity value) { logic.messageListDataRequest().then((MessageListEntity value) {
setState(() {}); setState(() {});
@ -71,31 +39,9 @@ class _MessageListPageState extends State<MessageListPage>
void initState() { void initState() {
super.initState(); super.initState();
//
_loadPushNotificationStatus();
getHttpData(); getHttpData();
} }
//
void _loadPushNotificationStatus() async {
final bool? enabled = await Storage.getBool('push_notification_enabled');
_pushNotificationEnabled.value = enabled ?? false;
}
//
Map<String, List<MessageItemEntity>> _groupMessagesByDate() {
Map<String, List<MessageItemEntity>> grouped = {};
state.itemDataList.forEach((item) {
String date = DateTool().dateToYMDString(item.createdAt!.toString());
if (!grouped.containsKey(date)) {
grouped[date] = [];
}
grouped[date]!.add(item);
});
return grouped;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -134,228 +80,20 @@ class _MessageListPageState extends State<MessageListPage>
}, child: Obx(() { }, child: Obx(() {
return state.itemDataList.value.isEmpty return state.itemDataList.value.isEmpty
? NoData() ? NoData()
: Stack( : SlidableAutoCloseBehavior(
children: [
Positioned(
top: 0,
left: 0,
right: 0,
child: Container(
height: showNotificationBanner ? 100 : 70,
child: Column(children: [
showNotificationBanner
? Container(
padding:
EdgeInsets.only(left: 10, right: 10),
color: AppColors.messageTipsColor,
height: 30,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('开启消息通知开关,及时获取通知',
style: TextStyle(
color: Colors.black,
fontSize: 20.sp)),
Row(children: [
!_pushNotificationEnabled.value
? GestureDetector(child: Text('去开启',
style: TextStyle(
color: Colors.blue,
fontSize: 20.sp)),
onTap: (){
}) : SizedBox.shrink(),
SizedBox(width: 10),
InkWell(
child: Image.asset(
'images/mine/icon_message_close.png',
width: 24.w,
height: 24.w),
onTap: () {
//
setState(() {
showNotificationBanner =
false;
});
}),
])
]))
: SizedBox.shrink(),
Container(
padding:
EdgeInsets.only(left: 15.w, right: 24.w, top: 20.h),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('告警',
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 30.sp)),
//
// GestureDetector(
// onTap: () {
// // api接口使
// // if (_showCheckboxes.value) {
// // deleteSelectedMessages();
// // } else {
// // setState(() {
// // _showCheckboxes.value =
// // !_showCheckboxes.value;
// // });
// // }
// },
// child: _showCheckboxes.value
// ? Text('删除',
// style: TextStyle(
// fontSize: 24.sp,
// color: Colors.red))
// : Image.asset(
// 'images/mine/icon_message_checbox.png',
// width: 30.w,
// height: 30.h),
// )
]),
)
]))),
Container(
child: Container(
padding: EdgeInsets.only(
top: showNotificationBanner ? 80 : 50),
child: ListView.builder( child: ListView.builder(
itemCount: _buildGroupedListItems().length, itemCount: state.itemDataList.value.length,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext c, int index) {
var item = _buildGroupedListItems()[index]; final MessageItemEntity messageItemEntity =
state.itemDataList.value[index];
if (item is String) { return Slidable(
// key: ValueKey(messageItemEntity.id),
return Container(
padding: EdgeInsets.symmetric(
horizontal: 16.w, vertical: 10.h),
color: AppColors.mainBackgroundColor,
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: item.substring(8, 10),
style: TextStyle(
color: Colors.black,
fontSize: 36.sp,
fontWeight: FontWeight.w600,
),
),
TextSpan(
text: ' ',
),
TextSpan(
text: item.substring(5, 7),
style: TextStyle(
color: Colors.grey, fontSize: 20.sp, fontWeight: FontWeight.w400),
),
],
),
),
);
} else if (item is MessageItemEntity) {
//
return _messageListItem(item, () {
Get.toNamed(Routers.messageDetailPage,
arguments: <String, MessageItemEntity>{
'messageItemEntity': item
});
});
}
return Container();
},
),
),
)
],
);
})),
);
}
//
List<dynamic> _buildGroupedListItems() {
List<dynamic> items = [];
Map<String, List<MessageItemEntity>> grouped = _groupMessagesByDate();
grouped.forEach((date, messages) {
items.add(date); //
items.addAll(messages.map((message) => message)); //
});
//
if (_selectedItems.length != state.itemDataList.value.length) {
_selectedItems.clear();
_selectedItems.addAll(
List.generate(state.itemDataList.value.length, (index) => false));
}
return items;
}
Widget _messageListItem(
MessageItemEntity messageItemEntity, Function() action) {
final int index = state.itemDataList.value.indexOf(messageItemEntity);
//
Map<String, List<MessageItemEntity>> grouped = _groupMessagesByDate();
bool isLastInGroupSimple = false;
//
for (var entry in grouped.entries) {
int messageIndex = entry.value.indexWhere((msg) => msg.id == messageItemEntity.id);
if (messageIndex != -1) {
//
isLastInGroupSimple = messageIndex == entry.value.length - 1;
break;
}
}
return GestureDetector(
onTap: () {
//
if (_showCheckboxes.value) {
_selectedItems[index] = !_selectedItems[index];
setState(() {});
} else {
//
action();
}
},
child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
Container(
padding: EdgeInsets.only(left: 10),
transform: Matrix4.translationValues(0, 20, 0),
child: Column(
children: [
Image.asset(
messageItemEntity.readAt! == 0
? 'images/mine/icon_message_unread.png'
: 'images/mine/icon_message_readed.png',
width: 18.w,
height: 18.h),
// 线
if (!isLastInGroupSimple)
Container(
width: 0.5,
height: 190.h,
color: AppColors.placeholderTextColor,
)
],
)),
Expanded(
child: Slidable(
key: Key(messageItemEntity.id.toString()), // item添加唯一key
endActionPane: ActionPane( endActionPane: ActionPane(
extentRatio: 0.2,
motion: const ScrollMotion(), motion: const ScrollMotion(),
children: [ children: <Widget>[
SlidableAction( SlidableAction(
onPressed: (context) { onPressed: (BuildContext context) {
//
logic.deletMessageDataRequest( logic.deletMessageDataRequest(
messageItemEntity.id!, () { messageItemEntity.id!, () {
logic.pageNo = 1; logic.pageNo = 1;
@ -364,124 +102,94 @@ class _MessageListPageState extends State<MessageListPage>
}, },
backgroundColor: Colors.red, backgroundColor: Colors.red,
foregroundColor: Colors.white, foregroundColor: Colors.white,
icon: Icons.delete, label: '删除'.tr,
label: '删除', padding: EdgeInsets.only(left: 5.w, right: 5.w),
), ),
], ],
), child: Container( ),
child: _messageListItem(messageItemEntity, () {
Get.toNamed(Routers.messageDetailPage,
arguments: <String, MessageItemEntity>{
'messageItemEntity': messageItemEntity
});
}),
);
}),
);
})),
);
}
Widget _messageListItem(
MessageItemEntity messageItemEntity, Function() action) {
return GestureDetector(
onTap: action,
child: Container(
height: 90.h,
width: 1.sw, width: 1.sw,
margin: EdgeInsets.all(20.h), margin: EdgeInsets.only(bottom: 2.h),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(10.w), borderRadius: BorderRadius.circular(10.w),
), ),
child: Container( child: Container(
width: 1.sw, width: 1.sw,
margin: EdgeInsets.only(left: 20.w, right: 20.w, top: 8.h), margin: EdgeInsets.only(left: 20.w, right: 20.w),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
// SizedBox(height: 4.h), Row(
// Row(
// children: <Widget>[
// Flexible(
// child: Text(
// //
// '远程开门请求',
// maxLines: 1,
// overflow: TextOverflow.ellipsis,
// style: TextStyle(
// fontSize: 22.sp,
// color: messageItemEntity.readAt! == 0
// ? AppColors.blackColor
// : AppColors.placeholderTextColor),
// ),
// ),
// ],
// ),
// SizedBox(height: 4.h),
Wrap(
children: <Widget>[ children: <Widget>[
// if (messageItemEntity.readAt! == 0) if (messageItemEntity.readAt! == 0)
// Container(
// width: 10.w,
// height: 10.w,
// decoration: BoxDecoration(
// color: Colors.red,
// borderRadius: BorderRadius.circular(5.w),
// ),
// )
// else
// Container(),
// if (messageItemEntity.readAt! == 0)
// SizedBox(width: 5.w)
// else
// Container(),
Container( Container(
margin: EdgeInsets.only(top: 4.h), width: 10.w,
height: 10.w,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(5.w),
),
)
else
Container(),
if (messageItemEntity.readAt! == 0)
SizedBox(width: 5.w)
else
Container(),
Flexible(
child: Text( child: Text(
DateTool().dateToHnString(messageItemEntity.createdAt!.toString()), messageItemEntity.data!,
style: TextStyle( maxLines: 1,
fontSize: 20.sp,
color: messageItemEntity.readAt! == 0
? AppColors.blackColor
: AppColors.placeholderTextColor,
),
),
),
Container(
width: 1,
height: 10,
margin: EdgeInsets.only(left: 5.w, right: 5.w, top: 10.h),
color: messageItemEntity.readAt! == 0
? AppColors.blackColor
: AppColors.placeholderTextColor,
),
Container(transform: Matrix4.translationValues(0, -18, 0),
child: Text(' ${messageItemEntity.data!}',
maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
fontSize: 20.sp, fontSize: 22.sp,
color: messageItemEntity.readAt! == 0 color: messageItemEntity.readAt! == 0
? AppColors.blackColor ? AppColors.blackColor
: AppColors.placeholderTextColor, : AppColors.placeholderTextColor),
),
), ),
)),
Container(transform: Matrix4.translationValues(0, -8, 0), child: GestureDetector(
child: Text('点击查看', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20.sp, color: AppColors.mainColor),),
),alignment: Alignment.centerRight,)
], ],
), ),
// SizedBox(height: 5.h), SizedBox(height: 10.h),
// Row( Row(
// mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
// children: <Widget>[ children: <Widget>[
// // Image.asset('images/mine/icon_mine_gatewaySignal_strong.png', width: 40.w, height: 40.w,), // Image.asset('images/mine/icon_mine_gatewaySignal_strong.png', width: 40.w, height: 40.w,),
// // SizedBox(width: 10.w,), // SizedBox(width: 10.w,),
// Text( Text(
// DateTool().dateToHnString(messageItemEntity DateTool().dateToYMDHNString(
// .createdAt! messageItemEntity.createdAt!.toString()),
// .toString()), style: TextStyle(
// style: TextStyle( fontSize: 18.sp,
// fontSize: 18.sp, color: messageItemEntity.readAt! == 0
// color: messageItemEntity.readAt! == 0 ? AppColors.blackColor
// ? AppColors.blackColor : AppColors.placeholderTextColor)),
// : AppColors.placeholderTextColor)), ],
// ], ),
// ), SizedBox(width: 20.h),
// SizedBox(width: 20.h), ],
]))))), ),
// ),
if (_showCheckboxes.value) ),
Checkbox( );
value: _selectedItems[index],
activeColor: Colors.blue,
onChanged: (val) {
_selectedItems[index] = val!;
setState(() {});
},
)
]));
} }
} }

View File

@ -1,34 +1,22 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart'; import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart';
import 'package:star_lock/flavors.dart'; import 'package:star_lock/flavors.dart';
import 'package:star_lock/mine/mine/starLockMine_state.dart'; import 'package:star_lock/mine/mine/starLockMine_state.dart';
import 'package:star_lock/tools/storage.dart';
import 'package:star_lock/tools/wechat/customer_tool.dart'; import 'package:star_lock/tools/wechat/customer_tool.dart';
import '../../appRouters.dart'; import '../../appRouters.dart';
import '../../app_settings/app_colors.dart'; import '../../app_settings/app_colors.dart';
import '../../baseWidget.dart'; import '../../baseWidget.dart';
import '../../tools/commonItem.dart';
import '../../tools/customNetworkImage.dart'; import '../../tools/customNetworkImage.dart';
import '../../tools/showTipView.dart';
import '../../tools/submitBtn.dart'; import '../../tools/submitBtn.dart';
import '../../tools/wechat/wechatManageTool.dart'; import '../../tools/wechat/wechatManageTool.dart';
import '../../tools/wechat/wx_push_miniProgram/wx_push_miniProgram.dart'; import '../../tools/wechat/wx_push_miniProgram/wx_push_miniProgram.dart';
import '../../translations/app_dept.dart';
import '../../translations/current_locale_tool.dart';
import '../mineSet/mineSet/mineSet_logic.dart';
import '../mineSet/mineSet/mineSet_state.dart';
import 'starLockMine_logic.dart'; import 'starLockMine_logic.dart';
class StarLockMinePage extends StatefulWidget { class StarLockMinePage extends StatefulWidget {
const StarLockMinePage({Key? key, this.showAppBar = true, this.showAbout = true}) : super(key: key); const StarLockMinePage({Key? key}) : super(key: key);
final bool showAppBar;
final bool showAbout;
@override @override
State<StarLockMinePage> createState() => StarLockMinePageState(); State<StarLockMinePage> createState() => StarLockMinePageState();
@ -39,127 +27,103 @@ GlobalKey<StarLockMinePageState> starLockMineKey = GlobalKey();
class StarLockMinePageState extends State<StarLockMinePage> with BaseWidget { class StarLockMinePageState extends State<StarLockMinePage> with BaseWidget {
final StarLockMineLogic logic = Get.put(StarLockMineLogic()); final StarLockMineLogic logic = Get.put(StarLockMineLogic());
final StarLockMineState state = Get.find<StarLockMineLogic>().state; final StarLockMineState state = Get.find<StarLockMineLogic>().state;
late final MineSetState stateSet;
late final MineSetLogic logicSet;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// MineSetLogic
if (!Get.isRegistered<MineSetLogic>()) {
Get.put(MineSetLogic());
}
logicSet = Get.find<MineSetLogic>();
stateSet = logicSet.state;
logicSet.userSettingsInfoRequest();
logic.getUserInfoRequest(); logic.getUserInfoRequest();
//
_checkNotificationPermission();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: SafeArea( backgroundColor: const Color(0xFFFFFFFF),
child: SingleChildScrollView(child: Container( body: Column(
margin: EdgeInsets.only(bottom: 20.h),
padding: EdgeInsets.symmetric(horizontal: 20.w),
child: Column(
children: <Widget>[ children: <Widget>[
SizedBox(
height: 20.h,
),
topWidget(), topWidget(),
SizedBox(
height: 20.h,
),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10.r),
),
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 15.h),
child: GestureDetector(
onTap: () {
Get.back();
Get.toNamed(Routers.minePersonInfoPage);
},
child: Row(
children: <Widget>[
Icon(
Icons.person,
size: 32.sp,
),
SizedBox(width: 15.w),
Text(
'个人信息'.tr,
style: TextStyle(fontSize: 28.sp),
),
const Spacer(),
Icon(
Icons.arrow_forward_ios_rounded,
color: Colors.grey[400],
)
],
),
),
),
SizedBox(
height: 20.h,
),
bottomListWidget(), bottomListWidget(),
SizedBox( SizedBox(
height: 20.h, height: 80.h,
), ),
Container( GestureDetector(
width: double.infinity, onTap: () {
decoration: BoxDecoration( WechatManageTool.getAppInfo(() {
color: Colors.white, WxPushWeChatMiniProgramTool.pushWeChatMiniProgram(
borderRadius: BorderRadius.circular(10.r), F.wechatAppInfo.wechatAppId, F.wechatAppInfo.universalLink);
});
},
child: Padding(
padding: EdgeInsets.only(left: 20.w, right: 20.w),
child: Image.asset(
'images/mine/icon_mine_wan_miniprogram.png',
// width: 400.w,
// height: 151.h,
fit: BoxFit.fill,
), ),
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 15.h), ),
child: getListDataView(), ),
)]))))); ],
),
);
} }
Widget topWidget() { Widget topWidget() {
return Row( return Container(
height: 380.h,
width: 1.sw,
color: AppColors.mainColor,
// color: Colors.red,
child: Stack(
children: <Widget>[ children: <Widget>[
Image.asset(
'images/mine/icon_mine_topBg.png',
width: 400.w,
height: 380.h,
fit: BoxFit.fill,
),
Center(
child: Column(
children: <Widget>[
SizedBox(
height: 120.h,
),
GestureDetector( GestureDetector(
onTap: () { onTap: () {
Get.back(); Get.back();
Get.toNamed(Routers.minePersonInfoPage); Get.toNamed(Routers.minePersonInfoPage);
}, },
child: Obx( child: Obx(() => SizedBox(
() => SizedBox( width: 105.w,
width: 68.w, height: 105.w,
height: 68.w,
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(52.5.w), borderRadius: BorderRadius.circular(52.5.w),
child: CustomNetworkImage( child: CustomNetworkImage(
url: state.userHeadUrl.value, url: state.userHeadUrl.value,
defaultUrl: 'images/controls_user.png', defaultUrl: 'images/controls_user.png',
width: 68.w, width: 105.w,
height: 68.h, height: 105.h,
), ),
), ),
)),
), ),
SizedBox(
height: 20.h,
), ),
), Obx(() => GestureDetector(
SizedBox(width: 20.w),
Obx(
() => GestureDetector(
onTap: () { onTap: () {
if (!state.isVip.value) { if (!state.isVip.value) {
Get.toNamed(Routers.advancedFeaturesWebPage, arguments: <String, int>{ // if (CommonDataManage().currentKeyInfo.isLockOwner !=
// 1) {
// logic.showToast('请先添加锁');
// } else {
Get.toNamed(Routers.advancedFeaturesWebPage,
arguments: <String, int>{
'webBuyType': XSConstantMacro.webBuyTypeVip, 'webBuyType': XSConstantMacro.webBuyTypeVip,
}); });
// } // }
} else { } else {
Get.toNamed(Routers.valueAddedServicesHighFunctionPage); Get.toNamed(
Routers.valueAddedServicesHighFunctionPage);
} }
}, },
child: Container( child: Container(
@ -170,12 +134,13 @@ class StarLockMinePageState extends State<StarLockMinePage> with BaseWidget {
Text( Text(
state.userNickName.value.isNotEmpty state.userNickName.value.isNotEmpty
? state.userNickName.value ? state.userNickName.value
: (state.userMobile.value.isNotEmpty ? state.userMobile.value : state.userEmail.value), : (state.userMobile.value.isNotEmpty
? state.userMobile.value
: state.userEmail.value),
style: TextStyle( style: TextStyle(
fontSize: 22.sp, fontSize: 22.sp,
color: Colors.black, color: Colors.white,
), )),
),
SizedBox( SizedBox(
width: 5.w, width: 5.w,
), ),
@ -194,82 +159,67 @@ class StarLockMinePageState extends State<StarLockMinePage> with BaseWidget {
], ],
), ),
), ),
), ))
),
// const Spacer(),
// Container(
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(10.r),
// ),
// padding: EdgeInsets.symmetric(horizontal: 15.w, vertical: 10.h),
// child: Row(
// children: [
// if (F.isSKY && Get.locale!.languageCode == 'zh')
// GestureDetector(
// onTap: () {
// Get.back();
// WechatManageTool.getAppInfo(CustomerTool.openCustomerService);
// },
// child: Image.asset(
// 'images/mine/icon_mine_main_supportStaff.png',
// width: 34.w,
// height: 34.w,
// ),
// ),
// SizedBox(
// width: 20.w,
// ),
// GestureDetector(
// onTap: () {
// Get.back();
// Get.toNamed(Routers.messageListPage);
// },
// child: Image.asset(
// 'images/mine/icon_mine_main_message.png',
// width: 36.w,
// height: 36.w,
// ),
// ),
// ],
// ),
// )
], ],
),
),
],
),
); );
} }
Widget bottomListWidget() { Widget bottomListWidget() {
return Container( return Container(
width: double.infinity, padding: EdgeInsets.only(
decoration: BoxDecoration( left: 60.w,
color: Colors.white, top: 50.h,
borderRadius: BorderRadius.circular(10.w),
), ),
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 20.w),
child: Column( child: Column(
children: [ children: [
// mineItem('images/mine/icon_mine_main_set.png', '设置'.tr, () { mineItem('images/mine/icon_mine_main_addLock.png', '添加设备'.tr, () {
// Get.back(); Get.back();
// Get.toNamed(Routers.mineSetPage); Get.toNamed(Routers.selectLockTypePage);
// }), }),
// SizedBox(height: 20.h), // mineItem('images/mine/icon_mine_main_gateway.png',
mineItem('images/mine/icon_mine_main_vip.png', '增值服务'.tr, () async { // TranslationLoader.lanKeys!.gateway!.tr, () {
final bool? isVip = await Storage.getBool(saveIsVip); // Navigator.pushNamed(context, Routers.gatewayListPage);
if (isVip == null || !isVip) { // }),
// vip状态是和账号绑定LockOwner没意义 mineItem('images/mine/icon_mine_main_message.png', '消息'.tr, () {
// if (CommonDataManage().currentKeyInfo.isLockOwner != 1) { Get.back();
// logic.showToast('请先添加锁'.tr); Get.toNamed(Routers.messageListPage);
// } else { // Toast.show(msg: "功能暂未开放");
// }),
Get.toNamed(Routers.advancedFeaturesWebPage, arguments: <String, int>{ //
'webBuyType': XSConstantMacro.webBuyTypeVip, // mineItem('images/mine/icon_mine_main_supportStaff.png',
})?.then((value) => logic.getUserInfoRequest()); // TranslationLoader.lanKeys!.supportStaff!.tr, () {
// } // Navigator.pushNamed(context, Routers.supportStaffPage);
} else { // }),
Get.toNamed(Routers.valueAddedServicesHighFunctionPage); mineItem('images/mine/icon_mine_main_set.png', '设置'.tr, () {
} Get.back();
Get.toNamed(Routers.mineSetPage);
}),
//
// if (F.isLite)
// Container()
// else
mineItem('images/mine/icon_mine_main_vip.png', '增值服务'.tr, () {
Get.back();
Get.toNamed(Routers.valueAddedServicesPage);
}),
// if (F.isLite)
// Container()
// else
mineItem('images/mine/icon_mine_main_shoppingcart.png', '配件商城'.tr,
() {
Get.back();
Get.toNamed(Routers.lockMallPage);
}),
if (F.isSKY && Get.locale!.languageCode == 'zh')
mineItem('images/mine/icon_mine_main_supportStaff.png', '客服'.tr,
() {
Get.back();
WechatManageTool.getAppInfo(CustomerTool.openCustomerService);
}), }),
SizedBox(height: 20.h),
mineItem('images/mine/icon_mine_main_about.png', '关于'.tr, () { mineItem('images/mine/icon_mine_main_about.png', '关于'.tr, () {
Get.back(); Get.back();
Get.toNamed(Routers.aboutPage); Get.toNamed(Routers.aboutPage);
@ -279,9 +229,52 @@ class StarLockMinePageState extends State<StarLockMinePage> with BaseWidget {
); );
} }
Widget mineItem(String lockTypeIcon, String lockTypeTitle, Function() action) { // Widget keyBottomWidget() {
// return Column(
// children: <Widget>[
// SubmitBtn(
// btnName: '退出'.tr,
// borderRadius: 20.w,
// fontSize: 32.sp,
// margin: EdgeInsets.only(left: 60.w, right: 60.w),
// padding: EdgeInsets.only(top: 15.w, bottom: 15.w),
// onClick: () {}),
// Container(
// padding: EdgeInsets.only(right: 30.w),
// // color: Colors.red,
// child: Row(
// mainAxisAlignment: MainAxisAlignment.end,
// children: <Widget>[
// TextButton(
// child: Text(
// '删除账号'.tr,
// style: TextStyle(
// color: AppColors.mainColor, fontWeight: FontWeight.w500),
// ),
// onPressed: () {},
// ),
// ],
// ),
// ),
// SizedBox(
// height: 30.h,
// )
// ],
// );
// }
Widget mineItem(
String lockTypeIcon, String lockTypeTitle, Function() action) {
return GestureDetector( return GestureDetector(
onTap: action, onTap: action,
child: Row(
children: <Widget>[
Center(
child: Container(
// height: 80.h,
width: 330.w,
padding: EdgeInsets.all(20.h),
color: Colors.white,
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
Image.asset( Image.asset(
@ -292,422 +285,15 @@ class StarLockMinePageState extends State<StarLockMinePage> with BaseWidget {
SizedBox(width: 15.w), SizedBox(width: 15.w),
Text( Text(
lockTypeTitle, lockTypeTitle,
style: TextStyle(fontSize: 28.sp), style: TextStyle(fontSize: 22.sp),
), ),
const Spacer(),
Icon(
Icons.arrow_forward_ios_rounded,
color: Colors.grey[400],
)
],
),
);
}
Widget getListDataView() {
//
return Column(
children: <Widget>[
/* 2024-01-12 by DaisyWu
CommonItem(
leftTitel: TranslationLoader.lanKeys!.prompTone!.tr,
rightTitle: "",
isHaveLine: true,
isHaveRightWidget: true,
rightWidget: SizedBox(
width: 60.w,
height: 50.h,
child: Obx(() => _isPrompToneSwitch()))),
CommonItem(
leftTitel: TranslationLoader.lanKeys!.touchUnlock!.tr,
rightTitle: "",
isHaveLine: true,
isHaveRightWidget: true,
rightWidget: SizedBox(
width: 60.w,
height: 50.h,
child: Obx(() => _isTouchUnlockSwitch()))),
*/
F.sw(
skyCall: () => const SizedBox(),
xhjCall: () => CommonItem(
leftTitel: '个人信息'.tr,
rightTitle: '',
isHaveLine: true,
isHaveDirection: true,
action: () {
Get.toNamed(Routers.minePersonInfoPage);
})),
CommonItem(
leftTitel: '消息推送'.tr,
rightTitle: '',
isHaveRightWidget: true,
isHaveLine: F.sw(
skyCall: () => F.appFlavor == Flavor.sky, xhjCall: () => true),
rightWidget: SizedBox(
width: 60.w,
height: 50.h,
child: Obx(_isPushNotificationSwitch)
)),
// if (F.appFlavor == Flavor.sky)
Visibility(
visible: stateSet.currentLanguageCode == 'zh_CN',
child: CommonItem(
leftTitel: '微信公众号推送'.tr,
rightTitle: '',
isHaveLine: true,
isHaveRightWidget: true,
rightWidget: SizedBox(
width: 60.w,
height: 50.h,
child: Obx(_isWechatPublicAccountPushSwitch),
),
),
),
SizedBox(height: 10.h),
CommonItem(
leftTitel: '锁用户管理'.tr,
rightTitle: '',
isHaveLine: true,
isHaveDirection: true,
action: () {
Get.toNamed(Routers.lockUserManageLisPage);
}),
CommonItem(
leftTitel: '授权管理员'.tr,
rightTitle: '',
isHaveLine: true,
isHaveDirection: true,
action: () {
Get.toNamed(Routers.authorizedAdministratorListPage);
}),
//by DaisyWu --
if (!F.isProductionEnv)
CommonItem(
leftTitel: '批量授权'.tr,
rightTitle: '',
isHaveLine: true,
isHaveDirection: true,
action: () {
Get.toNamed(Routers.authorityManagementPage);
// Toast.show(msg: "功能暂未开放");
}),
CommonItem(
leftTitel: '网关'.tr,
rightTitle: '',
isHaveLine: true,
isHaveDirection: true,
action: () {
Get.toNamed(Routers.gatewayListPage);
}),
CommonItem(
leftTitel: '锁分组'.tr,
rightTitle: '',
isHaveLine: true,
isHaveDirection: true,
action: () {
Get.toNamed(Routers.lockGroupListPage);
}),
CommonItem(
leftTitel: '转移智能锁'.tr,
rightTitle: '',
isHaveLine: true,
isHaveDirection: true,
action: () {
Get.toNamed(Routers.transferSmartLockPage);
}),
//
// CommonItem(
// leftTitel: '转移网关'.tr,
// rightTitle: '',
// isHaveLine: true,
// isHaveDirection: true,
// action: () {
// Get.toNamed(Routers.selectGetewayListPage);
// }),
SizedBox(
height: 10.h,
),
// AppLog.log('state.currentLanguageName: ${state.currentLanguageName} state.currentLanguage.value: ${state.currentLanguage.value}');
CommonItem(
leftTitel: '多语言'.tr,
rightTitle: stateSet.currentLanguageName,
isHaveLine: true,
isHaveDirection: true,
action: () async {
// Get.toNamed(Routers.mineMultiLanguagePage);
await Get.toNamed(Routers.mineMultiLanguagePage)!.then((value) {
setState(() {
if (value.containsKey('currentLanguage')) {
stateSet.currentLanguage.value = value['currentLanguage'];
}
});
});
}),
/* 2024-01-12 by DaisyWu
Obx(() => CommonItem(
leftTitel: TranslationLoader.lanKeys!.lockScreen!.tr,
rightTitle: (state.lockScreen.value == 1
? TranslationLoader.lanKeys!.opened!.tr
: TranslationLoader.lanKeys!.closed!.tr),
isHaveLine: true,
isHaveDirection: true,
action: () {
Navigator.pushNamed(context, Routers.lockScreenPage,
arguments: {'isOn': state.lockScreen.value}).then((value) {
logic.userSettingsInfoRequest();
});
})),
*/
Obx(() => CommonItem(
leftTitel: '隐藏无效开锁权限'.tr,
rightTitle:
(stateSet.hideExpiredAccessFlag.value == 1 ? '已开启'.tr : '已关闭'.tr),
isHaveLine: true,
isHaveDirection: true,
action: () {
Navigator.pushNamed(
context, Routers.hideInvalidUnlockPermissionsPage,
arguments: <String, int>{
'isOn': stateSet.hideExpiredAccessFlag.value
}).then((Object? value) {
logicSet.userSettingsInfoRequest();
});
})),
otherItem(
leftTitle: 'APP开锁时需手机连网的锁'.tr,
isHaveLine: true,
action: () {
Navigator.pushNamed(
context, Routers.aPPUnlockNeedMobileNetworkingLockPage);
}),
if (!F.isSKY)
CommonItem(
leftTitel: '增值服务'.tr,
isHaveLine: true,
isHaveDirection: true,
action: () {
Get.back();
Get.toNamed(Routers.valueAddedServicesPage);
},
),
SizedBox(
height: 10.h,
),
CommonItem(
leftTitel: 'Amazon Alexa'.tr,
rightTitle: '',
isHaveLine: true,
isHaveDirection: true,
action: () {
Get.toNamed(Routers.amazonAlexaPage, arguments: <String, dynamic>{
'isAmazonAlexa': stateSet.isAmazonAlexa.value,
'amazonAlexaData': stateSet.amazonAlexaData.value
});
}),
CommonItem(
leftTitel: 'Google Home'.tr,
rightTitle: '',
isHaveLine: true,
isHaveDirection: true,
action: () {
Get.toNamed(Routers.googleHomePage, arguments: <String, dynamic>{
'isGoogleHome': stateSet.isGoogleHome.value,
'googleHomeData': stateSet.googleHomeData.value
})?.then((Object? value) {
logicSet.userSettingsInfoRequest();
});
}),
// if (!F.isProductionEnv)
// CommonItem(
// leftTitel: '小米IOT平台'.tr,
// rightTitle: '',
// isHaveLine: widget.showAbout,
// isHaveDirection: true,
// action: () {
// logic.showToast('功能暂未开放'.tr);
// }),
if (!F.isSKY)
CommonItem(
leftTitel: '客服'.tr,
isHaveLine: widget.showAbout,
isHaveDirection: true,
action: () {
WechatManageTool.getAppInfo(CustomerTool.openCustomerService);
},
),
if (widget.showAbout)
CommonItem(
leftTitel: '关于'.tr,
isHaveLine: false,
isHaveDirection: true,
action: () {
Get.back();
Get.toNamed(Routers.aboutPage);
},
),
// CommonItem(leftTitel:TranslationLoader.lanKeys!.valueAddedServices!.tr, rightTitle:"", isHaveDirection: true, action: (){
//
// }),
SizedBox(
height: F.sw(skyCall: () => 50.h, xhjCall: () => 0.0),
),
// CommonItem(leftTitel:TranslationLoader.lanKeys!.about!.tr, rightTitle:"", isHaveLine: true, isHaveDirection: true, action: (){
//
// }),
// SizedBox(height: 10.h,),
// CommonItem(leftTitel:TranslationLoader.lanKeys!.userAgreement!.tr, rightTitle:"", isHaveLine: true, isHaveDirection: true, action: (){
//
// }),
// CommonItem(leftTitel:TranslationLoader.lanKeys!.privacyPolicy!.tr, rightTitle:"", isHaveLine: true, isHaveDirection: true, action: (){
//
// }),
// CommonItem(leftTitel:TranslationLoader.lanKeys!.personalInformationCollectionList!.tr, rightTitle:"", isHaveLine: true, isHaveDirection: true, action: (){
//
// }),
// CommonItem(leftTitel:TranslationLoader.lanKeys!.applicationPermissionDescription!.tr, rightTitle:"", isHaveLine: true, isHaveDirection: true, action: (){
//
// }),
// CommonItem(leftTitel:TranslationLoader.lanKeys!.thirdPartyInformationSharingList!.tr, rightTitle:"", isHaveLine: true, isHaveDirection: true, action: (){
//
// }),
F.sw(skyCall: keyBottomWidget, xhjCall: () => const SizedBox())
],
);
}
//
CupertinoSwitch _isWechatPublicAccountPushSwitch() {
return CupertinoSwitch(
activeColor: CupertinoColors.activeBlue,
trackColor: CupertinoColors.systemGrey5,
thumbColor: CupertinoColors.white,
value: stateSet.isWechatPublicAccountPush.value,
onChanged: (bool value) {
stateSet.isWechatPublicAccountPush.value =
!stateSet.isWechatPublicAccountPush.value;
logicSet.setMpWechatPushSwitchRequest(context);
},
);
}
CupertinoSwitch _isPushNotificationSwitch() {
return CupertinoSwitch(
activeColor: CupertinoColors.activeBlue,
trackColor: CupertinoColors.systemGrey5,
thumbColor: CupertinoColors.white,
value: stateSet.isPushNotification.value,
onChanged: (bool value) async {
// stateSet.isPushNotification.value = !stateSet.isPushNotification.value;
openAppSettings();
final PermissionStatus newStatus = await Permission.notification.status;
stateSet.isPushNotification.value = newStatus.isGranted;
},
);
}
Future<void> _checkNotificationPermission() async {
final PermissionStatus status = await Permission.notification.status;
stateSet.isPushNotification.value = status.isGranted;
}
Widget otherItem(
{String? leftTitle,
bool? isHaveLine,
Function()? action,
double? allHeight}) {
return GestureDetector(
onTap: action,
child: Container(
width: 1.sw,
padding:
EdgeInsets.only(left: 20.w, top: 15.h, bottom: 15.h, right: 10.w),
decoration: BoxDecoration(
color: Colors.white,
border: isHaveLine!
? Border(
bottom: BorderSide(
color: AppColors.greyLineColor, //
width: 2.0.h, //
),
)
: null,
),
child: Row(
children: <Widget>[
Expanded(
child: Text(leftTitle!, style: TextStyle(fontSize: 22.sp))),
SizedBox(width: 10.w),
if (CurrentLocaleTool.getCurrentLocaleString() ==
ExtensionLanguageType.fromLanguageType(LanguageType.hebrew)
.toString() ||
CurrentLocaleTool.getCurrentLocaleString() ==
ExtensionLanguageType.fromLanguageType(LanguageType.arabic)
.toString())
Image.asset(
'images/icon_left_grey.png',
width: 21.w,
height: 21.w,
)
else
Image.asset(
'images/icon_right_grey.png',
width: 12.w,
height: 21.w,
),
SizedBox(width: 5.w),
], ],
), ),
), ),
); ),
}
Widget keyBottomWidget() {
return Padding(
padding: F.sw(
skyCall: () => EdgeInsets.zero,
xhjCall: () => EdgeInsets.symmetric(horizontal: 15.w)),
child: Column(
children: <Widget>[
SubmitBtn(
btnName: '退出'.tr,
isDelete: true,
padding: EdgeInsets.symmetric(horizontal: 15.w),
onClick: () {
//退
ShowTipView().showIosTipWithContentDialog(
'确定要退出吗?'.tr, () async {
await logicSet.userLogoutRequest();
// showLoginOutAlertTipDialog();
});
}),
Container( Container(
padding: EdgeInsets.only(left: 30.w, top: 30.h), height: 0.5.h,
// color: Colors.red, color: Colors.grey,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
TextButton(
child: Text(
'删除账号'.tr,
style: TextStyle(
color: AppColors.darkGrayTextColor, fontSize: 18.sp),
),
onPressed: () {
ShowTipView().showIosTipWithContentDialog(
'删除账号后,你的所有信息及相关记录都会从平台彻底删除,且不可恢复,是否删除?'.tr, () {
//
Get.toNamed(Routers.safeVerifyPage);
});
},
),
],
),
),
SizedBox(
height: 30.h,
) )
], ],
), ),

View File

@ -14,8 +14,7 @@ import 'package:star_lock/talk/starChart/proto/talk_data_h264_frame.pb.dart';
// class UdpTalkDataHandler extends ScpMessageBaseHandle // class UdpTalkDataHandler extends ScpMessageBaseHandle
// implements ScpMessageHandler { // implements ScpMessageHandler {
class UdpTalkDataHandler extends ScpMessageBaseHandle class UdpTalkDataHandler extends ScpMessageBaseHandle implements ScpMessageHandler {
implements ScpMessageHandler {
// //
static final UdpTalkDataHandler instance = UdpTalkDataHandler(); static final UdpTalkDataHandler instance = UdpTalkDataHandler();
@ -73,10 +72,7 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle
// _asyncLog( // _asyncLog(
// '分包数据:messageId:$messageId [$spIndex/$spTotal] PayloadLength:$PayloadLength'); // '分包数据:messageId:$messageId [$spIndex/$spTotal] PayloadLength:$PayloadLength');
if (messageType == MessageTypeConstant.RealTimeData) { if (messageType == MessageTypeConstant.RealTimeData) {
if (spTotal != null && if (spTotal != null && spTotal > 1 && messageId != null && spIndex != null) {
spTotal > 1 &&
messageId != null &&
spIndex != null) {
// //
return handleFragmentedPayload( return handleFragmentedPayload(
messageId: messageId, messageId: messageId,
@ -129,13 +125,11 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle
talkDataH264Frame.mergeFromBuffer(talkData.content); talkDataH264Frame.mergeFromBuffer(talkData.content);
// AppLog.log('处理H264帧: frameType=${talkDataH264Frame.frameType}, frameSeq=${talkDataH264Frame.frameSeq},MessageId:${scpMessage.MessageId}'); // AppLog.log('处理H264帧: frameType=${talkDataH264Frame.frameType}, frameSeq=${talkDataH264Frame.frameSeq},MessageId:${scpMessage.MessageId}');
frameHandler.handleFrame(talkDataH264Frame, talkData, scpMessage); frameHandler.handleFrame(talkDataH264Frame, talkData, scpMessage);
} }
/// ///
void _handleVideoImage(TalkData talkData) async { void _handleVideoImage(TalkData talkData) async {
final List<Uint8List> processCompletePayload = final List<Uint8List> processCompletePayload = await _processCompletePayload(Uint8List.fromList(talkData.content));
await _processCompletePayload(Uint8List.fromList(talkData.content));
processCompletePayload.forEach((element) { processCompletePayload.forEach((element) {
talkData.content = element; talkData.content = element;
talkDataRepository.addTalkData( talkDataRepository.addTalkData(
@ -177,8 +171,7 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle
startIdx = i; startIdx = i;
i++; // Skip the next byte i++; // Skip the next byte
} else if (nextByte == 0xD9 && startIdx != -1) { } else if (nextByte == 0xD9 && startIdx != -1) {
frames frames.add(Uint8List.view(payload.buffer, startIdx, i + 2 - startIdx));
.add(Uint8List.view(payload.buffer, startIdx, i + 2 - startIdx));
startIdx = -1; startIdx = -1;
i++; // Skip the next byte i++; // Skip the next byte
} }

View File

@ -18,20 +18,18 @@ import 'package:star_lock/tools/push/xs_jPhush.dart';
import 'package:star_lock/tools/storage.dart'; import 'package:star_lock/tools/storage.dart';
import 'package:star_lock/translations/current_locale_tool.dart'; import 'package:star_lock/translations/current_locale_tool.dart';
class UdpTalkRequestHandler extends ScpMessageBaseHandle class UdpTalkRequestHandler extends ScpMessageBaseHandle implements ScpMessageHandler {
implements ScpMessageHandler { RxString currentLanguage = CurrentLocaleTool.getCurrentLocaleString().obs; //
RxString currentLanguage =
CurrentLocaleTool.getCurrentLocaleString().obs; //
@override @override
void handleReq(ScpMessage scpMessage) async { void handleReq(ScpMessage scpMessage) async {
// //
final loginData = await Storage.getLoginData(); final loginData = await Storage.getLoginData();
// //
if (loginData != null && if (loginData != null && (talkStatus.status != TalkStatus.passiveCallWaitingAnswer || talkStatus.status != TalkStatus.answeredSuccessfully)) {
(talkStatus.status != TalkStatus.passiveCallWaitingAnswer ||
talkStatus.status != TalkStatus.answeredSuccessfully)) {
// //
AppLog.log('收到对讲请求ToPeerId${scpMessage.ToPeerId}');
AppLog.log('收到对讲请求FromPeerId${scpMessage.FromPeerId}');
final TalkReq talkReq = scpMessage.Payload; final TalkReq talkReq = scpMessage.Payload;
startChartManage.FromPeerId = scpMessage.ToPeerId!; startChartManage.FromPeerId = scpMessage.ToPeerId!;
startChartManage.ToPeerId = scpMessage.FromPeerId!; startChartManage.ToPeerId = scpMessage.FromPeerId!;
@ -64,8 +62,6 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
_handleResponseSendExpect( _handleResponseSendExpect(
lockPeerID: scpMessage.FromPeerId!, lockPeerID: scpMessage.FromPeerId!,
); );
//
startChartManage.startTalkExpectTimer();
// //
startChartManage.stopCallRequestMessageTimer(); startChartManage.stopCallRequestMessageTimer();
// //
@ -97,8 +93,7 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
} }
// //
Future<void> _showTalkRequestNotification( Future<void> _showTalkRequestNotification({required String talkObjectName}) async {
{required String talkObjectName}) async {
if (Platform.isAndroid) { if (Platform.isAndroid) {
final Map<String, dynamic> message = { final Map<String, dynamic> message = {
'platform': 'all', 'platform': 'all',
@ -167,14 +162,12 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
void _handleRequestSendExpect({ void _handleRequestSendExpect({
required String lockPeerID, required String lockPeerID,
}) async { }) async {
final LockListInfoItemEntity currentKeyInfo = final LockListInfoItemEntity currentKeyInfo = CommonDataManage().currentKeyInfo;
CommonDataManage().currentKeyInfo;
var isH264 = currentKeyInfo.lockFeature?.isH264 == 1; var isH264 = currentKeyInfo.lockFeature?.isH264 == 1;
var isMJpeg = currentKeyInfo.lockFeature?.isMJpeg == 1; var isMJpeg = currentKeyInfo.lockFeature?.isMJpeg == 1;
final LockListInfoGroupEntity? lockListInfoGroupEntity = final LockListInfoGroupEntity? lockListInfoGroupEntity = await Storage.getLockMainListData();
await Storage.getLockMainListData();
if (lockListInfoGroupEntity != null) { if (lockListInfoGroupEntity != null) {
lockListInfoGroupEntity!.groupList?.forEach((element) { lockListInfoGroupEntity!.groupList?.forEach((element) {
final lockList = element.lockList; final lockList = element.lockList;
@ -195,18 +188,15 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
if (isH264) { if (isH264) {
// H264H264视频和G711音频期望 // H264H264视频和G711音频期望
startChartManage.sendOnlyH264VideoTalkExpectData(); startChartManage.sendOnlyH264VideoTalkExpectData();
print( print('app收到的对讲请求后发送的预期数据=========锁支持H264发送H264视频格式期望数据,peerID=${lockPeerID}');
'app收到的对讲请求后发送的预期数据=========锁支持H264发送H264视频格式期望数据,peerID=${lockPeerID}');
} else if (isMJpeg) { } else if (isMJpeg) {
// MJPEGG711音频期望 // MJPEGG711音频期望
startChartManage.sendOnlyImageVideoTalkExpectData(); startChartManage.sendOnlyImageVideoTalkExpectData();
print( print('app收到的对讲请求后发送的预期数据=========锁不支持H264支持MJPEG发送MJPEG视频格式期望数据,peerID=${lockPeerID}');
'app收到的对讲请求后发送的预期数据=========锁不支持H264支持MJPEG发送MJPEG视频格式期望数据,peerID=${lockPeerID}');
} else { } else {
// 使 // 使
startChartManage.sendOnlyImageVideoTalkExpectData(); startChartManage.sendOnlyImageVideoTalkExpectData();
print( print('app收到的对讲请求后发送的预期数据=========锁不支持H264和MJPEG默认发送MJPEG视频格式期望数据,peerID=${lockPeerID}');
'app收到的对讲请求后发送的预期数据=========锁不支持H264和MJPEG默认发送MJPEG视频格式期望数据,peerID=${lockPeerID}');
} }
} }
@ -214,14 +204,12 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
void _handleResponseSendExpect({ void _handleResponseSendExpect({
required String lockPeerID, required String lockPeerID,
}) async { }) async {
final LockListInfoItemEntity currentKeyInfo = final LockListInfoItemEntity currentKeyInfo = CommonDataManage().currentKeyInfo;
CommonDataManage().currentKeyInfo;
var isH264 = currentKeyInfo.lockFeature?.isH264 == 1; var isH264 = currentKeyInfo.lockFeature?.isH264 == 1;
var isMJpeg = currentKeyInfo.lockFeature?.isMJpeg == 1; var isMJpeg = currentKeyInfo.lockFeature?.isMJpeg == 1;
final LockListInfoGroupEntity? lockListInfoGroupEntity = final LockListInfoGroupEntity? lockListInfoGroupEntity = await Storage.getLockMainListData();
await Storage.getLockMainListData();
if (lockListInfoGroupEntity != null) { if (lockListInfoGroupEntity != null) {
lockListInfoGroupEntity!.groupList?.forEach((element) { lockListInfoGroupEntity!.groupList?.forEach((element) {
final lockList = element.lockList; final lockList = element.lockList;
@ -242,18 +230,15 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
if (isH264) { if (isH264) {
// H264H264视频和G711音频期望 // H264H264视频和G711音频期望
startChartManage.sendH264VideoAndG711AudioTalkExpectData(); startChartManage.sendH264VideoAndG711AudioTalkExpectData();
AppLog.log( AppLog.log('app主动发对讲请求收到回复后发送的预期数据=======锁支持H264发送H264视频格式期望数据,peerID=${lockPeerID}');
'app主动发对讲请求收到回复后发送的预期数据=======锁支持H264发送H264视频格式期望数据,peerID=${lockPeerID}');
} else if (isMJpeg) { } else if (isMJpeg) {
// MJPEGG711音频期望 // MJPEGG711音频期望
startChartManage.sendImageVideoAndG711AudioTalkExpectData(); startChartManage.sendImageVideoAndG711AudioTalkExpectData();
AppLog.log( AppLog.log('app主动发对讲请求收到回复后发送的预期数据=======锁不支持H264支持MJPEG发送MJPEG视频格式期望数据,peerID=${lockPeerID}');
'app主动发对讲请求收到回复后发送的预期数据=======锁不支持H264支持MJPEG发送MJPEG视频格式期望数据,peerID=${lockPeerID}');
} else { } else {
// 使 // 使
startChartManage.sendImageVideoAndG711AudioTalkExpectData(); startChartManage.sendImageVideoAndG711AudioTalkExpectData();
AppLog.log( AppLog.log('app主动发对讲请求收到回复后发送的预期数据=======锁不支持H264和MJPEG默认发送MJPEG视频格式期望数据,peerID=${lockPeerID}');
'app主动发对讲请求收到回复后发送的预期数据=======锁不支持H264和MJPEG默认发送MJPEG视频格式期望数据,peerID=${lockPeerID}');
} }
} }
} }

View File

@ -61,12 +61,9 @@ class StartChartManage {
// //
static final StartChartManage _instance = StartChartManage._internal(); static final StartChartManage _instance = StartChartManage._internal();
final TalkeRequestOverTimeTimerManager talkeRequestOverTimeTimerManager = final TalkeRequestOverTimeTimerManager talkeRequestOverTimeTimerManager = TalkeRequestOverTimeTimerManager();
TalkeRequestOverTimeTimerManager(); final TalkePingOverTimeTimerManager talkePingOverTimeTimerManager = TalkePingOverTimeTimerManager();
final TalkePingOverTimeTimerManager talkePingOverTimeTimerManager = final TalkDataOverTimeTimerManager talkDataOverTimeTimerManager = TalkDataOverTimeTimerManager();
TalkePingOverTimeTimerManager();
final TalkDataOverTimeTimerManager talkDataOverTimeTimerManager =
TalkDataOverTimeTimerManager();
// //
factory StartChartManage() { factory StartChartManage() {
@ -171,8 +168,7 @@ class StartChartManage {
FromPeerId = loginData?.starchart?.starchartId ?? ''; FromPeerId = loginData?.starchart?.starchartId ?? '';
} else { } else {
_log(text: '开始注册客户端'); _log(text: '开始注册客户端');
final StarChartRegisterNodeEntity requestStarChartRegisterNode = final StarChartRegisterNodeEntity requestStarChartRegisterNode = await _requestStarChartRegisterNode();
await _requestStarChartRegisterNode();
await _saveStarChartRegisterNodeToStorage(requestStarChartRegisterNode); await _saveStarChartRegisterNodeToStorage(requestStarChartRegisterNode);
FromPeerId = requestStarChartRegisterNode.peer!.id ?? ''; FromPeerId = requestStarChartRegisterNode.peer!.id ?? '';
bindUserStarchart(requestStarChartRegisterNode); bindUserStarchart(requestStarChartRegisterNode);
@ -180,18 +176,14 @@ class StartChartManage {
} }
// //
Future<void> bindUserStarchart( Future<void> bindUserStarchart(StarChartRegisterNodeEntity requestStarChartRegisterNode) async {
StarChartRegisterNodeEntity requestStarChartRegisterNode) async {
try { try {
final LoginEntity entity = await ApiRepository.to.bindUserStarchart( final LoginEntity entity = await ApiRepository.to.bindUserStarchart(
starchartId: requestStarChartRegisterNode.peer?.id ?? '', starchartId: requestStarChartRegisterNode.peer?.id ?? '',
starchartPeerPublicKey: starchartPeerPublicKey: requestStarChartRegisterNode.peer?.publicKey ?? '',
requestStarChartRegisterNode.peer?.publicKey ?? '', starchartPeerPrivateKey: requestStarChartRegisterNode.peer?.privateKey ?? '',
starchartPeerPrivateKey:
requestStarChartRegisterNode.peer?.privateKey ?? '',
); );
requestStarChartRegisterNode.peer?.id = requestStarChartRegisterNode.peer?.id = entity.data?.starchart?.starchartId;
entity.data?.starchart?.starchartId;
if (entity.errorCode!.codeIsSuccessful) { if (entity.errorCode!.codeIsSuccessful) {
AppLog.log('绑定成功'); AppLog.log('绑定成功');
} else { } else {
@ -204,14 +196,12 @@ class StartChartManage {
// //
Future<void> _relayQuery() async { Future<void> _relayQuery() async {
final RelayInfoEntity relayInfoEntity = final RelayInfoEntity relayInfoEntity = await StartChartApi.to.relayQueryInfo();
await StartChartApi.to.relayQueryInfo();
_saveRelayInfoEntityToStorage(relayInfoEntity); _saveRelayInfoEntityToStorage(relayInfoEntity);
if (relayInfoEntity.client_addr != null) { if (relayInfoEntity.client_addr != null) {
localPublicHost = relayInfoEntity.client_addr!; localPublicHost = relayInfoEntity.client_addr!;
} }
if (relayInfoEntity.relay_list != null && if (relayInfoEntity.relay_list != null && relayInfoEntity.relay_list!.length > 0) {
relayInfoEntity.relay_list!.length > 0) {
for (int i = 0; i <= relayInfoEntity.relay_list!.length; i++) { for (int i = 0; i <= relayInfoEntity.relay_list!.length; i++) {
final data = relayInfoEntity.relay_list?[i]; final data = relayInfoEntity.relay_list?[i];
if (data?.peerID != FromPeerId) { if (data?.peerID != FromPeerId) {
@ -239,8 +229,7 @@ class StartChartManage {
// udp // udp
Future<void> _onlineRelayService() async { Future<void> _onlineRelayService() async {
var addressIListenFrom = InternetAddress.anyIPv4; var addressIListenFrom = InternetAddress.anyIPv4;
await RawDatagramSocket.bind(addressIListenFrom, localPort) await RawDatagramSocket.bind(addressIListenFrom, localPort).then((RawDatagramSocket socket) {
.then((RawDatagramSocket socket) {
// (SO_RCVBUF = 8) // (SO_RCVBUF = 8)
if (AppPlatform.isAndroid) { if (AppPlatform.isAndroid) {
socket.setRawOption( socket.setRawOption(
@ -291,15 +280,15 @@ class StartChartManage {
} }
// RbcuInfo // RbcuInfo
void _sendRbcuInfoMessage( void _sendRbcuInfoMessage({required String ToPeerId, bool isResp = false}) async {
{required String ToPeerId, bool isResp = false}) async {
final uuid = _uuid.v1(); final uuid = _uuid.v1();
final int timestamp = DateTime.now().millisecondsSinceEpoch; final int timestamp = DateTime
.now()
.millisecondsSinceEpoch;
final Int64 int64Timestamp = Int64(timestamp); // 使 final Int64 int64Timestamp = Int64(timestamp); // 使
// ip地址和中继返回的外网地址 // ip地址和中继返回的外网地址
final List<ListenAddrData> listenAddrDataList = final List<ListenAddrData> listenAddrDataList = await _makeListenAddrDataList();
await _makeListenAddrDataList();
listenAddrDataList.insert( listenAddrDataList.insert(
0, // 0, //
ListenAddrData( ListenAddrData(
@ -309,15 +298,13 @@ class StartChartManage {
); );
final address = listenAddrDataList final address = listenAddrDataList
.where((element) => .where((element) => element.type == ListenAddrTypeConstant.local) //
element.type == ListenAddrTypeConstant.local) //
.map((e) => e.address) // List<String?> .map((e) => e.address) // List<String?>
.where((addr) => addr != null) // null .where((addr) => addr != null) // null
.map( .map(
(addr) => addr!.replaceAll(IpConstant.udpUrl, ''), (addr) => addr!.replaceAll(IpConstant.udpUrl, ''),
) // "udp://" ) // "udp://"
.cast< .cast<String>(); // Iterable<String>// Iterable<String?> Iterable<String>
String>(); // Iterable<String>// Iterable<String?> Iterable<String>
_rbcuSessionId = uuid; _rbcuSessionId = uuid;
final RbcuInfo rbcuInfo = RbcuInfo( final RbcuInfo rbcuInfo = RbcuInfo(
sessionId: uuid, sessionId: uuid,
@ -340,28 +327,21 @@ class StartChartManage {
void _sendRbcuProbeMessage() async { void _sendRbcuProbeMessage() async {
// //
String generateRandomString(int length) { String generateRandomString(int length) {
const chars = const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
final random = Random(); final random = Random();
return String.fromCharCodes( return String.fromCharCodes(
List.generate( List.generate(length, (index) => chars.codeUnitAt(random.nextInt(chars.length))),
length, (index) => chars.codeUnitAt(random.nextInt(chars.length))),
); );
} }
if (rbcuInfo != null && if (rbcuInfo != null && rbcuInfo!.address != null && rbcuInfo!.address.length > 0) {
rbcuInfo!.address != null &&
rbcuInfo!.address.length > 0) {
rbcuInfo!.address.forEach((element) { rbcuInfo!.address.forEach((element) {
// element // element
final parts = element.split(':'); final parts = element.split(':');
final host = parts[0]; // IP final host = parts[0]; // IP
final port = int.tryParse(parts[1]) ?? 0; // 0 final port = int.tryParse(parts[1]) ?? 0; // 0
final RbcuProbe rbcuProbe = RbcuProbe( final RbcuProbe rbcuProbe = RbcuProbe(sessionId: _rbcuSessionId, data: generateRandomString(100), targetAddress: element);
sessionId: _rbcuSessionId,
data: generateRandomString(100),
targetAddress: element);
final rbcuProBeBuffer = rbcuProbe.writeToBuffer(); final rbcuProBeBuffer = rbcuProbe.writeToBuffer();
_sendNatMessage(message: rbcuProBeBuffer, host: host, port: port); _sendNatMessage(message: rbcuProBeBuffer, host: host, port: port);
}); });
@ -378,8 +358,7 @@ class StartChartManage {
// //
void startSendingRbcuInfoMessages({required String ToPeerId}) { void startSendingRbcuInfoMessages({required String ToPeerId}) {
// 1 _sendRbcuInfoMessage // 1 _sendRbcuInfoMessage
rbcuInfoTimer ??= rbcuInfoTimer ??= Timer.periodic(Duration(seconds: _defaultIntervalTime), (timer) {
Timer.periodic(Duration(seconds: _defaultIntervalTime), (timer) {
// RbcuInfo // RbcuInfo
_log(text: '发送RbcuInfo 地址交换消息'); _log(text: '发送RbcuInfo 地址交换消息');
_sendRbcuInfoMessage(ToPeerId: ToPeerId); _sendRbcuInfoMessage(ToPeerId: ToPeerId);
@ -389,8 +368,7 @@ class StartChartManage {
// //
void startSendingRbcuProbeTMessages() { void startSendingRbcuProbeTMessages() {
// 1 _sendRbcuInfoMessage // 1 _sendRbcuInfoMessage
rbcuProbeTimer ??= rbcuProbeTimer ??= Timer.periodic(Duration(seconds: _defaultIntervalTime), (timer) {
Timer.periodic(Duration(seconds: _defaultIntervalTime), (timer) {
// RbcuProbe // RbcuProbe
_sendRbcuProbeMessage(); _sendRbcuProbeMessage();
}); });
@ -398,8 +376,7 @@ class StartChartManage {
// //
void startSendingRbcuConfirmTMessages() { void startSendingRbcuConfirmTMessages() {
rbcuConfirmTimer ??= rbcuConfirmTimer ??= Timer.periodic(Duration(seconds: _defaultIntervalTime), (timer) {
Timer.periodic(Duration(seconds: _defaultIntervalTime), (timer) {
// RbcuProbe // RbcuProbe
_sendRbcuConfirmMessage(); _sendRbcuConfirmMessage();
}); });
@ -458,11 +435,11 @@ class StartChartManage {
// ); // );
// } // }
// } // }
final LockListInfoItemEntity currentKeyInfo = final LockListInfoItemEntity currentKeyInfo = CommonDataManage().currentKeyInfo;
CommonDataManage().currentKeyInfo;
final isH264 = currentKeyInfo.lockFeature?.isH264 == 1; final isH264 = currentKeyInfo.lockFeature?.isH264 == 1;
final isMJpeg = currentKeyInfo.lockFeature?.isMJpeg == 1; final isMJpeg = currentKeyInfo.lockFeature?.isMJpeg == 1;
AppLog.log('isH264:${isH264}');
AppLog.log('isMJpeg:${isMJpeg}');
// 使H264MJPEG // 使H264MJPEG
if (isH264) { if (isH264) {
Get.toNamed( Get.toNamed(
@ -483,6 +460,7 @@ class StartChartManage {
seconds: _defaultIntervalTime, seconds: _defaultIntervalTime,
), ),
(Timer timer) async { (Timer timer) async {
AppLog.log('发送对讲请求:${ToPeerId}');
await sendCallRequestMessage(ToPeerId: ToPeerId); await sendCallRequestMessage(ToPeerId: ToPeerId);
}, },
); );
@ -526,8 +504,7 @@ class StartChartManage {
List<int> packetTalkData = payload.sublist(start, end); List<int> packetTalkData = payload.sublist(start, end);
// messageID // messageID
final messageId = final messageId = MessageCommand.getNextMessageId(toPeerId, increment: false);
MessageCommand.getNextMessageId(toPeerId, increment: false);
// //
final message = MessageCommand.talkDataMessage( final message = MessageCommand.talkDataMessage(
ToPeerId: toPeerId, ToPeerId: toPeerId,
@ -562,8 +539,7 @@ class StartChartManage {
final List<int> message = MessageCommand.heartbeatMessage( final List<int> message = MessageCommand.heartbeatMessage(
FromPeerId: FromPeerId, FromPeerId: FromPeerId,
ToPeerId: relayPeerId, ToPeerId: relayPeerId,
MessageId: MessageId: MessageCommand.getNextMessageId(relayPeerId, increment: true),
MessageCommand.getNextMessageId(relayPeerId, increment: true),
); );
await _sendMessage(message: message); await _sendMessage(message: message);
}, },
@ -572,8 +548,7 @@ class StartChartManage {
} }
// //
void sendEchoMessage( void sendEchoMessage({required List<int> payload, required String toPeerId}) async {
{required List<int> payload, required String toPeerId}) async {
// //
final int totalPackets = (payload.length / _maxPayloadSize).ceil(); final int totalPackets = (payload.length / _maxPayloadSize).ceil();
// //
@ -587,8 +562,7 @@ class StartChartManage {
List<int> packet = payload.sublist(start, end); List<int> packet = payload.sublist(start, end);
// messageID // messageID
final messageId = final messageId = MessageCommand.getNextMessageId(toPeerId, increment: false);
MessageCommand.getNextMessageId(toPeerId, increment: false);
// //
final message = MessageCommand.echoMessage( final message = MessageCommand.echoMessage(
ToPeerId: toPeerId, ToPeerId: toPeerId,
@ -606,13 +580,14 @@ class StartChartManage {
} }
// //
void sendGatewayResetMessage( void sendGatewayResetMessage({required String ToPeerId, required int gatewayId}) async {
{required String ToPeerId, required int gatewayId}) async {
final message = MessageCommand.gatewayResetMessage( final message = MessageCommand.gatewayResetMessage(
ToPeerId: ToPeerId, ToPeerId: ToPeerId,
FromPeerId: FromPeerId, FromPeerId: FromPeerId,
gatewayId: gatewayId, gatewayId: gatewayId,
time: DateTime.now().millisecondsSinceEpoch ~/ 1000, time: DateTime
.now()
.millisecondsSinceEpoch ~/ 1000,
MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: true), MessageId: MessageCommand.getNextMessageId(ToPeerId, increment: true),
); );
await _sendMessage(message: message); await _sendMessage(message: message);
@ -728,8 +703,7 @@ class StartChartManage {
} }
// //
Future<void> sendTalkPingMessage( Future<void> sendTalkPingMessage({required String ToPeerId, required String FromPeerId}) async {
{required String ToPeerId, required String FromPeerId}) async {
final message = MessageCommand.talkPingMessage( final message = MessageCommand.talkPingMessage(
ToPeerId: ToPeerId, ToPeerId: ToPeerId,
FromPeerId: FromPeerId, FromPeerId: FromPeerId,
@ -825,11 +799,9 @@ class StartChartManage {
// //
Future<void> _sendMessage({required List<int> message}) async { Future<void> _sendMessage({required List<int> message}) async {
var result = await _udpSocket?.send( var result = await _udpSocket?.send(message, InternetAddress(remoteHost), remotePort);
message, InternetAddress(remoteHost), remotePort);
if (result != message.length) { if (result != message.length) {
throw StartChartMessageException( throw StartChartMessageException('❌Udp send data error----> $result ${message.length}');
'❌Udp send data error----> $result ${message.length}');
// _udpSocket = null; // _udpSocket = null;
} }
@ -846,15 +818,11 @@ class StartChartManage {
} }
// //
Future<void> _sendNatMessage( Future<void> _sendNatMessage({required List<int> message, required String host, required int port}) async {
{required List<int> message,
required String host,
required int port}) async {
_log(text: '发送nat消息'); _log(text: '发送nat消息');
var result = await _udpSocket?.send(message, InternetAddress(host), port); var result = await _udpSocket?.send(message, InternetAddress(host), port);
if (result != message.length) { if (result != message.length) {
throw StartChartMessageException( throw StartChartMessageException('❌Udp send data error----> $result ${message.length}');
'❌Udp send data error----> $result ${message.length}');
// _udpSocket = null; // _udpSocket = null;
} }
} }
@ -864,8 +832,7 @@ class StartChartManage {
// //
final Map<String, String> deviceInfo = await _getDeviceInfo(); final Map<String, String> deviceInfo = await _getDeviceInfo();
// //
final StarChartRegisterNodeEntity response = final StarChartRegisterNodeEntity response = await StartChartApi.to.starChartRegisterNode(
await StartChartApi.to.starChartRegisterNode(
product: _productName, product: _productName,
model: '${deviceInfo['brand']}_${deviceInfo['model']}', model: '${deviceInfo['brand']}_${deviceInfo['model']}',
name: '${deviceInfo['id']}', name: '${deviceInfo['id']}',
@ -875,8 +842,7 @@ class StartChartManage {
} }
// //
Future<void> _saveStarChartRegisterNodeToStorage( Future<void> _saveStarChartRegisterNodeToStorage(StarChartRegisterNodeEntity starChartRegisterNodeEntity) async {
StarChartRegisterNodeEntity starChartRegisterNodeEntity) async {
if (starChartRegisterNodeEntity != null) { if (starChartRegisterNodeEntity != null) {
await Storage.saveStarChartRegisterNodeInfo(starChartRegisterNodeEntity); await Storage.saveStarChartRegisterNodeInfo(starChartRegisterNodeEntity);
final LoginData? loginData = await Storage.getLoginData(); final LoginData? loginData = await Storage.getLoginData();
@ -886,8 +852,7 @@ class StartChartManage {
} }
// //
Future<void> _saveRelayInfoEntityToStorage( Future<void> _saveRelayInfoEntityToStorage(RelayInfoEntity relayInfoEntity) async {
RelayInfoEntity relayInfoEntity) async {
if (relayInfoEntity != null) { if (relayInfoEntity != null) {
await Storage.saveRelayInfo(relayInfoEntity); await Storage.saveRelayInfo(relayInfoEntity);
} }
@ -909,8 +874,7 @@ class StartChartManage {
); );
// ip地址和中继返回的外网地址 // ip地址和中继返回的外网地址
final List<ListenAddrData> listenAddrDataList = final List<ListenAddrData> listenAddrDataList = await _makeListenAddrDataList();
await _makeListenAddrDataList();
// //
final RelayServiceData relayServiceData = RelayServiceData( final RelayServiceData relayServiceData = RelayServiceData(
@ -977,11 +941,12 @@ class StartChartManage {
String ipAddress = address.address; String ipAddress = address.address;
// IPv6 // IPv6
if (ipAddress.contains('%')) { if (ipAddress.contains('%')) {
ipAddress = ipAddress.split('%').first; ipAddress = ipAddress
.split('%')
.first;
} }
// IP // IP
if (ipAddress.isNotEmpty && if (ipAddress.isNotEmpty && !IpConstant.reportExcludeIp.contains(ipAddress)) {
!IpConstant.reportExcludeIp.contains(ipAddress)) {
ipAddresses.add(ipAddress); ipAddresses.add(ipAddress);
} }
} }
@ -998,8 +963,7 @@ class StartChartManage {
/// ///
Future<Map<String, String>> _getDeviceInfo() async { Future<Map<String, String>> _getDeviceInfo() async {
final Map<String, String> deviceInfo = final Map<String, String> deviceInfo = await DeviceInfoUtils.getDeviceInfo();
await DeviceInfoUtils.getDeviceInfo();
return deviceInfo; return deviceInfo;
} }
@ -1016,8 +980,7 @@ class StartChartManage {
if (host != null && port != null) { if (host != null && port != null) {
try { try {
// DNS // DNS
final List<InternetAddress> addresses = final List<InternetAddress> addresses = await InternetAddress.lookup(host);
await InternetAddress.lookup(host);
if (addresses.isEmpty) { if (addresses.isEmpty) {
throw FormatException('DNS resolution failed for $host'); throw FormatException('DNS resolution failed for $host');
} }
@ -1082,8 +1045,7 @@ class StartChartManage {
final int payloadType = scpMessage.PayloadType ?? 0; final int payloadType = scpMessage.PayloadType ?? 0;
final int messageType = scpMessage.MessageType ?? 0; final int messageType = scpMessage.MessageType ?? 0;
try { try {
final ScpMessageHandler handler = final ScpMessageHandler handler = ScpMessageHandlerFactory.createHandler(payloadType);
ScpMessageHandlerFactory.createHandler(payloadType);
if (messageType == MessageTypeConstant.Req) { if (messageType == MessageTypeConstant.Req) {
handler.handleReq(scpMessage); handler.handleReq(scpMessage);
} else if (messageType == MessageTypeConstant.Resp) { } else if (messageType == MessageTypeConstant.Resp) {
@ -1170,10 +1132,18 @@ class StartChartManage {
} }
/// ///
void changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer( void changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer({required TalkExpectReq talkExpect}) {
{required TalkExpectReq talkExpect}) {
_defaultTalkExpect = talkExpect; _defaultTalkExpect = talkExpect;
reStartTalkExpectMessageTimer(); sendTalkExpectMessage(
talkExpect: _defaultTalkExpect,
);
sendTalkExpectMessage(
talkExpect: _defaultTalkExpect,
);
sendTalkExpectMessage(
talkExpect: _defaultTalkExpect,
);
// reStartTalkExpectMessageTimer();
} }
void reSetDefaultTalkExpect() { void reSetDefaultTalkExpect() {
@ -1190,8 +1160,7 @@ class StartChartManage {
videoType: [VideoTypeE.IMAGE], videoType: [VideoTypeE.IMAGE],
audioType: [], audioType: [],
); );
changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer( changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer(talkExpect: talkExpectReq);
talkExpect: talkExpectReq);
} }
/// ///
@ -1200,20 +1169,17 @@ class StartChartManage {
videoType: [VideoTypeE.H264], videoType: [VideoTypeE.H264],
audioType: [], audioType: [],
); );
changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer( changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer(talkExpect: talkExpectReq);
talkExpect: talkExpectReq);
} }
/// ///
void sendImageVideoAndG711AudioTalkExpectData() { void sendImageVideoAndG711AudioTalkExpectData() {
changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer( changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer(talkExpect: TalkConstant.ImageExpect);
talkExpect: TalkConstant.ImageExpect);
} }
/// ///
void sendH264VideoAndG711AudioTalkExpectData() { void sendH264VideoAndG711AudioTalkExpectData() {
changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer( changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer(talkExpect: TalkConstant.H264Expect);
talkExpect: TalkConstant.H264Expect);
} }
/// ///

View File

@ -18,7 +18,7 @@ class _PermissionGuidancePageState extends State<PermissionGuidancePage> {
final List<Map<String, String>> _stepsData = [ final List<Map<String, String>> _stepsData = [
{ {
'image': 'images/guide/matter.png', 'image': 'images/guide/1.png',
'text': '步骤1打开应用信息点击通知管理选项', 'text': '步骤1打开应用信息点击通知管理选项',
}, },
{ {
@ -26,7 +26,7 @@ class _PermissionGuidancePageState extends State<PermissionGuidancePage> {
'text': '步骤2下滑点击呼叫提醒的通知选项', 'text': '步骤2下滑点击呼叫提醒的通知选项',
}, },
{ {
'image': 'images/guide/tuya.png', 'image': 'images/guide/3.png',
'text': '步骤3选择在锁定屏幕上的选项设置', 'text': '步骤3选择在锁定屏幕上的选项设置',
}, },
{ {

View File

@ -104,10 +104,6 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
codecType: 'h264', codecType: 'h264',
); );
// textureId // textureId
AppLog.log(
'StartChartManage().videoWidth:${StartChartManage().videoWidth}');
AppLog.log(
'StartChartManage().videoHeight:${StartChartManage().videoHeight}');
final textureId = await VideoDecodePlugin.initDecoder(config); final textureId = await VideoDecodePlugin.initDecoder(config);
if (textureId != null) { if (textureId != null) {
Future.microtask(() => state.textureId.value = textureId); Future.microtask(() => state.textureId.value = textureId);
@ -172,15 +168,11 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
ScpMessage scpMessage, ScpMessage scpMessage,
) { ) {
// frameSeq较小时阈值也小 // frameSeq较小时阈值也小
if (!_pendingStreamReset && if (!_pendingStreamReset && _lastFrameSeq != null && frameType == TalkDataH264Frame_FrameTypeE.I && frameSeq < _lastFrameSeq!) {
_lastFrameSeq != null &&
frameType == TalkDataH264Frame_FrameTypeE.I &&
frameSeq < _lastFrameSeq!) {
int dynamicThreshold = _getFrameSeqRolloverThreshold(_lastFrameSeq!); int dynamicThreshold = _getFrameSeqRolloverThreshold(_lastFrameSeq!);
if ((_lastFrameSeq! - frameSeq) > dynamicThreshold) { if ((_lastFrameSeq! - frameSeq) > dynamicThreshold) {
// I帧frameSeq大幅回绕loading并重置所有本地状态 // I帧frameSeq大幅回绕loading并重置所有本地状态
AppLog.log( AppLog.log('检测到新流I帧frameSeq大幅回绕进入loading并重置: frameSeq=$frameSeq, lastFrameSeq=$_lastFrameSeq, 阈值=$dynamicThreshold');
'检测到新流I帧frameSeq大幅回绕进入loading并重置: frameSeq=$frameSeq, lastFrameSeq=$_lastFrameSeq, 阈值=$dynamicThreshold');
Future.microtask(() => state.isLoading.value = true); Future.microtask(() => state.isLoading.value = true);
_pendingStreamReset = true; _pendingStreamReset = true;
// //
@ -197,8 +189,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
// //
} else { } else {
// //
AppLog.log( AppLog.log('检测到I帧乱序未超过回绕阈值$dynamicThreshold),丢弃: frameSeq=$frameSeq, lastFrameSeq=$_lastFrameSeq');
'检测到I帧乱序未超过回绕阈值$dynamicThreshold),丢弃: frameSeq=$frameSeq, lastFrameSeq=$_lastFrameSeq');
return; return;
} }
} }
@ -238,8 +229,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
// P/B帧 // P/B帧
while (state.h264FrameBuffer.length >= state.maxFrameBufferSize) { while (state.h264FrameBuffer.length >= state.maxFrameBufferSize) {
int pbIndex = state.h264FrameBuffer int pbIndex = state.h264FrameBuffer.indexWhere((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.P);
.indexWhere((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.P);
if (pbIndex != -1) { if (pbIndex != -1) {
state.h264FrameBuffer.removeAt(pbIndex); state.h264FrameBuffer.removeAt(pbIndex);
} else { } else {
@ -260,15 +250,17 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
final int intervalMs = (1000 / state.targetFps).round(); final int intervalMs = (1000 / state.targetFps).round();
// //
state.frameProcessTimer = state.frameProcessTimer = Timer.periodic(Duration(milliseconds: intervalMs), (timer) {
Timer.periodic(Duration(milliseconds: intervalMs), (timer) {
_processNextFrameFromBuffer(); _processNextFrameFromBuffer();
}); });
AppLog.log('启动帧处理定时器,目标帧率: ${state.targetFps}fps间隔: ${intervalMs}ms'); AppLog.log('启动帧处理定时器,目标帧率: ${state.targetFps}fps间隔: ${intervalMs}ms');
} }
///
/// ///
void _processNextFrameFromBuffer() async { void _processNextFrameFromBuffer() async {
final startTime = DateTime.now().microsecondsSinceEpoch;
// //
if (state.isProcessingFrame) { if (state.isProcessingFrame) {
return; return;
@ -279,25 +271,19 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
return; return;
} }
try {
// I帧frameSeq最小的I帧消费 // I帧frameSeq最小的I帧消费
final iFrames = state.h264FrameBuffer final iFrames = state.h264FrameBuffer.where((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.I).toList();
.where((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.I) iFrames.sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int));
.toList();
iFrames
.sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int));
if (iFrames.isNotEmpty) { if (iFrames.isNotEmpty) {
// I帧I帧frameSeq
final minIFrame = iFrames.first; final minIFrame = iFrames.first;
final minIFrameSeq = minIFrame['frameSeq']; final minIFrameSeq = minIFrame['frameSeq'];
final targetIndex = state.h264FrameBuffer.indexWhere( final targetIndex = state.h264FrameBuffer.indexWhere(
(f) => (f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.I && f['frameSeq'] == minIFrameSeq,
f['frameType'] == TalkDataH264Frame_FrameTypeE.I &&
f['frameSeq'] == minIFrameSeq,
); );
state.isProcessingFrame = true; state.isProcessingFrame = true;
final Map<String, dynamic>? frameMap = final Map<String, dynamic>? frameMap = state.h264FrameBuffer.removeAt(targetIndex);
state.h264FrameBuffer.removeAt(targetIndex);
if (frameMap == null) { if (frameMap == null) {
state.isProcessingFrame = false; state.isProcessingFrame = false;
return; return;
@ -307,12 +293,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
final int? frameSeq = frameMap['frameSeq']; final int? frameSeq = frameMap['frameSeq'];
final int? frameSeqI = frameMap['frameSeqI']; final int? frameSeqI = frameMap['frameSeqI'];
final int? pts = frameMap['pts']; final int? pts = frameMap['pts'];
final ScpMessage? scpMessage = frameMap['scpMessage']; if (frameData == null || frameType == null || frameSeq == null || frameSeqI == null || pts == null) {
if (frameData == null ||
frameType == null ||
frameSeq == null ||
frameSeqI == null ||
pts == null) {
state.isProcessingFrame = false; state.isProcessingFrame = false;
return; return;
} }
@ -321,11 +302,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
return; return;
} }
lastDecodedIFrameSeq = minIFrameSeq; lastDecodedIFrameSeq = minIFrameSeq;
// AppLog.log('送入解码器的P帧数据frameSeq:${frameSeq},frameSeqI:${frameSeqI},'
// 'frameType:${frameType},messageId:${scpMessage!.MessageId}');
// final spsData = NaluUtils.filterNalusByType(frameData, 7);
// final ppsData = NaluUtils.filterNalusByType(frameData, 8);
// AppLog.log('SPSDATA:${spsData}ppsData:${ppsData}');
await VideoDecodePlugin.sendFrame( await VideoDecodePlugin.sendFrame(
frameData: frameData, frameData: frameData,
frameType: 0, frameType: 0,
@ -340,24 +317,17 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
// I帧时refIFrameSeq等于lastDecodedIFrameSeq的P帧 // I帧时refIFrameSeq等于lastDecodedIFrameSeq的P帧
if (lastDecodedIFrameSeq != null) { if (lastDecodedIFrameSeq != null) {
final validPFrames = state.h264FrameBuffer final validPFrames =
.where((f) => state.h264FrameBuffer.where((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.P && f['frameSeqI'] == lastDecodedIFrameSeq).toList();
f['frameType'] == TalkDataH264Frame_FrameTypeE.P &&
f['frameSeqI'] == lastDecodedIFrameSeq)
.toList();
if (validPFrames.isNotEmpty) { if (validPFrames.isNotEmpty) {
validPFrames.sort( validPFrames.sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int));
(a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int));
final minPFrame = validPFrames.first; final minPFrame = validPFrames.first;
final targetIndex = state.h264FrameBuffer.indexWhere( final targetIndex = state.h264FrameBuffer.indexWhere(
(f) => (f) =>
f['frameType'] == TalkDataH264Frame_FrameTypeE.P && f['frameType'] == TalkDataH264Frame_FrameTypeE.P && f['frameSeq'] == minPFrame['frameSeq'] && f['frameSeqI'] == lastDecodedIFrameSeq,
f['frameSeq'] == minPFrame['frameSeq'] &&
f['frameSeqI'] == lastDecodedIFrameSeq,
); );
state.isProcessingFrame = true; state.isProcessingFrame = true;
final Map<String, dynamic>? frameMap = final Map<String, dynamic>? frameMap = state.h264FrameBuffer.removeAt(targetIndex);
state.h264FrameBuffer.removeAt(targetIndex);
if (frameMap == null) { if (frameMap == null) {
state.isProcessingFrame = false; state.isProcessingFrame = false;
return; return;
@ -367,12 +337,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
final int? frameSeq = frameMap['frameSeq']; final int? frameSeq = frameMap['frameSeq'];
final int? frameSeqI = frameMap['frameSeqI']; final int? frameSeqI = frameMap['frameSeqI'];
final int? pts = frameMap['pts']; final int? pts = frameMap['pts'];
final ScpMessage? scpMessage = frameMap['scpMessage']; if (frameData == null || frameType == null || frameSeq == null || frameSeqI == null || pts == null) {
if (frameData == null ||
frameType == null ||
frameSeq == null ||
frameSeqI == null ||
pts == null) {
state.isProcessingFrame = false; state.isProcessingFrame = false;
return; return;
} }
@ -380,8 +345,6 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
state.isProcessingFrame = false; state.isProcessingFrame = false;
return; return;
} }
// AppLog.log('送入解码器的I帧数据frameSeq:${frameSeq},frameSeqI:${frameSeqI},'
// 'frameType:${frameType},messageId:${scpMessage!.MessageId}');
await VideoDecodePlugin.sendFrame( await VideoDecodePlugin.sendFrame(
frameData: frameData, frameData: frameData,
@ -396,6 +359,16 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
} }
} }
// I帧到来 // I帧到来
} finally {
final endTime = DateTime.now().microsecondsSinceEpoch;
final durationMs = (endTime - startTime) / 1000.0;
// > 5ms
if (durationMs > 5) {
debugPrint('[_processNextFrameFromBuffer] 耗时: ${durationMs.toStringAsFixed(2)} ms');
// 使
// AppLog.log('Frame processing took ${durationMs.toStringAsFixed(2)} ms');
}
}
} }
/// ///
@ -427,8 +400,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
AppLog.log("==== 启动新的数据流监听 ===="); AppLog.log("==== 启动新的数据流监听 ====");
_isListening = true; _isListening = true;
_streamSubscription = state.talkDataRepository.talkDataStream _streamSubscription = state.talkDataRepository.talkDataStream.listen((TalkDataModel talkDataModel) async {
.listen((TalkDataModel talkDataModel) async {
_processFrame(talkDataModel); _processFrame(talkDataModel);
}); });
} }
@ -437,8 +409,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
void _playAudioFrames() { void _playAudioFrames() {
// //
// //
if (state.audioBuffer.isEmpty || if (state.audioBuffer.isEmpty || state.audioBuffer.length < audioBufferSize) {
state.audioBuffer.length < audioBufferSize) {
return; return;
} }
@ -446,8 +417,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
TalkData? oldestFrame; TalkData? oldestFrame;
int oldestIndex = -1; int oldestIndex = -1;
for (int i = 0; i < state.audioBuffer.length; i++) { for (int i = 0; i < state.audioBuffer.length; i++) {
if (oldestFrame == null || if (oldestFrame == null || state.audioBuffer[i].durationMs < oldestFrame.durationMs) {
state.audioBuffer[i].durationMs < oldestFrame.durationMs) {
oldestFrame = state.audioBuffer[i]; oldestFrame = state.audioBuffer[i];
oldestIndex = i; oldestIndex = i;
} }
@ -477,8 +447,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
break; break;
case TalkStatus.answeredSuccessfully: case TalkStatus.answeredSuccessfully:
state.oneMinuteTimeTimer?.cancel(); // state.oneMinuteTimeTimer?.cancel(); //
state.oneMinuteTimeTimer ??= state.oneMinuteTimeTimer ??= Timer.periodic(const Duration(seconds: 1), (Timer t) {
Timer.periodic(const Duration(seconds: 1), (Timer t) {
if (state.isLoading.isFalse) { if (state.isLoading.isFalse) {
state.oneMinuteTime.value++; state.oneMinuteTime.value++;
} }
@ -493,9 +462,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
/// ///
void _playAudioData(TalkData talkData) async { void _playAudioData(TalkData talkData) async {
if (state.isOpenVoice.value && if (state.isOpenVoice.value && state.isLoading.isFalse && state.isRecordingAudio.value == false) {
state.isLoading.isFalse &&
state.isRecordingAudio.value == false) {
List<int> encodedData = G711Tool.decode(talkData.content, 0); // 0A-law List<int> encodedData = G711Tool.decode(talkData.content, 0); // 0A-law
// PCM PcmArrayInt16 // PCM PcmArrayInt16
final PcmArrayInt16 fromList = PcmArrayInt16.fromList(encodedData); final PcmArrayInt16 fromList = PcmArrayInt16.fromList(encodedData);
@ -670,11 +637,9 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
AppLog.log('截图失败: 未找到当前上下文'); AppLog.log('截图失败: 未找到当前上下文');
return; return;
} }
final RenderRepaintBoundary boundary = state.globalKey.currentContext! final RenderRepaintBoundary boundary = state.globalKey.currentContext!.findRenderObject()! as RenderRepaintBoundary;
.findRenderObject()! as RenderRepaintBoundary;
final ui.Image image = await boundary.toImage(); final ui.Image image = await boundary.toImage();
final ByteData? byteData = final ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
await image.toByteData(format: ui.ImageByteFormat.png);
if (byteData == null) { if (byteData == null) {
AppLog.log('截图失败: 图像数据为空'); AppLog.log('截图失败: 图像数据为空');
@ -702,15 +667,13 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
// //
Future<void> remoteOpenLock() async { Future<void> remoteOpenLock() async {
final LockListInfoItemEntity currentKeyInfo = final LockListInfoItemEntity currentKeyInfo = CommonDataManage().currentKeyInfo;
CommonDataManage().currentKeyInfo;
var lockId = currentKeyInfo.lockId ?? 0; var lockId = currentKeyInfo.lockId ?? 0;
var remoteUnlock = currentKeyInfo.lockSetting?.remoteUnlock ?? 0; var remoteUnlock = currentKeyInfo.lockSetting?.remoteUnlock ?? 0;
final lockPeerId = StartChartManage().lockPeerId; final lockPeerId = StartChartManage().lockPeerId;
final LockListInfoGroupEntity? lockListInfoGroupEntity = final LockListInfoGroupEntity? lockListInfoGroupEntity = await Storage.getLockMainListData();
await Storage.getLockMainListData();
if (lockListInfoGroupEntity != null) { if (lockListInfoGroupEntity != null) {
lockListInfoGroupEntity!.groupList?.forEach((element) { lockListInfoGroupEntity!.groupList?.forEach((element) {
final lockList = element.lockList; final lockList = element.lockList;
@ -728,8 +691,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
}); });
} }
if (remoteUnlock == 1) { if (remoteUnlock == 1) {
final LoginEntity entity = await ApiRepository.to final LoginEntity entity = await ApiRepository.to.remoteOpenLock(lockId: lockId.toString(), timeOut: 60);
.remoteOpenLock(lockId: lockId.toString(), timeOut: 60);
if (entity.errorCode!.codeIsSuccessful) { if (entity.errorCode!.codeIsSuccessful) {
showToast('已开锁'.tr); showToast('已开锁'.tr);
StartChartManage().lockListPeerId = []; StartChartManage().lockListPeerId = [];
@ -756,8 +718,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
state.startRecordingAudioTime.value = DateTime.now(); state.startRecordingAudioTime.value = DateTime.now();
// //
state.voiceProcessor state.voiceProcessor?.addFrameListeners(<VoiceProcessorFrameListener>[_onFrame]);
?.addFrameListeners(<VoiceProcessorFrameListener>[_onFrame]);
state.voiceProcessor?.addErrorListener(_onError); state.voiceProcessor?.addErrorListener(_onError);
} else { } else {
// state.errorMessage.value = 'Recording permission not granted'; // state.errorMessage.value = 'Recording permission not granted';
@ -777,8 +738,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
state.endRecordingAudioTime.value = DateTime.now(); state.endRecordingAudioTime.value = DateTime.now();
// //
final Duration duration = state.endRecordingAudioTime.value final Duration duration = state.endRecordingAudioTime.value.difference(state.startRecordingAudioTime.value);
.difference(state.startRecordingAudioTime.value);
state.recordingAudioTime.value = duration.inSeconds; state.recordingAudioTime.value = duration.inSeconds;
} on PlatformException catch (ex) { } on PlatformException catch (ex) {
@ -848,10 +808,8 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
_bufferedAudioFrames.addAll(encodedData); _bufferedAudioFrames.addAll(encodedData);
// //
if (_startProcessingAudioTimer == null && if (_startProcessingAudioTimer == null && _bufferedAudioFrames.length > chunkSize) {
_bufferedAudioFrames.length > chunkSize) { _startProcessingAudioTimer = Timer.periodic(Duration(milliseconds: intervalMs), _sendAudioChunk);
_startProcessingAudioTimer =
Timer.periodic(Duration(milliseconds: intervalMs), _sendAudioChunk);
} }
} }
@ -887,8 +845,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
} }
/// ///
StartChartManage().changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer( StartChartManage().changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer(talkExpect: talkExpectReq);
talkExpect: talkExpectReq);
// loadingframeSeq回绕检测 // loadingframeSeq回绕检测
// frameSeq回绕检测标志 // frameSeq回绕检测标志

View File

@ -29,15 +29,12 @@ class TalkViewNativeDecodePage extends StatefulWidget {
const TalkViewNativeDecodePage({Key? key}) : super(key: key); const TalkViewNativeDecodePage({Key? key}) : super(key: key);
@override @override
State<TalkViewNativeDecodePage> createState() => State<TalkViewNativeDecodePage> createState() => _TalkViewNativeDecodePageState();
_TalkViewNativeDecodePageState();
} }
class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage> class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage> with TickerProviderStateMixin {
with TickerProviderStateMixin {
final TalkViewNativeDecodeLogic logic = Get.put(TalkViewNativeDecodeLogic()); final TalkViewNativeDecodeLogic logic = Get.put(TalkViewNativeDecodeLogic());
final TalkViewNativeDecodeState state = final TalkViewNativeDecodeState state = Get.find<TalkViewNativeDecodeLogic>().state;
Get.find<TalkViewNativeDecodeLogic>().state;
final startChartManage = StartChartManage(); final startChartManage = StartChartManage();
@override @override
@ -69,56 +66,39 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
// false 退 // false 退
return false; return false;
}, },
child: SizedBox( child: Container(
width: 1.sw, width: 1.sw,
height: 1.sh, height: 1.sh,
color: Colors.black.withOpacity(0.7),
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: <Widget>[ children: <Widget>[
// //
Obx( Obx(
() { () {
final double screenWidth = MediaQuery.of(context).size.width;
final double screenHeight = MediaQuery.of(context).size.height;
final double logicalWidth = MediaQuery.of(context).size.width;
final double logicalHeight = MediaQuery.of(context).size.height;
final double devicePixelRatio =
MediaQuery.of(context).devicePixelRatio;
//
final double physicalWidth = logicalWidth * devicePixelRatio;
final double physicalHeight = logicalHeight * devicePixelRatio;
//
const int rotatedImageWidth = 480; //
const int rotatedImageHeight = 864; //
//
final double scaleWidth = physicalWidth / rotatedImageWidth;
final double scaleHeight = physicalHeight / rotatedImageHeight;
max(scaleWidth, scaleHeight); //
// loading中或textureId为nullloading/ // loading中或textureId为nullloading/
if (state.isLoading.isTrue || state.textureId.value == null) { if (state.isLoading.isTrue || state.textureId.value == null) {
return Image.asset( return Image.asset(
'images/main/monitorBg.png', 'images/main/monitorBg.png',
width: screenWidth, width: 1.sw,
height: screenHeight, height: 1.sh,
fit: BoxFit.cover, fit: BoxFit.cover,
); );
} else { } else {
return Positioned.fill( return Positioned(
top: 0,
left: 0,
right: 0,
child: PopScope( child: PopScope(
canPop: false, canPop: false,
child: RepaintBoundary( child: RepaintBoundary(
key: state.globalKey, key: state.globalKey,
child: SizedBox.expand(
child: RotatedBox( child: RotatedBox(
// 使RotatedBox // 使RotatedBox
quarterTurns: startChartManage.rotateAngle ~/ 90, quarterTurns: startChartManage.rotateAngle ~/ 90,
child: Platform.isIOS child: state.isFullScreen.isFalse
? Transform.scale( ? AspectRatio(
scale: 1.008, // iOS白边 aspectRatio: StartChartManage().videoWidth / StartChartManage().videoHeight,
child: Texture( child: Texture(
textureId: state.textureId.value!, textureId: state.textureId.value!,
filterQuality: FilterQuality.medium, filterQuality: FilterQuality.medium,
@ -131,7 +111,6 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
), ),
), ),
), ),
),
); );
} }
}, },
@ -151,19 +130,14 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
width: 1.sw, width: 1.sw,
child: Obx( child: Obx(
() { () {
final String sec = (state.oneMinuteTime.value % 60) final String sec = (state.oneMinuteTime.value % 60).toString().padLeft(2, '0');
.toString() final String min = (state.oneMinuteTime.value ~/ 60).toString().padLeft(2, '0');
.padLeft(2, '0');
final String min = (state.oneMinuteTime.value ~/ 60)
.toString()
.padLeft(2, '0');
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Text( Text(
'$min:$sec', '$min:$sec',
style: TextStyle( style: TextStyle(fontSize: 26.sp, color: Colors.white),
fontSize: 26.sp, color: Colors.white),
), ),
], ],
); );
@ -177,9 +151,7 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
width: 1.sw - 30.w * 2, width: 1.sw - 30.w * 2,
// height: 300.h, // height: 300.h,
margin: EdgeInsets.all(30.w), margin: EdgeInsets.all(30.w),
decoration: BoxDecoration( decoration: BoxDecoration(color: Colors.black.withOpacity(0.2), borderRadius: BorderRadius.circular(20.h)),
color: Colors.black.withOpacity(0.2),
borderRadius: BorderRadius.circular(20.h)),
child: Column( child: Column(
children: <Widget>[ children: <Widget>[
SizedBox(height: 20.h), SizedBox(height: 20.h),
@ -191,9 +163,7 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
), ),
), ),
), ),
Obx(() => state.isLoading.isTrue Obx(() => state.isLoading.isTrue ? buildRotationTransition() : Container()),
? buildRotationTransition()
: Container()),
Obx(() => state.isLongPressing.value Obx(() => state.isLongPressing.value
? Positioned( ? Positioned(
top: 80.h, top: 80.h,
@ -213,8 +183,7 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
SizedBox(width: 10.w), SizedBox(width: 10.w),
Text( Text(
'正在说话...'.tr, '正在说话...'.tr,
style: TextStyle( style: TextStyle(fontSize: 20.sp, color: Colors.white),
fontSize: 20.sp, color: Colors.white),
), ),
], ],
), ),
@ -246,10 +215,8 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
width: 40.w, width: 40.w,
height: 40.w, height: 40.w,
image: state.isOpenVoice.value image: state.isOpenVoice.value
? const AssetImage( ? const AssetImage('images/main/icon_lockDetail_monitoringOpenVoice.png')
'images/main/icon_lockDetail_monitoringOpenVoice.png') : const AssetImage('images/main/icon_lockDetail_monitoringCloseVoice.png'))),
: const AssetImage(
'images/main/icon_lockDetail_monitoringCloseVoice.png'))),
), ),
), ),
SizedBox(width: 50.w), SizedBox(width: 50.w),
@ -264,11 +231,7 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
width: 50.w, width: 50.w,
height: 50.w, height: 50.w,
padding: EdgeInsets.all(5.w), padding: EdgeInsets.all(5.w),
child: Image( child: Image(width: 40.w, height: 40.w, image: const AssetImage('images/main/icon_lockDetail_monitoringScreenshot.png')),
width: 40.w,
height: 40.w,
image: const AssetImage(
'images/main/icon_lockDetail_monitoringScreenshot.png')),
), ),
), ),
SizedBox(width: 50.w), SizedBox(width: 50.w),
@ -293,8 +256,7 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
width: 40.w, width: 40.w,
height: 40.w, height: 40.w,
fit: BoxFit.fill, fit: BoxFit.fill,
image: const AssetImage( image: const AssetImage('images/main/icon_lockDetail_monitoringScreenRecording.png'),
'images/main/icon_lockDetail_monitoringScreenRecording.png'),
), ),
), ),
), ),
@ -330,13 +292,8 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
Text( Text(
q, q,
style: TextStyle( style: TextStyle(
color: state.currentQuality.value == q color: state.currentQuality.value == q ? AppColors.mainColor : Colors.black,
? AppColors.mainColor fontWeight: state.currentQuality.value == q ? FontWeight.bold : FontWeight.normal,
: Colors.black,
fontWeight:
state.currentQuality.value == q
? FontWeight.bold
: FontWeight.normal,
fontSize: 28.sp, fontSize: 28.sp,
), ),
), ),
@ -352,8 +309,7 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
); );
}, },
child: Container( child: Container(
child: Icon(Icons.high_quality_outlined, child: Icon(Icons.high_quality_outlined, color: Colors.white, size: 38.w),
color: Colors.white, size: 38.w),
), ),
), ),
Visibility( Visibility(
@ -377,9 +333,7 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
} }
Widget bottomBottomBtnWidget() { Widget bottomBottomBtnWidget() {
return Row( return Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
// //
Obx( Obx(
() => bottomBtnItemWidget( () => bottomBtnItemWidget(
@ -399,17 +353,14 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
state.isLongPressing.value = false; state.isLongPressing.value = false;
}, },
onClick: () async { onClick: () async {
if (state.talkStatus.value == if (state.talkStatus.value == TalkStatus.passiveCallWaitingAnswer) {
TalkStatus.passiveCallWaitingAnswer) {
// //
logic.initiateAnswerCommand(); logic.initiateAnswerCommand();
} }
}, },
), ),
), ),
bottomBtnItemWidget( bottomBtnItemWidget('images/main/icon_lockDetail_hangUp.png', '挂断'.tr, Colors.red, onClick: () {
'images/main/icon_lockDetail_hangUp.png', '挂断'.tr, Colors.red,
onClick: () {
// //
logic.udpHangUpAction(); logic.udpHangUpAction();
}), }),

View File

@ -0,0 +1,518 @@
import 'dart:async';
import 'dart:math';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:provider/provider.dart';
import 'package:star_lock/appRouters.dart';
import 'package:star_lock/flavors.dart';
import 'package:star_lock/talk/call/callTalk.dart';
import 'package:star_lock/talk/starChart/constant/talk_status.dart';
import 'package:star_lock/talk/starChart/handle/impl/debug_Info_model.dart';
import 'package:star_lock/talk/starChart/handle/impl/udp_talk_data_handler.dart';
import 'package:star_lock/talk/starChart/star_chart_manage.dart';
import 'package:star_lock/talk/starChart/views/native/talk_view_native_decode_logic.dart';
import 'package:star_lock/talk/starChart/views/native/talk_view_native_decode_state.dart';
import 'package:star_lock/talk/starChart/views/talkView/talk_view_logic.dart';
import 'package:star_lock/talk/starChart/views/talkView/talk_view_state.dart';
import 'package:video_decode_plugin/video_decode_plugin.dart';
import '../../../../app_settings/app_colors.dart';
import '../../../../tools/showTFView.dart';
class TalkViewNativeDecodePageDebug extends StatefulWidget {
const TalkViewNativeDecodePageDebug({Key? key}) : super(key: key);
@override
State<TalkViewNativeDecodePageDebug> createState() => _TalkViewNativeDecodePageDebugState();
}
class _TalkViewNativeDecodePageDebugState extends State<TalkViewNativeDecodePageDebug> with TickerProviderStateMixin {
final TalkViewNativeDecodeLogic logic = Get.put(TalkViewNativeDecodeLogic());
final TalkViewNativeDecodeState state = Get.find<TalkViewNativeDecodeLogic>().state;
final startChartManage = StartChartManage();
@override
void initState() {
super.initState();
state.animationController = AnimationController(
vsync: this, // 使TickerProvider是当前Widget
duration: const Duration(seconds: 1),
);
state.animationController.repeat();
//StatusListener
state.animationController.addStatusListener((AnimationStatus status) {
if (status == AnimationStatus.completed) {
state.animationController.reset();
state.animationController.forward();
} else if (status == AnimationStatus.dismissed) {
state.animationController.reset();
state.animationController.forward();
}
});
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
// false 退
return false;
},
child: Container(
width: 1.sw,
height: 1.sh,
color: Colors.black.withOpacity(0.7),
child: Stack(
alignment: Alignment.center,
children: <Widget>[
//
Obx(
() {
final double screenWidth = MediaQuery.of(context).size.width;
final double screenHeight = MediaQuery.of(context).size.height;
// loading中或textureId为nullloading/
if (state.isLoading.isTrue || state.textureId.value == null) {
return Image.asset(
'images/main/monitorBg.png',
width: screenWidth,
height: screenHeight,
fit: BoxFit.cover,
);
} else {
return PopScope(
canPop: false,
child: RepaintBoundary(
key: state.globalKey,
child: RotatedBox(
// 使RotatedBox
quarterTurns: startChartManage.rotateAngle ~/ 90,
child: Platform.isIOS
? Transform.scale(
scale: 1.008, // iOS白边
child: Texture(
textureId: state.textureId.value!,
filterQuality: FilterQuality.medium,
),
)
: state.isFullScreen.isFalse
? AspectRatio(
aspectRatio: StartChartManage().videoWidth / StartChartManage().videoHeight,
child: Texture(
textureId: state.textureId.value!,
filterQuality: FilterQuality.medium,
),
)
: Texture(
textureId: state.textureId.value!,
filterQuality: FilterQuality.medium,
),
),
),
);
}
},
),
ElevatedButton(
onPressed: () {
state.isFullScreen.value = !state.isFullScreen.value;
},
child: Obx(
() => Text(state.isFullScreen.isTrue ? '退出全屏' : '全屏'),
),
),
Obx(() => state.isLoading.isTrue
? Positioned(
bottom: 310.h,
child: Text(
'正在创建安全连接...'.tr,
style: TextStyle(color: Colors.black, fontSize: 26.sp),
))
: Container()),
Obx(() => state.isLoading.isFalse && state.oneMinuteTime.value > 0
? Positioned(
top: ScreenUtil().statusBarHeight + 75.h,
width: 1.sw,
child: Obx(
() {
final String sec = (state.oneMinuteTime.value % 60).toString().padLeft(2, '0');
final String min = (state.oneMinuteTime.value ~/ 60).toString().padLeft(2, '0');
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'$min:$sec',
style: TextStyle(fontSize: 26.sp, color: Colors.white),
),
],
);
},
),
)
: Container()),
Positioned(
bottom: 10.w,
child: Container(
width: 1.sw - 30.w * 2,
// height: 300.h,
margin: EdgeInsets.all(30.w),
decoration: BoxDecoration(color: Colors.black.withOpacity(0.2), borderRadius: BorderRadius.circular(20.h)),
child: Column(
children: <Widget>[
SizedBox(height: 20.h),
bottomTopBtnWidget(),
SizedBox(height: 20.h),
bottomBottomBtnWidget(),
SizedBox(height: 20.h),
],
),
),
),
Obx(() => state.isLoading.isTrue ? buildRotationTransition() : Container()),
Obx(() => state.isLongPressing.value
? Positioned(
top: 80.h,
left: 0,
right: 0,
child: Center(
child: Container(
padding: EdgeInsets.all(10.w),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.7),
borderRadius: BorderRadius.circular(10.w),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(Icons.mic, color: Colors.white, size: 24.w),
SizedBox(width: 10.w),
Text(
'正在说话...'.tr,
style: TextStyle(fontSize: 20.sp, color: Colors.white),
),
],
),
),
),
)
: Container()),
],
),
),
);
}
Widget bottomTopBtnWidget() {
return Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
//
GestureDetector(
onTap: () {
if (state.talkStatus.value == TalkStatus.answeredSuccessfully) {
//
logic.updateTalkExpect();
}
},
child: Container(
width: 50.w,
height: 50.w,
padding: EdgeInsets.all(5.w),
child: Obx(() => Image(
width: 40.w,
height: 40.w,
image: state.isOpenVoice.value
? const AssetImage('images/main/icon_lockDetail_monitoringOpenVoice.png')
: const AssetImage('images/main/icon_lockDetail_monitoringCloseVoice.png'))),
),
),
SizedBox(width: 50.w),
//
GestureDetector(
onTap: () async {
if (state.talkStatus.value == TalkStatus.answeredSuccessfully) {
await logic.captureAndSavePng();
}
},
child: Container(
width: 50.w,
height: 50.w,
padding: EdgeInsets.all(5.w),
child: Image(width: 40.w, height: 40.w, image: const AssetImage('images/main/icon_lockDetail_monitoringScreenshot.png')),
),
),
SizedBox(width: 50.w),
//
GestureDetector(
onTap: () async {
logic.showToast('功能暂未开放'.tr);
// if (
// state.talkStatus.value == TalkStatus.answeredSuccessfully) {
// if (state.isRecordingScreen.value) {
// await logic.stopRecording();
// } else {
// await logic.startRecording();
// }
// }
},
child: Container(
width: 50.w,
height: 50.w,
padding: EdgeInsets.all(5.w),
child: Image(
width: 40.w,
height: 40.w,
fit: BoxFit.fill,
image: const AssetImage('images/main/icon_lockDetail_monitoringScreenRecording.png'),
),
),
),
SizedBox(width: 50.w),
//
GestureDetector(
onTap: () async {
//
showModalBottomSheet(
context: context,
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20.w)),
),
builder: (BuildContext context) {
final List<String> qualities = ['高清', '标清'];
return SafeArea(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: qualities.map((q) {
return Obx(() => InkWell(
onTap: () {
Navigator.of(context).pop();
logic.onQualityChanged(q);
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 18.w),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Text(
q,
style: TextStyle(
color: state.currentQuality.value == q ? AppColors.mainColor : Colors.black,
fontWeight: state.currentQuality.value == q ? FontWeight.bold : FontWeight.normal,
fontSize: 28.sp,
),
),
],
),
),
));
}).toList(),
),
),
);
},
);
},
child: Container(
child: Icon(Icons.high_quality_outlined, color: Colors.white, size: 38.w),
),
),
Visibility(
visible: state.currentLanguage == 'zh_CN' && Platform.isAndroid,
child: SizedBox(width: 38.w),
),
Visibility(
visible: state.currentLanguage == 'zh_CN' && Platform.isAndroid,
child: IconButton(
icon: Icon(
Icons.notification_add_sharp,
size: 32.w,
color: Colors.white,
),
onPressed: () {
Get.toNamed(Routers.permissionGuidancePage);
},
),
)
]);
}
Widget bottomBottomBtnWidget() {
return Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[
//
Obx(
() => bottomBtnItemWidget(
getAnswerBtnImg(),
getAnswerBtnName(),
Colors.white,
longPress: () async {
if (state.talkStatus.value == TalkStatus.answeredSuccessfully) {
//
logic.startProcessingAudio();
state.isLongPressing.value = true;
}
},
longPressUp: () async {
//
logic.stopProcessingAudio();
state.isLongPressing.value = false;
},
onClick: () async {
if (state.talkStatus.value == TalkStatus.passiveCallWaitingAnswer) {
//
logic.initiateAnswerCommand();
}
},
),
),
bottomBtnItemWidget('images/main/icon_lockDetail_hangUp.png', '挂断'.tr, Colors.red, onClick: () {
//
logic.udpHangUpAction();
}),
bottomBtnItemWidget(
'images/main/icon_lockDetail_monitoringUnlock.png',
'开锁'.tr,
AppColors.mainColor,
onClick: () {
// if (state.talkStatus.value == TalkStatus.answeredSuccessfully &&
// state.listData.value.length > 0) {
// logic.udpOpenDoorAction();
// }
// if (UDPManage().remoteUnlock == 1) {
// logic.udpOpenDoorAction();
// showDeletPasswordAlertDialog(context);
// } else {
// logic.showToast('请在锁设置中开启远程开锁'.tr);
// }
logic.remoteOpenLock();
},
)
]);
}
String getAnswerBtnImg() {
switch (state.talkStatus.value) {
case TalkStatus.passiveCallWaitingAnswer:
return 'images/main/icon_lockDetail_monitoringAnswerCalls.png';
case TalkStatus.answeredSuccessfully:
case TalkStatus.proactivelyCallWaitingAnswer:
return 'images/main/icon_lockDetail_monitoringUnTalkback.png';
default:
return 'images/main/icon_lockDetail_monitoringAnswerCalls.png';
}
}
String getAnswerBtnName() {
switch (state.talkStatus.value) {
case TalkStatus.passiveCallWaitingAnswer:
return '接听'.tr;
case TalkStatus.proactivelyCallWaitingAnswer:
case TalkStatus.answeredSuccessfully:
return '长按说话'.tr;
default:
return '接听'.tr;
}
}
Widget bottomBtnItemWidget(
String iconUrl,
String name,
Color backgroundColor, {
required Function() onClick,
Function()? longPress,
Function()? longPressUp,
}) {
double wh = 80.w;
return GestureDetector(
onTap: onClick,
onLongPress: longPress,
onLongPressUp: longPressUp,
child: SizedBox(
height: 160.w,
width: 140.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
width: wh,
height: wh,
constraints: BoxConstraints(
minWidth: wh,
),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular((wh + 10.w * 2) / 2),
),
padding: EdgeInsets.all(20.w),
child: Image.asset(iconUrl, fit: BoxFit.fitWidth),
),
SizedBox(height: 20.w),
Text(
name,
style: TextStyle(fontSize: 20.sp, color: Colors.white),
textAlign: TextAlign.center, // 使
maxLines: 2, // 1
)
],
),
),
);
}
//
Color _getPacketLossColor(double lossRate) {
if (lossRate < 1.0) {
return Colors.green; // 1%绿
} else if (lossRate < 5.0) {
return Colors.yellow; // 1%-5%
} else if (lossRate < 10.0) {
return Colors.orange; // 5%-10%
} else {
return Colors.red; // 10%
}
}
//
Widget buildRotationTransition() {
return Positioned(
left: ScreenUtil().screenWidth / 2 - 220.w / 2,
top: ScreenUtil().screenHeight / 2 - 220.w / 2 - 150.h,
child: GestureDetector(
child: RotationTransition(
//
alignment: Alignment.center,
//
turns: state.animationController,
//view
child: AnimatedOpacity(
opacity: 0.5,
duration: const Duration(seconds: 2),
child: Image.asset(
'images/main/realTime_connecting.png',
width: 220.w,
height: 220.w,
),
),
),
onTap: () {
state.animationController.forward();
},
),
);
}
@override
void dispose() {
state.animationController.dispose();
CallTalk().finishAVData();
super.dispose();
}
}

View File

@ -37,8 +37,7 @@ class TalkViewNativeDecodeState {
Future<String?> userMobileIP = NetworkInfo().getWifiIP(); Future<String?> userMobileIP = NetworkInfo().getWifiIP();
Future<String?> userUid = Storage.getUid(); Future<String?> userUid = Storage.getUid();
RxInt udpStatus = RxInt udpStatus = 0.obs; //0 1 2 3 4 5 6 8 9
0.obs; //0 1 2 3 4 5 6 8 9
TextEditingController passwordTF = TextEditingController(); TextEditingController passwordTF = TextEditingController();
RxList<int> listAudioData = <int>[].obs; // RxList<int> listAudioData = <int>[].obs; //
@ -63,13 +62,12 @@ class TalkViewNativeDecodeState {
RxBool isPlaying = false.obs; // RxBool isPlaying = false.obs; //
Rx<TalkStatus> talkStatus = TalkStatus.none.obs; // Rx<TalkStatus> talkStatus = TalkStatus.none.obs; //
// startChartTalkStatus // startChartTalkStatus
final StartChartTalkStatus startChartTalkStatus = final StartChartTalkStatus startChartTalkStatus = StartChartTalkStatus.instance;
StartChartTalkStatus.instance;
// //
final TalkDataRepository talkDataRepository = TalkDataRepository.instance; final TalkDataRepository talkDataRepository = TalkDataRepository.instance;
RxBool isOpenVoice = true.obs; // RxBool isOpenVoice = false.obs; //
RxBool isRecordingScreen = false.obs; // RxBool isRecordingScreen = false.obs; //
RxBool isRecordingAudio = false.obs; // RxBool isRecordingAudio = false.obs; //
Rx<DateTime> startRecordingAudioTime = DateTime.now().obs; // Rx<DateTime> startRecordingAudioTime = DateTime.now().obs; //
@ -81,6 +79,7 @@ class TalkViewNativeDecodeState {
RxBool isLongPressing = false.obs; // RxBool isLongPressing = false.obs; //
// ID // ID
Rx<int?> textureId = Rx<int?>(null); Rx<int?> textureId = Rx<int?>(null);
// FPS监测相关变量 // FPS监测相关变量
RxInt lastFpsUpdateTime = 0.obs; // FPS更新时间 RxInt lastFpsUpdateTime = 0.obs; // FPS更新时间
@ -110,8 +109,8 @@ class TalkViewNativeDecodeState {
// H264帧缓冲区相关 // H264帧缓冲区相关
final List<Map<String, dynamic>> h264FrameBuffer = <Map<String, dynamic>>[]; // H264帧缓冲区 final List<Map<String, dynamic>> h264FrameBuffer = <Map<String, dynamic>>[]; // H264帧缓冲区
final int maxFrameBufferSize = 50; // final int maxFrameBufferSize = 25; //
final int targetFps = 60; // ,native的缓冲区 final int targetFps = 25; // ,native的缓冲区
Timer? frameProcessTimer; // Timer? frameProcessTimer; //
bool isProcessingFrame = false; // bool isProcessingFrame = false; //
int lastProcessedTimestamp = 0; // int lastProcessedTimestamp = 0; //
@ -122,6 +121,8 @@ class TalkViewNativeDecodeState {
// '高清' // '高清'
RxString currentQuality = '高清'.obs; // RxString currentQuality = '高清'.obs; //
RxString currentLanguage = RxString currentLanguage = CurrentLocaleTool.getCurrentLocaleString().obs; //
CurrentLocaleTool.getCurrentLocaleString().obs; //
//
RxBool isFullScreen = false.obs;
} }

View File

@ -67,7 +67,7 @@ class CommonItem extends StatelessWidget {
), ),
child: Text( child: Text(
leftTitel!, leftTitel!,
style: leftTitleStyle ?? TextStyle(fontSize: 28.sp), style: leftTitleStyle ?? TextStyle(fontSize: 22.sp),
overflow: TextOverflow.ellipsis, // overflow: TextOverflow.ellipsis, //
maxLines: 3, // 2 maxLines: 3, // 2
), ),

View File

@ -194,45 +194,6 @@ class DateTool {
return appointmentDate; return appointmentDate;
} }
///
String dateToMMString(String? timestamp) {
timestamp ??= '0';
int time = int.parse(timestamp);
if (timestamp.length == 10) {
time = time * 1000;
}
final DateTime nowDate = DateTime.fromMillisecondsSinceEpoch(time);
final String appointmentDate =
formatDate(nowDate, <String>[mm]);
return appointmentDate;
}
///
String dateToDDString(String? timestamp) {
timestamp ??= '0';
int time = int.parse(timestamp);
if (timestamp.length == 10) {
time = time * 1000;
}
final DateTime nowDate = DateTime.fromMillisecondsSinceEpoch(time);
final String appointmentDate =
formatDate(nowDate, <String>[dd]);
return appointmentDate;
}
///
String dateToHnString(String? timestamp) {
timestamp ??= '0';
int time = int.parse(timestamp);
if (timestamp.length == 10) {
time = time * 1000;
}
final DateTime nowDate = DateTime.fromMillisecondsSinceEpoch(time);
final String appointmentDate =
formatDate(nowDate, <String>[HH, ':', nn]);
return appointmentDate;
}
/// (-- :) /// (-- :)
String dateIntToYMDHNString(int? time) { String dateIntToYMDHNString(int? time) {
time ??= 0; time ??= 0;

View File

@ -261,7 +261,7 @@ dependencies:
jverify: 3.0.0 jverify: 3.0.0
#<cn> #<cn>
# umeng_common_sdk: 1.2.8 umeng_common_sdk: 1.2.8
#</cn> #</cn>
#<com> #<com>
firebase_analytics: 11.3.0 firebase_analytics: 11.3.0
@ -322,8 +322,8 @@ flutter:
assets: assets:
- images/ - images/
- images/tabbar/ - images/tabbar/
- images/guide/
- images/other/ - images/other/
- images/guide/
- images/main/ - images/main/
- images/main/addFingerprint/ - images/main/addFingerprint/
- images/mine/ - images/mine/