Merge branch 'main' into design
This commit is contained in:
@ -3,7 +3,9 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/common/constants.dart';
|
import 'package:pilipala/common/constants.dart';
|
||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
|
import 'package:pilipala/http/video.dart';
|
||||||
import 'package:pilipala/models/video_detail_res.dart';
|
import 'package:pilipala/models/video_detail_res.dart';
|
||||||
|
import 'package:pilipala/pages/video/detail/index.dart';
|
||||||
import 'package:pilipala/utils/utils.dart';
|
import 'package:pilipala/utils/utils.dart';
|
||||||
import 'package:scrollview_observer/scrollview_observer.dart';
|
import 'package:scrollview_observer/scrollview_observer.dart';
|
||||||
import '../models/common/video_episode_type.dart';
|
import '../models/common/video_episode_type.dart';
|
||||||
@ -20,6 +22,8 @@ class EpisodeBottomSheet {
|
|||||||
final double? sheetHeight;
|
final double? sheetHeight;
|
||||||
bool isFullScreen = false;
|
bool isFullScreen = false;
|
||||||
final UgcSeason? ugcSeason;
|
final UgcSeason? ugcSeason;
|
||||||
|
final int? currentEpisodeIndex;
|
||||||
|
final int? currentIndex;
|
||||||
|
|
||||||
EpisodeBottomSheet({
|
EpisodeBottomSheet({
|
||||||
required this.episodes,
|
required this.episodes,
|
||||||
@ -30,6 +34,8 @@ class EpisodeBottomSheet {
|
|||||||
this.sheetHeight,
|
this.sheetHeight,
|
||||||
this.isFullScreen = false,
|
this.isFullScreen = false,
|
||||||
this.ugcSeason,
|
this.ugcSeason,
|
||||||
|
this.currentEpisodeIndex,
|
||||||
|
this.currentIndex,
|
||||||
});
|
});
|
||||||
|
|
||||||
Widget buildShowContent() {
|
Widget buildShowContent() {
|
||||||
@ -42,6 +48,8 @@ class EpisodeBottomSheet {
|
|||||||
sheetHeight: sheetHeight,
|
sheetHeight: sheetHeight,
|
||||||
isFullScreen: isFullScreen,
|
isFullScreen: isFullScreen,
|
||||||
ugcSeason: ugcSeason,
|
ugcSeason: ugcSeason,
|
||||||
|
currentEpisodeIndex: currentEpisodeIndex,
|
||||||
|
currentIndex: currentIndex,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,6 +75,8 @@ class PagesBottomSheet extends StatefulWidget {
|
|||||||
this.sheetHeight,
|
this.sheetHeight,
|
||||||
this.isFullScreen = false,
|
this.isFullScreen = false,
|
||||||
this.ugcSeason,
|
this.ugcSeason,
|
||||||
|
this.currentEpisodeIndex,
|
||||||
|
this.currentIndex,
|
||||||
});
|
});
|
||||||
|
|
||||||
final List<dynamic> episodes;
|
final List<dynamic> episodes;
|
||||||
@ -77,41 +87,38 @@ class PagesBottomSheet extends StatefulWidget {
|
|||||||
final double? sheetHeight;
|
final double? sheetHeight;
|
||||||
final bool isFullScreen;
|
final bool isFullScreen;
|
||||||
final UgcSeason? ugcSeason;
|
final UgcSeason? ugcSeason;
|
||||||
|
final int? currentEpisodeIndex;
|
||||||
|
final int? currentIndex;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<PagesBottomSheet> createState() => _PagesBottomSheetState();
|
State<PagesBottomSheet> createState() => _PagesBottomSheetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PagesBottomSheetState extends State<PagesBottomSheet> {
|
class _PagesBottomSheetState extends State<PagesBottomSheet>
|
||||||
|
with TickerProviderStateMixin {
|
||||||
final ScrollController _listScrollController = ScrollController();
|
final ScrollController _listScrollController = ScrollController();
|
||||||
late ListObserverController _listObserverController;
|
late ListObserverController _listObserverController;
|
||||||
final ScrollController _scrollController = ScrollController();
|
final ScrollController _scrollController = ScrollController();
|
||||||
late int currentIndex;
|
late int currentIndex;
|
||||||
|
TabController? tabController;
|
||||||
|
List<ListObserverController>? _listObserverControllerList;
|
||||||
|
List<ScrollController>? _listScrollControllerList;
|
||||||
|
final String heroTag = Get.arguments['heroTag'];
|
||||||
|
VideoDetailController? _videoDetailController;
|
||||||
|
RxInt isSubscribe = (-1).obs;
|
||||||
|
bool isVisible = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
currentIndex =
|
currentIndex = widget.currentIndex ??
|
||||||
widget.episodes.indexWhere((dynamic e) => e.cid == widget.currentCid);
|
widget.episodes.indexWhere((dynamic e) => e.cid == widget.currentCid);
|
||||||
_listObserverController =
|
_scrollToInit();
|
||||||
ListObserverController(controller: _listScrollController);
|
_scrollPositionInit();
|
||||||
if (widget.dataType == VideoEpidoesType.videoEpisode) {
|
if (widget.dataType == VideoEpidoesType.videoEpisode) {
|
||||||
_listObserverController.initialIndexModel = ObserverIndexPositionModel(
|
_videoDetailController = Get.find<VideoDetailController>(tag: heroTag);
|
||||||
index: currentIndex,
|
_getSubscribeStatus();
|
||||||
isFixedHeight: true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
if (widget.dataType != VideoEpidoesType.videoEpisode) {
|
|
||||||
double itemHeight = (widget.isFullScreen
|
|
||||||
? 400
|
|
||||||
: Get.size.width - 3 * StyleString.safeSpace) /
|
|
||||||
5.2;
|
|
||||||
double offset = ((currentIndex - 1) / 2).ceil() * itemHeight;
|
|
||||||
_scrollController.jumpTo(offset);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String prefix() {
|
String prefix() {
|
||||||
@ -126,9 +133,117 @@ class _PagesBottomSheetState extends State<PagesBottomSheet> {
|
|||||||
return '选集';
|
return '选集';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 滚动器初始化
|
||||||
|
void _scrollToInit() {
|
||||||
|
/// 单个
|
||||||
|
_listObserverController =
|
||||||
|
ListObserverController(controller: _listScrollController);
|
||||||
|
|
||||||
|
if (widget.dataType == VideoEpidoesType.videoEpisode &&
|
||||||
|
widget.ugcSeason?.sections != null &&
|
||||||
|
widget.ugcSeason!.sections!.length > 1) {
|
||||||
|
tabController = TabController(
|
||||||
|
length: widget.ugcSeason!.sections!.length,
|
||||||
|
vsync: this,
|
||||||
|
initialIndex: widget.currentEpisodeIndex ?? 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// 多tab
|
||||||
|
_listScrollControllerList = List.generate(
|
||||||
|
widget.ugcSeason!.sections!.length,
|
||||||
|
(index) {
|
||||||
|
return ScrollController();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
_listObserverControllerList = List.generate(
|
||||||
|
widget.ugcSeason!.sections!.length,
|
||||||
|
(index) {
|
||||||
|
return ListObserverController(
|
||||||
|
controller: _listScrollControllerList![index],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 滚动器位置初始化
|
||||||
|
void _scrollPositionInit() {
|
||||||
|
if (widget.dataType == VideoEpidoesType.videoEpisode) {
|
||||||
|
// 单个 多tab
|
||||||
|
if (widget.ugcSeason?.sections != null) {
|
||||||
|
if (widget.ugcSeason!.sections!.length == 1) {
|
||||||
|
_listObserverController.initialIndexModel =
|
||||||
|
ObserverIndexPositionModel(
|
||||||
|
index: currentIndex,
|
||||||
|
isFixedHeight: true,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
_listObserverControllerList![widget.currentEpisodeIndex!]
|
||||||
|
.initialIndexModel = ObserverIndexPositionModel(
|
||||||
|
index: currentIndex,
|
||||||
|
isFixedHeight: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
if (widget.dataType != VideoEpidoesType.videoEpisode) {
|
||||||
|
double itemHeight = (widget.isFullScreen
|
||||||
|
? 400
|
||||||
|
: Get.size.width - 3 * StyleString.safeSpace) /
|
||||||
|
5.2;
|
||||||
|
double offset = ((currentIndex - 1) / 2).ceil() * itemHeight;
|
||||||
|
_scrollController.jumpTo(offset);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取订阅状态
|
||||||
|
void _getSubscribeStatus() async {
|
||||||
|
var res =
|
||||||
|
await VideoHttp.getSubscribeStatus(bvid: _videoDetailController!.bvid);
|
||||||
|
if (res['status']) {
|
||||||
|
isSubscribe.value = res['data']['season_fav'] ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更改订阅状态
|
||||||
|
void _changeSubscribeStatus() async {
|
||||||
|
if (isSubscribe.value == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dynamic result = await VideoHttp.seasonFav(
|
||||||
|
isFav: isSubscribe.value == 1,
|
||||||
|
seasonId: widget.ugcSeason!.id,
|
||||||
|
);
|
||||||
|
if (result['status']) {
|
||||||
|
SmartDialog.showToast(isSubscribe.value == 1 ? '取消订阅成功' : '订阅成功');
|
||||||
|
isSubscribe.value = isSubscribe.value == 1 ? 0 : 1;
|
||||||
|
} else {
|
||||||
|
SmartDialog.showToast(result['msg']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更改展开状态
|
||||||
|
void _changeVisible() {
|
||||||
|
setState(() {
|
||||||
|
isVisible = !isVisible;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
try {
|
||||||
_listObserverController.controller?.dispose();
|
_listObserverController.controller?.dispose();
|
||||||
|
_listScrollController.dispose();
|
||||||
|
for (var element in _listObserverControllerList!) {
|
||||||
|
element.controller?.dispose();
|
||||||
|
}
|
||||||
|
for (var element in _listScrollControllerList!) {
|
||||||
|
element.dispose();
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,23 +260,32 @@ class _PagesBottomSheetState extends State<PagesBottomSheet> {
|
|||||||
isFullScreen: widget.isFullScreen,
|
isFullScreen: widget.isFullScreen,
|
||||||
),
|
),
|
||||||
if (widget.ugcSeason != null) ...[
|
if (widget.ugcSeason != null) ...[
|
||||||
UgcSeasonBuild(ugcSeason: widget.ugcSeason!),
|
UgcSeasonBuild(
|
||||||
|
ugcSeason: widget.ugcSeason!,
|
||||||
|
isSubscribe: isSubscribe,
|
||||||
|
isVisible: isVisible,
|
||||||
|
changeFucCall: _changeSubscribeStatus,
|
||||||
|
changeVisible: _changeVisible,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Material(
|
child: Material(
|
||||||
child: widget.dataType == VideoEpidoesType.videoEpisode
|
child: widget.dataType == VideoEpidoesType.videoEpisode
|
||||||
|
? (widget.ugcSeason!.sections!.length == 1
|
||||||
? ListViewObserver(
|
? ListViewObserver(
|
||||||
controller: _listObserverController,
|
controller: _listObserverController,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
controller: _listScrollController,
|
controller: _listScrollController,
|
||||||
itemCount: widget.episodes.length + 1,
|
itemCount: widget.episodes.length + 1,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
bool isLastItem = index == widget.episodes.length;
|
bool isLastItem =
|
||||||
|
index == widget.episodes.length;
|
||||||
bool isCurrentIndex = currentIndex == index;
|
bool isCurrentIndex = currentIndex == index;
|
||||||
return isLastItem
|
return isLastItem
|
||||||
? SizedBox(
|
? SizedBox(
|
||||||
height:
|
height: MediaQuery.of(context)
|
||||||
MediaQuery.of(context).padding.bottom +
|
.padding
|
||||||
|
.bottom +
|
||||||
20,
|
20,
|
||||||
)
|
)
|
||||||
: EpisodeListItem(
|
: EpisodeListItem(
|
||||||
@ -175,6 +299,7 @@ class _PagesBottomSheetState extends State<PagesBottomSheet> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
: buildTabBar())
|
||||||
: Padding(
|
: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 12.0), // 设置左右间距为12
|
horizontal: 12.0), // 设置左右间距为12
|
||||||
@ -206,6 +331,65 @@ class _PagesBottomSheetState extends State<PagesBottomSheet> {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget buildTabBar() {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
// 背景色
|
||||||
|
Container(
|
||||||
|
color: Theme.of(context).colorScheme.surface,
|
||||||
|
child: TabBar(
|
||||||
|
controller: tabController,
|
||||||
|
isScrollable: true,
|
||||||
|
indicatorSize: TabBarIndicatorSize.label,
|
||||||
|
tabAlignment: TabAlignment.start,
|
||||||
|
splashBorderRadius: BorderRadius.circular(4),
|
||||||
|
tabs: [
|
||||||
|
...widget.ugcSeason!.sections!.map((SectionItem section) {
|
||||||
|
return Tab(
|
||||||
|
text: section.title,
|
||||||
|
);
|
||||||
|
}).toList()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: TabBarView(
|
||||||
|
controller: tabController,
|
||||||
|
children: [
|
||||||
|
...widget.ugcSeason!.sections!.map((SectionItem section) {
|
||||||
|
final int fIndex = widget.ugcSeason!.sections!.indexOf(section);
|
||||||
|
return ListViewObserver(
|
||||||
|
controller: _listObserverControllerList![fIndex],
|
||||||
|
child: ListView.builder(
|
||||||
|
controller: _listScrollControllerList![fIndex],
|
||||||
|
itemCount: section.episodes!.length + 1,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
final bool isLastItem = index == section.episodes!.length;
|
||||||
|
return isLastItem
|
||||||
|
? SizedBox(
|
||||||
|
height:
|
||||||
|
MediaQuery.of(context).padding.bottom + 20,
|
||||||
|
)
|
||||||
|
: EpisodeListItem(
|
||||||
|
episode: section.episodes![index], // 调整索引
|
||||||
|
index: index, // 调整索引
|
||||||
|
isCurrentIndex: widget.currentCid ==
|
||||||
|
section.episodes![index].cid,
|
||||||
|
dataType: widget.dataType,
|
||||||
|
changeFucCall: widget.changeFucCall,
|
||||||
|
isFullScreen: widget.isFullScreen,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TitleBar extends StatelessWidget {
|
class TitleBar extends StatelessWidget {
|
||||||
@ -507,77 +691,134 @@ class EpisodeGridItem extends StatelessWidget {
|
|||||||
|
|
||||||
class UgcSeasonBuild extends StatelessWidget {
|
class UgcSeasonBuild extends StatelessWidget {
|
||||||
final UgcSeason ugcSeason;
|
final UgcSeason ugcSeason;
|
||||||
|
final RxInt isSubscribe;
|
||||||
|
final bool isVisible;
|
||||||
|
final Function changeFucCall;
|
||||||
|
final Function changeVisible;
|
||||||
|
|
||||||
const UgcSeasonBuild({
|
const UgcSeasonBuild({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.ugcSeason,
|
required this.ugcSeason,
|
||||||
|
required this.isSubscribe,
|
||||||
|
required this.isVisible,
|
||||||
|
required this.changeFucCall,
|
||||||
|
required this.changeVisible,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
final ThemeData theme = Theme.of(context);
|
||||||
padding: const EdgeInsets.fromLTRB(12, 0, 12, 8),
|
final Color outline = theme.colorScheme.outline;
|
||||||
color: Theme.of(context).colorScheme.surface,
|
final Color surface = theme.colorScheme.surface;
|
||||||
|
final Color primary = theme.colorScheme.primary;
|
||||||
|
final Color onPrimary = theme.colorScheme.onPrimary;
|
||||||
|
final Color onInverseSurface = theme.colorScheme.onInverseSurface;
|
||||||
|
final TextStyle titleMedium = theme.textTheme.titleMedium!;
|
||||||
|
final TextStyle labelMedium = theme.textTheme.labelMedium!;
|
||||||
|
final Color dividerColor = theme.dividerColor.withOpacity(0.1);
|
||||||
|
|
||||||
|
return isVisible
|
||||||
|
? Container(
|
||||||
|
padding: const EdgeInsets.fromLTRB(12, 0, 12, 0),
|
||||||
|
color: surface,
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Divider(
|
Divider(height: 1, thickness: 1, color: dividerColor),
|
||||||
height: 1,
|
|
||||||
thickness: 1,
|
|
||||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Text(
|
|
||||||
'合集:${ugcSeason.title}',
|
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
if (ugcSeason.intro != null && ugcSeason.intro != '') ...[
|
|
||||||
const SizedBox(height: 4),
|
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(ugcSeason.intro ?? '',
|
child: Text(
|
||||||
style: TextStyle(
|
'合集:${ugcSeason.title}',
|
||||||
color: Theme.of(context).colorScheme.outline)),
|
style: titleMedium,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Obx(
|
||||||
|
() => isSubscribe.value == -1
|
||||||
|
? const SizedBox(height: 32)
|
||||||
|
: SizedBox(
|
||||||
|
height: 32,
|
||||||
|
child: FilledButton.tonal(
|
||||||
|
onPressed: () => changeFucCall.call(),
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(left: 8, right: 8),
|
||||||
|
foregroundColor: isSubscribe.value == 1
|
||||||
|
? outline
|
||||||
|
: onPrimary,
|
||||||
|
backgroundColor: isSubscribe.value == 1
|
||||||
|
? onInverseSurface
|
||||||
|
: primary,
|
||||||
|
),
|
||||||
|
child:
|
||||||
|
Text(isSubscribe.value == 1 ? '已订阅' : '订阅'),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
// SizedBox(
|
|
||||||
// height: 32,
|
|
||||||
// child: FilledButton.tonal(
|
|
||||||
// onPressed: () {},
|
|
||||||
// style: ButtonStyle(
|
|
||||||
// padding: MaterialStateProperty.all(EdgeInsets.zero),
|
|
||||||
// ),
|
|
||||||
// child: const Text('订阅'),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// const SizedBox(width: 6),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (ugcSeason.intro != null && ugcSeason.intro != '') ...[
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
ugcSeason.intro!,
|
||||||
|
style: TextStyle(color: outline, fontSize: 12),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text.rich(
|
Text.rich(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
fontSize: labelMedium.fontSize, color: outline),
|
||||||
color: Theme.of(context).colorScheme.outline,
|
|
||||||
),
|
|
||||||
children: [
|
children: [
|
||||||
TextSpan(text: '${Utils.numFormat(ugcSeason.stat!.view)}播放'),
|
TextSpan(
|
||||||
|
text: '${Utils.numFormat(ugcSeason.stat!.view)}播放'),
|
||||||
const TextSpan(text: ' · '),
|
const TextSpan(text: ' · '),
|
||||||
TextSpan(text: '${Utils.numFormat(ugcSeason.stat!.danmaku)}弹幕'),
|
TextSpan(
|
||||||
|
text:
|
||||||
|
'${Utils.numFormat(ugcSeason.stat!.danmaku)}弹幕'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 14),
|
const SizedBox(height: 14),
|
||||||
Divider(
|
Align(
|
||||||
height: 1,
|
alignment: Alignment.center,
|
||||||
thickness: 1,
|
child: Material(
|
||||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
color: surface,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () => changeVisible.call(),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10, horizontal: 0),
|
||||||
|
child: Text(
|
||||||
|
'收起简介',
|
||||||
|
style: TextStyle(color: primary, fontSize: 12),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Divider(height: 1, thickness: 1, color: dividerColor),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
)
|
||||||
|
: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () => changeVisible.call(),
|
||||||
|
child: Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.symmetric(vertical: 10, horizontal: 0),
|
||||||
|
child: Text(
|
||||||
|
'展开简介',
|
||||||
|
style: TextStyle(color: primary, fontSize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
|
|
||||||
Box<dynamic> setting = GStrorage.setting;
|
Box<dynamic> setting = GStorage.setting;
|
||||||
|
|
||||||
class CustomToast extends StatelessWidget {
|
class CustomToast extends StatelessWidget {
|
||||||
const CustomToast({super.key, required this.msg});
|
const CustomToast({super.key, required this.msg});
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import 'package:pilipala/utils/global_data_cache.dart';
|
|||||||
import '../../utils/storage.dart';
|
import '../../utils/storage.dart';
|
||||||
import '../constants.dart';
|
import '../constants.dart';
|
||||||
|
|
||||||
Box<dynamic> setting = GStrorage.setting;
|
Box<dynamic> setting = GStorage.setting;
|
||||||
|
|
||||||
class NetworkImgLayer extends StatelessWidget {
|
class NetworkImgLayer extends StatelessWidget {
|
||||||
const NetworkImgLayer({
|
const NetworkImgLayer({
|
||||||
|
|||||||
@ -495,7 +495,7 @@ class Api {
|
|||||||
static const activateBuvidApi = '/x/internal/gaia-gateway/ExClimbWuzhi';
|
static const activateBuvidApi = '/x/internal/gaia-gateway/ExClimbWuzhi';
|
||||||
|
|
||||||
/// 获取字幕配置
|
/// 获取字幕配置
|
||||||
static const getSubtitleConfig = '/x/player/v2';
|
static const getSubtitleConfig = '/x/player/wbi/v2';
|
||||||
|
|
||||||
/// 我的订阅
|
/// 我的订阅
|
||||||
static const userSubFolder = '/x/v3/fav/folder/collected/list';
|
static const userSubFolder = '/x/v3/fav/folder/collected/list';
|
||||||
@ -609,4 +609,14 @@ class Api {
|
|||||||
|
|
||||||
/// @我的
|
/// @我的
|
||||||
static const String messageAtAPi = '/x/msgfeed/at?';
|
static const String messageAtAPi = '/x/msgfeed/at?';
|
||||||
|
|
||||||
|
/// 订阅
|
||||||
|
static const String confirmSub = '/x/v3/fav/season/fav';
|
||||||
|
|
||||||
|
/// 订阅状态
|
||||||
|
static const String videoRelation = '/x/web-interface/archive/relation';
|
||||||
|
|
||||||
|
/// 获取空降区间
|
||||||
|
static const String getSkipSegments =
|
||||||
|
'${HttpString.sponsorBlockBaseUrl}/api/skipSegments';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:pilipala/models/sponsor_block/segment.dart';
|
||||||
|
|
||||||
import 'index.dart';
|
import 'index.dart';
|
||||||
|
|
||||||
class CommonHttp {
|
class CommonHttp {
|
||||||
@ -14,4 +16,31 @@ class CommonHttp {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future querySkipSegments({required String bvid}) async {
|
||||||
|
var res = await Request().getWithoutCookie(Api.getSkipSegments, data: {
|
||||||
|
'videoID': bvid,
|
||||||
|
});
|
||||||
|
if (res.data is List && res.data.isNotEmpty) {
|
||||||
|
try {
|
||||||
|
return {
|
||||||
|
'status': true,
|
||||||
|
'data': res.data
|
||||||
|
.map<SegmentDataModel>((e) => SegmentDataModel.fromJson(e))
|
||||||
|
.toList(),
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
return {
|
||||||
|
'status': false,
|
||||||
|
'data': [],
|
||||||
|
'msg': 'sponsorBlock数据解析失败: $err',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'status': false,
|
||||||
|
'data': [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ class HttpString {
|
|||||||
static const String passBaseUrl = 'https://passport.bilibili.com';
|
static const String passBaseUrl = 'https://passport.bilibili.com';
|
||||||
static const String messageBaseUrl = 'https://message.bilibili.com';
|
static const String messageBaseUrl = 'https://message.bilibili.com';
|
||||||
static const String bangumiBaseUrl = 'https://bili.meark.me';
|
static const String bangumiBaseUrl = 'https://bili.meark.me';
|
||||||
|
static const String sponsorBlockBaseUrl = 'https://www.bsbsb.top';
|
||||||
static const List<int> validateStatusCodes = [
|
static const List<int> validateStatusCodes = [
|
||||||
302,
|
302,
|
||||||
304,
|
304,
|
||||||
|
|||||||
@ -21,8 +21,8 @@ class Request {
|
|||||||
static late CookieManager cookieManager;
|
static late CookieManager cookieManager;
|
||||||
static late final Dio dio;
|
static late final Dio dio;
|
||||||
factory Request() => _instance;
|
factory Request() => _instance;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
static Box localCache = GStrorage.localCache;
|
static Box localCache = GStorage.localCache;
|
||||||
late bool enableSystemProxy;
|
late bool enableSystemProxy;
|
||||||
late String systemProxyHost;
|
late String systemProxyHost;
|
||||||
late String systemProxyPort;
|
late String systemProxyPort;
|
||||||
@ -32,8 +32,8 @@ class Request {
|
|||||||
|
|
||||||
/// 设置cookie
|
/// 设置cookie
|
||||||
static setCookie() async {
|
static setCookie() async {
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
final String cookiePath = await Utils.getCookiePath();
|
final String cookiePath = await Utils.getCookiePath();
|
||||||
final PersistCookieJar cookieJar = PersistCookieJar(
|
final PersistCookieJar cookieJar = PersistCookieJar(
|
||||||
ignoreExpires: true,
|
ignoreExpires: true,
|
||||||
@ -217,6 +217,13 @@ class Request {
|
|||||||
if (extra['ua'] != null) {
|
if (extra['ua'] != null) {
|
||||||
options.headers = {'user-agent': headerUa(type: extra['ua'])};
|
options.headers = {'user-agent': headerUa(type: extra['ua'])};
|
||||||
}
|
}
|
||||||
|
if (extra['opus-goback'] != null) {
|
||||||
|
if (extra['opus-goback'] != null) {
|
||||||
|
String cookieHeader = dio.options.headers['cookie'];
|
||||||
|
options.headers!['cookie'] =
|
||||||
|
'$cookieHeader; opus-goback = ${extra['opus-goback']}';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
options.responseType = resType;
|
options.responseType = resType;
|
||||||
|
|
||||||
|
|||||||
@ -470,8 +470,8 @@ class MemberHttp {
|
|||||||
SmartDialog.dismiss();
|
SmartDialog.dismiss();
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
String accessKey = res.data['data']['access_token'];
|
String accessKey = res.data['data']['access_token'];
|
||||||
Box localCache = GStrorage.localCache;
|
Box localCache = GStorage.localCache;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
var userInfo = userInfoCache.get('userInfoCache');
|
var userInfo = userInfoCache.get('userInfoCache');
|
||||||
localCache.put(
|
localCache.put(
|
||||||
LocalCacheKey.accessKey, {'mid': userInfo.mid, 'value': accessKey});
|
LocalCacheKey.accessKey, {'mid': userInfo.mid, 'value': accessKey});
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
import 'package:html/parser.dart';
|
import 'package:html/parser.dart';
|
||||||
import 'package:pilipala/models/read/opus.dart';
|
import 'package:pilipala/models/read/opus.dart';
|
||||||
import 'package:pilipala/models/read/read.dart';
|
import 'package:pilipala/models/read/read.dart';
|
||||||
@ -64,7 +65,7 @@ class ReadHttp {
|
|||||||
static Future parseArticleCv({required String id}) async {
|
static Future parseArticleCv({required String id}) async {
|
||||||
var res = await Request().get(
|
var res = await Request().get(
|
||||||
'https://www.bilibili.com/read/cv$id',
|
'https://www.bilibili.com/read/cv$id',
|
||||||
extra: {'ua': 'pc'},
|
extra: {'ua': 'pc', 'opus-goback': '1'},
|
||||||
);
|
);
|
||||||
String scriptContent =
|
String scriptContent =
|
||||||
extractScriptContents(parse(res.data).body!.outerHtml)[0];
|
extractScriptContents(parse(res.data).body!.outerHtml)[0];
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import '../utils/storage.dart';
|
|||||||
import 'index.dart';
|
import 'index.dart';
|
||||||
|
|
||||||
class SearchHttp {
|
class SearchHttp {
|
||||||
static Box setting = GStrorage.setting;
|
static Box setting = GStorage.setting;
|
||||||
static Future hotSearchList() async {
|
static Future hotSearchList() async {
|
||||||
var res = await Request().get(Api.hotSearchList);
|
var res = await Request().get(Api.hotSearchList);
|
||||||
if (res.data is String) {
|
if (res.data is String) {
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import 'dart:convert';
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:pilipala/utils/id_utils.dart';
|
||||||
import '../common/constants.dart';
|
import '../common/constants.dart';
|
||||||
import '../models/common/reply_type.dart';
|
import '../models/common/reply_type.dart';
|
||||||
import '../models/home/rcmd/result.dart';
|
import '../models/home/rcmd/result.dart';
|
||||||
@ -24,11 +25,11 @@ import 'init.dart';
|
|||||||
/// 返回{'status': bool, 'data': List}
|
/// 返回{'status': bool, 'data': List}
|
||||||
/// view层根据 status 判断渲染逻辑
|
/// view层根据 status 判断渲染逻辑
|
||||||
class VideoHttp {
|
class VideoHttp {
|
||||||
static Box localCache = GStrorage.localCache;
|
static Box localCache = GStorage.localCache;
|
||||||
static Box setting = GStrorage.setting;
|
static Box setting = GStorage.setting;
|
||||||
static bool enableRcmdDynamic =
|
static bool enableRcmdDynamic =
|
||||||
setting.get(SettingBoxKey.enableRcmdDynamic, defaultValue: true);
|
setting.get(SettingBoxKey.enableRcmdDynamic, defaultValue: true);
|
||||||
static Box userInfoCache = GStrorage.userInfo;
|
static Box userInfoCache = GStorage.userInfo;
|
||||||
|
|
||||||
// 首页推荐视频
|
// 首页推荐视频
|
||||||
static Future rcmdVideoList({required int ps, required int freshIdx}) async {
|
static Future rcmdVideoList({required int ps, required int freshIdx}) async {
|
||||||
@ -509,10 +510,11 @@ class VideoHttp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future getSubtitle({int? cid, String? bvid}) async {
|
static Future getSubtitle({int? cid, String? bvid, String? aid}) async {
|
||||||
var res = await Request().get(Api.getSubtitleConfig, data: {
|
var res = await Request().get(Api.getSubtitleConfig, data: {
|
||||||
'cid': cid,
|
'cid': cid,
|
||||||
'bvid': bvid,
|
if (bvid != null) 'bvid': bvid,
|
||||||
|
if (aid != null) 'aid': aid,
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
@ -559,4 +561,50 @@ class VideoHttp {
|
|||||||
final List body = res.data['body'];
|
final List body = res.data['body'];
|
||||||
return {'content': content, 'body': body};
|
return {'content': content, 'body': body};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<Map<String, dynamic>> getSubscribeStatus(
|
||||||
|
{required dynamic bvid}) async {
|
||||||
|
var res = await Request().get(
|
||||||
|
Api.videoRelation,
|
||||||
|
data: {
|
||||||
|
'aid': IdUtils.bv2av(bvid),
|
||||||
|
'bvid': bvid,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
return {
|
||||||
|
'status': true,
|
||||||
|
'data': res.data['data'],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'status': false,
|
||||||
|
'msg': res.data['message'],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future seasonFav({
|
||||||
|
required bool isFav,
|
||||||
|
required dynamic seasonId,
|
||||||
|
}) async {
|
||||||
|
var res = await Request().post(
|
||||||
|
isFav ? Api.cancelSub : Api.confirmSub,
|
||||||
|
data: {
|
||||||
|
'platform': 'web',
|
||||||
|
'season_id': seasonId,
|
||||||
|
'csrf': await Request.getCsrf(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
return {
|
||||||
|
'status': true,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'status': false,
|
||||||
|
'msg': res.data['message'],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ void main() async {
|
|||||||
MediaKit.ensureInitialized();
|
MediaKit.ensureInitialized();
|
||||||
await SystemChrome.setPreferredOrientations(
|
await SystemChrome.setPreferredOrientations(
|
||||||
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
|
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
|
||||||
await GStrorage.init();
|
await GStorage.init();
|
||||||
clearLogs();
|
clearLogs();
|
||||||
Request();
|
Request();
|
||||||
await Request.setCookie();
|
await Request.setCookie();
|
||||||
@ -73,7 +73,7 @@ class MyApp extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
// 主题色
|
// 主题色
|
||||||
Color defaultColor =
|
Color defaultColor =
|
||||||
colorThemeTypes[setting.get(SettingBoxKey.customColor, defaultValue: 0)]
|
colorThemeTypes[setting.get(SettingBoxKey.customColor, defaultValue: 0)]
|
||||||
|
|||||||
26
lib/models/sponsor_block/action_type.dart
Normal file
26
lib/models/sponsor_block/action_type.dart
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// 片段类型枚举
|
||||||
|
enum ActionType {
|
||||||
|
skip,
|
||||||
|
mute,
|
||||||
|
full,
|
||||||
|
poi,
|
||||||
|
chapter,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ActionTypeExtension on ActionType {
|
||||||
|
String get value => [
|
||||||
|
'skip',
|
||||||
|
'mute',
|
||||||
|
'full',
|
||||||
|
'poi',
|
||||||
|
'chapter',
|
||||||
|
][index];
|
||||||
|
|
||||||
|
String get label => [
|
||||||
|
'跳过',
|
||||||
|
'静音',
|
||||||
|
'完整观看',
|
||||||
|
'亮点',
|
||||||
|
'章节切换',
|
||||||
|
][index];
|
||||||
|
}
|
||||||
43
lib/models/sponsor_block/segment.dart
Normal file
43
lib/models/sponsor_block/segment.dart
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import 'action_type.dart';
|
||||||
|
import 'segment_type.dart';
|
||||||
|
|
||||||
|
class SegmentDataModel {
|
||||||
|
final SegmentType? category;
|
||||||
|
final ActionType? actionType;
|
||||||
|
final List? segment;
|
||||||
|
final String? uuid;
|
||||||
|
final num? videoDuration;
|
||||||
|
final int? locked;
|
||||||
|
final int? votes;
|
||||||
|
final String? description;
|
||||||
|
// 是否已经跳过
|
||||||
|
bool isSkip = false;
|
||||||
|
|
||||||
|
SegmentDataModel({
|
||||||
|
this.category,
|
||||||
|
this.actionType,
|
||||||
|
this.segment,
|
||||||
|
this.uuid,
|
||||||
|
this.videoDuration,
|
||||||
|
this.locked,
|
||||||
|
this.votes,
|
||||||
|
this.description,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory SegmentDataModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
return SegmentDataModel(
|
||||||
|
category: SegmentType.values.firstWhere(
|
||||||
|
(e) => e.value == json['category'],
|
||||||
|
orElse: () => SegmentType.sponsor),
|
||||||
|
actionType: ActionType.values.firstWhere(
|
||||||
|
(e) => e.value == json['actionType'],
|
||||||
|
orElse: () => ActionType.skip),
|
||||||
|
segment: json['segment'],
|
||||||
|
uuid: json['UUID'],
|
||||||
|
videoDuration: json['videoDuration'],
|
||||||
|
locked: json['locked'],
|
||||||
|
votes: json['votes'],
|
||||||
|
description: json['description'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
46
lib/models/sponsor_block/segment_type.dart
Normal file
46
lib/models/sponsor_block/segment_type.dart
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// 片段类型枚举
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
|
||||||
|
enum SegmentType {
|
||||||
|
sponsor,
|
||||||
|
intro,
|
||||||
|
outro,
|
||||||
|
interaction,
|
||||||
|
selfpromo,
|
||||||
|
music_offtopic,
|
||||||
|
preview,
|
||||||
|
poi_highlight,
|
||||||
|
filler,
|
||||||
|
exclusive_access,
|
||||||
|
chapter,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SegmentTypeExtension on SegmentType {
|
||||||
|
String get value => [
|
||||||
|
'sponsor',
|
||||||
|
'intro',
|
||||||
|
'outro',
|
||||||
|
'interaction',
|
||||||
|
'selfpromo',
|
||||||
|
'music_offtopic',
|
||||||
|
'preview',
|
||||||
|
'poi_highlight',
|
||||||
|
'filler',
|
||||||
|
'exclusive_access',
|
||||||
|
'chapter',
|
||||||
|
][index];
|
||||||
|
|
||||||
|
String get label => [
|
||||||
|
'赞助',
|
||||||
|
'开场介绍',
|
||||||
|
'片尾致谢',
|
||||||
|
'互动',
|
||||||
|
'自我推广',
|
||||||
|
'音乐',
|
||||||
|
'预览',
|
||||||
|
'亮点',
|
||||||
|
'无效填充',
|
||||||
|
'独家访问',
|
||||||
|
'章节',
|
||||||
|
][index];
|
||||||
|
}
|
||||||
@ -29,7 +29,7 @@ class ReplyMember {
|
|||||||
avatar = json['avatar'];
|
avatar = json['avatar'];
|
||||||
level = json['level_info']['current_level'];
|
level = json['level_info']['current_level'];
|
||||||
pendant = Pendant.fromJson(json['pendant']);
|
pendant = Pendant.fromJson(json['pendant']);
|
||||||
officialVerify = json['officia_verify'];
|
officialVerify = json['official_verify'];
|
||||||
vip = json['vip'];
|
vip = json['vip'];
|
||||||
fansDetail = json['fans_detail'];
|
fansDetail = json['fans_detail'];
|
||||||
userSailing = json['user_sailing'] != null
|
userSailing = json['user_sailing'] != null
|
||||||
|
|||||||
@ -641,6 +641,7 @@ class EpisodeItem {
|
|||||||
this.page,
|
this.page,
|
||||||
this.bvid,
|
this.bvid,
|
||||||
this.cover,
|
this.cover,
|
||||||
|
this.pages,
|
||||||
});
|
});
|
||||||
int? seasonId;
|
int? seasonId;
|
||||||
int? sectionId;
|
int? sectionId;
|
||||||
@ -655,6 +656,7 @@ class EpisodeItem {
|
|||||||
int? pubdate;
|
int? pubdate;
|
||||||
int? duration;
|
int? duration;
|
||||||
Stat? stat;
|
Stat? stat;
|
||||||
|
List<Page>? pages;
|
||||||
|
|
||||||
EpisodeItem.fromJson(Map<String, dynamic> json) {
|
EpisodeItem.fromJson(Map<String, dynamic> json) {
|
||||||
seasonId = json['season_id'];
|
seasonId = json['season_id'];
|
||||||
@ -670,6 +672,7 @@ class EpisodeItem {
|
|||||||
pubdate = json['arc']['pubdate'];
|
pubdate = json['arc']['pubdate'];
|
||||||
duration = json['arc']['duration'];
|
duration = json['arc']['duration'];
|
||||||
stat = Stat.fromJson(json['arc']['stat']);
|
stat = Stat.fromJson(json['arc']['stat']);
|
||||||
|
pages = json['pages'].map<Page>((e) => Page.fromJson(e)).toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,3 +715,18 @@ class Vip {
|
|||||||
status = json['status'];
|
status = json['status'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Page {
|
||||||
|
Page({
|
||||||
|
this.cid,
|
||||||
|
this.page,
|
||||||
|
});
|
||||||
|
|
||||||
|
int? cid;
|
||||||
|
int? page;
|
||||||
|
|
||||||
|
Page.fromJson(Map<String, dynamic> json) {
|
||||||
|
cid = json['cid'];
|
||||||
|
page = json['page'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ class BangumiController extends GetxController {
|
|||||||
RxInt total = 0.obs;
|
RxInt total = 0.obs;
|
||||||
int _currentPage = 1;
|
int _currentPage = 1;
|
||||||
bool isLoadingMore = true;
|
bool isLoadingMore = true;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
RxBool userLogin = false.obs;
|
RxBool userLogin = false.obs;
|
||||||
late int mid;
|
late int mid;
|
||||||
var userInfo;
|
var userInfo;
|
||||||
|
|||||||
@ -48,7 +48,7 @@ class BangumiIntroController extends GetxController {
|
|||||||
RxBool hasCoin = false.obs;
|
RxBool hasCoin = false.obs;
|
||||||
// 是否收藏
|
// 是否收藏
|
||||||
RxBool hasFav = false.obs;
|
RxBool hasFav = false.obs;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
bool userLogin = false;
|
bool userLogin = false;
|
||||||
Rx<FavFolderData> favFolderData = FavFolderData().obs;
|
Rx<FavFolderData> favFolderData = FavFolderData().obs;
|
||||||
List addMediaIdsNew = [];
|
List addMediaIdsNew = [];
|
||||||
|
|||||||
@ -116,7 +116,7 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
|||||||
String heroTag = Get.arguments['heroTag'];
|
String heroTag = Get.arguments['heroTag'];
|
||||||
late final BangumiIntroController bangumiIntroController;
|
late final BangumiIntroController bangumiIntroController;
|
||||||
late final VideoDetailController videoDetailCtr;
|
late final VideoDetailController videoDetailCtr;
|
||||||
Box localCache = GStrorage.localCache;
|
Box localCache = GStorage.localCache;
|
||||||
late double sheetHeight;
|
late double sheetHeight;
|
||||||
int? cid;
|
int? cid;
|
||||||
bool isProcessing = false;
|
bool isProcessing = false;
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import 'package:pilipala/common/widgets/stat/danmu.dart';
|
|||||||
import 'package:pilipala/common/widgets/stat/view.dart';
|
import 'package:pilipala/common/widgets/stat/view.dart';
|
||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
|
|
||||||
Box localCache = GStrorage.localCache;
|
Box localCache = GStorage.localCache;
|
||||||
late double sheetHeight;
|
late double sheetHeight;
|
||||||
|
|
||||||
class IntroDetail extends StatelessWidget {
|
class IntroDetail extends StatelessWidget {
|
||||||
|
|||||||
@ -36,7 +36,7 @@ class BangumiPanel extends StatefulWidget {
|
|||||||
class _BangumiPanelState extends State<BangumiPanel> {
|
class _BangumiPanelState extends State<BangumiPanel> {
|
||||||
late RxInt currentIndex = (-1).obs;
|
late RxInt currentIndex = (-1).obs;
|
||||||
final ScrollController listViewScrollCtr = ScrollController();
|
final ScrollController listViewScrollCtr = ScrollController();
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
dynamic userInfo;
|
dynamic userInfo;
|
||||||
// 默认未开通
|
// 默认未开通
|
||||||
int vipStatus = 0;
|
int vipStatus = 0;
|
||||||
|
|||||||
@ -22,7 +22,7 @@ class _BlackListPageState extends State<BlackListPage> {
|
|||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
Future? _futureBuilderFuture;
|
Future? _futureBuilderFuture;
|
||||||
bool _isLoadingMore = false;
|
bool _isLoadingMore = false;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
|||||||
@ -32,7 +32,7 @@ class _PlDanmakuState extends State<PlDanmaku> {
|
|||||||
late PlDanmakuController _plDanmakuController;
|
late PlDanmakuController _plDanmakuController;
|
||||||
DanmakuController? _controller;
|
DanmakuController? _controller;
|
||||||
// bool danmuPlayStatus = true;
|
// bool danmuPlayStatus = true;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
late bool enableShowDanmaku;
|
late bool enableShowDanmaku;
|
||||||
late List blockTypes;
|
late List blockTypes;
|
||||||
late double showArea;
|
late double showArea;
|
||||||
|
|||||||
@ -50,11 +50,11 @@ class DynamicsController extends GetxController {
|
|||||||
];
|
];
|
||||||
bool flag = false;
|
bool flag = false;
|
||||||
RxInt initialValue = 0.obs;
|
RxInt initialValue = 0.obs;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
RxBool userLogin = false.obs;
|
RxBool userLogin = false.obs;
|
||||||
var userInfo;
|
var userInfo;
|
||||||
RxBool isLoadingDynamic = false.obs;
|
RxBool isLoadingDynamic = false.obs;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class DynamicDetailController extends GetxController {
|
|||||||
ReplySortType _sortType = ReplySortType.time;
|
ReplySortType _sortType = ReplySortType.time;
|
||||||
RxString sortTypeTitle = ReplySortType.time.titles.obs;
|
RxString sortTypeTitle = ReplySortType.time.titles.obs;
|
||||||
RxString sortTypeLabel = ReplySortType.time.labels.obs;
|
RxString sortTypeLabel = ReplySortType.time.labels.obs;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
RxInt replyReqCode = 200.obs;
|
RxInt replyReqCode = 200.obs;
|
||||||
bool isEnd = false;
|
bool isEnd = false;
|
||||||
|
|
||||||
@ -37,13 +37,13 @@ class DynamicDetailController extends GetxController {
|
|||||||
acount.value =
|
acount.value =
|
||||||
int.parse(item!.modules!.moduleStat!.comment!.count ?? '0');
|
int.parse(item!.modules!.moduleStat!.comment!.count ?? '0');
|
||||||
}
|
}
|
||||||
int deaultReplySortIndex =
|
int defaultReplySortIndex =
|
||||||
setting.get(SettingBoxKey.replySortType, defaultValue: 0);
|
setting.get(SettingBoxKey.replySortType, defaultValue: 0);
|
||||||
if (deaultReplySortIndex == 2) {
|
if (defaultReplySortIndex == 2) {
|
||||||
setting.put(SettingBoxKey.replySortType, 0);
|
setting.put(SettingBoxKey.replySortType, 0);
|
||||||
deaultReplySortIndex = 0;
|
defaultReplySortIndex = 0;
|
||||||
}
|
}
|
||||||
_sortType = ReplySortType.values[deaultReplySortIndex];
|
_sortType = ReplySortType.values[defaultReplySortIndex];
|
||||||
sortTypeTitle.value = _sortType.titles;
|
sortTypeTitle.value = _sortType.titles;
|
||||||
sortTypeLabel.value = _sortType.labels;
|
sortTypeLabel.value = _sortType.labels;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,9 +9,7 @@ import 'package:pilipala/common/skeleton/dynamic_card.dart';
|
|||||||
import 'package:pilipala/common/widgets/http_error.dart';
|
import 'package:pilipala/common/widgets/http_error.dart';
|
||||||
import 'package:pilipala/common/widgets/no_data.dart';
|
import 'package:pilipala/common/widgets/no_data.dart';
|
||||||
import 'package:pilipala/models/dynamics/result.dart';
|
import 'package:pilipala/models/dynamics/result.dart';
|
||||||
import 'package:pilipala/plugin/pl_popup/index.dart';
|
|
||||||
import 'package:pilipala/utils/feed_back.dart';
|
import 'package:pilipala/utils/feed_back.dart';
|
||||||
import 'package:pilipala/utils/global_data_cache.dart';
|
|
||||||
import 'package:pilipala/utils/main_stream.dart';
|
import 'package:pilipala/utils/main_stream.dart';
|
||||||
import 'package:pilipala/utils/route_push.dart';
|
import 'package:pilipala/utils/route_push.dart';
|
||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
@ -19,7 +17,6 @@ import 'package:pilipala/utils/storage.dart';
|
|||||||
import '../mine/controller.dart';
|
import '../mine/controller.dart';
|
||||||
import 'controller.dart';
|
import 'controller.dart';
|
||||||
import 'widgets/dynamic_panel.dart';
|
import 'widgets/dynamic_panel.dart';
|
||||||
import 'up_dynamic/route_panel.dart';
|
|
||||||
import 'widgets/up_panel.dart';
|
import 'widgets/up_panel.dart';
|
||||||
|
|
||||||
class DynamicsPage extends StatefulWidget {
|
class DynamicsPage extends StatefulWidget {
|
||||||
@ -35,7 +32,7 @@ class _DynamicsPageState extends State<DynamicsPage>
|
|||||||
final MineController mineController = Get.put(MineController());
|
final MineController mineController = Get.put(MineController());
|
||||||
late Future _futureBuilderFuture;
|
late Future _futureBuilderFuture;
|
||||||
late Future _futureBuilderFutureUp;
|
late Future _futureBuilderFutureUp;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
late ScrollController scrollController;
|
late ScrollController scrollController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -209,21 +206,7 @@ class _DynamicsPageState extends State<DynamicsPage>
|
|||||||
return Obx(
|
return Obx(
|
||||||
() => UpPanel(
|
() => UpPanel(
|
||||||
upData: _dynamicsController.upData.value,
|
upData: _dynamicsController.upData.value,
|
||||||
onClickUpCb: (data) {
|
dynamicsController: _dynamicsController,
|
||||||
if (GlobalDataCache().enableDynamicSwitch) {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
PlPopupRoute(
|
|
||||||
child: OverlayPanel(
|
|
||||||
ctr: _dynamicsController,
|
|
||||||
upInfo: data,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
_dynamicsController.onTapUp(data);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -4,18 +4,22 @@ import 'package:get/get.dart';
|
|||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
import 'package:pilipala/models/dynamics/up.dart';
|
import 'package:pilipala/models/dynamics/up.dart';
|
||||||
import 'package:pilipala/models/live/item.dart';
|
import 'package:pilipala/models/live/item.dart';
|
||||||
|
import 'package:pilipala/plugin/pl_popup/index.dart';
|
||||||
import 'package:pilipala/utils/feed_back.dart';
|
import 'package:pilipala/utils/feed_back.dart';
|
||||||
import 'package:pilipala/utils/global_data_cache.dart';
|
import 'package:pilipala/utils/global_data_cache.dart';
|
||||||
import 'package:pilipala/utils/utils.dart';
|
import 'package:pilipala/utils/utils.dart';
|
||||||
|
|
||||||
|
import '../controller.dart';
|
||||||
|
import '../up_dynamic/route_panel.dart';
|
||||||
|
|
||||||
class UpPanel extends StatefulWidget {
|
class UpPanel extends StatefulWidget {
|
||||||
final FollowUpModel upData;
|
final FollowUpModel upData;
|
||||||
final Function? onClickUpCb;
|
final DynamicsController dynamicsController;
|
||||||
|
|
||||||
const UpPanel({
|
const UpPanel({
|
||||||
super.key,
|
super.key,
|
||||||
required this.upData,
|
required this.upData,
|
||||||
this.onClickUpCb,
|
required this.dynamicsController,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -39,7 +43,15 @@ class _UpPanelState extends State<UpPanel> {
|
|||||||
|
|
||||||
void onClickUp(data, i) {
|
void onClickUp(data, i) {
|
||||||
currentMid.value = data.mid;
|
currentMid.value = data.mid;
|
||||||
widget.onClickUpCb?.call(data);
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PlPopupRoute(
|
||||||
|
child: OverlayPanel(
|
||||||
|
ctr: widget.dynamicsController,
|
||||||
|
upInfo: data,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).then((value) => {currentMid.value = -1});
|
||||||
}
|
}
|
||||||
|
|
||||||
void onClickUpAni(data, i) {
|
void onClickUpAni(data, i) {
|
||||||
@ -49,7 +61,7 @@ class _UpPanelState extends State<UpPanel> {
|
|||||||
final upLen = upList.length;
|
final upLen = upList.length;
|
||||||
|
|
||||||
currentMid.value = data.mid;
|
currentMid.value = data.mid;
|
||||||
widget.onClickUpCb?.call(data);
|
widget.dynamicsController.onTapUp(data);
|
||||||
|
|
||||||
double moveDistance = 0.0;
|
double moveDistance = 0.0;
|
||||||
final totalItemsWidth = itemWidth * (upLen + liveLen);
|
final totalItemsWidth = itemWidth * (upLen + liveLen);
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import 'package:pilipala/models/fans/result.dart';
|
|||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
|
|
||||||
class FansController extends GetxController {
|
class FansController extends GetxController {
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
int pn = 1;
|
int pn = 1;
|
||||||
int ps = 20;
|
int ps = 20;
|
||||||
int total = 0;
|
int total = 0;
|
||||||
|
|||||||
@ -11,7 +11,7 @@ class FavController extends GetxController {
|
|||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
Rx<FavFolderData> favFolderData = FavFolderData().obs;
|
Rx<FavFolderData> favFolderData = FavFolderData().obs;
|
||||||
RxList<FavFolderItemData> favFolderList = <FavFolderItemData>[].obs;
|
RxList<FavFolderItemData> favFolderList = <FavFolderItemData>[].obs;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
UserInfoData? userInfo;
|
UserInfoData? userInfo;
|
||||||
int currentPage = 1;
|
int currentPage = 1;
|
||||||
int pageSize = 60;
|
int pageSize = 60;
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import 'package:pilipala/utils/storage.dart';
|
|||||||
/// 查看自己的关注时,可以查看分类
|
/// 查看自己的关注时,可以查看分类
|
||||||
/// 查看其他人的关注时,只可以看全部
|
/// 查看其他人的关注时,只可以看全部
|
||||||
class FollowController extends GetxController with GetTickerProviderStateMixin {
|
class FollowController extends GetxController with GetTickerProviderStateMixin {
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
int pn = 1;
|
int pn = 1;
|
||||||
int ps = 20;
|
int ps = 20;
|
||||||
int total = 0;
|
int total = 0;
|
||||||
|
|||||||
@ -12,11 +12,11 @@ class HistoryController extends GetxController {
|
|||||||
RxList<HisListItem> historyList = <HisListItem>[].obs;
|
RxList<HisListItem> historyList = <HisListItem>[].obs;
|
||||||
RxBool isLoadingMore = false.obs;
|
RxBool isLoadingMore = false.obs;
|
||||||
RxBool pauseStatus = false.obs;
|
RxBool pauseStatus = false.obs;
|
||||||
Box localCache = GStrorage.localCache;
|
Box localCache = GStorage.localCache;
|
||||||
RxBool isLoading = false.obs;
|
RxBool isLoading = false.obs;
|
||||||
RxBool enableMultiple = false.obs;
|
RxBool enableMultiple = false.obs;
|
||||||
RxInt checkedCount = 0.obs;
|
RxInt checkedCount = 0.obs;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
UserInfoData? userInfo;
|
UserInfoData? userInfo;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -14,12 +14,12 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
|
|||||||
late TabController tabController;
|
late TabController tabController;
|
||||||
late List tabsCtrList;
|
late List tabsCtrList;
|
||||||
late List<Widget> tabsPageList;
|
late List<Widget> tabsPageList;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
Box settingStorage = GStrorage.setting;
|
Box settingStorage = GStorage.setting;
|
||||||
RxBool userLogin = false.obs;
|
RxBool userLogin = false.obs;
|
||||||
RxString userFace = ''.obs;
|
RxString userFace = ''.obs;
|
||||||
var userInfo;
|
var userInfo;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
late final StreamController<bool> searchBarStream =
|
late final StreamController<bool> searchBarStream =
|
||||||
StreamController<bool>.broadcast();
|
StreamController<bool>.broadcast();
|
||||||
late bool hideSearchBar;
|
late bool hideSearchBar;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import 'package:hive/hive.dart';
|
|||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
|
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
|
|
||||||
class HomeAppBar extends StatelessWidget {
|
class HomeAppBar extends StatelessWidget {
|
||||||
const HomeAppBar({super.key});
|
const HomeAppBar({super.key});
|
||||||
|
|||||||
@ -25,7 +25,7 @@ class HtmlRenderController extends GetxController {
|
|||||||
ReplySortType _sortType = ReplySortType.time;
|
ReplySortType _sortType = ReplySortType.time;
|
||||||
RxString sortTypeTitle = ReplySortType.time.titles.obs;
|
RxString sortTypeTitle = ReplySortType.time.titles.obs;
|
||||||
RxString sortTypeLabel = ReplySortType.time.labels.obs;
|
RxString sortTypeLabel = ReplySortType.time.labels.obs;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class LaterController extends GetxController {
|
|||||||
RxList<HotVideoItemModel> laterList = <HotVideoItemModel>[].obs;
|
RxList<HotVideoItemModel> laterList = <HotVideoItemModel>[].obs;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
RxBool isLoading = false.obs;
|
RxBool isLoading = false.obs;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
UserInfoData? userInfo;
|
UserInfoData? userInfo;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -17,7 +17,7 @@ class LiveController extends GetxController {
|
|||||||
RxInt liveFollowingCount = 0.obs;
|
RxInt liveFollowingCount = 0.obs;
|
||||||
bool flag = false;
|
bool flag = false;
|
||||||
OverlayEntry? popupDialog;
|
OverlayEntry? popupDialog;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import 'package:pilipala/utils/storage.dart';
|
|||||||
|
|
||||||
class LiveFollowController extends GetxController {
|
class LiveFollowController extends GetxController {
|
||||||
RxInt crossAxisCount = 2.obs;
|
RxInt crossAxisCount = 2.obs;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
int _currentPage = 1;
|
int _currentPage = 1;
|
||||||
RxInt liveFollowingCount = 0.obs;
|
RxInt liveFollowingCount = 0.obs;
|
||||||
RxList<LiveFollowingItemModel> liveFollowingList =
|
RxList<LiveFollowingItemModel> liveFollowingList =
|
||||||
|
|||||||
@ -33,7 +33,7 @@ class LiveRoomController extends GetxController {
|
|||||||
int? tempCurrentQn;
|
int? tempCurrentQn;
|
||||||
late List<Map<String, dynamic>> acceptQnList;
|
late List<Map<String, dynamic>> acceptQnList;
|
||||||
RxString currentQnDesc = ''.obs;
|
RxString currentQnDesc = ''.obs;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
int userId = 0;
|
int userId = 0;
|
||||||
PlSocket? plSocket;
|
PlSocket? plSocket;
|
||||||
List<String> danmuHostList = [];
|
List<String> danmuHostList = [];
|
||||||
|
|||||||
@ -35,7 +35,7 @@ class _BottomControlState extends State<BottomControl> {
|
|||||||
TextStyle subTitleStyle = const TextStyle(fontSize: 12);
|
TextStyle subTitleStyle = const TextStyle(fontSize: 12);
|
||||||
TextStyle titleStyle = const TextStyle(fontSize: 14);
|
TextStyle titleStyle = const TextStyle(fontSize: 14);
|
||||||
Size get preferredSize => const Size(double.infinity, kToolbarHeight);
|
Size get preferredSize => const Size(double.infinity, kToolbarHeight);
|
||||||
Box localCache = GStrorage.localCache;
|
Box localCache = GStorage.localCache;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
|||||||
@ -20,12 +20,12 @@ class MainController extends GetxController {
|
|||||||
late List<int> navBarSort;
|
late List<int> navBarSort;
|
||||||
final StreamController<bool> bottomBarStream =
|
final StreamController<bool> bottomBarStream =
|
||||||
StreamController<bool>.broadcast();
|
StreamController<bool>.broadcast();
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
DateTime? _lastPressedAt;
|
DateTime? _lastPressedAt;
|
||||||
late bool hideTabBar;
|
late bool hideTabBar;
|
||||||
late PageController pageController;
|
late PageController pageController;
|
||||||
int selectedIndex = 0;
|
int selectedIndex = 0;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
dynamic userInfo;
|
dynamic userInfo;
|
||||||
RxBool userLogin = false.obs;
|
RxBool userLogin = false.obs;
|
||||||
late Rx<DynamicBadgeMode> dynamicBadgeType = DynamicBadgeMode.number.obs;
|
late Rx<DynamicBadgeMode> dynamicBadgeType = DynamicBadgeMode.number.obs;
|
||||||
|
|||||||
@ -30,7 +30,7 @@ class _MainAppState extends State<MainApp> with SingleTickerProviderStateMixin {
|
|||||||
late MineController _mineController;
|
late MineController _mineController;
|
||||||
|
|
||||||
int? _lastSelectTime; //上次点击时间
|
int? _lastSelectTime; //上次点击时间
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
late bool enableMYBar;
|
late bool enableMYBar;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -113,14 +113,14 @@ class _MainAppState extends State<MainApp> with SingleTickerProviderStateMixin {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() async {
|
void dispose() async {
|
||||||
await GStrorage.close();
|
await GStorage.close();
|
||||||
EventBus().off(EventName.loginEvent);
|
EventBus().off(EventName.loginEvent);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Box localCache = GStrorage.localCache;
|
Box localCache = GStorage.localCache;
|
||||||
double statusBarHeight = MediaQuery.of(context).padding.top;
|
double statusBarHeight = MediaQuery.of(context).padding.top;
|
||||||
double sheetHeight = MediaQuery.sizeOf(context).height -
|
double sheetHeight = MediaQuery.sizeOf(context).height -
|
||||||
MediaQuery.of(context).padding.top -
|
MediaQuery.of(context).padding.top -
|
||||||
|
|||||||
@ -18,7 +18,7 @@ class MemberController extends GetxController {
|
|||||||
late Map userStat;
|
late Map userStat;
|
||||||
RxString face = ''.obs;
|
RxString face = ''.obs;
|
||||||
String? heroTag;
|
String? heroTag;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
late int ownerMid;
|
late int ownerMid;
|
||||||
// 投稿列表
|
// 投稿列表
|
||||||
RxList<VListItemModel>? archiveList = <VListItemModel>[].obs;
|
RxList<VListItemModel>? archiveList = <VListItemModel>[].obs;
|
||||||
|
|||||||
@ -41,6 +41,7 @@ class MemberSeasonsPanel extends StatelessWidget {
|
|||||||
'category': '1',
|
'category': '1',
|
||||||
'mid': item.meta!.mid.toString(),
|
'mid': item.meta!.mid.toString(),
|
||||||
'seriesId': item.meta!.seriesId.toString(),
|
'seriesId': item.meta!.seriesId.toString(),
|
||||||
|
'seasonId': item.meta!.seasonId.toString(),
|
||||||
'seasonName': item.meta!.name!,
|
'seasonName': item.meta!.name!,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,8 @@ class MemberSeasonsController extends GetxController {
|
|||||||
seasonId = int.parse(Get.parameters['seasonId']!);
|
seasonId = int.parse(Get.parameters['seasonId']!);
|
||||||
}
|
}
|
||||||
if (category == '1') {
|
if (category == '1') {
|
||||||
seriesId = int.parse(Get.parameters['seriesId']!);
|
seriesId = int.tryParse(Get.parameters['seriesId']!);
|
||||||
|
seasonId = int.tryParse(Get.parameters['seasonId']!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +74,27 @@ class MemberSeasonsController extends GetxController {
|
|||||||
getSeasonDetail('onLoad');
|
getSeasonDetail('onLoad');
|
||||||
}
|
}
|
||||||
if (category == '1') {
|
if (category == '1') {
|
||||||
|
if (seasonId != null) {
|
||||||
|
getSeasonDetail('onLoad');
|
||||||
|
}
|
||||||
|
if (seriesId != null) {
|
||||||
getSeriesDetail('onLoad');
|
getSeriesDetail('onLoad');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 下拉刷新
|
||||||
|
Future onRefresh() async {
|
||||||
|
if (category == '0') {
|
||||||
|
return getSeasonDetail('onRefresh');
|
||||||
|
}
|
||||||
|
if (category == '1') {
|
||||||
|
if (seasonId != null) {
|
||||||
|
return getSeasonDetail('onRefresh');
|
||||||
|
}
|
||||||
|
if (seriesId != null) {
|
||||||
|
return getSeriesDetail('onRefresh');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -23,9 +23,7 @@ class _MemberSeasonsPageState extends State<MemberSeasonsPage> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
category = Get.parameters['category']!;
|
category = Get.parameters['category']!;
|
||||||
_futureBuilderFuture = category == '0'
|
_futureBuilderFuture = _memberSeasonsController.onRefresh();
|
||||||
? _memberSeasonsController.getSeasonDetail('onRefresh')
|
|
||||||
: _memberSeasonsController.getSeriesDetail('onRefresh');
|
|
||||||
scrollController = _memberSeasonsController.scrollController;
|
scrollController = _memberSeasonsController.scrollController;
|
||||||
scrollController.addListener(
|
scrollController.addListener(
|
||||||
() {
|
() {
|
||||||
|
|||||||
@ -136,6 +136,7 @@ class MessageUtils {
|
|||||||
.replaceAll('}', '');
|
.replaceAll('}', '');
|
||||||
result[linkText] = match.group(0)!;
|
result[linkText] = match.group(0)!;
|
||||||
}
|
}
|
||||||
|
print('str: $str');
|
||||||
message += str;
|
message += str;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -144,6 +145,10 @@ class MessageUtils {
|
|||||||
}
|
}
|
||||||
lastMatchEnd = end;
|
lastMatchEnd = end;
|
||||||
}
|
}
|
||||||
|
// 处理剩余的未匹配部分
|
||||||
|
if (lastMatchEnd < text.length) {
|
||||||
|
message += text.substring(lastMatchEnd + 1);
|
||||||
|
}
|
||||||
result['message'] = message;
|
result['message'] = message;
|
||||||
} else {
|
} else {
|
||||||
result['message'] = text;
|
result['message'] = text;
|
||||||
|
|||||||
@ -17,8 +17,8 @@ class MineController extends GetxController {
|
|||||||
Rx<UserInfoData> userInfo = UserInfoData().obs;
|
Rx<UserInfoData> userInfo = UserInfoData().obs;
|
||||||
Rx<ThemeType> themeType = ThemeType.system.obs;
|
Rx<ThemeType> themeType = ThemeType.system.obs;
|
||||||
Rx<FavFolderData> favFolderData = FavFolderData().obs;
|
Rx<FavFolderData> favFolderData = FavFolderData().obs;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
List menuList = [
|
List menuList = [
|
||||||
{
|
{
|
||||||
'icon': Icons.history,
|
'icon': Icons.history,
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import 'package:pilipala/http/user.dart';
|
|||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
|
|
||||||
class MineEditController extends GetxController {
|
class MineEditController extends GetxController {
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
final formKey = GlobalKey<FormState>();
|
final formKey = GlobalKey<FormState>();
|
||||||
final TextEditingController unameCtr = TextEditingController();
|
final TextEditingController unameCtr = TextEditingController();
|
||||||
final TextEditingController useridCtr = TextEditingController();
|
final TextEditingController useridCtr = TextEditingController();
|
||||||
|
|||||||
@ -14,7 +14,7 @@ class RankController extends GetxController with GetTickerProviderStateMixin {
|
|||||||
late TabController tabController;
|
late TabController tabController;
|
||||||
late List tabsCtrList;
|
late List tabsCtrList;
|
||||||
late List<Widget> tabsPageList;
|
late List<Widget> tabsPageList;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
late final StreamController<bool> searchBarStream =
|
late final StreamController<bool> searchBarStream =
|
||||||
StreamController<bool>.broadcast();
|
StreamController<bool>.broadcast();
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ class RcmdController extends GetxController {
|
|||||||
// RxList<RecVideoItemModel> webVideoList = <RecVideoItemModel>[].obs;
|
// RxList<RecVideoItemModel> webVideoList = <RecVideoItemModel>[].obs;
|
||||||
bool isLoadingMore = true;
|
bool isLoadingMore = true;
|
||||||
OverlayEntry? popupDialog;
|
OverlayEntry? popupDialog;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
RxInt crossAxisCount = 2.obs;
|
RxInt crossAxisCount = 2.obs;
|
||||||
late bool enableSaveLastData;
|
late bool enableSaveLastData;
|
||||||
late String defaultRcmdType = 'web';
|
late String defaultRcmdType = 'web';
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class SSearchController extends GetxController {
|
|||||||
RxString searchKeyWord = ''.obs;
|
RxString searchKeyWord = ''.obs;
|
||||||
Rx<TextEditingController> controller = TextEditingController().obs;
|
Rx<TextEditingController> controller = TextEditingController().obs;
|
||||||
RxList<HotSearchItem> hotSearchList = <HotSearchItem>[].obs;
|
RxList<HotSearchItem> hotSearchList = <HotSearchItem>[].obs;
|
||||||
Box localCache = GStrorage.localCache;
|
Box localCache = GStorage.localCache;
|
||||||
List historyCacheList = [];
|
List historyCacheList = [];
|
||||||
RxList historyList = [].obs;
|
RxList historyList = [].obs;
|
||||||
RxList<SearchSuggestItem> searchSuggestList = <SearchSuggestItem>[].obs;
|
RxList<SearchSuggestItem> searchSuggestList = <SearchSuggestItem>[].obs;
|
||||||
@ -23,7 +23,7 @@ class SSearchController extends GetxController {
|
|||||||
Debouncer(delay: const Duration(milliseconds: 200)); // 设置延迟时间
|
Debouncer(delay: const Duration(milliseconds: 200)); // 设置延迟时间
|
||||||
String hintText = '搜索';
|
String hintText = '搜索';
|
||||||
RxString defaultSearch = ''.obs;
|
RxString defaultSearch = ''.obs;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
bool enableHotKey = true;
|
bool enableHotKey = true;
|
||||||
bool enableSearchSuggest = true;
|
bool enableSearchSuggest = true;
|
||||||
|
|
||||||
|
|||||||
@ -13,9 +13,9 @@ import '../main/index.dart';
|
|||||||
import 'widgets/select_dialog.dart';
|
import 'widgets/select_dialog.dart';
|
||||||
|
|
||||||
class SettingController extends GetxController {
|
class SettingController extends GetxController {
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
Box localCache = GStrorage.localCache;
|
Box localCache = GStorage.localCache;
|
||||||
|
|
||||||
RxBool userLogin = false.obs;
|
RxBool userLogin = false.obs;
|
||||||
RxBool feedBackEnable = false.obs;
|
RxBool feedBackEnable = false.obs;
|
||||||
|
|||||||
@ -19,8 +19,8 @@ class ExtraSetting extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ExtraSettingState extends State<ExtraSetting> {
|
class _ExtraSettingState extends State<ExtraSetting> {
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
static Box localCache = GStrorage.localCache;
|
static Box localCache = GStorage.localCache;
|
||||||
late dynamic defaultReplySort;
|
late dynamic defaultReplySort;
|
||||||
late dynamic defaultDynamicType;
|
late dynamic defaultDynamicType;
|
||||||
late dynamic enableSystemProxy;
|
late dynamic enableSystemProxy;
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class ActionMenuSetPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ActionMenuSetPageState extends State<ActionMenuSetPage> {
|
class _ActionMenuSetPageState extends State<ActionMenuSetPage> {
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
late List<String> actionTypeSort;
|
late List<String> actionTypeSort;
|
||||||
late List<Map> allLabels;
|
late List<Map> allLabels;
|
||||||
|
|
||||||
|
|||||||
@ -142,7 +142,7 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ColorSelectController extends GetxController {
|
class ColorSelectController extends GetxController {
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
RxBool dynamicColor = true.obs;
|
RxBool dynamicColor = true.obs;
|
||||||
RxInt type = 0.obs;
|
RxInt type = 0.obs;
|
||||||
late final List<Map<String, dynamic>> colorThemes;
|
late final List<Map<String, dynamic>> colorThemes;
|
||||||
|
|||||||
@ -16,7 +16,7 @@ class _SetDiaplayModeState extends State<SetDiaplayMode> {
|
|||||||
List<DisplayMode> modes = <DisplayMode>[];
|
List<DisplayMode> modes = <DisplayMode>[];
|
||||||
DisplayMode? active;
|
DisplayMode? active;
|
||||||
DisplayMode? preferred;
|
DisplayMode? preferred;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
|
|
||||||
final ValueNotifier<int> page = ValueNotifier<int>(0);
|
final ValueNotifier<int> page = ValueNotifier<int>(0);
|
||||||
late final PageController controller = PageController()
|
late final PageController controller = PageController()
|
||||||
|
|||||||
@ -11,7 +11,7 @@ class FontSizeSelectPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _FontSizeSelectPageState extends State<FontSizeSelectPage> {
|
class _FontSizeSelectPageState extends State<FontSizeSelectPage> {
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
List<double> list = [0.9, 0.95, 1.0, 1.05, 1.1, 1.15, 1.2, 1.25, 1.3];
|
List<double> list = [0.9, 0.95, 1.0, 1.05, 1.1, 1.15, 1.2, 1.25, 1.3];
|
||||||
late double minsize;
|
late double minsize;
|
||||||
late double maxSize;
|
late double maxSize;
|
||||||
|
|||||||
@ -12,7 +12,7 @@ class TabbarSetPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _TabbarSetPageState extends State<TabbarSetPage> {
|
class _TabbarSetPageState extends State<TabbarSetPage> {
|
||||||
Box settingStorage = GStrorage.setting;
|
Box settingStorage = GStorage.setting;
|
||||||
late List defaultTabs;
|
late List defaultTabs;
|
||||||
late List<String> tabbarSort;
|
late List<String> tabbarSort;
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class NavigationBarSetPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _NavigationbarSetPageState extends State<NavigationBarSetPage> {
|
class _NavigationbarSetPageState extends State<NavigationBarSetPage> {
|
||||||
Box settingStorage = GStrorage.setting;
|
Box settingStorage = GStorage.setting;
|
||||||
late List defaultNavTabs;
|
late List defaultNavTabs;
|
||||||
late List<int> navBarSort;
|
late List<int> navBarSort;
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ class PlayGesturePage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _PlayGesturePageState extends State<PlayGesturePage> {
|
class _PlayGesturePageState extends State<PlayGesturePage> {
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
late int fullScreenGestureMode;
|
late int fullScreenGestureMode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -14,8 +14,8 @@ class PlaySpeedPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _PlaySpeedPageState extends State<PlaySpeedPage> {
|
class _PlaySpeedPageState extends State<PlaySpeedPage> {
|
||||||
Box videoStorage = GStrorage.video;
|
Box videoStorage = GStorage.video;
|
||||||
Box settingStorage = GStrorage.setting;
|
Box settingStorage = GStorage.setting;
|
||||||
late double playSpeedDefault;
|
late double playSpeedDefault;
|
||||||
late List<double> playSpeedSystem;
|
late List<double> playSpeedSystem;
|
||||||
late double longPressSpeedDefault;
|
late double longPressSpeedDefault;
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class PlaySetting extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _PlaySettingState extends State<PlaySetting> {
|
class _PlaySettingState extends State<PlaySetting> {
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
late dynamic defaultVideoQa;
|
late dynamic defaultVideoQa;
|
||||||
late dynamic defaultLiveQa;
|
late dynamic defaultLiveQa;
|
||||||
late dynamic defaultAudioQa;
|
late dynamic defaultAudioQa;
|
||||||
|
|||||||
@ -14,7 +14,7 @@ class PrivacySetting extends StatefulWidget {
|
|||||||
|
|
||||||
class _PrivacySettingState extends State<PrivacySetting> {
|
class _PrivacySettingState extends State<PrivacySetting> {
|
||||||
bool userLogin = false;
|
bool userLogin = false;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
var userInfo;
|
var userInfo;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -17,10 +17,10 @@ class RecommendSetting extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _RecommendSettingState extends State<RecommendSetting> {
|
class _RecommendSettingState extends State<RecommendSetting> {
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
static Box localCache = GStrorage.localCache;
|
static Box localCache = GStorage.localCache;
|
||||||
late dynamic defaultRcmdType;
|
late dynamic defaultRcmdType;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
late dynamic userInfo;
|
late dynamic userInfo;
|
||||||
bool userLogin = false;
|
bool userLogin = false;
|
||||||
late dynamic accessKeyInfo;
|
late dynamic accessKeyInfo;
|
||||||
@ -247,10 +247,9 @@ class _RecommendSettingState extends State<RecommendSetting> {
|
|||||||
'* 其它(如热门视频、手动搜索、链接跳转等)均不受过滤器影响。\n'
|
'* 其它(如热门视频、手动搜索、链接跳转等)均不受过滤器影响。\n'
|
||||||
'* 设定较严苛的条件可导致推荐项数锐减或多次请求,请酌情选择。\n'
|
'* 设定较严苛的条件可导致推荐项数锐减或多次请求,请酌情选择。\n'
|
||||||
'* 后续可能会增加更多过滤条件,敬请期待。',
|
'* 后续可能会增加更多过滤条件,敬请期待。',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context).textTheme.labelSmall!.copyWith(
|
||||||
.textTheme
|
color:
|
||||||
.labelSmall!
|
Theme.of(context).colorScheme.outline.withOpacity(0.7)),
|
||||||
.copyWith(color: Theme.of(context).colorScheme.outline.withOpacity(0.7)),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|||||||
@ -28,7 +28,7 @@ class _StyleSettingState extends State<StyleSetting> {
|
|||||||
final ColorSelectController colorSelectController =
|
final ColorSelectController colorSelectController =
|
||||||
Get.put(ColorSelectController());
|
Get.put(ColorSelectController());
|
||||||
|
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
late int picQuality;
|
late int picQuality;
|
||||||
late ThemeType _tempThemeValue;
|
late ThemeType _tempThemeValue;
|
||||||
late dynamic defaultCustomRows;
|
late dynamic defaultCustomRows;
|
||||||
|
|||||||
@ -19,7 +19,7 @@ class SetSelectItem extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SetSelectItemState extends State<SetSelectItem> {
|
class _SetSelectItemState extends State<SetSelectItem> {
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
late dynamic currentVal;
|
late dynamic currentVal;
|
||||||
late int currentIndex;
|
late int currentIndex;
|
||||||
late List menus;
|
late List menus;
|
||||||
|
|||||||
@ -28,7 +28,7 @@ class SetSwitchItem extends StatefulWidget {
|
|||||||
|
|
||||||
class _SetSwitchItemState extends State<SetSwitchItem> {
|
class _SetSwitchItemState extends State<SetSwitchItem> {
|
||||||
// ignore: non_constant_identifier_names
|
// ignore: non_constant_identifier_names
|
||||||
Box Setting = GStrorage.setting;
|
Box Setting = GStorage.setting;
|
||||||
late bool val;
|
late bool val;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import '../../models/user/sub_folder.dart';
|
|||||||
class SubController extends GetxController {
|
class SubController extends GetxController {
|
||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
Rx<SubFolderModelData> subFolderData = SubFolderModelData().obs;
|
Rx<SubFolderModelData> subFolderData = SubFolderModelData().obs;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
UserInfoData? userInfo;
|
UserInfoData? userInfo;
|
||||||
int currentPage = 1;
|
int currentPage = 1;
|
||||||
int pageSize = 20;
|
int pageSize = 20;
|
||||||
|
|||||||
@ -6,11 +6,14 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:ns_danmaku/ns_danmaku.dart';
|
import 'package:ns_danmaku/ns_danmaku.dart';
|
||||||
|
import 'package:pilipala/http/common.dart';
|
||||||
import 'package:pilipala/http/constants.dart';
|
import 'package:pilipala/http/constants.dart';
|
||||||
import 'package:pilipala/http/user.dart';
|
import 'package:pilipala/http/user.dart';
|
||||||
import 'package:pilipala/http/video.dart';
|
import 'package:pilipala/http/video.dart';
|
||||||
import 'package:pilipala/models/common/reply_type.dart';
|
import 'package:pilipala/models/common/reply_type.dart';
|
||||||
import 'package:pilipala/models/common/search_type.dart';
|
import 'package:pilipala/models/common/search_type.dart';
|
||||||
|
import 'package:pilipala/models/sponsor_block/segment.dart';
|
||||||
|
import 'package:pilipala/models/sponsor_block/segment_type.dart';
|
||||||
import 'package:pilipala/models/video/later.dart';
|
import 'package:pilipala/models/video/later.dart';
|
||||||
import 'package:pilipala/models/video/play/quality.dart';
|
import 'package:pilipala/models/video/play/quality.dart';
|
||||||
import 'package:pilipala/models/video/play/url.dart';
|
import 'package:pilipala/models/video/play/url.dart';
|
||||||
@ -68,9 +71,9 @@ class VideoDetailController extends GetxController
|
|||||||
RxBool enableHA = false.obs;
|
RxBool enableHA = false.obs;
|
||||||
|
|
||||||
/// 本地存储
|
/// 本地存储
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
Box localCache = GStrorage.localCache;
|
Box localCache = GStorage.localCache;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
|
|
||||||
RxInt oid = 0.obs;
|
RxInt oid = 0.obs;
|
||||||
// 评论id 请求楼中楼评论使用
|
// 评论id 请求楼中楼评论使用
|
||||||
@ -120,6 +123,8 @@ class VideoDetailController extends GetxController
|
|||||||
RxBool isWatchLaterVisible = false.obs;
|
RxBool isWatchLaterVisible = false.obs;
|
||||||
RxString watchLaterTitle = ''.obs;
|
RxString watchLaterTitle = ''.obs;
|
||||||
RxInt watchLaterCount = 0.obs;
|
RxInt watchLaterCount = 0.obs;
|
||||||
|
List<SegmentDataModel> skipSegments = <SegmentDataModel>[];
|
||||||
|
int? lastPosition;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
@ -188,6 +193,11 @@ class VideoDetailController extends GetxController
|
|||||||
tabCtr.addListener(() {
|
tabCtr.addListener(() {
|
||||||
onTabChanged();
|
onTabChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// 仅投稿视频skip
|
||||||
|
if (videoType == SearchType.video) {
|
||||||
|
querySkipSegments();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showReplyReplyPanel(oid, fRpid, firstFloor, currentReply, loadMore) {
|
showReplyReplyPanel(oid, fRpid, firstFloor, currentReply, loadMore) {
|
||||||
@ -305,6 +315,7 @@ class VideoDetailController extends GetxController
|
|||||||
plPlayerController.headerControl = headerControl;
|
plPlayerController.headerControl = headerControl;
|
||||||
|
|
||||||
plPlayerController.subtitles.value = subtitles;
|
plPlayerController.subtitles.value = subtitles;
|
||||||
|
onPositionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 视频链接
|
// 视频链接
|
||||||
@ -706,6 +717,53 @@ class VideoDetailController extends GetxController
|
|||||||
isWatchLaterVisible.value = tabCtr.index == 0;
|
isWatchLaterVisible.value = tabCtr.index == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取sponsorBlock数据
|
||||||
|
Future querySkipSegments() async {
|
||||||
|
var res = await CommonHttp.querySkipSegments(bvid: bvid);
|
||||||
|
if (res['status']) {
|
||||||
|
/// TODO 根据segmentType过滤数据
|
||||||
|
skipSegments = res['data'] ?? [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听视频进度
|
||||||
|
void onPositionChanged() async {
|
||||||
|
final List<SegmentDataModel> sponsorSkipSegments = skipSegments
|
||||||
|
.where((e) => e.category!.value == SegmentType.sponsor.value)
|
||||||
|
.toList();
|
||||||
|
if (sponsorSkipSegments.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
plPlayerController.videoPlayerController?.stream.position
|
||||||
|
.listen((Duration position) async {
|
||||||
|
final int positionMs = position.inSeconds;
|
||||||
|
|
||||||
|
// 如果当前秒与上次处理的秒相同,则直接返回
|
||||||
|
if (lastPosition != null && lastPosition! == positionMs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPosition = positionMs;
|
||||||
|
for (SegmentDataModel segment in sponsorSkipSegments) {
|
||||||
|
try {
|
||||||
|
final segmentStart = segment.segment!.first.toInt();
|
||||||
|
final segmentEnd = segment.segment!.last.toInt();
|
||||||
|
|
||||||
|
/// 只有顺序播放时才skip,跳转时间点不会skip
|
||||||
|
if (positionMs == segmentStart && !segment.isSkip) {
|
||||||
|
await plPlayerController.videoPlayerController
|
||||||
|
?.seek(Duration(seconds: segmentEnd));
|
||||||
|
segment.isSkip = true;
|
||||||
|
SmartDialog.showToast('已跳过${segment.category!.label}片段');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
SmartDialog.showToast('skipSegments error: $err');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
super.onClose();
|
super.onClose();
|
||||||
|
|||||||
@ -41,7 +41,7 @@ class VideoIntroController extends GetxController {
|
|||||||
RxBool hasFav = false.obs;
|
RxBool hasFav = false.obs;
|
||||||
// 是否不喜欢
|
// 是否不喜欢
|
||||||
RxBool hasDisLike = false.obs;
|
RxBool hasDisLike = false.obs;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
bool userLogin = false;
|
bool userLogin = false;
|
||||||
Rx<FavFolderData> favFolderData = FavFolderData().obs;
|
Rx<FavFolderData> favFolderData = FavFolderData().obs;
|
||||||
List addMediaIdsNew = [];
|
List addMediaIdsNew = [];
|
||||||
@ -63,6 +63,7 @@ class VideoIntroController extends GetxController {
|
|||||||
PersistentBottomSheetController? bottomSheetController;
|
PersistentBottomSheetController? bottomSheetController;
|
||||||
late bool enableRelatedVideo;
|
late bool enableRelatedVideo;
|
||||||
UgcSeason? ugcSeason;
|
UgcSeason? ugcSeason;
|
||||||
|
RxList<Part> pages = <Part>[].obs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
@ -84,18 +85,20 @@ class VideoIntroController extends GetxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取视频简介&分p
|
// 获取视频简介&分p
|
||||||
Future queryVideoIntro() async {
|
Future queryVideoIntro({cover}) async {
|
||||||
var result = await VideoHttp.videoIntro(bvid: bvid);
|
var result = await VideoHttp.videoIntro(bvid: bvid);
|
||||||
if (result['status']) {
|
if (result['status']) {
|
||||||
videoDetail.value = result['data']!;
|
videoDetail.value = result['data']!;
|
||||||
ugcSeason = result['data']!.ugcSeason;
|
ugcSeason = result['data']!.ugcSeason;
|
||||||
if (videoDetail.value.pages!.isNotEmpty && lastPlayCid.value == 0) {
|
pages.value = result['data']!.pages!;
|
||||||
lastPlayCid.value = videoDetail.value.pages!.first.cid!;
|
lastPlayCid.value = videoDetail.value.cid!;
|
||||||
|
if (pages.isNotEmpty) {
|
||||||
|
lastPlayCid.value = pages.first.cid!;
|
||||||
}
|
}
|
||||||
final VideoDetailController videoDetailCtr =
|
final VideoDetailController videoDetailCtr =
|
||||||
Get.find<VideoDetailController>(tag: heroTag);
|
Get.find<VideoDetailController>(tag: heroTag);
|
||||||
videoDetailCtr.tabs.value = ['简介', '评论 ${result['data']?.stat?.reply}'];
|
videoDetailCtr.tabs.value = ['简介', '评论 ${result['data']?.stat?.reply}'];
|
||||||
videoDetailCtr.cover.value = result['data'].pic ?? '';
|
videoDetailCtr.cover.value = cover ?? result['data'].pic ?? '';
|
||||||
// 获取到粉丝数再返回
|
// 获取到粉丝数再返回
|
||||||
await queryUserStat();
|
await queryUserStat();
|
||||||
}
|
}
|
||||||
@ -470,8 +473,7 @@ class VideoIntroController extends GetxController {
|
|||||||
videoReplyCtr.queryReplyList(type: 'init');
|
videoReplyCtr.queryReplyList(type: 'init');
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
this.bvid = bvid;
|
this.bvid = bvid;
|
||||||
lastPlayCid.value = cid;
|
await queryVideoIntro(cover: cover);
|
||||||
await queryVideoIntro();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void startTimer() {
|
void startTimer() {
|
||||||
@ -521,9 +523,8 @@ class VideoIntroController extends GetxController {
|
|||||||
final List<EpisodeItem> episodesList = sections[i].episodes!;
|
final List<EpisodeItem> episodesList = sections[i].episodes!;
|
||||||
episodes.addAll(episodesList);
|
episodes.addAll(episodesList);
|
||||||
}
|
}
|
||||||
} else if (videoDetail.value.pages != null) {
|
} else if (pages.isNotEmpty) {
|
||||||
isPages = true;
|
isPages = true;
|
||||||
final List<Part> pages = videoDetail.value.pages!;
|
|
||||||
episodes.addAll(pages);
|
episodes.addAll(pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,10 +622,9 @@ class VideoIntroController extends GetxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (videoDetail.value.pages != null &&
|
if (pages.length > 1) {
|
||||||
videoDetail.value.pages!.length > 1) {
|
|
||||||
dataType = VideoEpidoesType.videoPart;
|
dataType = VideoEpidoesType.videoPart;
|
||||||
episodes = videoDetail.value.pages!;
|
episodes = pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerUtils.showRightDialog(
|
DrawerUtils.showRightDialog(
|
||||||
|
|||||||
@ -137,8 +137,8 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
late String heroTag;
|
late String heroTag;
|
||||||
late final VideoIntroController videoIntroController;
|
late final VideoIntroController videoIntroController;
|
||||||
late final VideoDetailController videoDetailCtr;
|
late final VideoDetailController videoDetailCtr;
|
||||||
final Box<dynamic> localCache = GStrorage.localCache;
|
final Box<dynamic> localCache = GStorage.localCache;
|
||||||
final Box<dynamic> setting = GStrorage.setting;
|
final Box<dynamic> setting = GStorage.setting;
|
||||||
late double sheetHeight;
|
late double sheetHeight;
|
||||||
late final dynamic owner;
|
late final dynamic owner;
|
||||||
late int mid;
|
late int mid;
|
||||||
@ -404,27 +404,18 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
Obx(
|
Obx(
|
||||||
() => SeasonPanel(
|
() => SeasonPanel(
|
||||||
ugcSeason: widget.videoDetail!.ugcSeason!,
|
ugcSeason: widget.videoDetail!.ugcSeason!,
|
||||||
cid: videoIntroController.lastPlayCid.value != 0
|
cid: videoIntroController.lastPlayCid.value,
|
||||||
? videoIntroController.lastPlayCid.value
|
|
||||||
: widget.videoDetail!.pages!.first.cid,
|
|
||||||
sheetHeight: videoDetailCtr.sheetHeight.value,
|
sheetHeight: videoDetailCtr.sheetHeight.value,
|
||||||
changeFuc: (bvid, cid, aid, cover) =>
|
changeFuc: videoIntroController.changeSeasonOrbangu,
|
||||||
videoIntroController.changeSeasonOrbangu(
|
|
||||||
bvid,
|
|
||||||
cid,
|
|
||||||
aid,
|
|
||||||
cover,
|
|
||||||
),
|
|
||||||
videoIntroCtr: videoIntroController,
|
videoIntroCtr: videoIntroController,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
// 合集 videoEpisode
|
// 合集 videoEpisode
|
||||||
if (widget.videoDetail!.pages != null &&
|
if (videoIntroController.pages.length > 1) ...[
|
||||||
widget.videoDetail!.pages!.length > 1) ...[
|
|
||||||
Obx(
|
Obx(
|
||||||
() => PagesPanel(
|
() => PagesPanel(
|
||||||
pages: widget.videoDetail!.pages!,
|
pages: videoIntroController.pages,
|
||||||
cid: videoIntroController.lastPlayCid.value,
|
cid: videoIntroController.lastPlayCid.value,
|
||||||
sheetHeight: videoDetailCtr.sheetHeight.value,
|
sheetHeight: videoDetailCtr.sheetHeight.value,
|
||||||
changeFuc: (cid, cover) =>
|
changeFuc: (cid, cover) =>
|
||||||
|
|||||||
@ -16,7 +16,7 @@ class FavPanel extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _FavPanelState extends State<FavPanel> {
|
class _FavPanelState extends State<FavPanel> {
|
||||||
final Box<dynamic> localCache = GStrorage.localCache;
|
final Box<dynamic> localCache = GStorage.localCache;
|
||||||
late Future _futureBuilderFuture;
|
late Future _futureBuilderFuture;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -18,7 +18,7 @@ class GroupPanel extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _GroupPanelState extends State<GroupPanel> {
|
class _GroupPanelState extends State<GroupPanel> {
|
||||||
final Box<dynamic> localCache = GStrorage.localCache;
|
final Box<dynamic> localCache = GStorage.localCache;
|
||||||
late Future _futureBuilderFuture;
|
late Future _futureBuilderFuture;
|
||||||
late List<MemberTagItemModel> tagsList;
|
late List<MemberTagItemModel> tagsList;
|
||||||
bool showDefault = true;
|
bool showDefault = true;
|
||||||
|
|||||||
@ -3,7 +3,6 @@ import 'dart:math';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/models/video_detail_res.dart';
|
import 'package:pilipala/models/video_detail_res.dart';
|
||||||
import 'package:pilipala/pages/video/detail/index.dart';
|
|
||||||
import 'package:pilipala/pages/video/detail/introduction/index.dart';
|
import 'package:pilipala/pages/video/detail/introduction/index.dart';
|
||||||
import '../../../../../common/pages_bottom_sheet.dart';
|
import '../../../../../common/pages_bottom_sheet.dart';
|
||||||
import '../../../../../models/common/video_episode_type.dart';
|
import '../../../../../models/common/video_episode_type.dart';
|
||||||
@ -32,25 +31,26 @@ class _PagesPanelState extends State<PagesPanel> {
|
|||||||
late int cid;
|
late int cid;
|
||||||
late RxInt currentIndex = (-1).obs;
|
late RxInt currentIndex = (-1).obs;
|
||||||
final String heroTag = Get.arguments['heroTag'];
|
final String heroTag = Get.arguments['heroTag'];
|
||||||
late VideoDetailController _videoDetailController;
|
|
||||||
final ScrollController listViewScrollCtr = ScrollController();
|
final ScrollController listViewScrollCtr = ScrollController();
|
||||||
late PersistentBottomSheetController? _bottomSheetController;
|
PersistentBottomSheetController? _bottomSheetController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
cid = widget.cid;
|
cid = widget.cid;
|
||||||
episodes = widget.pages;
|
episodes = widget.pages;
|
||||||
_videoDetailController = Get.find<VideoDetailController>(tag: heroTag);
|
updateCurrentIndexAndScroll();
|
||||||
currentIndex.value = episodes.indexWhere((Part e) => e.cid == cid);
|
widget.videoIntroCtr.lastPlayCid.listen((int p0) {
|
||||||
scrollToIndex();
|
|
||||||
_videoDetailController.cid.listen((int p0) {
|
|
||||||
cid = p0;
|
cid = p0;
|
||||||
currentIndex.value = episodes.indexWhere((Part e) => e.cid == cid);
|
updateCurrentIndexAndScroll();
|
||||||
scrollToIndex();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateCurrentIndexAndScroll() {
|
||||||
|
currentIndex.value = widget.pages.indexWhere((Part e) => e.cid == cid);
|
||||||
|
scrollToIndex();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
listViewScrollCtr.dispose();
|
listViewScrollCtr.dispose();
|
||||||
@ -60,7 +60,10 @@ class _PagesPanelState extends State<PagesPanel> {
|
|||||||
void changeFucCall(item, i) async {
|
void changeFucCall(item, i) async {
|
||||||
widget.changeFuc?.call(item.cid, item.cover);
|
widget.changeFuc?.call(item.cid, item.cover);
|
||||||
currentIndex.value = i;
|
currentIndex.value = i;
|
||||||
|
cid = item.cid;
|
||||||
|
if (_bottomSheetController != null) {
|
||||||
_bottomSheetController?.close();
|
_bottomSheetController?.close();
|
||||||
|
}
|
||||||
scrollToIndex();
|
scrollToIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +115,7 @@ class _PagesPanelState extends State<PagesPanel> {
|
|||||||
widget.videoIntroCtr.bottomSheetController =
|
widget.videoIntroCtr.bottomSheetController =
|
||||||
_bottomSheetController = EpisodeBottomSheet(
|
_bottomSheetController = EpisodeBottomSheet(
|
||||||
currentCid: cid,
|
currentCid: cid,
|
||||||
episodes: episodes,
|
episodes: widget.pages,
|
||||||
changeFucCall: changeFucCall,
|
changeFucCall: changeFucCall,
|
||||||
sheetHeight: widget.sheetHeight,
|
sheetHeight: widget.sheetHeight,
|
||||||
dataType: VideoEpidoesType.videoPart,
|
dataType: VideoEpidoesType.videoPart,
|
||||||
|
|||||||
@ -33,6 +33,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
|||||||
final String heroTag = Get.arguments['heroTag'];
|
final String heroTag = Get.arguments['heroTag'];
|
||||||
late VideoDetailController _videoDetailController;
|
late VideoDetailController _videoDetailController;
|
||||||
late PersistentBottomSheetController? _bottomSheetController;
|
late PersistentBottomSheetController? _bottomSheetController;
|
||||||
|
int currentEpisodeIndex = -1;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -41,13 +42,12 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
|||||||
_videoDetailController = Get.find<VideoDetailController>(tag: heroTag);
|
_videoDetailController = Get.find<VideoDetailController>(tag: heroTag);
|
||||||
|
|
||||||
/// 根据 cid 找到对应集,找到对应 episodes
|
/// 根据 cid 找到对应集,找到对应 episodes
|
||||||
/// 有多个episodes时,只显示其中一个
|
|
||||||
/// TODO 同时显示多个合集
|
|
||||||
final List<SectionItem> sections = widget.ugcSeason.sections!;
|
final List<SectionItem> sections = widget.ugcSeason.sections!;
|
||||||
for (int i = 0; i < sections.length; i++) {
|
for (int i = 0; i < sections.length; i++) {
|
||||||
final List<EpisodeItem> episodesList = sections[i].episodes!;
|
final List<EpisodeItem> episodesList = sections[i].episodes!;
|
||||||
for (int j = 0; j < episodesList.length; j++) {
|
for (int j = 0; j < episodesList.length; j++) {
|
||||||
if (episodesList[j].cid == cid) {
|
if (episodesList[j].cid == cid) {
|
||||||
|
currentEpisodeIndex = i;
|
||||||
episodes = episodesList;
|
episodes = episodesList;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -55,10 +55,10 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 取对应 season_id 的 episodes
|
/// 取对应 season_id 的 episodes
|
||||||
currentIndex.value = episodes.indexWhere((EpisodeItem e) => e.cid == cid);
|
getCurrentIndex();
|
||||||
_videoDetailController.cid.listen((int p0) {
|
_videoDetailController.cid.listen((int p0) {
|
||||||
cid = p0;
|
cid = p0;
|
||||||
currentIndex.value = episodes.indexWhere((EpisodeItem e) => e.cid == cid);
|
getCurrentIndex();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +73,23 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
|||||||
_bottomSheetController?.close();
|
_bottomSheetController?.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取currentIndex
|
||||||
|
void getCurrentIndex() {
|
||||||
|
currentIndex.value = episodes.indexWhere((EpisodeItem e) => e.cid == cid);
|
||||||
|
final List<SectionItem> sections = widget.ugcSeason.sections!;
|
||||||
|
if (sections.length == 1 && sections.first.type == 1) {
|
||||||
|
final List<EpisodeItem> episodesList = sections.first.episodes!;
|
||||||
|
for (int i = 0; i < episodesList.length; i++) {
|
||||||
|
for (int j = 0; j < episodesList[i].pages!.length; j++) {
|
||||||
|
if (episodesList[i].pages![j].cid == cid) {
|
||||||
|
currentIndex.value = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Widget buildEpisodeListItem(
|
Widget buildEpisodeListItem(
|
||||||
EpisodeItem episode,
|
EpisodeItem episode,
|
||||||
int index,
|
int index,
|
||||||
@ -125,6 +142,8 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
|||||||
sheetHeight: widget.sheetHeight,
|
sheetHeight: widget.sheetHeight,
|
||||||
dataType: VideoEpidoesType.videoEpisode,
|
dataType: VideoEpidoesType.videoEpisode,
|
||||||
ugcSeason: widget.ugcSeason,
|
ugcSeason: widget.ugcSeason,
|
||||||
|
currentEpisodeIndex: currentEpisodeIndex,
|
||||||
|
currentIndex: currentIndex.value,
|
||||||
).show(context);
|
).show(context);
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
|||||||
@ -32,20 +32,20 @@ class VideoReplyController extends GetxController {
|
|||||||
RxString sortTypeTitle = ReplySortType.time.titles.obs;
|
RxString sortTypeTitle = ReplySortType.time.titles.obs;
|
||||||
RxString sortTypeLabel = ReplySortType.time.labels.obs;
|
RxString sortTypeLabel = ReplySortType.time.labels.obs;
|
||||||
|
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
RxInt replyReqCode = 200.obs;
|
RxInt replyReqCode = 200.obs;
|
||||||
bool isEnd = false;
|
bool isEnd = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
int deaultReplySortIndex =
|
int defaultReplySortIndex =
|
||||||
setting.get(SettingBoxKey.replySortType, defaultValue: 0) as int;
|
setting.get(SettingBoxKey.replySortType, defaultValue: 0) as int;
|
||||||
if (deaultReplySortIndex == 2) {
|
if (defaultReplySortIndex == 2) {
|
||||||
setting.put(SettingBoxKey.replySortType, 0);
|
setting.put(SettingBoxKey.replySortType, 0);
|
||||||
deaultReplySortIndex = 0;
|
defaultReplySortIndex = 0;
|
||||||
}
|
}
|
||||||
_sortType = ReplySortType.values[deaultReplySortIndex];
|
_sortType = ReplySortType.values[defaultReplySortIndex];
|
||||||
sortTypeTitle.value = _sortType.titles;
|
sortTypeTitle.value = _sortType.titles;
|
||||||
sortTypeLabel.value = _sortType.labels;
|
sortTypeLabel.value = _sortType.labels;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ import 'package:pilipala/utils/utils.dart';
|
|||||||
import 'reply_save.dart';
|
import 'reply_save.dart';
|
||||||
import 'zan.dart';
|
import 'zan.dart';
|
||||||
|
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
|
|
||||||
class ReplyItem extends StatelessWidget {
|
class ReplyItem extends StatelessWidget {
|
||||||
const ReplyItem({
|
const ReplyItem({
|
||||||
@ -235,55 +235,10 @@ class ReplyItem extends StatelessWidget {
|
|||||||
// title
|
// title
|
||||||
Container(
|
Container(
|
||||||
margin: const EdgeInsets.only(top: 10, left: 45, right: 6, bottom: 4),
|
margin: const EdgeInsets.only(top: 10, left: 45, right: 6, bottom: 4),
|
||||||
child: !replySave
|
child: Text.rich(
|
||||||
? LayoutBuilder(builder:
|
overflow: TextOverflow.ellipsis,
|
||||||
(BuildContext context, BoxConstraints boxConstraints) {
|
maxLines:
|
||||||
String text = replyItem?.content?.message ?? '';
|
replyLevel == '1' && replyItem!.content!.isText! ? 5 : 999,
|
||||||
bool didExceedMaxLines = false;
|
|
||||||
final double maxWidth = boxConstraints.maxWidth;
|
|
||||||
TextPainter? textPainter;
|
|
||||||
final int maxLines =
|
|
||||||
replyItem!.content!.isText! && replyLevel == '1'
|
|
||||||
? 6
|
|
||||||
: 999;
|
|
||||||
try {
|
|
||||||
textPainter = TextPainter(
|
|
||||||
text: TextSpan(text: text),
|
|
||||||
maxLines: maxLines,
|
|
||||||
textDirection: Directionality.of(context),
|
|
||||||
);
|
|
||||||
textPainter.layout(maxWidth: maxWidth);
|
|
||||||
didExceedMaxLines = textPainter.didExceedMaxLines;
|
|
||||||
} catch (e) {
|
|
||||||
debugPrint('Error while measuring text: $e');
|
|
||||||
didExceedMaxLines = false;
|
|
||||||
}
|
|
||||||
return replyContent(context, didExceedMaxLines, textPainter);
|
|
||||||
})
|
|
||||||
: replyContent(context, false, null),
|
|
||||||
),
|
|
||||||
// 操作区域
|
|
||||||
bottonAction(context, replyItem!.replyControl, replySave),
|
|
||||||
// 一楼的评论
|
|
||||||
if ((replyItem!.rcount! > 0) && showReplyRow!) ...[
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 5, bottom: 12),
|
|
||||||
child: ReplyItemRow(
|
|
||||||
replies: replyItem!.replies,
|
|
||||||
replyControl: replyItem!.replyControl,
|
|
||||||
// f_rpid: replyItem!.rpid,
|
|
||||||
replyItem: replyItem,
|
|
||||||
replyReply: replyReply,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget replyContent(
|
|
||||||
BuildContext context, bool? didExceedMaxLines, TextPainter? textPainter) {
|
|
||||||
return Text.rich(
|
|
||||||
style: const TextStyle(height: 1.75),
|
style: const TextStyle(height: 1.75),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
@ -303,11 +258,27 @@ class ReplyItem extends StatelessWidget {
|
|||||||
replyItem!,
|
replyItem!,
|
||||||
replyReply,
|
replyReply,
|
||||||
null,
|
null,
|
||||||
didExceedMaxLines ?? false,
|
|
||||||
textPainter,
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// 操作区域
|
||||||
|
bottonAction(context, replyItem!.replyControl, replySave),
|
||||||
|
// 一楼的评论
|
||||||
|
if ((replyItem!.rcount! > 0) && showReplyRow!) ...[
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 5, bottom: 12),
|
||||||
|
child: ReplyItemRow(
|
||||||
|
replies: replyItem!.replies,
|
||||||
|
replyControl: replyItem!.replyControl,
|
||||||
|
// f_rpid: replyItem!.rpid,
|
||||||
|
replyItem: replyItem,
|
||||||
|
replyReply: replyReply,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,8 +464,12 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
fs: 9,
|
fs: 9,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
buildContent(context, replies![i], replyReply,
|
buildContent(
|
||||||
replyItem, false, null),
|
context,
|
||||||
|
replies![i],
|
||||||
|
replyReply,
|
||||||
|
replyItem,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -540,8 +515,6 @@ InlineSpan buildContent(
|
|||||||
replyItem,
|
replyItem,
|
||||||
replyReply,
|
replyReply,
|
||||||
fReplyItem,
|
fReplyItem,
|
||||||
bool didExceedMaxLines,
|
|
||||||
TextPainter? textPainter,
|
|
||||||
) {
|
) {
|
||||||
final String routePath = Get.currentRoute;
|
final String routePath = Get.currentRoute;
|
||||||
bool isVideoPage = routePath.startsWith('/video');
|
bool isVideoPage = routePath.startsWith('/video');
|
||||||
@ -553,25 +526,6 @@ InlineSpan buildContent(
|
|||||||
final content = replyItem.content;
|
final content = replyItem.content;
|
||||||
final List<InlineSpan> spanChilds = <InlineSpan>[];
|
final List<InlineSpan> spanChilds = <InlineSpan>[];
|
||||||
|
|
||||||
if (didExceedMaxLines && content.message != '') {
|
|
||||||
final textSize = textPainter!.size;
|
|
||||||
var position = textPainter.getPositionForOffset(
|
|
||||||
Offset(
|
|
||||||
textSize.width,
|
|
||||||
textSize.height,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
final endOffset = textPainter.getOffsetBefore(position.offset);
|
|
||||||
|
|
||||||
if (endOffset != null && endOffset > 0) {
|
|
||||||
content.message = content.message.substring(0, endOffset);
|
|
||||||
} else {
|
|
||||||
content.message = content.message.substring(0, position.offset);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
content.message = content.message2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 投票
|
// 投票
|
||||||
if (content.vote.isNotEmpty) {
|
if (content.vote.isNotEmpty) {
|
||||||
content.message.splitMapJoin(RegExp(r"\{vote:.*?\}"),
|
content.message.splitMapJoin(RegExp(r"\{vote:.*?\}"),
|
||||||
@ -921,17 +875,6 @@ InlineSpan buildContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (didExceedMaxLines) {
|
|
||||||
spanChilds.add(
|
|
||||||
TextSpan(
|
|
||||||
text: '\n查看更多',
|
|
||||||
style: TextStyle(
|
|
||||||
color: colorScheme.primary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 图片渲染
|
// 图片渲染
|
||||||
if (content.pictures.isNotEmpty) {
|
if (content.pictures.isNotEmpty) {
|
||||||
final List<String> picList = <String>[];
|
final List<String> picList = <String>[];
|
||||||
|
|||||||
@ -42,7 +42,7 @@ class VideoReplyReplyPanel extends StatefulWidget {
|
|||||||
class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
|
class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
|
||||||
late VideoReplyReplyController _videoReplyReplyController;
|
late VideoReplyReplyController _videoReplyReplyController;
|
||||||
late AnimationController replyAnimationCtl;
|
late AnimationController replyAnimationCtl;
|
||||||
final Box<dynamic> localCache = GStrorage.localCache;
|
final Box<dynamic> localCache = GStorage.localCache;
|
||||||
Future? _futureBuilderFuture;
|
Future? _futureBuilderFuture;
|
||||||
late ScrollController scrollController;
|
late ScrollController scrollController;
|
||||||
|
|
||||||
|
|||||||
@ -54,8 +54,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
Rx<PlayerStatus> playerStatus = PlayerStatus.playing.obs;
|
Rx<PlayerStatus> playerStatus = PlayerStatus.playing.obs;
|
||||||
double doubleOffset = 0;
|
double doubleOffset = 0;
|
||||||
|
|
||||||
final Box<dynamic> localCache = GStrorage.localCache;
|
final Box<dynamic> localCache = GStorage.localCache;
|
||||||
final Box<dynamic> setting = GStrorage.setting;
|
final Box<dynamic> setting = GStorage.setting;
|
||||||
late double statusBarHeight;
|
late double statusBarHeight;
|
||||||
final double videoHeight = Get.size.width * 9 / 16;
|
final double videoHeight = Get.size.width * 9 / 16;
|
||||||
late Future _futureBuilderFuture;
|
late Future _futureBuilderFuture;
|
||||||
@ -101,7 +101,9 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
|
|
||||||
videoSourceInit();
|
videoSourceInit();
|
||||||
appbarStreamListen();
|
appbarStreamListen();
|
||||||
|
if (autoPlayEnable) {
|
||||||
fullScreenStatusListener();
|
fullScreenStatusListener();
|
||||||
|
}
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
floating = vdCtr.floating!;
|
floating = vdCtr.floating!;
|
||||||
}
|
}
|
||||||
@ -137,7 +139,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
autoEnterPip(status: status);
|
autoEnterPip(status: status);
|
||||||
if (status == PlayerStatus.completed) {
|
if (status == PlayerStatus.completed) {
|
||||||
// 结束播放退出全屏
|
// 结束播放退出全屏
|
||||||
if (autoExitFullcreen) {
|
if (autoExitFullcreen && plPlayerController!.isFullScreen.value) {
|
||||||
plPlayerController!.triggerFullScreen(status: false);
|
plPlayerController!.triggerFullScreen(status: false);
|
||||||
}
|
}
|
||||||
shutdownTimerService.handleWaitingFinished();
|
shutdownTimerService.handleWaitingFinished();
|
||||||
@ -184,6 +186,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
await vdCtr.playerInit(autoplay: true);
|
await vdCtr.playerInit(autoplay: true);
|
||||||
plPlayerController = vdCtr.plPlayerController;
|
plPlayerController = vdCtr.plPlayerController;
|
||||||
plPlayerController!.addStatusLister(playerListener);
|
plPlayerController!.addStatusLister(playerListener);
|
||||||
|
fullScreenStatusListener();
|
||||||
vdCtr.autoPlay.value = true;
|
vdCtr.autoPlay.value = true;
|
||||||
vdCtr.isShowCover.value = false;
|
vdCtr.isShowCover.value = false;
|
||||||
isShowing.value = true;
|
isShowing.value = true;
|
||||||
|
|||||||
@ -52,8 +52,8 @@ class _HeaderControlState extends State<HeaderControl> {
|
|||||||
static const TextStyle subTitleStyle = TextStyle(fontSize: 12);
|
static const TextStyle subTitleStyle = TextStyle(fontSize: 12);
|
||||||
static const TextStyle titleStyle = TextStyle(fontSize: 14);
|
static const TextStyle titleStyle = TextStyle(fontSize: 14);
|
||||||
Size get preferredSize => const Size(double.infinity, kToolbarHeight);
|
Size get preferredSize => const Size(double.infinity, kToolbarHeight);
|
||||||
final Box<dynamic> localCache = GStrorage.localCache;
|
final Box<dynamic> localCache = GStorage.localCache;
|
||||||
final Box<dynamic> videoStorage = GStrorage.video;
|
final Box<dynamic> videoStorage = GStorage.video;
|
||||||
late List<double> speedsList;
|
late List<double> speedsList;
|
||||||
double buttonSpace = 8;
|
double buttonSpace = 8;
|
||||||
RxBool isFullScreen = false.obs;
|
RxBool isFullScreen = false.obs;
|
||||||
|
|||||||
@ -20,7 +20,7 @@ class WhisperDetailController extends GetxController {
|
|||||||
//表情转换图片规则
|
//表情转换图片规则
|
||||||
RxList<dynamic> eInfos = [].obs;
|
RxList<dynamic> eInfos = [].obs;
|
||||||
final TextEditingController replyContentController = TextEditingController();
|
final TextEditingController replyContentController = TextEditingController();
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
List emoteList = [];
|
List emoteList = [];
|
||||||
List<String> picList = [];
|
List<String> picList = [];
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@ class _WhisperDetailPageState extends State<WhisperDetailPage>
|
|||||||
late double emoteHeight = 230.0;
|
late double emoteHeight = 230.0;
|
||||||
double keyboardHeight = 0.0; // 键盘高度
|
double keyboardHeight = 0.0; // 键盘高度
|
||||||
RxString toolbarType = ''.obs;
|
RxString toolbarType = ''.obs;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
|||||||
@ -56,8 +56,7 @@ class ChatItem extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
bool isOwner =
|
bool isOwner = item.senderUid == GStorage.userInfo.get('userInfoCache').mid;
|
||||||
item.senderUid == GStrorage.userInfo.get('userInfoCache').mid;
|
|
||||||
|
|
||||||
bool isPic = item.msgType == MsgType.pic.value; // 图片
|
bool isPic = item.msgType == MsgType.pic.value; // 图片
|
||||||
bool isText = item.msgType == MsgType.text.value; // 文本
|
bool isText = item.msgType == MsgType.text.value; // 文本
|
||||||
|
|||||||
@ -27,9 +27,9 @@ import '../../models/video/subTitile/content.dart';
|
|||||||
import '../../models/video/subTitile/result.dart';
|
import '../../models/video/subTitile/result.dart';
|
||||||
// import 'package:wakelock_plus/wakelock_plus.dart';
|
// import 'package:wakelock_plus/wakelock_plus.dart';
|
||||||
|
|
||||||
Box videoStorage = GStrorage.video;
|
Box videoStorage = GStorage.video;
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
Box localCache = GStrorage.localCache;
|
Box localCache = GStorage.localCache;
|
||||||
|
|
||||||
class PlPlayerController {
|
class PlPlayerController {
|
||||||
Player? _videoPlayerController;
|
Player? _videoPlayerController;
|
||||||
@ -1033,6 +1033,8 @@ class PlPlayerController {
|
|||||||
if (progress >= content['from']! && progress <= content['to']!) {
|
if (progress >= content['from']! && progress <= content['to']!) {
|
||||||
subtitleContent.value = content['content']!;
|
subtitleContent.value = content['content']!;
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
subtitleContent.value = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,7 +82,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
final RxDouble _distance = 0.0.obs;
|
final RxDouble _distance = 0.0.obs;
|
||||||
final RxBool _volumeInterceptEventStream = false.obs;
|
final RxBool _volumeInterceptEventStream = false.obs;
|
||||||
|
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
late FullScreenMode mode;
|
late FullScreenMode mode;
|
||||||
late int defaultBtmProgressBehavior;
|
late int defaultBtmProgressBehavior;
|
||||||
late bool enableQuickDouble;
|
late bool enableQuickDouble;
|
||||||
|
|||||||
@ -66,7 +66,7 @@ import '../pages/whisper/index.dart';
|
|||||||
import '../pages/whisper_detail/index.dart';
|
import '../pages/whisper_detail/index.dart';
|
||||||
import '../utils/storage.dart';
|
import '../utils/storage.dart';
|
||||||
|
|
||||||
Box<dynamic> setting = GStrorage.setting;
|
Box<dynamic> setting = GStorage.setting;
|
||||||
|
|
||||||
class Routes {
|
class Routes {
|
||||||
static final List<GetPage<dynamic>> getPages = [
|
static final List<GetPage<dynamic>> getPages = [
|
||||||
|
|||||||
@ -24,7 +24,7 @@ Future<VideoPlayerServiceHandler> initAudioService() async {
|
|||||||
|
|
||||||
class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
|
class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
|
||||||
static final List<MediaItem> _item = [];
|
static final List<MediaItem> _item = [];
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
bool enableBackgroundPlay = false;
|
bool enableBackgroundPlay = false;
|
||||||
PlPlayerController player = PlPlayerController();
|
PlPlayerController player = PlPlayerController();
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ void DisableBatteryOpt() async {
|
|||||||
}
|
}
|
||||||
// 本地缓存中读取 是否禁用了电池优化 默认未禁用
|
// 本地缓存中读取 是否禁用了电池优化 默认未禁用
|
||||||
bool isDisableBatteryOptLocal =
|
bool isDisableBatteryOptLocal =
|
||||||
GStrorage.localCache.get('isDisableBatteryOptLocal', defaultValue: false);
|
GStorage.localCache.get('isDisableBatteryOptLocal', defaultValue: false);
|
||||||
if (!isDisableBatteryOptLocal) {
|
if (!isDisableBatteryOptLocal) {
|
||||||
final isBatteryOptimizationDisabled =
|
final isBatteryOptimizationDisabled =
|
||||||
await DisableBatteryOptimization.isBatteryOptimizationDisabled;
|
await DisableBatteryOptimization.isBatteryOptimizationDisabled;
|
||||||
@ -17,11 +17,11 @@ void DisableBatteryOpt() async {
|
|||||||
final hasDisabled = await DisableBatteryOptimization
|
final hasDisabled = await DisableBatteryOptimization
|
||||||
.showDisableBatteryOptimizationSettings();
|
.showDisableBatteryOptimizationSettings();
|
||||||
// 设置为已禁用
|
// 设置为已禁用
|
||||||
GStrorage.localCache.put('isDisableBatteryOptLocal', hasDisabled == true);
|
GStorage.localCache.put('isDisableBatteryOptLocal', hasDisabled == true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isManufacturerBatteryOptimizationDisabled = GStrorage.localCache
|
bool isManufacturerBatteryOptimizationDisabled = GStorage.localCache
|
||||||
.get('isManufacturerBatteryOptimizationDisabled', defaultValue: false);
|
.get('isManufacturerBatteryOptimizationDisabled', defaultValue: false);
|
||||||
if (!isManufacturerBatteryOptimizationDisabled) {
|
if (!isManufacturerBatteryOptimizationDisabled) {
|
||||||
final isManBatteryOptimizationDisabled = await DisableBatteryOptimization
|
final isManBatteryOptimizationDisabled = await DisableBatteryOptimization
|
||||||
@ -33,7 +33,7 @@ void DisableBatteryOpt() async {
|
|||||||
"按照步骤操作以禁用电池优化,以保证应用在后台正常运行",
|
"按照步骤操作以禁用电池优化,以保证应用在后台正常运行",
|
||||||
);
|
);
|
||||||
// 设置为已禁用
|
// 设置为已禁用
|
||||||
GStrorage.localCache.put(
|
GStorage.localCache.put(
|
||||||
'isManufacturerBatteryOptimizationDisabled', hasDisabled == true);
|
'isManufacturerBatteryOptimizationDisabled', hasDisabled == true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,8 +9,8 @@ class Data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future historyStatus() async {
|
static Future historyStatus() async {
|
||||||
Box localCache = GStrorage.localCache;
|
Box localCache = GStorage.localCache;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
if (userInfoCache.get('userInfoCache') == null) {
|
if (userInfoCache.get('userInfoCache') == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'storage.dart';
|
import 'storage.dart';
|
||||||
|
|
||||||
Box<dynamic> setting = GStrorage.setting;
|
Box<dynamic> setting = GStorage.setting;
|
||||||
void feedBack() {
|
void feedBack() {
|
||||||
// 设置中是否开启
|
// 设置中是否开启
|
||||||
final bool enable =
|
final bool enable =
|
||||||
|
|||||||
@ -5,10 +5,10 @@ import 'package:pilipala/plugin/pl_player/models/play_speed.dart';
|
|||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
import '../models/common/index.dart';
|
import '../models/common/index.dart';
|
||||||
|
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStorage.setting;
|
||||||
Box localCache = GStrorage.localCache;
|
Box localCache = GStorage.localCache;
|
||||||
Box videoStorage = GStrorage.video;
|
Box videoStorage = GStorage.video;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
|
|
||||||
class GlobalDataCache {
|
class GlobalDataCache {
|
||||||
late int imgQuality;
|
late int imgQuality;
|
||||||
|
|||||||
@ -18,9 +18,6 @@ import 'package:pilipala/utils/storage.dart';
|
|||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
class LoginUtils {
|
class LoginUtils {
|
||||||
static Box userInfoCache = GStrorage.userInfo;
|
|
||||||
static Box localCache = GStrorage.localCache;
|
|
||||||
|
|
||||||
static Future refreshLoginStatus(bool status) async {
|
static Future refreshLoginStatus(bool status) async {
|
||||||
try {
|
try {
|
||||||
// 更改我的页面登录状态
|
// 更改我的页面登录状态
|
||||||
@ -76,7 +73,7 @@ class LoginUtils {
|
|||||||
if (result['status'] && result['data'].isLogin) {
|
if (result['status'] && result['data'].isLogin) {
|
||||||
SmartDialog.showToast('登录成功');
|
SmartDialog.showToast('登录成功');
|
||||||
try {
|
try {
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
if (!userInfoCache.isOpen) {
|
if (!userInfoCache.isOpen) {
|
||||||
userInfoCache = await Hive.openBox('userInfo');
|
userInfoCache = await Hive.openBox('userInfo');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class RecommendFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void update() {
|
static void update() {
|
||||||
var setting = GStrorage.setting;
|
var setting = GStorage.setting;
|
||||||
// filterUnfollowedRatio =
|
// filterUnfollowedRatio =
|
||||||
// setting.get(SettingBoxKey.filterUnfollowedRatio, defaultValue: 0);
|
// setting.get(SettingBoxKey.filterUnfollowedRatio, defaultValue: 0);
|
||||||
minDurationForRcmd =
|
minDurationForRcmd =
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import 'package:hive_flutter/hive_flutter.dart';
|
|||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:pilipala/models/user/info.dart';
|
import 'package:pilipala/models/user/info.dart';
|
||||||
|
|
||||||
class GStrorage {
|
class GStorage {
|
||||||
static late final Box<dynamic> userInfo;
|
static late final Box<dynamic> userInfo;
|
||||||
static late final Box<dynamic> localCache;
|
static late final Box<dynamic> localCache;
|
||||||
static late final Box<dynamic> setting;
|
static late final Box<dynamic> setting;
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import '../http/index.dart';
|
|||||||
import 'storage.dart';
|
import 'storage.dart';
|
||||||
|
|
||||||
class WbiSign {
|
class WbiSign {
|
||||||
static Box<dynamic> localCache = GStrorage.localCache;
|
static Box<dynamic> localCache = GStorage.localCache;
|
||||||
final List<int> mixinKeyEncTab = <int>[
|
final List<int> mixinKeyEncTab = <int>[
|
||||||
46,
|
46,
|
||||||
47,
|
47,
|
||||||
|
|||||||
20
pubspec.lock
20
pubspec.lock
@ -533,18 +533,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: file_selector_linux
|
name: file_selector_linux
|
||||||
sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492"
|
sha256: "712ce7fab537ba532c8febdb1a8f167b32441e74acd68c3ccb2e36dcb52c4ab2"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.2+1"
|
version: "0.9.3"
|
||||||
file_selector_macos:
|
file_selector_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: file_selector_macos
|
name: file_selector_macos
|
||||||
sha256: cb284e267f8e2a45a904b5c094d2ba51d0aabfc20b1538ab786d9ef7dc2bf75c
|
sha256: "271ab9986df0c135d45c3cdb6bd0faa5db6f4976d3e4b437cf7d0f258d941bfc"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.4+1"
|
version: "0.9.4+2"
|
||||||
file_selector_platform_interface:
|
file_selector_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -557,10 +557,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: file_selector_windows
|
name: file_selector_windows
|
||||||
sha256: "2ad726953f6e8affbc4df8dc78b77c3b4a060967a291e528ef72ae846c60fb69"
|
sha256: "8f5d2f6590d51ecd9179ba39c64f722edc15226cc93dcc8698466ad36a4a85a4"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.3+2"
|
version: "0.9.3+3"
|
||||||
fixnum:
|
fixnum:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -842,10 +842,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image_picker_ios
|
name: image_picker_ios
|
||||||
sha256: "6703696ad49f5c3c8356d576d7ace84d1faf459afb07accbb0fae780753ff447"
|
sha256: "4f0568120c6fcc0aaa04511cb9f9f4d29fc3d0139884b1d06be88dcec7641d6b"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.12"
|
version: "0.8.12+1"
|
||||||
image_picker_linux:
|
image_picker_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1438,10 +1438,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: scrollview_observer
|
name: scrollview_observer
|
||||||
sha256: fa408bcfd41e19da841eb53fc471f8f952d5ef818b854d2505c4bb3f0c876381
|
sha256: "8537ba32e5a15ade301e5c77ae858fd8591695defaad1821eca9eeb4ac28a157"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.22.0"
|
version: "1.23.0"
|
||||||
sentry:
|
sentry:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
Reference in New Issue
Block a user