develop_sky #1
@ -71,21 +71,45 @@ class FirebaseHelper {
|
||||
}
|
||||
|
||||
Future<void> initSdk() async {
|
||||
FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true);
|
||||
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 {
|
||||
FirebaseAnalytics.instance.setUserId(id: userId);
|
||||
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 {
|
||||
FirebaseAnalytics.instance.setUserId(id: '');
|
||||
const bool isProductVmMode = bool.fromEnvironment('dart.vm.product');
|
||||
if (F.isProductionEnv &&
|
||||
isProductVmMode &&
|
||||
defaultTargetPlatform == TargetPlatform.android) {
|
||||
FirebaseAnalytics.instance.setUserId(id: '');
|
||||
}
|
||||
}
|
||||
}
|
||||
//</com>
|
||||
|
||||
@ -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播放页面
|
||||
];
|
||||
|
||||
@ -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(),
|
||||
};
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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()),
|
||||
),
|
||||
),
|
||||
|
||||
@ -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,26 +97,56 @@ 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);
|
||||
}
|
||||
await downloadFile(timbre.timbrePackUrl);
|
||||
// 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 的 code(格式:languageCode_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) {
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -40,7 +58,17 @@ class SpeechLanguageSettingsState {
|
||||
// 分包发送进度(0.0~1.0)
|
||||
RxDouble progress = 0.0.obs;
|
||||
|
||||
RxInt selectedValue = 1.obs;
|
||||
RxInt selectedValue = 1.obs;
|
||||
|
||||
// 响应式字符串集合(自动触发 UI 更新)
|
||||
final RxList<String> soundTypeList = List.of({
|
||||
'男声'.tr,
|
||||
'女声'.tr,
|
||||
}).obs;
|
||||
|
||||
RxInt selectSoundTypeIndex = 0.obs;
|
||||
|
||||
|
||||
RxString tempLangStr=''.obs;
|
||||
RxString tempTimbreStr=''.obs;
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
|
||||
}
|
||||
@ -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,25 +123,30 @@ 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);
|
||||
}
|
||||
await downloadFile(timbre.timbrePackUrl);
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//下载语音包
|
||||
@ -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');
|
||||
|
||||
@ -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,22 +26,31 @@ class _LockVoiceSettingState extends State<LockVoiceSetting> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return EasyRefreshTool(
|
||||
onRefresh: () {
|
||||
logic.sendGetDeviceModelBleMessage();
|
||||
},
|
||||
child: Scaffold(
|
||||
backgroundColor: AppColors.mainBackgroundColor,
|
||||
appBar: TitleAppBar(
|
||||
barTitle: '锁语音包设置'.tr,
|
||||
haveBack: false,
|
||||
haveOtherLeftWidget: true,
|
||||
leftWidget: TextButton(
|
||||
onPressed: () {
|
||||
Get.offAllNamed(Routers.starLockMain);
|
||||
},
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.mainBackgroundColor,
|
||||
appBar: TitleAppBar(
|
||||
barTitle: '锁语音包设置'.tr,
|
||||
haveBack: false,
|
||||
haveOtherLeftWidget: true,
|
||||
leftWidget: TextButton(
|
||||
onPressed: () {
|
||||
Get.offAllNamed(Routers.starLockMain);
|
||||
},
|
||||
child: Text(
|
||||
'跳过'.tr,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
backgroundColor: AppColors.mainColor,
|
||||
actionsList: [
|
||||
TextButton(
|
||||
onPressed: logic.saveSpeechLanguageSettings,
|
||||
child: Text(
|
||||
'跳过'.tr,
|
||||
'保存'.tr,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 24.sp,
|
||||
@ -48,23 +58,9 @@ class _LockVoiceSettingState extends State<LockVoiceSetting> {
|
||||
),
|
||||
),
|
||||
),
|
||||
backgroundColor: AppColors.mainColor,
|
||||
actionsList: [
|
||||
TextButton(
|
||||
onPressed: logic.saveSpeechLanguageSettings,
|
||||
child: Text(
|
||||
'保存'.tr,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: _buildBody(),
|
||||
],
|
||||
),
|
||||
body: _buildBody(),
|
||||
);
|
||||
}
|
||||
|
||||
@ -72,70 +68,99 @@ class _LockVoiceSettingState extends State<LockVoiceSetting> {
|
||||
return Obx(
|
||||
() => SingleChildScrollView(
|
||||
child: Column(
|
||||
children: _buildList(),
|
||||
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;
|
||||
// 更新选中的语言
|
||||
state.selectPassthroughListIndex.value = index;
|
||||
}, // 默认图标, // 右侧的图标
|
||||
),
|
||||
),
|
||||
_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;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user