feat: dynamic: custom publish time, custom reply option

This commit is contained in:
bggRGjQaUbCoE
2024-10-09 21:15:37 +08:00
parent 46daa23ad7
commit 848635ef97
4 changed files with 222 additions and 61 deletions

View File

@@ -1,6 +1,7 @@
import 'dart:io'; import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'package:PiliPalaX/http/constants.dart'; import 'package:PiliPalaX/http/constants.dart';
import 'package:PiliPalaX/pages/dynamics/view.dart' show ReplyOption;
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import '../models/msg/account.dart'; import '../models/msg/account.dart';
@@ -149,6 +150,8 @@ class MsgHttp {
dynamic dynIdStr, // repost dynamic dynIdStr, // repost
dynamic rawText, dynamic rawText,
List? pics, List? pics,
int? publishTime,
ReplyOption replyOption = ReplyOption.allow,
}) async { }) async {
String csrf = await Request.getCsrf(); String csrf = await Request.getCsrf();
var res = await Request().post( var res = await Request().post(
@@ -156,17 +159,26 @@ class MsgHttp {
queryParameters: { queryParameters: {
'platform': 'web', 'platform': 'web',
'csrf': csrf, 'csrf': csrf,
'x-bili-device-req-json[platform]': 'web', 'x-bili-device-req-json': {"platform": "web", "device": "pc"},
'x-bili-device-req-json[device]': 'pc', 'x-bili-web-req-json': {"spm_id": "333.999"},
'x-bili-web-req-json[spm_id]': 333.999,
}, },
data: { data: {
"dyn_req": { "dyn_req": {
"content": { "content": {
"contents": [ "contents": [
{"raw_text": rawText, "type": 1, "biz_id": ""} {
"raw_text": rawText,
"type": 1,
"biz_id": "",
}
] ]
}, },
if (dynIdStr == null)
"option": {
if (publishTime != null) "timer_pub_time": publishTime,
if (replyOption == ReplyOption.close) "close_comment": 1,
if (replyOption == ReplyOption.choose) "up_choose_comment": 1,
},
"scene": dynIdStr != null "scene": dynIdStr != null
? 4 ? 4
: pics != null : pics != null

View File

@@ -14,10 +14,17 @@ import 'package:hive/hive.dart';
import 'package:PiliPalaX/utils/feed_back.dart'; import 'package:PiliPalaX/utils/feed_back.dart';
import 'package:PiliPalaX/utils/storage.dart'; import 'package:PiliPalaX/utils/storage.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:intl/intl.dart';
import 'controller.dart'; import 'controller.dart';
import 'widgets/up_panel.dart'; import 'widgets/up_panel.dart';
enum ReplyOption { allow, close, choose }
extension ReplyOptionExtension on ReplyOption {
String get title => ['允许评论', '关闭评论', '精选评论'][index];
}
class DynamicsPage extends StatefulWidget { class DynamicsPage extends StatefulWidget {
const DynamicsPage({super.key}); const DynamicsPage({super.key});
@@ -234,6 +241,9 @@ class _CreatePanelState extends State<CreatePanel> {
late final _pathList = <String>[]; late final _pathList = <String>[];
late final _pathStream = StreamController<List<String>>(); late final _pathStream = StreamController<List<String>>();
DateTime? _publishTime;
ReplyOption _replyOption = ReplyOption.allow;
@override @override
void dispose() { void dispose() {
_isEnableStream.close(); _isEnableStream.close();
@@ -243,16 +253,18 @@ class _CreatePanelState extends State<CreatePanel> {
} }
Future _onCreate() async { Future _onCreate() async {
if (_pathList.isEmpty) { // if (_pathList.isEmpty) {
dynamic result = await MsgHttp.createTextDynamic(_ctr.text); // dynamic result = await MsgHttp.createTextDynamic(_ctr.text);
if (result['status']) { // if (result['status']) {
Get.back(); // Get.back();
SmartDialog.showToast('发布成功'); // SmartDialog.showToast('发布成功');
} else { // } else {
SmartDialog.showToast(result['msg']); // SmartDialog.showToast(result['msg']);
} // }
} else { // } else {
final pics = []; List? pics;
if (_pathList.isNotEmpty) {
pics = [];
for (int i = 0; i < _pathList.length; i++) { for (int i = 0; i < _pathList.length; i++) {
SmartDialog.showLoading(msg: '正在上传图片: ${i + 1}/${_pathList.length}'); SmartDialog.showLoading(msg: '正在上传图片: ${i + 1}/${_pathList.length}');
dynamic result = await MsgHttp.uploadBfs(_pathList[i]); dynamic result = await MsgHttp.uploadBfs(_pathList[i]);
@@ -273,18 +285,23 @@ class _CreatePanelState extends State<CreatePanel> {
SmartDialog.dismiss(); SmartDialog.dismiss();
} }
} }
dynamic result = await MsgHttp.createDynamic(
mid: GStorage.userInfo.get('userInfoCache').mid,
rawText: _ctr.text,
pics: pics,
);
if (result['status']) {
Get.back();
SmartDialog.showToast('发布成功');
} else {
SmartDialog.showToast(result['msg']);
}
} }
dynamic result = await MsgHttp.createDynamic(
mid: GStorage.userInfo.get('userInfoCache').mid,
rawText: _ctr.text,
pics: pics,
publishTime: _publishTime != null
? _publishTime!.millisecondsSinceEpoch ~/ 1000
: null,
replyOption: _replyOption,
);
if (result['status']) {
Get.back();
SmartDialog.showToast('发布成功');
} else {
SmartDialog.showToast(result['msg']);
}
// }
} }
@override @override
@@ -372,6 +389,136 @@ class _CreatePanelState extends State<CreatePanel> {
), ),
), ),
), ),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_publishTime == null
? FilledButton.tonal(
style: FilledButton.styleFrom(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 10,
),
visualDensity: const VisualDensity(
horizontal: -2,
vertical: -2,
),
),
onPressed: () {
DateTime nowDate = DateTime.now();
showDatePicker(
context: context,
initialDate: nowDate,
firstDate: nowDate,
lastDate: DateTime(
nowDate.year,
nowDate.month,
nowDate.day + 7,
),
).then(
(selectedDate) {
if (selectedDate != null && context.mounted) {
if (selectedDate.day == nowDate.day) {
SmartDialog.showToast('至少选择10分钟之后');
}
TimeOfDay nowTime = TimeOfDay.now();
showTimePicker(
context: context,
initialTime: TimeOfDay(
hour: nowTime.hour,
minute: nowTime.minute + 10,
),
).then((selectedTime) {
if (selectedTime != null) {
if (selectedDate.day == nowDate.day) {
if (selectedTime.hour < nowTime.hour) {
SmartDialog.showToast('时间设置错误');
return;
} else if (selectedTime.hour ==
nowTime.hour) {
if (selectedTime.minute <
nowTime.minute + 10) {
SmartDialog.showToast('时间设置错误');
return;
}
}
}
setState(() {
_publishTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
});
}
});
}
},
);
},
child: const Text('定时发布'),
)
: OutlinedButton.icon(
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 10,
),
visualDensity: const VisualDensity(
horizontal: -2,
vertical: -2,
),
),
onPressed: () {
setState(() {
_publishTime = null;
});
},
label: Text(
DateFormat('yyyy-MM-dd HH:mm').format(_publishTime!)),
icon: Icon(Icons.clear, size: 20),
iconAlignment: IconAlignment.end,
),
PopupMenuButton(
initialValue: _replyOption,
onSelected: (item) {
setState(() {
_replyOption = item;
});
},
itemBuilder: (context) => ReplyOption.values
.map((item) => PopupMenuItem<ReplyOption>(
value: item,
child: Text(item.title),
))
.toList(),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
_replyOption.title,
style: TextStyle(
height: 1,
color: Theme.of(context).colorScheme.primary,
),
strutStyle: StrutStyle(leading: 0, height: 1),
),
Icon(
size: 20,
Icons.keyboard_arrow_right,
color: Theme.of(context).colorScheme.primary,
)
],
),
)
],
),
),
const SizedBox(height: 10),
StreamBuilder( StreamBuilder(
initialData: const [], initialData: const [],
stream: _pathStream.stream, stream: _pathStream.stream,
@@ -386,43 +533,45 @@ class _CreatePanelState extends State<CreatePanel> {
itemCount: _pathList.length == 9 ? 9 : _pathList.length + 1, itemCount: _pathList.length == 9 ? 9 : _pathList.length + 1,
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (_pathList.length != 9 && index == _pathList.length) { if (_pathList.length != 9 && index == _pathList.length) {
return Ink( return Material(
width: 75, child: Ink(
height: 75, width: 75,
decoration: BoxDecoration( height: 75,
borderRadius: BorderRadius.circular(12), decoration: BoxDecoration(
color: Theme.of(context).colorScheme.secondaryContainer, borderRadius: BorderRadius.circular(12),
), color: Theme.of(context).colorScheme.secondaryContainer,
child: InkWell( ),
onTap: () async { child: InkWell(
List<XFile> pickedFiles = onTap: () async {
await _imagePicker.pickMultiImage( List<XFile> pickedFiles =
limit: 9, await _imagePicker.pickMultiImage(
imageQuality: 100, limit: 9,
); imageQuality: 100,
if (pickedFiles.isNotEmpty) { );
for (int i = 0; i < pickedFiles.length; i++) { if (pickedFiles.isNotEmpty) {
if (_pathList.length == 9) { for (int i = 0; i < pickedFiles.length; i++) {
SmartDialog.showToast('最多选择9张图片'); if (_pathList.length == 9) {
if (i != 0) { SmartDialog.showToast('最多选择9张图片');
_pathStream.add(_pathList); if (i != 0) {
} _pathStream.add(_pathList);
break; }
} else { break;
_pathList.add(pickedFiles[i].path); } else {
if (i == pickedFiles.length - 1) { _pathList.add(pickedFiles[i].path);
_pathStream.add(_pathList); if (i == pickedFiles.length - 1) {
_pathStream.add(_pathList);
}
} }
} }
if (_pathList.isNotEmpty && !_isEnable) {
_isEnable = true;
_isEnableStream.add(true);
}
} }
if (_pathList.isNotEmpty && !_isEnable) { },
_isEnable = true; borderRadius: BorderRadius.circular(12),
_isEnableStream.add(true); child: const Center(child: Icon(Icons.add)),
} ),
}
},
borderRadius: BorderRadius.circular(12),
child: const Center(child: Icon(Icons.add)),
), ),
); );
} else { } else {

View File

@@ -990,7 +990,7 @@ packages:
source: hosted source: hosted
version: "0.2.1+1" version: "0.2.1+1"
intl: intl:
dependency: transitive dependency: "direct main"
description: description:
name: intl name: intl
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf

View File

@@ -165,7 +165,7 @@ dependencies:
ref: main ref: main
path: packages/chat_bottom_container path: packages/chat_bottom_container
image_picker: ^1.1.2 image_picker: ^1.1.2
intl: ^0.19.0
dependency_overrides: dependency_overrides:
# mime: # mime: