mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-05-15 21:53:59 +08:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
047e3cd26f | ||
|
|
a04da4c34a | ||
|
|
95c35cac58 | ||
|
|
9429225029 | ||
|
|
9cf9867fac |
43
lib/models/live/quality.dart
Normal file
43
lib/models/live/quality.dart
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
enum LiveQuality {
|
||||||
|
dolby,
|
||||||
|
super4K,
|
||||||
|
origin,
|
||||||
|
veryHigh,
|
||||||
|
bluRay,
|
||||||
|
superHD,
|
||||||
|
smooth,
|
||||||
|
flunt,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension LiveQualityCode on LiveQuality {
|
||||||
|
static final List<int> _codeList = [
|
||||||
|
30000,
|
||||||
|
20000,
|
||||||
|
10000,
|
||||||
|
400,
|
||||||
|
250,
|
||||||
|
150,
|
||||||
|
80,
|
||||||
|
];
|
||||||
|
int get code => _codeList[index];
|
||||||
|
|
||||||
|
static LiveQuality? fromCode(int code) {
|
||||||
|
final index = _codeList.indexOf(code);
|
||||||
|
if (index != -1) {
|
||||||
|
return LiveQuality.values[index];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension VideoQualityDesc on LiveQuality {
|
||||||
|
static final List<String> _descList = [
|
||||||
|
'杜比',
|
||||||
|
'4K',
|
||||||
|
'原画',
|
||||||
|
'蓝光',
|
||||||
|
'超清',
|
||||||
|
'流畅',
|
||||||
|
];
|
||||||
|
get description => _descList[index];
|
||||||
|
}
|
||||||
@@ -114,7 +114,7 @@ class _BangumiPageState extends State<BangumiPage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: Grid.mediumCardWidth / 2 / 0.75 +
|
height: Grid.smallCardWidth / 2 / 0.75 +
|
||||||
MediaQuery.textScalerOf(context).scale(50),
|
MediaQuery.textScalerOf(context).scale(50),
|
||||||
child: Obx(
|
child: Obx(
|
||||||
() => _buildFollowBody(
|
() => _buildFollowBody(
|
||||||
@@ -199,7 +199,7 @@ class _BangumiPageState extends State<BangumiPage>
|
|||||||
_bangumiController.queryBangumiFollow(false);
|
_bangumiController.queryBangumiFollow(false);
|
||||||
}
|
}
|
||||||
return Container(
|
return Container(
|
||||||
width: Grid.mediumCardWidth / 2,
|
width: Grid.smallCardWidth / 2,
|
||||||
margin: EdgeInsets.only(
|
margin: EdgeInsets.only(
|
||||||
left: StyleString.safeSpace,
|
left: StyleString.safeSpace,
|
||||||
right: index == loadingState.response.length - 1
|
right: index == loadingState.response.length - 1
|
||||||
|
|||||||
@@ -320,7 +320,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
|||||||
children: [
|
children: [
|
||||||
Builder(
|
Builder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
double padding = max(context.width / 2 - Grid.mediumCardWidth, 0);
|
double padding = max(context.width / 2 - Grid.smallCardWidth, 0);
|
||||||
if (orientation == Orientation.portrait) {
|
if (orientation == Orientation.portrait) {
|
||||||
return CustomScrollView(
|
return CustomScrollView(
|
||||||
controller: _dynamicDetailController.scrollController,
|
controller: _dynamicDetailController.scrollController,
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ class _DynamicsTabPageState extends State<DynamicsTabPage>
|
|||||||
slivers: [
|
slivers: [
|
||||||
const SliverFillRemaining(),
|
const SliverFillRemaining(),
|
||||||
SliverConstrainedCrossAxis(
|
SliverConstrainedCrossAxis(
|
||||||
maxExtent: Grid.mediumCardWidth * 2,
|
maxExtent: Grid.smallCardWidth * 2,
|
||||||
sliver: SliverList(
|
sliver: SliverList(
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(context, index) {
|
(context, index) {
|
||||||
@@ -184,7 +184,7 @@ class _DynamicsTabPageState extends State<DynamicsTabPage>
|
|||||||
slivers: [
|
slivers: [
|
||||||
const SliverFillRemaining(),
|
const SliverFillRemaining(),
|
||||||
SliverConstrainedCrossAxis(
|
SliverConstrainedCrossAxis(
|
||||||
maxExtent: Grid.mediumCardWidth * 2,
|
maxExtent: Grid.smallCardWidth * 2,
|
||||||
sliver: SliverList(
|
sliver: SliverList(
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(context, index) {
|
(context, index) {
|
||||||
|
|||||||
@@ -177,7 +177,15 @@ InlineSpan? richNode(item, context) {
|
|||||||
WidgetSpan(
|
WidgetSpan(
|
||||||
alignment: PlaceholderAlignment.middle,
|
alignment: PlaceholderAlignment.middle,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {},
|
onTap: () {
|
||||||
|
Get.toNamed(
|
||||||
|
'/webview',
|
||||||
|
parameters: {
|
||||||
|
'url':
|
||||||
|
'https://www.bilibili.com/h5/lottery/result?business_id=${item.idStr}'
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'${i.origText} ',
|
'${i.origText} ',
|
||||||
style: authorStyle,
|
style: authorStyle,
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
|||||||
children: [
|
children: [
|
||||||
OrientationBuilder(
|
OrientationBuilder(
|
||||||
builder: (context, orientation) {
|
builder: (context, orientation) {
|
||||||
double padding = max(context.width / 2 - Grid.mediumCardWidth, 0);
|
double padding = max(context.width / 2 - Grid.smallCardWidth, 0);
|
||||||
return Row(
|
return Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:PiliPlus/models/live/danmu_info.dart';
|
import 'package:PiliPlus/models/live/danmu_info.dart';
|
||||||
|
import 'package:PiliPlus/models/live/quality.dart';
|
||||||
import 'package:PiliPlus/tcp/live.dart';
|
import 'package:PiliPlus/tcp/live.dart';
|
||||||
import 'package:PiliPlus/utils/danmaku.dart';
|
import 'package:PiliPlus/utils/danmaku.dart';
|
||||||
import 'package:PiliPlus/utils/storage.dart';
|
import 'package:PiliPlus/utils/storage.dart';
|
||||||
@@ -31,6 +32,10 @@ class LiveRoomController extends GetxController {
|
|||||||
DanmakuController? controller;
|
DanmakuController? controller;
|
||||||
bool showDanmaku = true;
|
bool showDanmaku = true;
|
||||||
|
|
||||||
|
late int currentQn = 10000;
|
||||||
|
late List<Map> acceptQnList = <Map>[];
|
||||||
|
RxString currentQnDesc = ''.obs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
@@ -58,12 +63,26 @@ class LiveRoomController extends GetxController {
|
|||||||
bool? isPortrait;
|
bool? isPortrait;
|
||||||
|
|
||||||
Future queryLiveInfo() async {
|
Future queryLiveInfo() async {
|
||||||
var res = await LiveHttp.liveRoomInfo(roomId: roomId, qn: 10000);
|
var res = await LiveHttp.liveRoomInfo(roomId: roomId, qn: currentQn);
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
isPortrait = res['data'].isPortrait;
|
isPortrait = res['data'].isPortrait;
|
||||||
List<CodecItem> codec =
|
List<CodecItem> codec =
|
||||||
res['data'].playurlInfo.playurl.stream.first.format.first.codec;
|
res['data'].playurlInfo.playurl.stream.first.format.first.codec;
|
||||||
CodecItem item = codec.first;
|
CodecItem item = codec.first;
|
||||||
|
// 以服务端返回的码率为准
|
||||||
|
currentQn = item.currentQn!;
|
||||||
|
List acceptQn = item.acceptQn!;
|
||||||
|
acceptQnList = acceptQn.map((e) {
|
||||||
|
return {
|
||||||
|
'code': e,
|
||||||
|
'desc': LiveQuality.values
|
||||||
|
.firstWhere((element) => element.code == e)
|
||||||
|
.description,
|
||||||
|
};
|
||||||
|
}).toList();
|
||||||
|
currentQnDesc.value = LiveQuality.values
|
||||||
|
.firstWhere((element) => element.code == currentQn)
|
||||||
|
.description;
|
||||||
String videoUrl = VideoUtils.getCdnUrl(item);
|
String videoUrl = VideoUtils.getCdnUrl(item);
|
||||||
await playerInit(videoUrl);
|
await playerInit(videoUrl);
|
||||||
return res;
|
return res;
|
||||||
@@ -183,4 +202,16 @@ class LiveRoomController extends GetxController {
|
|||||||
scrollController.dispose();
|
scrollController.dispose();
|
||||||
super.onClose();
|
super.onClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 修改画质
|
||||||
|
void changeQn(int qn) async {
|
||||||
|
if (currentQn == qn) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentQn = qn;
|
||||||
|
currentQnDesc.value = LiveQuality.values
|
||||||
|
.firstWhere((element) => element.code == currentQn)
|
||||||
|
.description;
|
||||||
|
await queryLiveInfo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,15 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:PiliPlus/models/video/play/url.dart';
|
import 'package:PiliPlus/models/video/play/url.dart';
|
||||||
import 'package:PiliPlus/pages/live_room/index.dart';
|
import 'package:PiliPlus/pages/live_room/index.dart';
|
||||||
import 'package:PiliPlus/plugin/pl_player/index.dart';
|
import 'package:PiliPlus/plugin/pl_player/index.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
class BottomControl extends StatefulWidget implements PreferredSizeWidget {
|
class BottomControl extends StatefulWidget implements PreferredSizeWidget {
|
||||||
final PlPlayerController? controller;
|
final PlPlayerController controller;
|
||||||
final LiveRoomController? liveRoomCtr;
|
final LiveRoomController liveRoomCtr;
|
||||||
final Floating? floating;
|
final Floating? floating;
|
||||||
const BottomControl({
|
const BottomControl({
|
||||||
this.controller,
|
required this.controller,
|
||||||
this.liveRoomCtr,
|
required this.liveRoomCtr,
|
||||||
this.floating,
|
this.floating,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
@@ -87,7 +88,7 @@ class _BottomControlState extends State<BottomControl> {
|
|||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
bool canUsePiP = false;
|
bool canUsePiP = false;
|
||||||
widget.controller!.hiddenControls(false);
|
widget.controller.hiddenControls(false);
|
||||||
try {
|
try {
|
||||||
canUsePiP = await widget.floating!.isPipAvailable;
|
canUsePiP = await widget.floating!.isPipAvailable;
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
@@ -104,6 +105,31 @@ class _BottomControlState extends State<BottomControl> {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
],
|
],
|
||||||
|
Obx(
|
||||||
|
() => SizedBox(
|
||||||
|
width: 30,
|
||||||
|
child: PopupMenuButton<int>(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
initialValue: widget.liveRoomCtr.currentQn,
|
||||||
|
onSelected: (value) {
|
||||||
|
widget.liveRoomCtr.changeQn(value);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
widget.liveRoomCtr.currentQnDesc.value,
|
||||||
|
style: const TextStyle(color: Colors.white, fontSize: 13),
|
||||||
|
),
|
||||||
|
itemBuilder: (BuildContext context) {
|
||||||
|
return widget.liveRoomCtr.acceptQnList.map((e) {
|
||||||
|
return PopupMenuItem<int>(
|
||||||
|
value: e['code'],
|
||||||
|
child: Text(e['desc']),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
ComBtn(
|
ComBtn(
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.fullscreen,
|
Icons.fullscreen,
|
||||||
@@ -111,8 +137,8 @@ class _BottomControlState extends State<BottomControl> {
|
|||||||
size: 20,
|
size: 20,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
fuc: () => widget.controller!.triggerFullScreen(
|
fuc: () => widget.controller.triggerFullScreen(
|
||||||
status: !widget.controller!.isFullScreen.value),
|
status: !widget.controller.isFullScreen.value),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ class _MemberDynamicsPageState extends State<MemberDynamicsPage>
|
|||||||
slivers: [
|
slivers: [
|
||||||
const SliverFillRemaining(),
|
const SliverFillRemaining(),
|
||||||
SliverConstrainedCrossAxis(
|
SliverConstrainedCrossAxis(
|
||||||
maxExtent: Grid.mediumCardWidth * 2,
|
maxExtent: Grid.smallCardWidth * 2,
|
||||||
sliver: SliverList(
|
sliver: SliverList(
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(context, index) {
|
(context, index) {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class SearchDynamic extends StatelessWidget {
|
|||||||
slivers: [
|
slivers: [
|
||||||
const SliverFillRemaining(),
|
const SliverFillRemaining(),
|
||||||
SliverConstrainedCrossAxis(
|
SliverConstrainedCrossAxis(
|
||||||
maxExtent: Grid.mediumCardWidth * 2,
|
maxExtent: Grid.smallCardWidth * 2,
|
||||||
sliver: SliverList(
|
sliver: SliverList(
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(context, index) {
|
(context, index) {
|
||||||
|
|||||||
@@ -50,14 +50,15 @@ class GStorage {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
static List<String> get tabbarSort => setting.get(SettingBoxKey.tabbarSort,
|
static List<String> get tabbarSort =>
|
||||||
defaultValue: TabType.values.map((item) => item.name).toList());
|
List<String>.from(setting.get(SettingBoxKey.tabbarSort,
|
||||||
|
defaultValue: TabType.values.map((item) => item.name).toList()));
|
||||||
|
|
||||||
static List<Pair<SegmentType, SkipType>> get blockSettings {
|
static List<Pair<SegmentType, SkipType>> get blockSettings {
|
||||||
List list = setting.get(
|
List<int> list = List<int>.from(setting.get(
|
||||||
SettingBoxKey.blockSettings,
|
SettingBoxKey.blockSettings,
|
||||||
defaultValue: List.generate(SegmentType.values.length, (_) => 1),
|
defaultValue: List.generate(SegmentType.values.length, (_) => 1),
|
||||||
);
|
));
|
||||||
return SegmentType.values
|
return SegmentType.values
|
||||||
.map((item) => Pair<SegmentType, SkipType>(
|
.map((item) => Pair<SegmentType, SkipType>(
|
||||||
first: item,
|
first: item,
|
||||||
@@ -67,10 +68,10 @@ class GStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static List<Color> get blockColor {
|
static List<Color> get blockColor {
|
||||||
List list = setting.get(
|
List<String> list = List<String>.from(setting.get(
|
||||||
SettingBoxKey.blockColor,
|
SettingBoxKey.blockColor,
|
||||||
defaultValue: List.generate(SegmentType.values.length, (_) => ''),
|
defaultValue: List.generate(SegmentType.values.length, (_) => ''),
|
||||||
);
|
));
|
||||||
return SegmentType.values
|
return SegmentType.values
|
||||||
.map((item) => list[item.index].isNotEmpty
|
.map((item) => list[item.index].isNotEmpty
|
||||||
? Color(
|
? Color(
|
||||||
|
|||||||
Reference in New Issue
Block a user