mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
show livetime
tweak Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -10,7 +10,7 @@ import 'package:PiliPlus/http/loading_state.dart';
|
|||||||
import 'package:PiliPlus/models_new/dynamic/dyn_mention/group.dart';
|
import 'package:PiliPlus/models_new/dynamic/dyn_mention/group.dart';
|
||||||
import 'package:PiliPlus/pages/dynamics_mention/controller.dart';
|
import 'package:PiliPlus/pages/dynamics_mention/controller.dart';
|
||||||
import 'package:PiliPlus/pages/dynamics_mention/widgets/item.dart';
|
import 'package:PiliPlus/pages/dynamics_mention/widgets/item.dart';
|
||||||
import 'package:PiliPlus/pages/search/controller.dart';
|
import 'package:PiliPlus/pages/search/controller.dart' show SearchKeywordMixin;
|
||||||
import 'package:PiliPlus/utils/context_ext.dart';
|
import 'package:PiliPlus/utils/context_ext.dart';
|
||||||
import 'package:PiliPlus/utils/extension.dart';
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -80,8 +80,7 @@ class _DynMentionPanelState extends State<DynMentionPanel>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ValueChanged<String> get onKeywordChanged =>
|
void onKeywordChanged(String value) => _controller
|
||||||
(value) => _controller
|
|
||||||
..enableClear.value = value.isNotEmpty
|
..enableClear.value = value.isNotEmpty
|
||||||
..onRefresh().whenComplete(
|
..onRefresh().whenComplete(
|
||||||
() => WidgetsBinding.instance.addPostFrameCallback(
|
() => WidgetsBinding.instance.addPostFrameCallback(
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import 'package:PiliPlus/http/loading_state.dart';
|
|||||||
import 'package:PiliPlus/models_new/dynamic/dyn_topic_top/topic_item.dart';
|
import 'package:PiliPlus/models_new/dynamic/dyn_topic_top/topic_item.dart';
|
||||||
import 'package:PiliPlus/pages/dynamics_select_topic/controller.dart';
|
import 'package:PiliPlus/pages/dynamics_select_topic/controller.dart';
|
||||||
import 'package:PiliPlus/pages/dynamics_select_topic/widgets/item.dart';
|
import 'package:PiliPlus/pages/dynamics_select_topic/widgets/item.dart';
|
||||||
import 'package:PiliPlus/pages/search/controller.dart';
|
import 'package:PiliPlus/pages/search/controller.dart' show SearchKeywordMixin;
|
||||||
import 'package:PiliPlus/utils/context_ext.dart';
|
import 'package:PiliPlus/utils/context_ext.dart';
|
||||||
import 'package:PiliPlus/utils/extension.dart';
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -78,8 +78,7 @@ class _SelectTopicPanelState extends State<SelectTopicPanel>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ValueChanged<String> get onKeywordChanged =>
|
void onKeywordChanged(String value) => _controller
|
||||||
(value) => _controller
|
|
||||||
..enableClear.value = value.isNotEmpty
|
..enableClear.value = value.isNotEmpty
|
||||||
..onRefresh().whenComplete(
|
..onRefresh().whenComplete(
|
||||||
() => WidgetsBinding.instance.addPostFrameCallback(
|
() => WidgetsBinding.instance.addPostFrameCallback(
|
||||||
|
|||||||
@@ -38,6 +38,24 @@ class LiveRoomController extends GetxController {
|
|||||||
RxBool isLoaded = false.obs;
|
RxBool isLoaded = false.obs;
|
||||||
Rx<RoomInfoH5Data?> roomInfoH5 = Rx<RoomInfoH5Data?>(null);
|
Rx<RoomInfoH5Data?> roomInfoH5 = Rx<RoomInfoH5Data?>(null);
|
||||||
|
|
||||||
|
Rx<int?> liveTime = Rx<int?>(null);
|
||||||
|
static const periodMins = 5;
|
||||||
|
Timer? liveTimeTimer;
|
||||||
|
|
||||||
|
void startLiveTimer() {
|
||||||
|
if (liveTime.value != null) {
|
||||||
|
liveTimeTimer ??= Timer.periodic(
|
||||||
|
const Duration(minutes: periodMins),
|
||||||
|
(_) => liveTime.refresh(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancelLiveTimer() {
|
||||||
|
liveTimeTimer?.cancel();
|
||||||
|
liveTimeTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
// dm
|
// dm
|
||||||
LiveDmInfoData? dmInfo;
|
LiveDmInfoData? dmInfo;
|
||||||
List<RichTextItem>? savedDanmaku;
|
List<RichTextItem>? savedDanmaku;
|
||||||
@@ -104,6 +122,8 @@ class LiveRoomController extends GetxController {
|
|||||||
if (data.roomId != null) {
|
if (data.roomId != null) {
|
||||||
roomId = data.roomId!;
|
roomId = data.roomId!;
|
||||||
}
|
}
|
||||||
|
liveTime.value = data.liveTime;
|
||||||
|
startLiveTimer();
|
||||||
isPortrait.value = data.isPortrait ?? false;
|
isPortrait.value = data.isPortrait ?? false;
|
||||||
List<CodecItem> codec =
|
List<CodecItem> codec =
|
||||||
data.playurlInfo!.playurl!.stream!.first.format!.first.codec!;
|
data.playurlInfo!.playurl!.stream!.first.format!.first.codec!;
|
||||||
@@ -237,6 +257,7 @@ class LiveRoomController extends GetxController {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
|
cancelLiveTimer();
|
||||||
savedDanmaku?.clear();
|
savedDanmaku?.clear();
|
||||||
savedDanmaku = null;
|
savedDanmaku = null;
|
||||||
scrollController
|
scrollController
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart';
|
|||||||
import 'package:PiliPlus/plugin/pl_player/view.dart';
|
import 'package:PiliPlus/plugin/pl_player/view.dart';
|
||||||
import 'package:PiliPlus/services/service_locator.dart';
|
import 'package:PiliPlus/services/service_locator.dart';
|
||||||
import 'package:PiliPlus/utils/context_ext.dart';
|
import 'package:PiliPlus/utils/context_ext.dart';
|
||||||
|
import 'package:PiliPlus/utils/duration_util.dart';
|
||||||
import 'package:PiliPlus/utils/extension.dart';
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:PiliPlus/utils/page_utils.dart';
|
import 'package:PiliPlus/utils/page_utils.dart';
|
||||||
import 'package:PiliPlus/utils/storage.dart';
|
import 'package:PiliPlus/utils/storage.dart';
|
||||||
@@ -67,11 +68,14 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
if (status != PlayerStatus.playing) {
|
if (status != PlayerStatus.playing) {
|
||||||
plPlayerController.danmakuController?.pause();
|
plPlayerController.danmakuController?.pause();
|
||||||
_liveRoomController
|
_liveRoomController
|
||||||
|
..cancelLiveTimer()
|
||||||
..msgStream?.close()
|
..msgStream?.close()
|
||||||
..msgStream = null;
|
..msgStream = null;
|
||||||
} else {
|
} else {
|
||||||
plPlayerController.danmakuController?.resume();
|
plPlayerController.danmakuController?.resume();
|
||||||
_liveRoomController.liveMsg();
|
_liveRoomController
|
||||||
|
..startLiveTimer()
|
||||||
|
..liveMsg();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +98,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||||
if (state == AppLifecycleState.resumed) {
|
if (state == AppLifecycleState.resumed) {
|
||||||
if (!plPlayerController.showDanmaku) {
|
if (!plPlayerController.showDanmaku) {
|
||||||
|
_liveRoomController.startLiveTimer();
|
||||||
plPlayerController.showDanmaku = true;
|
plPlayerController.showDanmaku = true;
|
||||||
if (isFullScreen && Platform.isIOS) {
|
if (isFullScreen && Platform.isIOS) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
@@ -104,6 +109,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (state == AppLifecycleState.paused) {
|
} else if (state == AppLifecycleState.paused) {
|
||||||
|
_liveRoomController.cancelLiveTimer();
|
||||||
plPlayerController
|
plPlayerController
|
||||||
..showDanmaku = false
|
..showDanmaku = false
|
||||||
..danmakuController?.clear();
|
..danmakuController?.clear();
|
||||||
@@ -313,12 +319,12 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
title: Obx(
|
title: Obx(
|
||||||
() {
|
() {
|
||||||
RoomInfoH5Data? roomInfoH5 = _liveRoomController.roomInfoH5.value;
|
RoomInfoH5Data? roomInfoH5 = _liveRoomController.roomInfoH5.value;
|
||||||
return roomInfoH5 == null
|
if (roomInfoH5 == null) {
|
||||||
? const SizedBox.shrink()
|
return const SizedBox.shrink();
|
||||||
: GestureDetector(
|
}
|
||||||
|
return GestureDetector(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onTap: () =>
|
onTap: () => Get.toNamed('/member?mid=${roomInfoH5.roomInfo?.uid}'),
|
||||||
Get.toNamed('/member?mid=${roomInfoH5.roomInfo?.uid}'),
|
|
||||||
child: Row(
|
child: Row(
|
||||||
spacing: 10,
|
spacing: 10,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -337,12 +343,28 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
roomInfoH5.anchorInfo!.baseInfo!.uname!,
|
roomInfoH5.anchorInfo!.baseInfo!.uname!,
|
||||||
style: const TextStyle(fontSize: 14),
|
style: const TextStyle(fontSize: 14),
|
||||||
),
|
),
|
||||||
if (roomInfoH5.watchedShow?.textLarge?.isNotEmpty ==
|
Obx(() {
|
||||||
true)
|
final liveTime = _liveRoomController.liveTime.value;
|
||||||
Text(
|
final textLarge = roomInfoH5.watchedShow?.textLarge;
|
||||||
roomInfoH5.watchedShow!.textLarge!,
|
String text = '';
|
||||||
style: const TextStyle(fontSize: 12),
|
if (textLarge != null) {
|
||||||
),
|
text += textLarge;
|
||||||
|
}
|
||||||
|
if (liveTime != null) {
|
||||||
|
if (text.isNotEmpty) {
|
||||||
|
text += ' ';
|
||||||
|
}
|
||||||
|
text +=
|
||||||
|
'开播${DurationUtil.formatDurationBetween(
|
||||||
|
liveTime * 1000,
|
||||||
|
DateTime.now().millisecondsSinceEpoch,
|
||||||
|
)}';
|
||||||
|
}
|
||||||
|
if (text.isEmpty) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
return Text(text, style: const TextStyle(fontSize: 12));
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -351,18 +373,19 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
// IconButton(
|
||||||
tooltip: '刷新',
|
// tooltip: '刷新',
|
||||||
onPressed: _liveRoomController.queryLiveUrl,
|
// onPressed: _liveRoomController.queryLiveUrl,
|
||||||
icon: const Icon(Icons.refresh, size: 20),
|
// icon: const Icon(Icons.refresh, size: 20),
|
||||||
),
|
// ),
|
||||||
PopupMenuButton(
|
PopupMenuButton(
|
||||||
icon: const Icon(Icons.more_vert, size: 20),
|
icon: const Icon(Icons.more_vert, size: 20),
|
||||||
itemBuilder: (BuildContext context) => <PopupMenuEntry>[
|
itemBuilder: (BuildContext context) {
|
||||||
|
final liveUrl =
|
||||||
|
'https://live.bilibili.com/${_liveRoomController.roomId}';
|
||||||
|
return <PopupMenuEntry>[
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
onTap: () => Utils.copyText(
|
onTap: () => Utils.copyText(liveUrl),
|
||||||
'https://live.bilibili.com/${_liveRoomController.roomId}',
|
|
||||||
),
|
|
||||||
child: Row(
|
child: Row(
|
||||||
spacing: 10,
|
spacing: 10,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -377,9 +400,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
onTap: () => Utils.shareText(
|
onTap: () => Utils.shareText(liveUrl),
|
||||||
'https://live.bilibili.com/${_liveRoomController.roomId}',
|
|
||||||
),
|
|
||||||
child: Row(
|
child: Row(
|
||||||
spacing: 10,
|
spacing: 10,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -394,10 +415,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
onTap: () => PageUtils.inAppWebview(
|
onTap: () => PageUtils.inAppWebview(liveUrl, off: true),
|
||||||
'https://live.bilibili.com/h5/${_liveRoomController.roomId}',
|
|
||||||
off: true,
|
|
||||||
),
|
|
||||||
child: Row(
|
child: Row(
|
||||||
spacing: 10,
|
spacing: 10,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -423,8 +441,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
"cover": roomInfo.roomInfo!.cover!,
|
"cover": roomInfo.roomInfo!.cover!,
|
||||||
"sourceID": _liveRoomController.roomId.toString(),
|
"sourceID": _liveRoomController.roomId.toString(),
|
||||||
"title": roomInfo.roomInfo!.title!,
|
"title": roomInfo.roomInfo!.title!,
|
||||||
"url":
|
"url": liveUrl,
|
||||||
"https://live.bilibili.com/${_liveRoomController.roomId}",
|
|
||||||
"authorID": roomInfo.roomInfo!.uid.toString(),
|
"authorID": roomInfo.roomInfo!.uid.toString(),
|
||||||
"source": "直播",
|
"source": "直播",
|
||||||
"desc": roomInfo.roomInfo!.title!,
|
"desc": roomInfo.roomInfo!.title!,
|
||||||
@@ -448,7 +465,8 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
];
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ mixin SearchKeywordMixin {
|
|||||||
Duration duration = const Duration(milliseconds: 200);
|
Duration duration = const Duration(milliseconds: 200);
|
||||||
StreamController<String>? ctr;
|
StreamController<String>? ctr;
|
||||||
StreamSubscription<String>? sub;
|
StreamSubscription<String>? sub;
|
||||||
ValueChanged<String> get onKeywordChanged;
|
void onKeywordChanged(String value);
|
||||||
|
|
||||||
void subInit() {
|
void subInit() {
|
||||||
ctr = StreamController<String>();
|
ctr = StreamController<String>();
|
||||||
@@ -170,7 +170,7 @@ class SSearchController extends GetxController with SearchKeywordMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ValueChanged<String> get onKeywordChanged => (String value) async {
|
Future<void> onKeywordChanged(String value) async {
|
||||||
var res = await SearchHttp.searchSuggest(term: value);
|
var res = await SearchHttp.searchSuggest(term: value);
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
SearchSuggestModel data = res['data'];
|
SearchSuggestModel data = res['data'];
|
||||||
@@ -178,7 +178,7 @@ class SSearchController extends GetxController with SearchKeywordMixin {
|
|||||||
searchSuggestList.value = data.tag!;
|
searchSuggestList.value = data.tag!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
void onLongSelect(String word) {
|
void onLongSelect(String word) {
|
||||||
historyList.remove(word);
|
historyList.remove(word);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
|
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
|
||||||
import 'package:PiliPlus/pages/search/controller.dart';
|
import 'package:PiliPlus/pages/search/controller.dart' show SearchKeywordMixin;
|
||||||
import 'package:PiliPlus/pages/setting/models/extra_settings.dart';
|
import 'package:PiliPlus/pages/setting/models/extra_settings.dart';
|
||||||
import 'package:PiliPlus/pages/setting/models/model.dart';
|
import 'package:PiliPlus/pages/setting/models/model.dart';
|
||||||
import 'package:PiliPlus/pages/setting/models/play_settings.dart';
|
import 'package:PiliPlus/pages/setting/models/play_settings.dart';
|
||||||
@@ -39,7 +39,7 @@ class _SettingsSearchPageState extends State<SettingsSearchPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ValueChanged<String> get onKeywordChanged => (value) {
|
void onKeywordChanged(String value) {
|
||||||
if (value.isEmpty) {
|
if (value.isEmpty) {
|
||||||
_list.clear();
|
_list.clear();
|
||||||
} else {
|
} else {
|
||||||
@@ -54,7 +54,7 @@ class _SettingsSearchPageState extends State<SettingsSearchPage>
|
|||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
|||||||
@@ -32,4 +32,26 @@ class DurationUtil {
|
|||||||
}
|
}
|
||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String formatDurationBetween(int startMillis, int endMillis) {
|
||||||
|
int diffMillis = endMillis - startMillis;
|
||||||
|
final duration = Duration(milliseconds: diffMillis);
|
||||||
|
|
||||||
|
final years = duration.inDays ~/ 365;
|
||||||
|
final months = (duration.inDays % 365) ~/ 30;
|
||||||
|
final days = (duration.inDays % 365) % 30;
|
||||||
|
final hours = duration.inHours % 24;
|
||||||
|
final minutes = duration.inMinutes % 60;
|
||||||
|
|
||||||
|
var format = '';
|
||||||
|
|
||||||
|
if (years > 0) format += '$years年';
|
||||||
|
if (months > 0) format += '$months月';
|
||||||
|
if (days > 0) format += '$days天';
|
||||||
|
if (hours > 0) format += '$hours小时';
|
||||||
|
|
||||||
|
format += '$minutes分钟';
|
||||||
|
|
||||||
|
return format;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user