Merge branch 'develop_sky_liyi' into 'develop_sky'

Develop sky liyi

See merge request StarlockTeam/app-starlock!219
This commit is contained in:
李仪 2025-07-25 07:03:55 +00:00
commit 92a2407fb4
14 changed files with 609 additions and 286 deletions

View File

@ -71,21 +71,45 @@ class FirebaseHelper {
}
Future<void> initSdk() async {
const bool isProductVmMode = bool.fromEnvironment('dart.vm.product');
if (F.isProductionEnv &&
isProductVmMode &&
defaultTargetPlatform == TargetPlatform.android) {
FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true);
}
}
Future<void> login(String userId) async {
const bool isProductVmMode = bool.fromEnvironment('dart.vm.product');
if (F.isProductionEnv &&
isProductVmMode &&
defaultTargetPlatform == TargetPlatform.android) {
FirebaseAnalytics.instance.setUserId(id: userId);
}
}
Future<void> trackEvent(
String eventName, Map<String, Object>? parameters) async {
FirebaseAnalytics.instance
.logEvent(name: eventName, parameters: parameters);
String eventName,
Map<String, Object>? parameters,
) async {
const bool isProductVmMode = bool.fromEnvironment('dart.vm.product');
if (F.isProductionEnv &&
isProductVmMode &&
defaultTargetPlatform == TargetPlatform.android) {
FirebaseAnalytics.instance.logEvent(
name: eventName,
parameters: parameters,
);
}
}
Future<void> logout() async {
const bool isProductVmMode = bool.fromEnvironment('dart.vm.product');
if (F.isProductionEnv &&
isProductVmMode &&
defaultTargetPlatform == TargetPlatform.android) {
FirebaseAnalytics.instance.setUserId(id: '');
}
}
}
//</com>

View File

@ -27,6 +27,7 @@ import 'package:star_lock/main/lockDetail/lockSet/liveVideo/liveVideo_page.dart'
import 'package:star_lock/main/lockDetail/lockSet/motorPower/motorPower_page.dart';
import 'package:star_lock/main/lockDetail/lockSet/openDoorDirection/openDoorDirection_page.dart';
import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart';
import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_page.dart';
import 'package:star_lock/main/lockDetail/messageWarn/addFamily/addFamily_page.dart';
import 'package:star_lock/main/lockDetail/messageWarn/lockUser/lockUser_page.dart';
import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/coerceOpenDoor/coerceFingerprint/coerceFingerprint_page.dart';
@ -443,6 +444,8 @@ abstract class Routers {
static const String motorPowerPage = '/motorPowerPage'; //
static const String speechLanguageSettingsPage =
'/speechLanguageSettingsPage'; //
static const String thirdPartyPlatformPage =
'/thirdPartyPlatformPage'; //
static const String openDoorDirectionPage = '/openDoorDirectionPage'; //
static const String catEyeWorkModePage = '/catEyeWorkModePage'; //
static const String msgNotificationPage = '/msgNotificationPage'; //
@ -528,8 +531,7 @@ abstract class Routers {
'/imageTransmissionView'; //()
static const String permissionGuidancePage =
'/permissionGuidancePage'; //
static const String lockVoiceSettingPage =
'/lockVoiceSetting'; //
static const String lockVoiceSettingPage = '/lockVoiceSetting'; //
}
abstract class AppRouters {
@ -1218,8 +1220,10 @@ abstract class AppRouters {
name: Routers.permissionGuidancePage,
page: () => PermissionGuidancePage()),
GetPage<dynamic>(
name: Routers.lockVoiceSettingPage,
page: () => LockVoiceSetting()),
name: Routers.lockVoiceSettingPage, page: () => LockVoiceSetting()),
GetPage<dynamic>(
name: Routers.thirdPartyPlatformPage,
page: () => ThirdPartyPlatformPage()),
//
// GetPage<dynamic>(name: Routers.h264View, page: () => H264WebView()), // webview播放页面
];

View File

