|
|
|
@ -1,14 +1,68 @@ |
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
|
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
|
|
|
import 'package:get/get.dart'; |
|
|
|
import 'package:get_storage/get_storage.dart'; |
|
|
|
|
|
|
|
class SpeakerBottomSheet extends StatelessWidget { |
|
|
|
const SpeakerBottomSheet({super.key}); |
|
|
|
import '../../../data/services/db/sqflite_api.dart'; |
|
|
|
import '../controllers/meeting_details_controller.dart'; |
|
|
|
|
|
|
|
class SpeakerBottomSheet extends StatefulWidget { |
|
|
|
final int id; |
|
|
|
final String speakerName; |
|
|
|
|
|
|
|
const SpeakerBottomSheet(this.id, this.speakerName, {super.key}); |
|
|
|
|
|
|
|
@override |
|
|
|
State<SpeakerBottomSheet> createState() => _SpeakerBottomSheetState(); |
|
|
|
} |
|
|
|
|
|
|
|
class _SpeakerBottomSheetState extends State<SpeakerBottomSheet> { |
|
|
|
final _controller = Get.find<MeetingDetailsController>(); |
|
|
|
final GetStorage _storage = GetStorage(); |
|
|
|
|
|
|
|
final TextEditingController _speakerController = TextEditingController(); |
|
|
|
int _type = 1; |
|
|
|
List _historySpeakerList = []; |
|
|
|
List _speakerList = []; |
|
|
|
|
|
|
|
@override |
|
|
|
void initState() { |
|
|
|
super.initState(); |
|
|
|
_getSpeakerList(); |
|
|
|
} |
|
|
|
|
|
|
|
void _getSpeakerList() { |
|
|
|
_historySpeakerList = _storage.read("speaker_list") ?? []; |
|
|
|
List speakerList = List.from(_historySpeakerList); |
|
|
|
List textList = _controller.textList; |
|
|
|
for (var element in textList) { |
|
|
|
String speaker = element['speaker']; |
|
|
|
if (speaker.isNotEmpty && |
|
|
|
!RegExp(r'^Speaker \d+$').hasMatch(speaker) && |
|
|
|
!speakerList.contains(speaker)) { |
|
|
|
speakerList.add(speaker); |
|
|
|
} |
|
|
|
} |
|
|
|
setState(() { |
|
|
|
_speakerList = speakerList; |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
@override |
|
|
|
void dispose() { |
|
|
|
_speakerController.dispose(); |
|
|
|
super.dispose(); |
|
|
|
} |
|
|
|
|
|
|
|
@override |
|
|
|
Widget build(BuildContext context) { |
|
|
|
return Padding( |
|
|
|
padding: EdgeInsets.symmetric(horizontal: 12.w), |
|
|
|
padding: EdgeInsets.only( |
|
|
|
left: 12.w, |
|
|
|
right: 12.w, |
|
|
|
bottom: MediaQuery.of(context).viewInsets.bottom, |
|
|
|
), |
|
|
|
child: Column( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: [ |
|
|
|
@ -49,17 +103,45 @@ class SpeakerBottomSheet extends StatelessWidget { |
|
|
|
color: Colors.grey[300], |
|
|
|
), |
|
|
|
Container( |
|
|
|
height: 46.w, |
|
|
|
margin: EdgeInsets.symmetric(vertical: 15.w), |
|
|
|
alignment: Alignment.center, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Colors.white, |
|
|
|
borderRadius: BorderRadius.circular(12.r), |
|
|
|
), |
|
|
|
child: TextField( |
|
|
|
controller: _speakerController, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
color: Colors.black87, |
|
|
|
letterSpacing: 0, |
|
|
|
height: 1.4, |
|
|
|
), |
|
|
|
decoration: InputDecoration( |
|
|
|
hintText: widget.speakerName, |
|
|
|
hintStyle: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
color: Colors.grey[400], |
|
|
|
letterSpacing: 0, |
|
|
|
height: 1.4, |
|
|
|
), |
|
|
|
isDense: true, |
|
|
|
fillColor: Colors.transparent, |
|
|
|
border: InputBorder.none, |
|
|
|
contentPadding: EdgeInsets.symmetric( |
|
|
|
horizontal: 10.w, |
|
|
|
vertical: 12.w, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
Container( |
|
|
|
constraints: BoxConstraints(maxHeight: 1.sh - 390.w), |
|
|
|
constraints: BoxConstraints( |
|
|
|
maxHeight: |
|
|
|
1.sh - 390.w - MediaQuery.of(context).viewInsets.bottom, |
|
|
|
), |
|
|
|
child: ListView.builder( |
|
|
|
itemCount: 30, |
|
|
|
itemCount: _speakerList.length, |
|
|
|
shrinkWrap: true, |
|
|
|
itemBuilder: (BuildContext context, int index) { |
|
|
|
return Container( |
|
|
|
@ -83,15 +165,22 @@ class SpeakerBottomSheet extends StatelessWidget { |
|
|
|
color: Colors.grey[600]!, |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox( |
|
|
|
height: 42.w, |
|
|
|
child: Align( |
|
|
|
alignment: Alignment.centerLeft, |
|
|
|
child: Text( |
|
|
|
'龙哥', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 14.sp, |
|
|
|
color: Colors.black87, |
|
|
|
GestureDetector( |
|
|
|
onTap: () { |
|
|
|
_speakerController.text = _speakerList[index]; |
|
|
|
}, |
|
|
|
behavior: HitTestBehavior.translucent, |
|
|
|
child: SizedBox( |
|
|
|
width: 200.w, |
|
|
|
height: 42.w, |
|
|
|
child: Align( |
|
|
|
alignment: Alignment.centerLeft, |
|
|
|
child: Text( |
|
|
|
_speakerList[index], |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 14.sp, |
|
|
|
color: Colors.black87, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
@ -102,12 +191,25 @@ class SpeakerBottomSheet extends StatelessWidget { |
|
|
|
}, |
|
|
|
), |
|
|
|
), |
|
|
|
_row('应用到当前段落', false), |
|
|
|
_row('应用到这个发言者的所有段落', true, description: '总结将根据模版自动更新'), |
|
|
|
_row('应用到当前段落', _type == 0, onTap: () { |
|
|
|
setState(() { |
|
|
|
_type = 0; |
|
|
|
}); |
|
|
|
}), |
|
|
|
_row( |
|
|
|
'应用到这个发言者的所有段落', |
|
|
|
_type == 1, |
|
|
|
description: '总结将根据模版自动更新', |
|
|
|
onTap: () { |
|
|
|
setState(() { |
|
|
|
_type = 1; |
|
|
|
}); |
|
|
|
}, |
|
|
|
), |
|
|
|
Padding( |
|
|
|
padding: EdgeInsets.only(top: 10.w, bottom: 20.w), |
|
|
|
child: GestureDetector( |
|
|
|
onTap: () {}, |
|
|
|
onTap: _save, |
|
|
|
child: Container( |
|
|
|
height: 48.w, |
|
|
|
alignment: Alignment.center, |
|
|
|
@ -130,35 +232,39 @@ class SpeakerBottomSheet extends StatelessWidget { |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
Widget _row(String name, bool isActive, {String? description}) { |
|
|
|
return Padding( |
|
|
|
padding: EdgeInsets.symmetric(vertical: 10.w), |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
isActive ? _round() : _circle(), |
|
|
|
Expanded( |
|
|
|
child: Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
name, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 14.sp, |
|
|
|
color: Colors.black87, |
|
|
|
), |
|
|
|
), |
|
|
|
if (description != null) |
|
|
|
Widget _row(String name, bool isActive, |
|
|
|
{String? description, Function()? onTap}) { |
|
|
|
return GestureDetector( |
|
|
|
onTap: onTap, |
|
|
|
child: Padding( |
|
|
|
padding: EdgeInsets.symmetric(vertical: 10.w), |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
isActive ? _round() : _circle(), |
|
|
|
Expanded( |
|
|
|
child: Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
description, |
|
|
|
name, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 10.sp, |
|
|
|
color: Colors.grey[500]!, |
|
|
|
fontSize: 14.sp, |
|
|
|
color: Colors.black87, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
if (description != null) |
|
|
|
Text( |
|
|
|
description, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 10.sp, |
|
|
|
color: Colors.grey[500]!, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
@ -199,4 +305,75 @@ class SpeakerBottomSheet extends StatelessWidget { |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
void _save() { |
|
|
|
if (_speakerController.text.isNotEmpty && |
|
|
|
_speakerController.text != widget.speakerName) { |
|
|
|
if (_type == 0) { |
|
|
|
_single(); |
|
|
|
} else { |
|
|
|
_all(); |
|
|
|
} |
|
|
|
} else { |
|
|
|
Get.back(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void _single() async { |
|
|
|
EasyLoading.show(); |
|
|
|
List list = [ |
|
|
|
{ |
|
|
|
'id': widget.id, |
|
|
|
'speaker': _speakerController.text, |
|
|
|
} |
|
|
|
]; |
|
|
|
var result = await SqfliteApi.editMeetingSpeaker(list); |
|
|
|
if (result != null) { |
|
|
|
int index = |
|
|
|
_controller.textList.indexWhere((item) => item['id'] == widget.id); |
|
|
|
if (index != -1) { |
|
|
|
final dataMap = Map<String, dynamic>.from(_controller.textList[index]); |
|
|
|
dataMap['speaker'] = _speakerController.text; |
|
|
|
_controller.textList[index] = dataMap; |
|
|
|
} |
|
|
|
_addHistorySpeaker(); |
|
|
|
Get.back(); |
|
|
|
} |
|
|
|
EasyLoading.dismiss(); |
|
|
|
} |
|
|
|
|
|
|
|
void _all() async { |
|
|
|
EasyLoading.show(); |
|
|
|
List textList = _controller.textList; |
|
|
|
List newTextList = []; |
|
|
|
List editSpeakerList = []; |
|
|
|
for (var element in textList) { |
|
|
|
final dataMap = Map<String, dynamic>.from(element); |
|
|
|
if (dataMap['speaker'] == widget.speakerName) { |
|
|
|
dataMap['speaker'] = _speakerController.text; |
|
|
|
editSpeakerList.add({ |
|
|
|
'id': dataMap['id'], |
|
|
|
'speaker': dataMap['speaker'], |
|
|
|
}); |
|
|
|
} |
|
|
|
newTextList.add(dataMap); |
|
|
|
} |
|
|
|
var result = await SqfliteApi.editMeetingSpeaker(editSpeakerList); |
|
|
|
if (result != null) { |
|
|
|
_controller.textList.value = newTextList; |
|
|
|
_addHistorySpeaker(); |
|
|
|
Get.back(); |
|
|
|
} |
|
|
|
EasyLoading.dismiss(); |
|
|
|
} |
|
|
|
|
|
|
|
void _addHistorySpeaker() { |
|
|
|
String speaker = _speakerController.text; |
|
|
|
if (speaker.isNotEmpty && |
|
|
|
!RegExp(r'^Speaker \d+$').hasMatch(speaker) && |
|
|
|
!_historySpeakerList.contains(speaker)) { |
|
|
|
_historySpeakerList.add(speaker); |
|
|
|
_storage.write("speaker_list", _historySpeakerList); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|