mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-05-31 08:08:19 +08:00
feat: dynamic: custom publish time, custom reply option
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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,10 +285,15 @@ class _CreatePanelState extends State<CreatePanel> {
|
|||||||
SmartDialog.dismiss();
|
SmartDialog.dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
dynamic result = await MsgHttp.createDynamic(
|
dynamic result = await MsgHttp.createDynamic(
|
||||||
mid: GStorage.userInfo.get('userInfoCache').mid,
|
mid: GStorage.userInfo.get('userInfoCache').mid,
|
||||||
rawText: _ctr.text,
|
rawText: _ctr.text,
|
||||||
pics: pics,
|
pics: pics,
|
||||||
|
publishTime: _publishTime != null
|
||||||
|
? _publishTime!.millisecondsSinceEpoch ~/ 1000
|
||||||
|
: null,
|
||||||
|
replyOption: _replyOption,
|
||||||
);
|
);
|
||||||
if (result['status']) {
|
if (result['status']) {
|
||||||
Get.back();
|
Get.back();
|
||||||
@@ -284,7 +301,7 @@ class _CreatePanelState extends State<CreatePanel> {
|
|||||||
} else {
|
} else {
|
||||||
SmartDialog.showToast(result['msg']);
|
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,7 +533,8 @@ 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(
|
||||||
|
child: Ink(
|
||||||
width: 75,
|
width: 75,
|
||||||
height: 75,
|
height: 75,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@@ -424,6 +572,7 @@ class _CreatePanelState extends State<CreatePanel> {
|
|||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
child: const Center(child: Icon(Icons.add)),
|
child: const Center(child: Icon(Icons.add)),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user