Merge branch 'main' into opt-followUp
This commit is contained in:
@ -626,4 +626,7 @@ class Api {
|
|||||||
/// 修复标题和海报
|
/// 修复标题和海报
|
||||||
// /api/view?id=${aid} /all/video/av${aid} /video/av${aid}/
|
// /api/view?id=${aid} /all/video/av${aid} /video/av${aid}/
|
||||||
static const String fixTitleAndPic = '${HttpString.biliplusBaseUrl}/api/view';
|
static const String fixTitleAndPic = '${HttpString.biliplusBaseUrl}/api/view';
|
||||||
|
|
||||||
|
/// 专栏详情
|
||||||
|
static const String opusDetail = '/x/polymer/web-dynamic/v1/opus/detail';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -215,4 +215,25 @@ class DynamicsHttp {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future opusDetail({
|
||||||
|
required int opusId,
|
||||||
|
}) async {
|
||||||
|
var res = await Request().get(
|
||||||
|
Api.opusDetail,
|
||||||
|
data: {'id': opusId},
|
||||||
|
);
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
return {
|
||||||
|
'status': true,
|
||||||
|
'data': res.data['data'],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'status': false,
|
||||||
|
'data': [],
|
||||||
|
'msg': res.data['message'],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -216,6 +216,21 @@ class BuildMainApp extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
Box setting = GStorage.setting;
|
||||||
|
|
||||||
|
/// 纯黑模式主题配置
|
||||||
|
ColorScheme? pureDarkColorScheme;
|
||||||
|
final bool enablePureBlack =
|
||||||
|
setting.get(SettingBoxKey.enablePureBlack, defaultValue: false);
|
||||||
|
if (enablePureBlack) {
|
||||||
|
pureDarkColorScheme = darkColorScheme.copyWith(
|
||||||
|
background: Colors.black,
|
||||||
|
surface: Colors.black,
|
||||||
|
onPrimary: Colors.black,
|
||||||
|
onSecondary: Colors.black,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
final SnackBarThemeData snackBarTheme = SnackBarThemeData(
|
final SnackBarThemeData snackBarTheme = SnackBarThemeData(
|
||||||
actionTextColor: lightColorScheme.primary,
|
actionTextColor: lightColorScheme.primary,
|
||||||
backgroundColor: lightColorScheme.secondaryContainer,
|
backgroundColor: lightColorScheme.secondaryContainer,
|
||||||
@ -255,13 +270,13 @@ class BuildMainApp extends StatelessWidget {
|
|||||||
title: 'PiliPala',
|
title: 'PiliPala',
|
||||||
theme: buildThemeData(
|
theme: buildThemeData(
|
||||||
currentThemeValue == ThemeType.dark
|
currentThemeValue == ThemeType.dark
|
||||||
? darkColorScheme
|
? pureDarkColorScheme ?? darkColorScheme
|
||||||
: lightColorScheme,
|
: lightColorScheme,
|
||||||
),
|
),
|
||||||
darkTheme: buildThemeData(
|
darkTheme: buildThemeData(
|
||||||
currentThemeValue == ThemeType.light
|
currentThemeValue == ThemeType.light
|
||||||
? lightColorScheme
|
? lightColorScheme
|
||||||
: darkColorScheme,
|
: pureDarkColorScheme ?? darkColorScheme,
|
||||||
),
|
),
|
||||||
localizationsDelegates: const [
|
localizationsDelegates: const [
|
||||||
GlobalCupertinoLocalizations.delegate,
|
GlobalCupertinoLocalizations.delegate,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:pilipala/http/html.dart';
|
import 'package:pilipala/http/dynamics.dart';
|
||||||
import 'package:pilipala/http/reply.dart';
|
import 'package:pilipala/http/reply.dart';
|
||||||
import 'package:pilipala/models/common/reply_sort_type.dart';
|
import 'package:pilipala/models/common/reply_sort_type.dart';
|
||||||
import 'package:pilipala/models/video/reply/item.dart';
|
import 'package:pilipala/models/video/reply/item.dart';
|
||||||
@ -12,6 +12,7 @@ class DynamicDetailController extends GetxController {
|
|||||||
DynamicDetailController(this.oid, this.type);
|
DynamicDetailController(this.oid, this.type);
|
||||||
int? oid;
|
int? oid;
|
||||||
int? type;
|
int? type;
|
||||||
|
int? opusId;
|
||||||
dynamic item;
|
dynamic item;
|
||||||
int? floor;
|
int? floor;
|
||||||
String nextOffset = "";
|
String nextOffset = "";
|
||||||
@ -56,6 +57,12 @@ class DynamicDetailController extends GetxController {
|
|||||||
if (reqType == 'init') {
|
if (reqType == 'init') {
|
||||||
nextOffset = '';
|
nextOffset = '';
|
||||||
noMore.value = '';
|
noMore.value = '';
|
||||||
|
if (opusId != null && oid == 0) {
|
||||||
|
var res = await DynamicsHttp.opusDetail(opusId: opusId!);
|
||||||
|
if (res['status']) {
|
||||||
|
oid = int.parse(res['data']['item']['basic']['comment_id_str']);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var res = await ReplyHttp.replyList(
|
var res = await ReplyHttp.replyList(
|
||||||
oid: oid!,
|
oid: oid!,
|
||||||
@ -110,15 +117,12 @@ class DynamicDetailController extends GetxController {
|
|||||||
sortTypeTitle.value = _sortType.titles;
|
sortTypeTitle.value = _sortType.titles;
|
||||||
sortTypeLabel.value = _sortType.labels;
|
sortTypeLabel.value = _sortType.labels;
|
||||||
replyList.clear();
|
replyList.clear();
|
||||||
|
noMore.value = '';
|
||||||
|
isLoadingMore = false;
|
||||||
|
isEnd = false;
|
||||||
queryReplyList(reqType: 'init');
|
queryReplyList(reqType: 'init');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据jumpUrl获取动态html
|
|
||||||
reqHtmlByOpusId(int id) async {
|
|
||||||
var res = await HtmlHttp.reqHtml(id, 'opus');
|
|
||||||
oid = res['commentId'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上拉加载
|
// 上拉加载
|
||||||
Future onLoad() async {
|
Future onLoad() async {
|
||||||
queryReplyList(reqType: 'onLoad');
|
queryReplyList(reqType: 'onLoad');
|
||||||
|
|||||||
@ -89,9 +89,8 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
|||||||
_dynamicDetailController = Get.put(
|
_dynamicDetailController = Get.put(
|
||||||
DynamicDetailController(oid, replyType),
|
DynamicDetailController(oid, replyType),
|
||||||
tag: opusId.toString());
|
tag: opusId.toString());
|
||||||
|
_dynamicDetailController.opusId = opusId;
|
||||||
_futureBuilderFuture = _dynamicDetailController.queryReplyList();
|
_futureBuilderFuture = _dynamicDetailController.queryReplyList();
|
||||||
await _dynamicDetailController.reqHtmlByOpusId(opusId!);
|
|
||||||
setState(() {});
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oid = moduleDynamic.major!.draw!.id!;
|
oid = moduleDynamic.major!.draw!.id!;
|
||||||
|
|||||||
@ -194,26 +194,31 @@ class _LivePageState extends State<LivePage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
InkWell(
|
Obx(
|
||||||
onTap: () {
|
() => Visibility(
|
||||||
Get.toNamed('/liveFollowing');
|
visible: _liveController.liveFollowingCount.value > 0,
|
||||||
},
|
child: InkWell(
|
||||||
highlightColor: Colors.transparent,
|
onTap: () {
|
||||||
splashColor: Colors.transparent,
|
Get.toNamed('/liveFollowing');
|
||||||
child: Row(
|
},
|
||||||
children: [
|
highlightColor: Colors.transparent,
|
||||||
Text(
|
splashColor: Colors.transparent,
|
||||||
'查看更多',
|
child: Row(
|
||||||
style: TextStyle(
|
children: [
|
||||||
fontSize: 14,
|
Text(
|
||||||
color: Theme.of(context).colorScheme.outline,
|
'查看更多',
|
||||||
),
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Theme.of(context).colorScheme.outline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
Icons.chevron_right,
|
||||||
|
color: Theme.of(context).colorScheme.outline,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
Icon(
|
),
|
||||||
Icons.chevron_right,
|
|
||||||
color: Theme.of(context).colorScheme.outline,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -222,19 +227,18 @@ class _LivePageState extends State<LivePage>
|
|||||||
future: _futureBuilderFuture2,
|
future: _futureBuilderFuture2,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
if (snapshot.data == null) {
|
|
||||||
return const SizedBox();
|
|
||||||
}
|
|
||||||
Map? data = snapshot.data;
|
Map? data = snapshot.data;
|
||||||
if (data?['status']) {
|
if (data != null && data['status']) {
|
||||||
RxList list = _liveController.liveFollowingList;
|
RxList list = _liveController.liveFollowingList;
|
||||||
return LiveFollowingListView(list: list);
|
return list.isNotEmpty
|
||||||
|
? LiveFollowingListView(list: list)
|
||||||
|
: const Center(child: Text('没有人在直播'));
|
||||||
} else {
|
} else {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 80,
|
height: 80,
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
data?['msg'] ?? '',
|
data?['msg'] ?? '请求异常',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).colorScheme.outline,
|
color: Theme.of(context).colorScheme.outline,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
@ -283,6 +287,15 @@ class LiveFollowingListView extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
onLongPress: () {
|
||||||
|
Get.toNamed(
|
||||||
|
'/member?mid=${list[index].uid}',
|
||||||
|
arguments: {
|
||||||
|
'face': list[index].face,
|
||||||
|
'heroTag': list[index].uid.toString(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 54,
|
width: 54,
|
||||||
height: 54,
|
height: 54,
|
||||||
|
|||||||
@ -9,7 +9,7 @@ class LiveFollowController extends GetxController {
|
|||||||
RxInt crossAxisCount = 2.obs;
|
RxInt crossAxisCount = 2.obs;
|
||||||
Box setting = GStorage.setting;
|
Box setting = GStorage.setting;
|
||||||
int _currentPage = 1;
|
int _currentPage = 1;
|
||||||
RxInt liveFollowingCount = 0.obs;
|
RxString liveFollowingCount = '- '.obs;
|
||||||
RxList<LiveFollowingItemModel> liveFollowingList =
|
RxList<LiveFollowingItemModel> liveFollowingList =
|
||||||
<LiveFollowingItemModel>[].obs;
|
<LiveFollowingItemModel>[].obs;
|
||||||
|
|
||||||
@ -28,10 +28,11 @@ class LiveFollowController extends GetxController {
|
|||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
if (type == 'init') {
|
if (type == 'init') {
|
||||||
liveFollowingList.value = res['data'].list;
|
liveFollowingList.value = res['data'].list;
|
||||||
liveFollowingCount.value = res['data'].liveCount;
|
liveFollowingCount.value = res['data'].liveCount.toString();
|
||||||
} else if (type == 'onLoad') {
|
} else if (type == 'onLoad') {
|
||||||
liveFollowingList.addAll(res['data'].list);
|
liveFollowingList.addAll(res['data'].list);
|
||||||
}
|
}
|
||||||
|
liveFollowingList.removeWhere((e) => e.liveStatus != 1);
|
||||||
_currentPage += 1;
|
_currentPage += 1;
|
||||||
} else {
|
} else {
|
||||||
SmartDialog.showToast(res['msg']);
|
SmartDialog.showToast(res['msg']);
|
||||||
|
|||||||
@ -110,7 +110,8 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final mediaQuery = MediaQuery.of(context);
|
final mediaQuery = MediaQuery.of(context);
|
||||||
final isPortrait = mediaQuery.orientation == Orientation.portrait;
|
final isPortrait = mediaQuery.orientation == Orientation.portrait;
|
||||||
final isLandscape = mediaQuery.orientation == Orientation.landscape;
|
final RxBool isLandscape =
|
||||||
|
(mediaQuery.orientation == Orientation.landscape).obs;
|
||||||
|
|
||||||
final padding = mediaQuery.padding;
|
final padding = mediaQuery.padding;
|
||||||
|
|
||||||
@ -194,7 +195,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
Obx(
|
Obx(
|
||||||
() => SizedBox(
|
() => SizedBox(
|
||||||
height: padding.top +
|
height: padding.top +
|
||||||
(_liveRoomController.isPortrait.value || isLandscape
|
(_liveRoomController.isPortrait.value || isLandscape.value
|
||||||
? 0
|
? 0
|
||||||
: kToolbarHeight),
|
: kToolbarHeight),
|
||||||
),
|
),
|
||||||
@ -205,14 +206,14 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
if (plPlayerController.isFullScreen.value == true) {
|
if (plPlayerController.isFullScreen.value == true) {
|
||||||
plPlayerController.triggerFullScreen(status: false);
|
plPlayerController.triggerFullScreen(status: false);
|
||||||
}
|
}
|
||||||
if (isLandscape) {
|
if (isLandscape.value) {
|
||||||
verticalScreen();
|
verticalScreen();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Obx(
|
child: Obx(
|
||||||
() => Container(
|
() => Container(
|
||||||
width: Get.size.width,
|
width: Get.size.width,
|
||||||
height: isLandscape
|
height: isLandscape.value
|
||||||
? Get.size.height
|
? Get.size.height
|
||||||
: !_liveRoomController.isPortrait.value
|
: !_liveRoomController.isPortrait.value
|
||||||
? Get.size.width * 9 / 16
|
? Get.size.width * 9 / 16
|
||||||
@ -313,7 +314,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
),
|
),
|
||||||
// 消息列表
|
// 消息列表
|
||||||
Visibility(
|
Visibility(
|
||||||
visible: !isLandscape,
|
visible: !isLandscape.value,
|
||||||
child: Obx(
|
child: Obx(
|
||||||
() => Align(
|
() => Align(
|
||||||
alignment: Alignment.bottomCenter,
|
alignment: Alignment.bottomCenter,
|
||||||
|
|||||||
@ -249,6 +249,15 @@ class _StyleSettingState extends State<StyleSetting> {
|
|||||||
'当前模式:${settingController.themeType.value.description}',
|
'当前模式:${settingController.themeType.value.description}',
|
||||||
style: subTitleStyle)),
|
style: subTitleStyle)),
|
||||||
),
|
),
|
||||||
|
SetSwitchItem(
|
||||||
|
title: '纯黑模式',
|
||||||
|
subTitle: '深色模式时使用纯黑色背景,适用于OLED屏幕',
|
||||||
|
setKey: SettingBoxKey.enablePureBlack,
|
||||||
|
defaultVal: false,
|
||||||
|
callFn: (bool val) => {
|
||||||
|
if (val && Get.isDarkMode) {Get.appUpdate()}
|
||||||
|
},
|
||||||
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
dense: false,
|
dense: false,
|
||||||
onTap: () => settingController.setDynamicBadgeMode(context),
|
onTap: () => settingController.setDynamicBadgeMode(context),
|
||||||
|
|||||||
@ -276,7 +276,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
WidgetSpan(
|
WidgetSpan(
|
||||||
child: Visibility(
|
child: Visibility(
|
||||||
visible: widget.videoDetail!.copyright == 2,
|
visible: widget.videoDetail!.copyright == 2,
|
||||||
child: const PBadge(text: '转载', type: 'color'),
|
child: const PBadge(text: '转载', type: 'color', stack: 'relative'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const TextSpan(text: ' '),
|
const TextSpan(text: ' '),
|
||||||
|
|||||||
@ -73,7 +73,7 @@ class VideoReplyController extends GetxController {
|
|||||||
/// 临时修复
|
/// 临时修复
|
||||||
final bool flag = replyList
|
final bool flag = replyList
|
||||||
.any((ReplyItemModel reply) => reply.rpid == replies.first.rpid);
|
.any((ReplyItemModel reply) => reply.rpid == replies.first.rpid);
|
||||||
if (replies.length == 1 && flag) {
|
if (replies.length == 1 && flag && type == 'onLoad') {
|
||||||
replies.clear();
|
replies.clear();
|
||||||
isEnd = true;
|
isEnd = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -196,7 +196,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
|||||||
future: _futureBuilderFuture,
|
future: _futureBuilderFuture,
|
||||||
builder: (BuildContext context, snapshot) {
|
builder: (BuildContext context, snapshot) {
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
var data = snapshot.data;
|
Map? data = snapshot.data;
|
||||||
if (_videoReplyController.replyList.isNotEmpty ||
|
if (_videoReplyController.replyList.isNotEmpty ||
|
||||||
(data != null && data['status'])) {
|
(data != null && data['status'])) {
|
||||||
// 请求成功
|
// 请求成功
|
||||||
@ -258,7 +258,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
|||||||
} else {
|
} else {
|
||||||
// 请求错误
|
// 请求错误
|
||||||
return HttpError(
|
return HttpError(
|
||||||
errMsg: data['msg'],
|
errMsg: data?['msg'] ?? '请求异常',
|
||||||
fn: () {
|
fn: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_futureBuilderFuture =
|
_futureBuilderFuture =
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
||||||
import 'package:floating/floating.dart';
|
import 'package:floating/floating.dart';
|
||||||
@ -76,7 +77,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
getStatusHeight();
|
getStatusHeight();
|
||||||
heroTag = Get.arguments['heroTag'];
|
heroTag = Get.arguments['heroTag'];
|
||||||
vdCtr = Get.put(VideoDetailController(), tag: heroTag);
|
vdCtr = Get.put(VideoDetailController(), tag: heroTag);
|
||||||
vdCtr.sheetHeight.value = localCache.get('sheetHeight');
|
vdCtr.sheetHeight.value = GlobalDataCache.sheetHeight;
|
||||||
videoIntroController = Get.put(
|
videoIntroController = Get.put(
|
||||||
VideoIntroController(bvid: Get.parameters['bvid']!),
|
VideoIntroController(bvid: Get.parameters['bvid']!),
|
||||||
tag: heroTag);
|
tag: heroTag);
|
||||||
@ -223,8 +224,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
void _extendNestCtrListener() {
|
void _extendNestCtrListener() {
|
||||||
final double offset = _extendNestCtr.position.pixels;
|
final double offset = _extendNestCtr.position.pixels;
|
||||||
if (vdCtr.videoDirection.value == 'horizontal') {
|
if (vdCtr.videoDirection.value == 'horizontal') {
|
||||||
vdCtr.sheetHeight.value =
|
vdCtr.sheetHeight.value = max(GlobalDataCache.sheetHeight,
|
||||||
Get.size.height - videoHeight - statusBarHeight + offset;
|
Get.size.height - videoHeight - statusBarHeight + offset);
|
||||||
appbarStream.add(offset);
|
appbarStream.add(offset);
|
||||||
} else {
|
} else {
|
||||||
if (offset > (Get.size.width * 22 / 16 - videoHeight)) {
|
if (offset > (Get.size.width * 22 / 16 - videoHeight)) {
|
||||||
|
|||||||
@ -1068,13 +1068,10 @@ class _HeaderControlState extends State<HeaderControl> {
|
|||||||
);
|
);
|
||||||
final bool isLandscape =
|
final bool isLandscape =
|
||||||
MediaQuery.of(context).orientation == Orientation.landscape;
|
MediaQuery.of(context).orientation == Orientation.landscape;
|
||||||
return AppBar(
|
return Padding(
|
||||||
backgroundColor: Colors.transparent,
|
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||||
foregroundColor: Colors.white,
|
child: Column(
|
||||||
primary: false,
|
mainAxisSize: MainAxisSize.min,
|
||||||
automaticallyImplyLeading: false,
|
|
||||||
titleSpacing: 14,
|
|
||||||
title: Column(
|
|
||||||
children: [
|
children: [
|
||||||
if (isFullScreen.value && isLandscape) ...[
|
if (isFullScreen.value && isLandscape) ...[
|
||||||
Row(
|
Row(
|
||||||
@ -1083,10 +1080,7 @@ class _HeaderControlState extends State<HeaderControl> {
|
|||||||
if (videoIntroController.isShowOnlineTotal)
|
if (videoIntroController.isShowOnlineTotal)
|
||||||
Text(
|
Text(
|
||||||
'${videoIntroController.total.value}人正在看',
|
'${videoIntroController.total.value}人正在看',
|
||||||
style: const TextStyle(
|
style: textStyle,
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -1097,18 +1091,12 @@ class _HeaderControlState extends State<HeaderControl> {
|
|||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
String currentTime = _formatTime(snapshot.data!);
|
String currentTime = _formatTime(snapshot.data!);
|
||||||
return Text(
|
return Text(currentTime, style: textStyle);
|
||||||
currentTime,
|
|
||||||
style: const TextStyle(fontSize: 12),
|
|
||||||
);
|
|
||||||
} else if (snapshot.connectionState ==
|
} else if (snapshot.connectionState ==
|
||||||
ConnectionState.waiting) {
|
ConnectionState.waiting) {
|
||||||
// 如果Stream还未发出数据,先显示初始获取的时间
|
// 如果Stream还未发出数据,先显示初始获取的时间
|
||||||
String currentTime = _formatTime(initialTime);
|
String currentTime = _formatTime(initialTime);
|
||||||
return Text(
|
return Text(currentTime, style: textStyle);
|
||||||
currentTime,
|
|
||||||
style: const TextStyle(fontSize: 12),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
}
|
}
|
||||||
@ -1159,7 +1147,8 @@ class _HeaderControlState extends State<HeaderControl> {
|
|||||||
() => Marquee(
|
() => Marquee(
|
||||||
text: videoIntroController.videoDetail.value.title ??
|
text: videoIntroController.videoDetail.value.title ??
|
||||||
'',
|
'',
|
||||||
style: const TextStyle(fontSize: 16),
|
style: const TextStyle(
|
||||||
|
fontSize: 16, color: Colors.white),
|
||||||
scrollAxis: Axis.horizontal,
|
scrollAxis: Axis.horizontal,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
blankSpace: constraints.maxWidth,
|
blankSpace: constraints.maxWidth,
|
||||||
|
|||||||
@ -45,36 +45,44 @@ class WhisperController extends GetxController {
|
|||||||
if (isLoading) return;
|
if (isLoading) return;
|
||||||
var res = await MsgHttp.sessionList(
|
var res = await MsgHttp.sessionList(
|
||||||
endTs: type == 'onLoad' ? sessionList.last.sessionTs : null);
|
endTs: type == 'onLoad' ? sessionList.last.sessionTs : null);
|
||||||
if (res['status'] &&
|
try {
|
||||||
res['data'].sessionList != null &&
|
if (res['status'] &&
|
||||||
res['data'].sessionList.isNotEmpty) {
|
res['data'].sessionList != null &&
|
||||||
await queryAccountList(res['data'].sessionList);
|
res['data'].sessionList.isNotEmpty) {
|
||||||
// 将 accountList 转换为 Map 结构
|
await queryAccountList(res['data'].sessionList);
|
||||||
Map<int, dynamic> accountMap = {};
|
// 将 accountList 转换为 Map 结构
|
||||||
for (var j in accountList) {
|
Map<int, dynamic> accountMap = {};
|
||||||
accountMap[j.mid!] = j;
|
for (var j in accountList) {
|
||||||
}
|
accountMap[j.mid!] = j;
|
||||||
|
}
|
||||||
|
|
||||||
// 遍历 sessionList,通过 mid 查找并赋值 accountInfo
|
// 遍历 sessionList,通过 mid 查找并赋值 accountInfo
|
||||||
for (var i in res['data'].sessionList) {
|
for (var i in res['data'].sessionList) {
|
||||||
var accountInfo = accountMap[i.talkerId];
|
var accountInfo = accountMap[i.talkerId];
|
||||||
if (accountInfo != null) {
|
if (accountInfo != null) {
|
||||||
i.accountInfo = accountInfo;
|
i.accountInfo = accountInfo;
|
||||||
|
}
|
||||||
|
if (i.talkerId == 844424930131966) {
|
||||||
|
i.accountInfo = AccountListModel(
|
||||||
|
name: 'UP主小助手',
|
||||||
|
face:
|
||||||
|
'https://message.biliimg.com/bfs/im/489a63efadfb202366c2f88853d2217b5ddc7a13.png',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (i.talkerId == 844424930131966) {
|
if (type == 'onLoad') {
|
||||||
i.accountInfo = AccountListModel(
|
sessionList.addAll(res['data'].sessionList);
|
||||||
name: 'UP主小助手',
|
} else {
|
||||||
face:
|
sessionList.value = res['data'].sessionList;
|
||||||
'https://message.biliimg.com/bfs/im/489a63efadfb202366c2f88853d2217b5ddc7a13.png',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type == 'onLoad') {
|
} catch (err) {
|
||||||
sessionList.addAll(res['data'].sessionList);
|
res = {
|
||||||
} else {
|
'status': false,
|
||||||
sessionList.value = res['data'].sessionList;
|
'message': err.toString(),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,7 +44,24 @@ class _WhisperPageState extends State<WhisperPage> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: const Text('消息')),
|
appBar: AppBar(
|
||||||
|
title: const Text('消息'),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.open_in_browser_rounded,
|
||||||
|
color: Theme.of(context).colorScheme.primary),
|
||||||
|
tooltip: '用浏览器打开',
|
||||||
|
onPressed: () {
|
||||||
|
Get.toNamed('/webview', parameters: {
|
||||||
|
'url': 'https://message.bilibili.com',
|
||||||
|
'type': 'whisper',
|
||||||
|
'pageTitle': '消息中心',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12)
|
||||||
|
],
|
||||||
|
),
|
||||||
body: RefreshIndicator(
|
body: RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
_whisperController.unread();
|
_whisperController.unread();
|
||||||
|
|||||||
@ -521,6 +521,7 @@ class SystemNotice extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Map content = item.content ?? '';
|
Map content = item.content ?? '';
|
||||||
|
Color primary = Theme.of(context).colorScheme.primary;
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
@ -557,12 +558,35 @@ class SystemNotice extends StatelessWidget {
|
|||||||
.labelSmall!
|
.labelSmall!
|
||||||
.copyWith(color: Theme.of(context).colorScheme.outline),
|
.copyWith(color: Theme.of(context).colorScheme.outline),
|
||||||
),
|
),
|
||||||
Divider(
|
Divider(color: primary.withOpacity(0.05)),
|
||||||
color: Theme.of(context).colorScheme.primary.withOpacity(0.05),
|
SelectableText(content['text']),
|
||||||
),
|
if (content['jump_text'] != null &&
|
||||||
SelectableText(
|
content['jump_uri'] != null) ...[
|
||||||
content['text'],
|
Divider(color: primary.withOpacity(0.05)),
|
||||||
)
|
Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Get.toNamed('/webview', parameters: {
|
||||||
|
'url': content['jump_uri'],
|
||||||
|
'type': 'url',
|
||||||
|
'pageTitle': content['jump_text'] == ''
|
||||||
|
? '查看详情'
|
||||||
|
: content['jump_text'],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor:
|
||||||
|
MaterialStateProperty.resolveWith((states) {
|
||||||
|
return primary.withAlpha(20);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
child: Text(content['jump_text'] == ''
|
||||||
|
? '查看详情'
|
||||||
|
: content['jump_text']),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -292,10 +292,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||||
),
|
),
|
||||||
child: const Text(
|
child: const Text('选集', style: textStyle),
|
||||||
'选集',
|
|
||||||
style: TextStyle(color: Colors.white, fontSize: 13),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -310,14 +307,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||||
),
|
),
|
||||||
child: Obx(
|
child: Obx(
|
||||||
() => Text(
|
() => Text(_.videoFitDEsc.value, style: textStyle),
|
||||||
_.videoFitDEsc.value,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -339,10 +329,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
height: 40,
|
height: 40,
|
||||||
padding: const EdgeInsets.only(left: 20),
|
padding: const EdgeInsets.only(left: 20),
|
||||||
value: speed,
|
value: speed,
|
||||||
child: Text(
|
child: Text('${speed}x', style: textStyle),
|
||||||
'${speed}x',
|
|
||||||
style: textStyle.copyWith(fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
},
|
},
|
||||||
@ -352,10 +339,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
margin: const EdgeInsets.only(right: 4),
|
margin: const EdgeInsets.only(right: 4),
|
||||||
child: Obx(
|
child: Obx(
|
||||||
() => Text(
|
() => Text('${_.playbackSpeed.toString()}x', style: textStyle),
|
||||||
'${_.playbackSpeed.toString()}x',
|
|
||||||
style: textStyle.copyWith(fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -443,336 +427,338 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
);
|
);
|
||||||
return Stack(
|
return ClipRect(
|
||||||
fit: StackFit.passthrough,
|
child: Stack(
|
||||||
children: <Widget>[
|
fit: StackFit.passthrough,
|
||||||
Obx(
|
children: <Widget>[
|
||||||
() => Video(
|
Obx(
|
||||||
key: ValueKey(_.videoFit.value),
|
() => Video(
|
||||||
controller: videoController,
|
key: ValueKey(_.videoFit.value),
|
||||||
controls: NoVideoControls,
|
controller: videoController,
|
||||||
alignment: widget.alignment!,
|
controls: NoVideoControls,
|
||||||
pauseUponEnteringBackgroundMode: !enableBackgroundPlay,
|
alignment: widget.alignment!,
|
||||||
resumeUponEnteringForegroundMode: true,
|
pauseUponEnteringBackgroundMode: !enableBackgroundPlay,
|
||||||
subtitleViewConfiguration: const SubtitleViewConfiguration(
|
resumeUponEnteringForegroundMode: true,
|
||||||
style: subTitleStyle,
|
subtitleViewConfiguration: const SubtitleViewConfiguration(
|
||||||
padding: EdgeInsets.all(24.0),
|
style: subTitleStyle,
|
||||||
|
padding: EdgeInsets.all(24.0),
|
||||||
|
),
|
||||||
|
fit: _.videoFit.value,
|
||||||
),
|
),
|
||||||
fit: _.videoFit.value,
|
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
/// 长按倍速 toast
|
/// 长按倍速 toast
|
||||||
Obx(
|
Obx(
|
||||||
() => Align(
|
() => Align(
|
||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
child: FractionalTranslation(
|
child: FractionalTranslation(
|
||||||
translation: const Offset(0.0, 0.3), // 上下偏移量(负数向上偏移)
|
translation: const Offset(0.0, 0.3), // 上下偏移量(负数向上偏移)
|
||||||
child: AnimatedOpacity(
|
child: AnimatedOpacity(
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
opacity: _.doubleSpeedStatus.value ? 1.0 : 0.0,
|
opacity: _.doubleSpeedStatus.value ? 1.0 : 0.0,
|
||||||
duration: const Duration(milliseconds: 150),
|
duration: const Duration(milliseconds: 150),
|
||||||
child: Container(
|
child: Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0x88000000),
|
color: const Color(0x88000000),
|
||||||
borderRadius: BorderRadius.circular(16.0),
|
borderRadius: BorderRadius.circular(16.0),
|
||||||
),
|
|
||||||
height: 32.0,
|
|
||||||
width: 70.0,
|
|
||||||
child: const Center(
|
|
||||||
child: Text(
|
|
||||||
'倍速中',
|
|
||||||
style: TextStyle(color: Colors.white, fontSize: 13),
|
|
||||||
),
|
),
|
||||||
)),
|
height: 32.0,
|
||||||
|
width: 70.0,
|
||||||
|
child: const Center(
|
||||||
|
child: Text(
|
||||||
|
'倍速中',
|
||||||
|
style: TextStyle(color: Colors.white, fontSize: 13),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
/// 时间进度 toast
|
/// 时间进度 toast
|
||||||
Obx(
|
Obx(
|
||||||
() => Align(
|
() => Align(
|
||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
child: FractionalTranslation(
|
child: FractionalTranslation(
|
||||||
translation: const Offset(0.0, 1.0), // 上下偏移量(负数向上偏移)
|
translation: const Offset(0.0, 1.0), // 上下偏移量(负数向上偏移)
|
||||||
child: AnimatedOpacity(
|
child: AnimatedOpacity(
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
opacity: _.isSliderMoving.value ? 1.0 : 0.0,
|
opacity: _.isSliderMoving.value ? 1.0 : 0.0,
|
||||||
duration: const Duration(milliseconds: 150),
|
duration: const Duration(milliseconds: 150),
|
||||||
child: IntrinsicWidth(
|
child: IntrinsicWidth(
|
||||||
child: Container(
|
child: Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0x88000000),
|
color: const Color(0x88000000),
|
||||||
borderRadius: BorderRadius.circular(64.0),
|
borderRadius: BorderRadius.circular(64.0),
|
||||||
),
|
),
|
||||||
height: 34.0,
|
height: 34.0,
|
||||||
padding: const EdgeInsets.only(left: 10, right: 10),
|
padding: const EdgeInsets.only(left: 10, right: 10),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Obx(() {
|
Obx(() {
|
||||||
return Text(
|
return Text(
|
||||||
_.sliderTempPosition.value.inMinutes >= 60
|
_.sliderTempPosition.value.inMinutes >= 60
|
||||||
? printDurationWithHours(
|
? printDurationWithHours(
|
||||||
_.sliderTempPosition.value)
|
_.sliderTempPosition.value)
|
||||||
: printDuration(_.sliderTempPosition.value),
|
: printDuration(_.sliderTempPosition.value),
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
const SizedBox(width: 2),
|
const SizedBox(width: 2),
|
||||||
const Text('/', style: textStyle),
|
const Text('/', style: textStyle),
|
||||||
const SizedBox(width: 2),
|
const SizedBox(width: 2),
|
||||||
Obx(
|
Obx(
|
||||||
() => Text(
|
() => Text(
|
||||||
_.duration.value.inMinutes >= 60
|
_.duration.value.inMinutes >= 60
|
||||||
? printDurationWithHours(_.duration.value)
|
? printDurationWithHours(_.duration.value)
|
||||||
: printDuration(_.duration.value),
|
: printDuration(_.duration.value),
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
/// 音量🔊 控制条展示
|
/// 音量🔊 控制条展示
|
||||||
Obx(
|
Obx(
|
||||||
() => ControlBar(
|
() => ControlBar(
|
||||||
visible: _volumeIndicator.value,
|
visible: _volumeIndicator.value,
|
||||||
icon: _volumeValue.value < 1.0 / 3.0
|
icon: _volumeValue.value < 1.0 / 3.0
|
||||||
? Icons.volume_mute
|
? Icons.volume_mute
|
||||||
: _volumeValue.value < 2.0 / 3.0
|
: _volumeValue.value < 2.0 / 3.0
|
||||||
? Icons.volume_down
|
? Icons.volume_down
|
||||||
: Icons.volume_up,
|
: Icons.volume_up,
|
||||||
value: _volumeValue.value,
|
value: _volumeValue.value,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
/// 亮度🌞 控制条展示
|
/// 亮度🌞 控制条展示
|
||||||
Obx(
|
Obx(
|
||||||
() => ControlBar(
|
() => ControlBar(
|
||||||
visible: _brightnessIndicator.value,
|
visible: _brightnessIndicator.value,
|
||||||
icon: _brightnessValue.value < 1.0 / 3.0
|
icon: _brightnessValue.value < 1.0 / 3.0
|
||||||
? Icons.brightness_low
|
? Icons.brightness_low
|
||||||
: _brightnessValue.value < 2.0 / 3.0
|
: _brightnessValue.value < 2.0 / 3.0
|
||||||
? Icons.brightness_medium
|
? Icons.brightness_medium
|
||||||
: Icons.brightness_high,
|
: Icons.brightness_high,
|
||||||
value: _brightnessValue.value,
|
value: _brightnessValue.value,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
// Obx(() {
|
// Obx(() {
|
||||||
// if (_.buffered.value == Duration.zero) {
|
// if (_.buffered.value == Duration.zero) {
|
||||||
// return Positioned.fill(
|
// return Positioned.fill(
|
||||||
// child: Container(
|
// child: Container(
|
||||||
// color: Colors.black,
|
// color: Colors.black,
|
||||||
// child: Center(
|
// child: Center(
|
||||||
// child: Image.asset(
|
// child: Image.asset(
|
||||||
// 'assets/images/loading.gif',
|
// 'assets/images/loading.gif',
|
||||||
// height: 25,
|
// height: 25,
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
// );
|
// );
|
||||||
// } else {
|
// } else {
|
||||||
// return Container();
|
// return Container();
|
||||||
// }
|
// }
|
||||||
// }),
|
// }),
|
||||||
|
|
||||||
/// 弹幕面板
|
/// 弹幕面板
|
||||||
if (widget.danmuWidget != null)
|
if (widget.danmuWidget != null)
|
||||||
Positioned.fill(top: 4, child: widget.danmuWidget!),
|
Positioned.fill(top: 4, child: widget.danmuWidget!),
|
||||||
|
|
||||||
/// 开启且有字幕时展示
|
/// 开启且有字幕时展示
|
||||||
Stack(
|
Stack(
|
||||||
children: [
|
children: [
|
||||||
Positioned(
|
Positioned(
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
bottom: 30,
|
bottom: 30,
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: Obx(
|
child: Obx(
|
||||||
() => Visibility(
|
() => Visibility(
|
||||||
visible: widget.controller.subTitleCode.value != -1,
|
visible: widget.controller.subTitleCode.value != -1,
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
color: widget.controller.subtitleContent.value != ''
|
color: widget.controller.subtitleContent.value != ''
|
||||||
? Colors.black.withOpacity(0.6)
|
? Colors.black.withOpacity(0.6)
|
||||||
: Colors.transparent,
|
: Colors.transparent,
|
||||||
),
|
|
||||||
padding: widget.controller.subTitleCode.value != -1
|
|
||||||
? const EdgeInsets.symmetric(
|
|
||||||
horizontal: 10,
|
|
||||||
vertical: 4,
|
|
||||||
)
|
|
||||||
: EdgeInsets.zero,
|
|
||||||
child: Text(
|
|
||||||
widget.controller.subtitleContent.value,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
),
|
||||||
),
|
padding: widget.controller.subTitleCode.value != -1
|
||||||
)),
|
? const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 4,
|
||||||
|
)
|
||||||
|
: EdgeInsets.zero,
|
||||||
|
child: Text(
|
||||||
|
widget.controller.subtitleContent.value,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
|
||||||
),
|
|
||||||
|
|
||||||
/// 手势
|
|
||||||
Positioned.fill(
|
|
||||||
left: 16,
|
|
||||||
top: 25,
|
|
||||||
right: 15,
|
|
||||||
bottom: 15,
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
_.controls = !_.showControls.value;
|
|
||||||
},
|
|
||||||
onDoubleTapDown: (TapDownDetails details) {
|
|
||||||
// live模式下禁用 锁定时🔒禁用
|
|
||||||
if (_.videoType == 'live' || _.controlsLock.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final double totalWidth = MediaQuery.sizeOf(context).width;
|
|
||||||
final double tapPosition = details.localPosition.dx;
|
|
||||||
final double sectionWidth = totalWidth / 3;
|
|
||||||
String type = 'left';
|
|
||||||
if (tapPosition < sectionWidth) {
|
|
||||||
type = 'left';
|
|
||||||
} else if (tapPosition < sectionWidth * 2) {
|
|
||||||
type = 'center';
|
|
||||||
} else {
|
|
||||||
type = 'right';
|
|
||||||
}
|
|
||||||
doubleTapFuc(type);
|
|
||||||
},
|
|
||||||
onLongPressStart: (LongPressStartDetails detail) {
|
|
||||||
feedBack();
|
|
||||||
_.setDoubleSpeedStatus(true);
|
|
||||||
},
|
|
||||||
onLongPressEnd: (LongPressEndDetails details) {
|
|
||||||
_.setDoubleSpeedStatus(false);
|
|
||||||
},
|
|
||||||
|
|
||||||
/// 水平位置 快进 live模式下禁用
|
|
||||||
onHorizontalDragUpdate: (DragUpdateDetails details) {
|
|
||||||
// live模式下禁用 锁定时🔒禁用
|
|
||||||
if (_.videoType == 'live' || _.controlsLock.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// final double tapPosition = details.localPosition.dx;
|
|
||||||
final int curSliderPosition =
|
|
||||||
_.sliderPosition.value.inMilliseconds;
|
|
||||||
final double scale = 90000 / MediaQuery.sizeOf(context).width;
|
|
||||||
final Duration pos = Duration(
|
|
||||||
milliseconds:
|
|
||||||
curSliderPosition + (details.delta.dx * scale).round());
|
|
||||||
final Duration result =
|
|
||||||
pos.clamp(Duration.zero, _.duration.value);
|
|
||||||
_.onUpdatedSliderProgress(result);
|
|
||||||
_.onChangedSliderStart();
|
|
||||||
},
|
|
||||||
onHorizontalDragEnd: (DragEndDetails details) {
|
|
||||||
if (_.videoType == 'live' || _.controlsLock.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_.onChangedSliderEnd();
|
|
||||||
_.seekTo(_.sliderPosition.value, type: 'slider');
|
|
||||||
},
|
|
||||||
// 垂直方向 音量/亮度调节
|
|
||||||
onVerticalDragUpdate: (DragUpdateDetails details) async {
|
|
||||||
final double totalWidth = MediaQuery.sizeOf(context).width;
|
|
||||||
final double tapPosition = details.localPosition.dx;
|
|
||||||
final double sectionWidth =
|
|
||||||
fullScreenGestureMode == FullScreenGestureMode.none
|
|
||||||
? totalWidth / 2
|
|
||||||
: totalWidth / 3;
|
|
||||||
final double delta = details.delta.dy;
|
|
||||||
|
|
||||||
/// 锁定时禁用
|
|
||||||
if (_.controlsLock.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (lastFullScreenToggleTime != null &&
|
|
||||||
DateTime.now().difference(lastFullScreenToggleTime!) <
|
|
||||||
const Duration(milliseconds: 500)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (tapPosition < sectionWidth) {
|
|
||||||
// 左边区域 👈
|
|
||||||
final double level = (_.isFullScreen.value
|
|
||||||
? Get.size.height
|
|
||||||
: screenWidth * 9 / 16) *
|
|
||||||
3;
|
|
||||||
final double brightness =
|
|
||||||
_brightnessValue.value - delta / level;
|
|
||||||
final double result = brightness.clamp(0.0, 1.0);
|
|
||||||
setBrightness(result);
|
|
||||||
} else if (isUsingFullScreenGestures(tapPosition, sectionWidth)) {
|
|
||||||
// 全屏
|
|
||||||
final double dy = details.delta.dy;
|
|
||||||
const double threshold = 7.0; // 滑动阈值
|
|
||||||
final bool flag = fullScreenGestureMode !=
|
|
||||||
FullScreenGestureMode.fromBottomtoTop;
|
|
||||||
if (dy > _distance.value &&
|
|
||||||
dy > threshold &&
|
|
||||||
!_.controlsLock.value) {
|
|
||||||
if (_.isFullScreen.value ^ flag) {
|
|
||||||
lastFullScreenToggleTime = DateTime.now();
|
|
||||||
// 下滑退出全屏
|
|
||||||
await widget.controller.triggerFullScreen(status: flag);
|
|
||||||
widget.fullScreenCb?.call(flag);
|
|
||||||
}
|
|
||||||
_distance.value = 0.0;
|
|
||||||
} else if (dy < _distance.value &&
|
|
||||||
dy < -threshold &&
|
|
||||||
!_.controlsLock.value) {
|
|
||||||
if (!_.isFullScreen.value ^ flag) {
|
|
||||||
lastFullScreenToggleTime = DateTime.now();
|
|
||||||
// 上滑进入全屏
|
|
||||||
await widget.controller.triggerFullScreen(status: !flag);
|
|
||||||
widget.fullScreenCb?.call(!flag);
|
|
||||||
}
|
|
||||||
_distance.value = 0.0;
|
|
||||||
}
|
|
||||||
_distance.value = dy;
|
|
||||||
} else {
|
|
||||||
// 右边区域 👈
|
|
||||||
EasyThrottle.throttle(
|
|
||||||
'setVolume', const Duration(milliseconds: 20), () {
|
|
||||||
final double level = (_.isFullScreen.value
|
|
||||||
? Get.size.height
|
|
||||||
: screenWidth * 9 / 16);
|
|
||||||
final double volume = _volumeValue.value -
|
|
||||||
double.parse(delta.toStringAsFixed(1)) / level;
|
|
||||||
final double result = volume.clamp(0.0, 1.0);
|
|
||||||
setVolume(result);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onVerticalDragEnd: (DragEndDetails details) {},
|
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
// 头部、底部控制条
|
/// 手势
|
||||||
Obx(
|
Positioned.fill(
|
||||||
() => Column(
|
left: 16,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
top: 25,
|
||||||
children: [
|
right: 15,
|
||||||
if (widget.headerControl != null || _.headerControl != null) ...[
|
bottom: 15,
|
||||||
Flexible(
|
child: GestureDetector(
|
||||||
child: ClipRect(
|
onTap: () {
|
||||||
|
_.controls = !_.showControls.value;
|
||||||
|
},
|
||||||
|
onDoubleTapDown: (TapDownDetails details) {
|
||||||
|
// live模式下禁用 锁定时🔒禁用
|
||||||
|
if (_.videoType == 'live' || _.controlsLock.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final double totalWidth = MediaQuery.sizeOf(context).width;
|
||||||
|
final double tapPosition = details.localPosition.dx;
|
||||||
|
final double sectionWidth = totalWidth / 3;
|
||||||
|
String type = 'left';
|
||||||
|
if (tapPosition < sectionWidth) {
|
||||||
|
type = 'left';
|
||||||
|
} else if (tapPosition < sectionWidth * 2) {
|
||||||
|
type = 'center';
|
||||||
|
} else {
|
||||||
|
type = 'right';
|
||||||
|
}
|
||||||
|
doubleTapFuc(type);
|
||||||
|
},
|
||||||
|
onLongPressStart: (LongPressStartDetails detail) {
|
||||||
|
feedBack();
|
||||||
|
_.setDoubleSpeedStatus(true);
|
||||||
|
},
|
||||||
|
onLongPressEnd: (LongPressEndDetails details) {
|
||||||
|
_.setDoubleSpeedStatus(false);
|
||||||
|
},
|
||||||
|
|
||||||
|
/// 水平位置 快进 live模式下禁用
|
||||||
|
onHorizontalDragUpdate: (DragUpdateDetails details) {
|
||||||
|
// live模式下禁用 锁定时🔒禁用
|
||||||
|
if (_.videoType == 'live' || _.controlsLock.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// final double tapPosition = details.localPosition.dx;
|
||||||
|
final int curSliderPosition =
|
||||||
|
_.sliderPosition.value.inMilliseconds;
|
||||||
|
final double scale = 90000 / MediaQuery.sizeOf(context).width;
|
||||||
|
final Duration pos = Duration(
|
||||||
|
milliseconds:
|
||||||
|
curSliderPosition + (details.delta.dx * scale).round());
|
||||||
|
final Duration result =
|
||||||
|
pos.clamp(Duration.zero, _.duration.value);
|
||||||
|
_.onUpdatedSliderProgress(result);
|
||||||
|
_.onChangedSliderStart();
|
||||||
|
},
|
||||||
|
onHorizontalDragEnd: (DragEndDetails details) {
|
||||||
|
if (_.videoType == 'live' || _.controlsLock.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_.onChangedSliderEnd();
|
||||||
|
_.seekTo(_.sliderPosition.value, type: 'slider');
|
||||||
|
},
|
||||||
|
// 垂直方向 音量/亮度调节
|
||||||
|
onVerticalDragUpdate: (DragUpdateDetails details) async {
|
||||||
|
final double totalWidth = MediaQuery.sizeOf(context).width;
|
||||||
|
final double tapPosition = details.localPosition.dx;
|
||||||
|
final double sectionWidth =
|
||||||
|
fullScreenGestureMode == FullScreenGestureMode.none
|
||||||
|
? totalWidth / 2
|
||||||
|
: totalWidth / 3;
|
||||||
|
final double delta = details.delta.dy;
|
||||||
|
|
||||||
|
/// 锁定时禁用
|
||||||
|
if (_.controlsLock.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (lastFullScreenToggleTime != null &&
|
||||||
|
DateTime.now().difference(lastFullScreenToggleTime!) <
|
||||||
|
const Duration(milliseconds: 500)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tapPosition < sectionWidth) {
|
||||||
|
// 左边区域 👈
|
||||||
|
final double level = (_.isFullScreen.value
|
||||||
|
? Get.size.height
|
||||||
|
: screenWidth * 9 / 16) *
|
||||||
|
3;
|
||||||
|
final double brightness =
|
||||||
|
_brightnessValue.value - delta / level;
|
||||||
|
final double result = brightness.clamp(0.0, 1.0);
|
||||||
|
setBrightness(result);
|
||||||
|
} else if (isUsingFullScreenGestures(
|
||||||
|
tapPosition, sectionWidth)) {
|
||||||
|
// 全屏
|
||||||
|
final double dy = details.delta.dy;
|
||||||
|
const double threshold = 7.0; // 滑动阈值
|
||||||
|
final bool flag = fullScreenGestureMode !=
|
||||||
|
FullScreenGestureMode.fromBottomtoTop;
|
||||||
|
if (dy > _distance.value &&
|
||||||
|
dy > threshold &&
|
||||||
|
!_.controlsLock.value) {
|
||||||
|
if (_.isFullScreen.value ^ flag) {
|
||||||
|
lastFullScreenToggleTime = DateTime.now();
|
||||||
|
// 下滑退出全屏
|
||||||
|
await widget.controller.triggerFullScreen(status: flag);
|
||||||
|
widget.fullScreenCb?.call(flag);
|
||||||
|
}
|
||||||
|
_distance.value = 0.0;
|
||||||
|
} else if (dy < _distance.value &&
|
||||||
|
dy < -threshold &&
|
||||||
|
!_.controlsLock.value) {
|
||||||
|
if (!_.isFullScreen.value ^ flag) {
|
||||||
|
lastFullScreenToggleTime = DateTime.now();
|
||||||
|
// 上滑进入全屏
|
||||||
|
await widget.controller.triggerFullScreen(status: !flag);
|
||||||
|
widget.fullScreenCb?.call(!flag);
|
||||||
|
}
|
||||||
|
_distance.value = 0.0;
|
||||||
|
}
|
||||||
|
_distance.value = dy;
|
||||||
|
} else {
|
||||||
|
// 右边区域 👈
|
||||||
|
EasyThrottle.throttle(
|
||||||
|
'setVolume', const Duration(milliseconds: 20), () {
|
||||||
|
final double level = (_.isFullScreen.value
|
||||||
|
? Get.size.height
|
||||||
|
: screenWidth * 9 / 16);
|
||||||
|
final double volume = _volumeValue.value -
|
||||||
|
double.parse(delta.toStringAsFixed(1)) / level;
|
||||||
|
final double result = volume.clamp(0.0, 1.0);
|
||||||
|
setVolume(result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onVerticalDragEnd: (DragEndDetails details) {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// 头部、底部控制条
|
||||||
|
Obx(
|
||||||
|
() => Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
if (widget.headerControl != null ||
|
||||||
|
_.headerControl != null) ...[
|
||||||
|
Flexible(
|
||||||
child: AppBarAni(
|
child: AppBarAni(
|
||||||
controller: animationController,
|
controller: animationController,
|
||||||
visible: !_.controlsLock.value && _.showControls.value,
|
visible: !_.controlsLock.value && _.showControls.value,
|
||||||
@ -780,13 +766,11 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
child: widget.headerControl ?? _.headerControl!,
|
child: widget.headerControl ?? _.headerControl!,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
] else ...[
|
||||||
] else ...[
|
const SizedBox.shrink()
|
||||||
const SizedBox.shrink()
|
],
|
||||||
],
|
Flexible(
|
||||||
Flexible(
|
flex: _.videoType == 'live' ? 0 : 1,
|
||||||
flex: _.videoType == 'live' ? 0 : 1,
|
|
||||||
child: ClipRect(
|
|
||||||
child: AppBarAni(
|
child: AppBarAni(
|
||||||
controller: animationController,
|
controller: animationController,
|
||||||
visible: !_.controlsLock.value && _.showControls.value,
|
visible: !_.controlsLock.value && _.showControls.value,
|
||||||
@ -799,141 +783,141 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
/// 进度条 live模式下禁用
|
/// 进度条 live模式下禁用
|
||||||
|
|
||||||
Obx(
|
Obx(
|
||||||
() {
|
() {
|
||||||
final int value = _.sliderPositionSeconds.value;
|
final int value = _.sliderPositionSeconds.value;
|
||||||
final int max = _.durationSeconds.value;
|
final int max = _.durationSeconds.value;
|
||||||
final int buffer = _.bufferedSeconds.value;
|
final int buffer = _.bufferedSeconds.value;
|
||||||
if (_.showControls.value) {
|
if (_.showControls.value) {
|
||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
if (defaultBtmProgressBehavior ==
|
if (defaultBtmProgressBehavior ==
|
||||||
BtmProgresBehavior.alwaysHide.code) {
|
BtmProgresBehavior.alwaysHide.code) {
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
}
|
}
|
||||||
if (defaultBtmProgressBehavior ==
|
if (defaultBtmProgressBehavior ==
|
||||||
BtmProgresBehavior.onlyShowFullScreen.code &&
|
BtmProgresBehavior.onlyShowFullScreen.code &&
|
||||||
!_.isFullScreen.value) {
|
!_.isFullScreen.value) {
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
} else if (defaultBtmProgressBehavior ==
|
} else if (defaultBtmProgressBehavior ==
|
||||||
BtmProgresBehavior.onlyHideFullScreen.code &&
|
BtmProgresBehavior.onlyHideFullScreen.code &&
|
||||||
_.isFullScreen.value) {
|
_.isFullScreen.value) {
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_.videoType == 'live') {
|
if (_.videoType == 'live') {
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
}
|
}
|
||||||
if (value > max || max <= 0) {
|
if (value > max || max <= 0) {
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
}
|
}
|
||||||
return Positioned(
|
return Positioned(
|
||||||
bottom: -1.5,
|
bottom: -1.5,
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
child: ProgressBar(
|
child: ProgressBar(
|
||||||
progress: Duration(seconds: value),
|
progress: Duration(seconds: value),
|
||||||
buffered: Duration(seconds: buffer),
|
buffered: Duration(seconds: buffer),
|
||||||
total: Duration(seconds: max),
|
total: Duration(seconds: max),
|
||||||
progressBarColor: colorTheme,
|
progressBarColor: colorTheme,
|
||||||
baseBarColor: Colors.white.withOpacity(0.2),
|
baseBarColor: Colors.white.withOpacity(0.2),
|
||||||
bufferedBarColor: Colors.white.withOpacity(0.6),
|
bufferedBarColor: Colors.white.withOpacity(0.6),
|
||||||
timeLabelLocation: TimeLabelLocation.none,
|
timeLabelLocation: TimeLabelLocation.none,
|
||||||
thumbColor: colorTheme,
|
thumbColor: colorTheme,
|
||||||
barHeight: 3,
|
barHeight: 3,
|
||||||
thumbRadius: 0.0,
|
thumbRadius: 0.0,
|
||||||
// onDragStart: (duration) {
|
// onDragStart: (duration) {
|
||||||
// _.onChangedSliderStart();
|
// _.onChangedSliderStart();
|
||||||
// },
|
// },
|
||||||
// onDragEnd: () {
|
// onDragEnd: () {
|
||||||
// _.onChangedSliderEnd();
|
// _.onChangedSliderEnd();
|
||||||
// },
|
// },
|
||||||
// onDragUpdate: (details) {
|
// onDragUpdate: (details) {
|
||||||
// print(details);
|
// print(details);
|
||||||
// },
|
// },
|
||||||
// onSeek: (duration) {
|
// onSeek: (duration) {
|
||||||
// feedBack();
|
// feedBack();
|
||||||
// _.onChangedSlider(duration.inSeconds.toDouble());
|
// _.onChangedSlider(duration.inSeconds.toDouble());
|
||||||
// _.seekTo(duration);
|
// _.seekTo(duration);
|
||||||
// },
|
// },
|
||||||
),
|
),
|
||||||
// SlideTransition(
|
// SlideTransition(
|
||||||
// position: Tween<Offset>(
|
// position: Tween<Offset>(
|
||||||
// begin: Offset.zero,
|
// begin: Offset.zero,
|
||||||
// end: const Offset(0, -1),
|
// end: const Offset(0, -1),
|
||||||
// ).animate(CurvedAnimation(
|
// ).animate(CurvedAnimation(
|
||||||
// parent: animationController,
|
// parent: animationController,
|
||||||
// curve: Curves.easeInOut,
|
// curve: Curves.easeInOut,
|
||||||
// )),
|
// )),
|
||||||
// child: ),
|
// child: ),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
// 锁
|
// 锁
|
||||||
Obx(
|
Obx(
|
||||||
() => Visibility(
|
() => Visibility(
|
||||||
visible: _.videoType != 'live' && _.isFullScreen.value,
|
visible: _.videoType != 'live' && _.isFullScreen.value,
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: FractionalTranslation(
|
child: FractionalTranslation(
|
||||||
translation: const Offset(1, 0.0),
|
translation: const Offset(1, 0.0),
|
||||||
child: Visibility(
|
child: Visibility(
|
||||||
visible: _.showControls.value,
|
visible: _.showControls.value,
|
||||||
child: ComBtn(
|
child: ComBtn(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
_.controlsLock.value
|
_.controlsLock.value
|
||||||
? FontAwesomeIcons.lock
|
? FontAwesomeIcons.lock
|
||||||
: FontAwesomeIcons.lockOpen,
|
: FontAwesomeIcons.lockOpen,
|
||||||
size: 15,
|
size: 15,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
fuc: () => _.onLockControl(!_.controlsLock.value),
|
||||||
),
|
),
|
||||||
fuc: () => _.onLockControl(!_.controlsLock.value),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
//
|
||||||
//
|
Obx(() {
|
||||||
Obx(() {
|
if (_.dataStatus.loading || _.isBuffering.value) {
|
||||||
if (_.dataStatus.loading || _.isBuffering.value) {
|
return Center(
|
||||||
return Center(
|
child: Container(
|
||||||
child: Container(
|
padding: const EdgeInsets.all(30),
|
||||||
padding: const EdgeInsets.all(30),
|
decoration: const BoxDecoration(
|
||||||
decoration: const BoxDecoration(
|
shape: BoxShape.circle,
|
||||||
shape: BoxShape.circle,
|
gradient: RadialGradient(
|
||||||
gradient: RadialGradient(
|
colors: [Colors.black26, Colors.transparent],
|
||||||
colors: [Colors.black26, Colors.transparent],
|
),
|
||||||
|
),
|
||||||
|
child: Lottie.asset(
|
||||||
|
'assets/loading.json',
|
||||||
|
width: 200,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Lottie.asset(
|
);
|
||||||
'assets/loading.json',
|
} else {
|
||||||
width: 200,
|
return const SizedBox();
|
||||||
),
|
}
|
||||||
),
|
}),
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return const SizedBox();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
/// 快进/快退面板
|
/// 快进/快退面板
|
||||||
SeekPanel(
|
SeekPanel(
|
||||||
mountSeekBackwardButton: _mountSeekBackwardButton,
|
mountSeekBackwardButton: _mountSeekBackwardButton,
|
||||||
mountSeekForwardButton: _mountSeekForwardButton,
|
mountSeekForwardButton: _mountSeekForwardButton,
|
||||||
hideSeekBackwardButton: _hideSeekBackwardButton,
|
hideSeekBackwardButton: _hideSeekBackwardButton,
|
||||||
hideSeekForwardButton: _hideSeekForwardButton,
|
hideSeekForwardButton: _hideSeekForwardButton,
|
||||||
onSubmittedcb: _handleSubmittedCallback,
|
onSubmittedcb: _handleSubmittedCallback,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,19 +18,18 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Padding(
|
||||||
color: Colors.transparent,
|
|
||||||
height: 90,
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 18),
|
padding: const EdgeInsets.symmetric(horizontal: 18),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(7, 0, 7, 6),
|
padding: const EdgeInsets.fromLTRB(7, 0, 7, 4),
|
||||||
child: ProgressBarWidget(controller: controller!),
|
child: ProgressBarWidget(controller: controller!),
|
||||||
),
|
),
|
||||||
Row(children: buildBottomControl!),
|
Row(children: buildBottomControl!),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 6),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -137,7 +137,8 @@ class SettingBoxKey {
|
|||||||
enableGradientBg = 'enableGradientBg',
|
enableGradientBg = 'enableGradientBg',
|
||||||
enableDynamicSwitch = 'enableDynamicSwitch',
|
enableDynamicSwitch = 'enableDynamicSwitch',
|
||||||
navBarSort = 'navBarSort',
|
navBarSort = 'navBarSort',
|
||||||
actionTypeSort = 'actionTypeSort';
|
actionTypeSort = 'actionTypeSort',
|
||||||
|
enablePureBlack = 'enablePureBlack';
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalCacheKey {
|
class LocalCacheKey {
|
||||||
|
|||||||
Reference in New Issue
Block a user