@ -5,11 +5,13 @@ class TimbreItem {
final String timbre;
final String name;
final String timbrePackUrl;
final int isFemale;
TimbreItem({
required this.timbre,
required this.name,
required this.timbrePackUrl,
required this.isFemale,
});
factory TimbreItem.fromJson(Map<String, dynamic> json) {
@ -17,6 +19,7 @@ class TimbreItem {
timbre: json['timbre'] ?? '',
name: json['name'] ?? '',
timbrePackUrl: json['timbrePackUrl'] ?? '',
isFemale: json['isFemale'] ?? 0,
);
}
@ -25,23 +28,27 @@ class TimbreItem {
'timbre': timbre,
'name': name,
'timbrePackUrl': timbrePackUrl,
'isFemale': isFemale,
};
}
@override
String toString() {
return 'TimbreItem{timbre: $timbre, name: $name, timbrePackUrl: $timbrePackUrl}';
return 'TimbreItem{timbre: $timbre, name: $name, timbrePackUrl: '
'$timbrePackUrl},isFemale: $isFemale}';
}
}
//
class PassthroughItem {
final String lang;
final String langText;
final List<TimbreItem> timbres;
PassthroughItem({
required this.lang,
required this.timbres,
required this.langText,
});
factory PassthroughItem.fromJson(Map<String, dynamic> json) {
@ -53,6 +60,7 @@ class PassthroughItem {
: <TimbreItem>[];
return PassthroughItem(
lang: json['lang'] ?? '',
langText: json['langText'] ?? '',
timbres: timbresList,
);
}
@ -60,6 +68,7 @@ class PassthroughItem {
Map<String, dynamic> toJson() {
return {
'lang': lang,
'langText': langText,
'timbres': timbres.map((e) => e.toJson()).toList(),
};
}

View File

@ -686,7 +686,7 @@ class LockSetLogic extends BaseGetXController {
updataLockSet(getTokenList);
} else if (connectionState == BluetoothConnectionState.disconnected) {
// cancelBlueConnetctToastTimer();
// if(state.ifCurrentScreen.value == true){
// if (state.ifCurrentScreen.value == true) {
// showBlueConnetctToast();
// }
}
@ -745,12 +745,13 @@ class LockSetLogic extends BaseGetXController {
// _scanListDiscoveredDeviceSubscription.cancel();
}
//
sendGetDeviceModelBleMessage() {
showEasyLoading();
showBlueConnetctToastTimer(action: () {
dismissEasyLoading();
});
// showEasyLoading();
// showBlueConnetctToastTimer(action: () {
// dismissEasyLoading();
// });
BlueManage().blueSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState deviceConnectionState) async {
if (deviceConnectionState == BluetoothConnectionState.connected) {
@ -761,13 +762,19 @@ class LockSetLogic extends BaseGetXController {
);
} else if (deviceConnectionState ==
BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
showBlueConnetctToast();
// dismissEasyLoading();
// cancelBlueConnetctToastTimer();
// showBlueConnetctToast();
}
});
}
@override
void dispose() {
_replySubscription.cancel();
super.dispose();
}
void _handlerDeviceModelReply(GetDeviceModelReply reply) async {
final int status = reply.data[2];
switch (status) {
@ -783,7 +790,6 @@ class LockSetLogic extends BaseGetXController {
String rawData = String.fromCharCodes(deviceModelBytes);
int firstNullIndex = rawData.indexOf('\u0000');
String deviceModelValue = rawData.substring(0, firstNullIndex);
print(deviceModelValue); // : 2403
print('获取到 DeviceModel (原始): $deviceModelValue');
await Storage.setString(deviceModel, deviceModelValue);
break;

View File

@ -540,6 +540,19 @@ class _LockSetPageState extends State<LockSetPage>
'lockSetInfoData': state.lockSetInfoData.value
});
})),
//
CommonItem(
leftTitel: '第三方平台'.tr,
rightTitle: '',
isHaveLine: true,
isHaveDirection: true,
action: () {
Get.toNamed(Routers.thirdPartyPlatformPage,
arguments: <String, LockSetInfoData>{
'lockSetInfoData': state.lockSetInfoData.value
});
},
),
// 广使
/* 2024-01-12 广 by DaisyWu
Obx(() => Visibility(
@ -606,7 +619,7 @@ class _LockSetPageState extends State<LockSetPage>
state.lockFeature.value.appUnlockOnline == 1,
child: otherItem(
leftTitle: '开锁时是否需联网'.tr,
isHaveLine: false,
isHaveLine: true,
rightWidget: _openLockNeedOnlineSwitch()),
),
),

View File

@ -27,6 +27,7 @@ import 'package:http/http.dart' as http;
import 'package:star_lock/tools/commonDataManage.dart';
import 'package:star_lock/tools/eventBusEventManage.dart';
import 'package:star_lock/tools/storage.dart';
import 'package:star_lock/translations/app_dept.dart';
class SpeechLanguageSettingsLogic extends BaseGetXController {
final SpeechLanguageSettingsState state = SpeechLanguageSettingsState();
@ -34,6 +35,8 @@ class SpeechLanguageSettingsLogic extends BaseGetXController {
@override
void onInit() async {
final findLocaleIndex = _findLocaleIndex();
state.selectPassthroughListIndex.value = findLocaleIndex;
super.onInit();
_replySubscription =
EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async {
@ -47,28 +50,7 @@ class SpeechLanguageSettingsLogic extends BaseGetXController {
} else if (reply is VoicePackageConfigureProcessReply) {
_handlerVoicePackageConfigureProcess(reply);
} else if (reply is VoicePackageConfigureConfirmationReply) {
final PassthroughItem item =
state.languages[state.selectPassthroughListIndex.value];
final timbre = item.timbres[state.selectLanguageIndex.value];
final LoginEntity entity =
await ApiRepository.to.settingCurrentVoiceTimbre(
data: {
'lang': item.lang,
'timbre': timbre.timbre,
},
lockId: state.lockSetInfoData.value.lockId!,
);
if (entity.errorCode!.codeIsSuccessful) {
showSuccess('设置成功'.tr, something: () {
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre
?.lang = item.lang;
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre
?.timbre = timbre.timbre;
eventBus.fire(
PassCurrentLockInformationEvent(state.lockSetInfoData.value));
});
}
dismissEasyLoading();
_handlerVoicePackageConfigureConfirmation(reply);
}
});
state.deviceModel.value = await Storage.getString(deviceModel) ?? '';
@ -76,35 +58,37 @@ class SpeechLanguageSettingsLogic extends BaseGetXController {
if (state.deviceModel.value != null) {
await initList();
}
// await sendGetDeviceModelBleMessage();
}
///
/// //{ "vendor": "XL", "model": "JL-BLE-01"}
initList() async {
showEasyLoading();
try {
final PassthroughListResponse entity = await ApiRepository.to
.getPassthroughList(data: {'deviceType': state.deviceModel.value});
final vendor = state.lockSetInfoData.value.lockBasicInfo?.vendor;
final model = state.lockSetInfoData.value.lockBasicInfo?.model;
final PassthroughListResponse entity =
await ApiRepository.to.getPassthroughList(data: {
'vendor': vendor!,
'model': model!,
});
if (entity.errorCode!.codeIsSuccessful) {
state.languages.value = entity.data!!;
final oldTimbre = state
.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre;
final oldLang = state
final lang = state
.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang;
for (int index = 0; index < state.languages.value.length; index++) {
final element = state.languages.value[index];
final timbre = state
.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre;
state.languages.value.forEach((element) {
final timbres = element.timbres;
for (int i = 0; i < timbres.length; i++) {
final timbre = timbres[i].timbre;
if ((oldLang != null && oldLang == element.lang) &&
(oldTimbre != null && oldTimbre == timbre)) {
state.selectPassthroughListIndex.value = index;
state.selectLanguageIndex.value = i;
}
}
timbres.forEach((item) {
if (lang == element.lang && item.timbre == timbre) {
state.selectSoundTypeIndex.value = item.isFemale;
}
});
});
}
} catch (e) {
debugPrint('获取语音包出现错误:$e');
@ -113,27 +97,57 @@ class SpeechLanguageSettingsLogic extends BaseGetXController {
}
}
void saveSpeechLanguageSettings() async {
//
if (state.progress.value > 0) {
return;
}
final oldTimbre =
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre;
final oldLang =
/// locales code lang -1
int _findLocaleIndex() {
// 1. lang null
final lang =
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang;
EasyLoading.showProgress(state.progress.value, status: '正在发送数据');
final PassthroughItem item =
state.languages[state.selectPassthroughListIndex.value];
final timbre = item.timbres[state.selectLanguageIndex.value];
debugPrint('选中的语音是:${timbre}');
if ((oldLang != null && oldLang == item.lang) &&
(oldTimbre != null && oldTimbre == timbre.timbre)) {
showToast('已设置为当前选择的语音包'.tr);
// 2. lang null -1
if (lang == null) return -1;
// 3. locales
final locales = appDept.deptSupportedLocales;
// 4. 使 indexWhere
return locales.indexWhere((element) {
// countryCode null
if (element.countryCode == null) return false;
// locale codelanguageCode_countryCode
final currentCode = '${element.languageCode}_${element.countryCode}';
// lang
return currentCode == lang;
});
}
void saveSpeechLanguageSettings() async {
final language =
state.appLocalLanguages[state.selectPassthroughListIndex.value];
// languageCode和countryCode
final locales = appDept.deptSupportedLocales;
locales.forEach((element) {
final lanTitle = ExtensionLanguageType.fromLocale(element).lanTitle;
if (lanTitle == language) {
if (element.countryCode != null) {
String code = element.languageCode + '_' + element.countryCode!;
state.languages.forEach((item) async {
if (item.lang == code) {
item.timbres.forEach((timbre) async {
if (timbre.isFemale == state.selectSoundTypeIndex.value) {
state.tempLangStr.value = item.lang;
state.tempTimbreStr.value = timbre.timbre;
await downloadFile(timbre.timbrePackUrl);
}
});
}
});
}
}
});
}
void changeSelectIndex(int index) {
state.selectLanguageIndex.value = index;
@ -363,4 +377,37 @@ class SpeechLanguageSettingsLogic extends BaseGetXController {
state.data = null;
super.onClose();
}
void _handlerVoicePackageConfigureConfirmation(
VoicePackageConfigureConfirmationReply reply,
) async {
final int status = reply.data[2];
switch (status) {
case 0x00:
cancelBlueConnetctToastTimer();
final LoginEntity entity =
await ApiRepository.to.settingCurrentVoiceTimbre(
data: {
'lang': state.tempLangStr.value,
'timbre': state.tempTimbreStr.value,
},
lockId: state.lockSetInfoData.value.lockId!,
);
if (entity.errorCode!.codeIsSuccessful) {
showSuccess('设置成功'.tr, something: () {
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre
?.lang = state.tempLangStr.value;
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre
?.timbre = state.tempTimbreStr.value;
eventBus.fire(
PassCurrentLockInformationEvent(state.lockSetInfoData.value));
});
}
dismissEasyLoading();
break;
default:
showToast('语音设置失败'.tr);
break;
}
}
}

View File

@ -8,6 +8,7 @@ import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart';
import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart';
import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart';
import 'package:star_lock/tools/EasyRefreshTool.dart';
import 'package:star_lock/tools/commonItem.dart';
import 'package:star_lock/tools/titleAppBar.dart';
class SpeechLanguageSettingsPage extends StatefulWidget {
@ -47,12 +48,7 @@ class _SpeechLanguageSettingsPageState
),
],
),
body: EasyRefreshTool(
child: _buildBody(),
onRefresh: () {
logic.sendGetDeviceModelBleMessage();
},
),
body: _buildBody(),
);
}
@ -61,30 +57,57 @@ class _SpeechLanguageSettingsPageState
() => SingleChildScrollView(
child: Column(
children: [
// Container(
// width: 1.sw,
// decoration: BoxDecoration(color: Colors.white),
// child: Column(
// children: [
// RadioListTile(
// title: Text("男声".tr),
// value: 1,
// groupValue: state.selectedValue.value,
// onChanged: (value) {
// state.selectedValue.value = int.parse(value.toString());
// },
// ),
// RadioListTile(
// title: Text("女声".tr),
// value: 2,
// groupValue: state.selectedValue.value,
// onChanged: (value) {
// state.selectedValue.value = int.parse(value.toString());
// },
// )
// ],
// ),
// ),
Container(
width: 1.sw,
decoration: BoxDecoration(color: Colors.white),
child: ListView.builder(
itemCount: state.soundTypeList.length,
itemBuilder: (BuildContext context, int index) {
// itemCount - 1
final isLastItem = index == state.soundTypeList.length - 1;
// platFormSet RxList<Platform>
final platform = state.soundTypeList.value[index];
return CommonItem(
leftTitel: state.soundTypeList.value[index],
rightTitle: '',
isHaveLine: !isLastItem,
// 线
isHaveDirection: false,
isHaveRightWidget: true,
rightWidget: Radio<String>(
// Radio 使 id
value: platform,
// selectPlatFormIndex id
groupValue: state.soundTypeList
.value[state.selectSoundTypeIndex.value],
//
activeColor: AppColors.mainColor,
// Radio
onChanged: (value) {
if (value != null) {
setState(() {
// id
final newIndex = state.soundTypeList.value
.indexWhere((p) => p == value);
if (newIndex != -1) {
state.selectSoundTypeIndex.value = newIndex;
}
});
}
},
),
action: () {
setState(() {
state.selectSoundTypeIndex.value = index;
});
},
);
},
shrinkWrap: true,
physics: const AlwaysScrollableScrollPhysics(),
),
),
SizedBox(
height: 8.h,
),
@ -98,72 +121,42 @@ class _SpeechLanguageSettingsPageState
}
List<Widget> _buildList() {
final languages = state.languages;
final appLocalLanguages = state.appLocalLanguages;
return List.generate(
languages.length,
(index) => _buildItem(languages[index], index),
);
}
_buildItem(PassthroughItem language, int index) {
final timbres = language.timbres;
final isSelected = state.selectPassthroughListIndex == index;
return ExpansionTile(
title: Text(
PassthroughLangHelper.getLangText(language.lang),
style: TextStyle(
fontSize: 24.sp,
fontWeight: isSelected ? FontWeight.bold : null,
),
),
onExpansionChanged: (bool expanded) {},
initiallyExpanded: false,
backgroundColor: Colors.white,
collapsedBackgroundColor: Colors.white,
expandedCrossAxisAlignment: CrossAxisAlignment.center,
expandedAlignment: Alignment.center,
shape: InputBorder.none,
maintainState: true,
//
collapsedShape: InputBorder.none,
//
childrenPadding: EdgeInsets.only(left: 12.w),
children: List.generate(
timbres.length,
(int languageIndex) => ListTile(
title: Text(
timbres[languageIndex].name,
style: TextStyle(
fontSize: 22.sp,
fontWeight:
state.selectLanguageIndex == languageIndex && isSelected
? FontWeight.bold
: null,
),
),
trailing: state.selectLanguageIndex == languageIndex && isSelected
? Icon(
Icons.check_circle,
color: AppColors.mainColor,
) //
: null, //
onTap: () {
//
state.selectLanguageIndex.value = languageIndex;
//
state.selectPassthroughListIndex.value = index;
}, // , //
),
appLocalLanguages.length,
(index) => _buildItem(
appLocalLanguages[index],
index,
),
);
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
if (EasyLoading.isShow) {
EasyLoading.dismiss(animation: true);
}
}
_buildItem(String appLocalLanguages, index) {
return CommonItem(
leftTitel: appLocalLanguages,
rightTitle: '',
isHaveLine: true,
isHaveDirection: false,
isHaveRightWidget: true,
rightWidget: state.selectPassthroughListIndex.value == index
? Image(
image: const AssetImage('images/icon_item_checked.png'),
width: 30.w,
height: 30.w,
fit: BoxFit.contain,
)
: Container(),
action: () {
state.selectPassthroughListIndex.value = index;
},
);
}
}

View File

@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart';
import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart';
import 'package:star_lock/translations/app_dept.dart';
class SpeechLanguageSettingsState {
SpeechLanguageSettingsState() {
@ -11,6 +12,25 @@ class SpeechLanguageSettingsState {
lockSetInfoData.value = map['lockSetInfoData'];
}
List<String> get appLocalLanguages {
final locales = appDept.deptSupportedLocales;
final languageCode = locales[1].languageCode;
final countryCode = locales[1].countryCode;
String localeStr = '';
if (countryCode != null) {
localeStr = languageCode + '_' + countryCode;
appLocalLanguageCodes.add(localeStr);
}
final list = locales
.map((e) => ExtensionLanguageType.fromLocale(e).lanTitle)
.toList();
return list;
}
List<String> appLocalLanguageCodes = [];
Rx<LockSetInfoData> lockSetInfoData = LockSetInfoData().obs;
//
@ -21,8 +41,6 @@ class SpeechLanguageSettingsState {
final RxList<PassthroughItem> languages = <PassthroughItem>[].obs;
Map<int, String> languageSpeechDeviceTypeMapping = {0: '2403'};
RxBool otaUpdateIng = false.obs;
RxDouble otaProgress = 0.00.obs;
RxString deviceModel = '2403'.obs;
@ -42,5 +60,15 @@ class SpeechLanguageSettingsState {
RxInt selectedValue = 1.obs;
// UI
final RxList<String> soundTypeList = List.of({
'男声'.tr,
'女声'.tr,
}).obs;
RxInt selectSoundTypeIndex = 0.obs;
RxString tempLangStr=''.obs;
RxString tempTimbreStr=''.obs;
}

View File

@ -0,0 +1,19 @@
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart';
import 'package:star_lock/tools/baseGetXController.dart';
class ThirdPartyPlatformLogic extends BaseGetXController {
ThirdPartyPlatformState state = ThirdPartyPlatformState();
void savePlatFormSetting() {
// showEasyLoading();
showToast('功能待开放'.tr);
// dismissEasyLoading();
}
@override
void dispose() {
dismissEasyLoading();
super.dispose();
}
}

View File

@ -0,0 +1,97 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:star_lock/app_settings/app_colors.dart';
import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_logic.dart';
import 'package:star_lock/main/lockDetail/lockSet/thirdPartyPlatform/third_party_platform_state.dart';
import 'package:star_lock/tools/commonItem.dart';
import 'package:star_lock/tools/titleAppBar.dart';
class ThirdPartyPlatformPage extends StatefulWidget {
const ThirdPartyPlatformPage();
@override
State<ThirdPartyPlatformPage> createState() => _ThirdPartyPlatformPageState();
}
class _ThirdPartyPlatformPageState extends State<ThirdPartyPlatformPage> {
final ThirdPartyPlatformLogic logic = Get.put(ThirdPartyPlatformLogic());
final ThirdPartyPlatformState state =
Get.find<ThirdPartyPlatformLogic>().state;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: TitleAppBar(
barTitle: '第三方平台设置'.tr,
haveBack: true,
backgroundColor: AppColors.mainColor,
actionsList: [
TextButton(
onPressed: logic.savePlatFormSetting,
child: Text(
'保存'.tr,
style: TextStyle(
color: Colors.white,
fontSize: 24.sp,
fontWeight: FontWeight.w500,
),
),
),
],
),
body: _buildBody(),
);
}
Widget _buildBody() {
return ListView.builder(
itemCount: state.platFormSet.length,
itemBuilder: (BuildContext context, int index) {
// itemCount - 1
final isLastItem = index == state.platFormSet.length - 1;
// platFormSet RxList<Platform>
final platform = state.platFormSet.value[index];
return CommonItem(
leftTitel: state.platFormSet.value[index],
rightTitle: '',
isHaveLine: !isLastItem,
// 线
isHaveDirection: false,
isHaveRightWidget: true,
rightWidget: Radio<String>(
// Radio 使 id
value: platform,
// selectPlatFormIndex id
groupValue:
state.platFormSet.value[state.selectPlatFormIndex.value],
//
activeColor: AppColors.mainColor,
// Radio
onChanged: (value) {
if (value != null) {
setState(() {
// id
final newIndex =
state.platFormSet.value.indexWhere((p) => p == value);
if (newIndex != -1) {
state.selectPlatFormIndex.value = newIndex;
}
});
}
},
),
action: () {
setState(() {
state.selectPlatFormIndex.value = index;
});
},
);
},
shrinkWrap: true,
physics: const AlwaysScrollableScrollPhysics(),
);
}
}

View File

@ -0,0 +1,24 @@
import 'dart:ui';
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart';
import 'package:star_lock/translations/app_dept.dart';
class ThirdPartyPlatformState {
ThirdPartyPlatformState() {
final map = Get.arguments;
lockSetInfoData.value = map['lockSetInfoData'];
}
Rx<LockSetInfoData> lockSetInfoData = LockSetInfoData().obs;
// UI
final RxList<String> platFormSet = List.of({
'锁通通'.tr,
'涂鸦智能'.tr,
}).obs;
RxInt selectPlatFormIndex = 0.obs;
}

View File

@ -25,6 +25,7 @@ import 'package:star_lock/tools/eventBusEventManage.dart';
import 'package:star_lock/tools/showTipView.dart';
import 'package:star_lock/tools/storage.dart';
import 'package:http/http.dart' as http;
import 'package:star_lock/translations/app_dept.dart';
class LockVoiceSettingLogic extends BaseGetXController {
LockVoiceSettingState state = LockVoiceSettingState();
@ -122,26 +123,31 @@ class LockVoiceSettingLogic extends BaseGetXController {
}
void saveSpeechLanguageSettings() async {
//
if (state.progress.value > 0) {
return;
}
final oldTimbre =
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre;
final oldLang =
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang;
final language =
state.appLocalLanguages[state.selectPassthroughListIndex.value];
// languageCode和countryCode
final locales = appDept.deptSupportedLocales;
locales.forEach((element) {
final lanTitle = ExtensionLanguageType.fromLocale(element).lanTitle;
if (lanTitle == language) {
if (element.countryCode != null) {
String code = element.languageCode + '_' + element.countryCode!;
EasyLoading.showProgress(state.progress.value, status: '正在发送数据');
final PassthroughItem item =
state.languages[state.selectPassthroughListIndex.value];
final timbre = item.timbres[state.selectLanguageIndex.value];
debugPrint('选中的语音是:${timbre}');
if ((oldLang != null && oldLang == item.lang) &&
(oldTimbre != null && oldTimbre == timbre.timbre)) {
showToast('已设置为当前选择的语音包'.tr);
}
state.languages.forEach((item) async {
if (item.lang == code) {
item.timbres.forEach((timbre) async {
if (timbre.isFemale == state.selectSoundTypeIndex.value) {
state.tempLangStr.value = item.lang;
state.tempTimbreStr.value = timbre.timbre;
await downloadFile(timbre.timbrePackUrl);
}
});
}
});
}
}
});
}
//
Future<void> downloadFile(String url) async {
@ -263,27 +269,28 @@ class LockVoiceSettingLogic extends BaseGetXController {
initList() async {
showEasyLoading();
try {
final PassthroughListResponse entity = await ApiRepository.to
.getPassthroughList(data: {'deviceType': state.deviceModel.value});
final vendor = state.lockSetInfoData.value.lockBasicInfo?.vendor;
final model = state.lockSetInfoData.value.lockBasicInfo?.model;
final PassthroughListResponse entity =
await ApiRepository.to.getPassthroughList(data: {
'vendor': vendor!,
'model': model!,
});
if (entity.errorCode!.codeIsSuccessful) {
state.languages.value = entity.data!!;
final oldTimbre = state
.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre;
final oldLang = state
final lang = state
.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang;
for (int index = 0; index < state.languages.value.length; index++) {
final element = state.languages.value[index];
final timbre = state
.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre;
state.languages.value.forEach((element) {
final timbres = element.timbres;
for (int i = 0; i < timbres.length; i++) {
final timbre = timbres[i].timbre;
if ((oldLang != null && oldLang == element.lang) &&
(oldTimbre != null && oldTimbre == timbre)) {
state.selectPassthroughListIndex.value = index;
state.selectLanguageIndex.value = i;
}
}
timbres.forEach((item) {
if (lang == element.lang && item.timbre == timbre) {
state.selectSoundTypeIndex.value = item.isFemale;
}
});
});
}
} catch (e) {
debugPrint('获取语音包出现错误:$e');

View File

@ -10,6 +10,7 @@ import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart';
import 'package:star_lock/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart';
import 'package:star_lock/mine/addLock/lock_voice_setting/lock_voice_setting_state.dart';
import 'package:star_lock/tools/EasyRefreshTool.dart';
import 'package:star_lock/tools/commonItem.dart';
import 'package:star_lock/tools/titleAppBar.dart';
class LockVoiceSetting extends StatefulWidget {
@ -25,11 +26,7 @@ class _LockVoiceSettingState extends State<LockVoiceSetting> {
@override
Widget build(BuildContext context) {
return EasyRefreshTool(
onRefresh: () {
logic.sendGetDeviceModelBleMessage();
},
child: Scaffold(
return Scaffold(
backgroundColor: AppColors.mainBackgroundColor,
appBar: TitleAppBar(
barTitle: '锁语音包设置'.tr,
@ -64,7 +61,6 @@ class _LockVoiceSettingState extends State<LockVoiceSetting> {
],
),
body: _buildBody(),
),
);
}
@ -72,70 +68,99 @@ class _LockVoiceSettingState extends State<LockVoiceSetting> {
return Obx(
() => SingleChildScrollView(
child: Column(
children: [
Container(
width: 1.sw,
decoration: BoxDecoration(color: Colors.white),
child: ListView.builder(
itemCount: state.soundTypeList.length,
itemBuilder: (BuildContext context, int index) {
// itemCount - 1
final isLastItem = index == state.soundTypeList.length - 1;
// platFormSet RxList<Platform>
final platform = state.soundTypeList.value[index];
return CommonItem(
leftTitel: state.soundTypeList.value[index],
rightTitle: '',
isHaveLine: !isLastItem,
// 线
isHaveDirection: false,
isHaveRightWidget: true,
rightWidget: Radio<String>(
// Radio 使 id
value: platform,
// selectPlatFormIndex id
groupValue: state.soundTypeList
.value[state.selectSoundTypeIndex.value],
//
activeColor: AppColors.mainColor,
// Radio
onChanged: (value) {
if (value != null) {
setState(() {
// id
final newIndex = state.soundTypeList.value
.indexWhere((p) => p == value);
if (newIndex != -1) {
state.selectSoundTypeIndex.value = newIndex;
}
});
}
},
),
action: () {
setState(() {
state.selectSoundTypeIndex.value = index;
});
},
);
},
shrinkWrap: true,
physics: const AlwaysScrollableScrollPhysics(),
),
),
SizedBox(
height: 8.h,
),
Column(
children: _buildList(),
),
],
),
),
);
}
List<Widget> _buildList() {
final languages = state.languages;
final appLocalLanguages = state.appLocalLanguages;
return List.generate(
languages.length,
(index) => _buildItem(languages[index], index),
appLocalLanguages.length,
(index) => _buildItem(
appLocalLanguages[index],
index,
),
);
}
_buildItem(PassthroughItem language, int index) {
final timbres = language.timbres;
final isSelected = state.selectPassthroughListIndex == index;
return ExpansionTile(
title: Text(
PassthroughLangHelper.getLangText(language.lang),
style: TextStyle(
fontSize: 24.sp,
fontWeight: isSelected ? FontWeight.bold : null,
),
),
onExpansionChanged: (bool expanded) {},
initiallyExpanded: false,
backgroundColor: Colors.white,
collapsedBackgroundColor: Colors.white,
expandedCrossAxisAlignment: CrossAxisAlignment.center,
expandedAlignment: Alignment.center,
shape: InputBorder.none,
maintainState: true,
//
collapsedShape: InputBorder.none,
//
childrenPadding: EdgeInsets.only(left: 12.w),
children: List.generate(
timbres.length,
(int languageIndex) => ListTile(
title: Text(
timbres[languageIndex].name,
style: TextStyle(
fontSize: 22.sp,
fontWeight:
state.selectLanguageIndex == languageIndex && isSelected
? FontWeight.bold
: null,
),
),
trailing: state.selectLanguageIndex == languageIndex && isSelected
? Icon(
Icons.check_circle,
color: AppColors.mainColor,
) //
: null, //
onTap: () {
//
state.selectLanguageIndex.value = languageIndex;
//
_buildItem(String appLocalLanguages, index) {
return CommonItem(
leftTitel: appLocalLanguages,
rightTitle: '',
isHaveLine: true,
isHaveDirection: false,
isHaveRightWidget: true,
rightWidget: state.selectPassthroughListIndex.value == index
? Image(
image: const AssetImage('images/icon_item_checked.png'),
width: 30.w,
height: 30.w,
fit: BoxFit.contain,
)
: Container(),
action: () {
state.selectPassthroughListIndex.value = index;
}, // , //
),
),
},
);
}

View File

@ -3,6 +3,7 @@ import 'dart:typed_data';
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart';
import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart';
import 'package:star_lock/translations/app_dept.dart';
class LockVoiceSettingState {
LockVoiceSettingState() {
@ -17,6 +18,24 @@ class LockVoiceSettingState {
List<String> get appLocalLanguages {
final locales = appDept.deptSupportedLocales;
final languageCode = locales[1].languageCode;
final countryCode = locales[1].countryCode;
String localeStr = '';
if (countryCode != null) {
localeStr = languageCode + '_' + countryCode;
appLocalLanguageCodes.add(localeStr);
}
final list = locales
.map((e) => ExtensionLanguageType.fromLocale(e).lanTitle)
.toList();
return list;
}
List<String> appLocalLanguageCodes = [];
//
RxInt selectPassthroughListIndex = 0.obs;
@ -43,5 +62,13 @@ class LockVoiceSettingState {
// 0.0~1.0
RxDouble progress = 0.0.obs;
// UI
final RxList<String> soundTypeList = List.of({
'男声'.tr,
'女声'.tr,
}).obs;
RxInt selectSoundTypeIndex = 0.obs;
RxString tempLangStr=''.obs;
RxString tempTimbreStr=''.obs;
}