mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-01 16:48:16 +08:00
@@ -1,6 +1,7 @@
|
||||
import 'package:PiliPlus/models_new/video/video_ai_conclusion/model_result.dart';
|
||||
import 'package:PiliPlus/pages/common/slide/common_slide_page.dart';
|
||||
import 'package:PiliPlus/pages/video/controller.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/selectable_text.dart';
|
||||
import 'package:PiliPlus/utils/duration_utils.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -69,7 +70,7 @@ class _AiDetailState extends State<AiConclusionPanel>
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||
child: SelectableText(
|
||||
child: selectableText(
|
||||
widget.item.summary!,
|
||||
style: const TextStyle(
|
||||
fontSize: 15,
|
||||
@@ -98,57 +99,59 @@ class _AiDetailState extends State<AiConclusionPanel>
|
||||
itemCount: widget.item.outline!.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = widget.item.outline![index];
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (index != 0) const SizedBox(height: 10),
|
||||
SelectableText(
|
||||
item.title!,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
height: 1.5,
|
||||
return SelectionArea(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (index != 0) const SizedBox(height: 10),
|
||||
Text(
|
||||
item.title!,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
...?item.partOutline?.map(
|
||||
(item) => Wrap(
|
||||
children: [
|
||||
SelectableText.rich(
|
||||
TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: theme.colorScheme.onSurface,
|
||||
height: 1.5,
|
||||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: DurationUtils.formatDuration(
|
||||
item.timestamp,
|
||||
),
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
try {
|
||||
Get.find<VideoDetailController>(
|
||||
tag: Get.arguments['heroTag'],
|
||||
).plPlayerController.seekTo(
|
||||
Duration(seconds: item.timestamp!),
|
||||
);
|
||||
} catch (_) {}
|
||||
},
|
||||
const SizedBox(height: 6),
|
||||
...?item.partOutline?.map(
|
||||
(item) => Wrap(
|
||||
children: [
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: theme.colorScheme.onSurface,
|
||||
height: 1.5,
|
||||
),
|
||||
const TextSpan(text: ' '),
|
||||
TextSpan(text: item.content!),
|
||||
],
|
||||
children: [
|
||||
TextSpan(
|
||||
text: DurationUtils.formatDuration(
|
||||
item.timestamp,
|
||||
),
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
try {
|
||||
Get.find<VideoDetailController>(
|
||||
tag: Get.arguments['heroTag'],
|
||||
).plPlayerController.seekTo(
|
||||
Duration(seconds: item.timestamp!),
|
||||
);
|
||||
} catch (_) {}
|
||||
},
|
||||
),
|
||||
const TextSpan(text: ' '),
|
||||
TextSpan(text: item.content!),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -277,7 +277,7 @@ class PgcIntroController extends CommonIntroController {
|
||||
}
|
||||
|
||||
// 修改分P或番剧分集
|
||||
Future<void> onChangeEpisode(BaseEpisodeItem episode) async {
|
||||
Future<bool> onChangeEpisode(BaseEpisodeItem episode) async {
|
||||
try {
|
||||
final int epId = episode.epId ?? episode.id!;
|
||||
final String bvid = episode.bvid ?? this.bvid;
|
||||
@@ -285,7 +285,7 @@ class PgcIntroController extends CommonIntroController {
|
||||
final int? cid =
|
||||
episode.cid ?? await SearchHttp.ab2c(aid: aid, bvid: bvid);
|
||||
if (cid == null) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
final String? cover = episode.cover;
|
||||
|
||||
@@ -323,8 +323,10 @@ class PgcIntroController extends CommonIntroController {
|
||||
this.cid.value = cid;
|
||||
queryOnlineTotal();
|
||||
queryVideoIntro(episode as EpisodeItem);
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (kDebugMode) debugPrint('pgc onChangeEpisode: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:PiliPlus/models_new/video/video_tag/data.dart';
|
||||
import 'package:PiliPlus/pages/common/slide/common_slide_page.dart';
|
||||
import 'package:PiliPlus/pages/pgc_review/view.dart';
|
||||
import 'package:PiliPlus/pages/search/widgets/search_text.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/selectable_text.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart' hide TabBarView;
|
||||
@@ -108,7 +109,7 @@ class _IntroDetailState extends State<PgcIntroPanel>
|
||||
bottom: MediaQuery.viewPaddingOf(context).bottom + 100,
|
||||
),
|
||||
children: [
|
||||
SelectableText(
|
||||
selectableText(
|
||||
widget.item.title!,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
@@ -152,7 +153,7 @@ class _IntroDetailState extends State<PgcIntroPanel>
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
SelectableText(
|
||||
selectableText(
|
||||
widget.item.evaluate!,
|
||||
style: textStyle,
|
||||
),
|
||||
|
||||
@@ -463,7 +463,7 @@ class UgcIntroController extends CommonIntroController with ReloadMixin {
|
||||
}
|
||||
|
||||
// 修改分P或番剧分集
|
||||
Future<void> onChangeEpisode(
|
||||
Future<bool> onChangeEpisode(
|
||||
BaseEpisodeItem episode, {
|
||||
bool isStein = false,
|
||||
}) async {
|
||||
@@ -473,7 +473,7 @@ class UgcIntroController extends CommonIntroController with ReloadMixin {
|
||||
final int? cid =
|
||||
episode.cid ?? await SearchHttp.ab2c(aid: aid, bvid: bvid);
|
||||
if (cid == null) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
final String? cover = episode.cover;
|
||||
|
||||
@@ -488,7 +488,7 @@ class UgcIntroController extends CommonIntroController with ReloadMixin {
|
||||
cid: cid,
|
||||
cover: cover,
|
||||
);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,8 +546,10 @@ class UgcIntroController extends CommonIntroController with ReloadMixin {
|
||||
|
||||
this.cid.value = cid;
|
||||
queryOnlineTotal();
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (kDebugMode) debugPrint('ugc onChangeEpisode: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import 'package:PiliPlus/pages/video/introduction/ugc/controller.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/action_item.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/page.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/season.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/selectable_text.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/triple_state.dart';
|
||||
import 'package:PiliPlus/utils/app_scheme.dart';
|
||||
import 'package:PiliPlus/utils/date_utils.dart';
|
||||
@@ -327,13 +328,9 @@ class _UgcIntroPanelState extends TripleState<UgcIntroPanel> {
|
||||
),
|
||||
if (videoDetail.descV2?.isNotEmpty == true) ...[
|
||||
const SizedBox(height: 8),
|
||||
SelectableText.rich(
|
||||
selectableRichText(
|
||||
style: const TextStyle(height: 1.4),
|
||||
TextSpan(
|
||||
children: [
|
||||
buildContent(theme, videoDetail),
|
||||
],
|
||||
),
|
||||
buildContent(theme, videoDetail),
|
||||
),
|
||||
],
|
||||
Obx(() {
|
||||
@@ -601,7 +598,7 @@ class _UgcIntroPanelState extends TripleState<UgcIntroPanel> {
|
||||
caseSensitive: false,
|
||||
);
|
||||
|
||||
InlineSpan buildContent(ThemeData theme, VideoDetailData content) {
|
||||
TextSpan buildContent(ThemeData theme, VideoDetailData content) {
|
||||
if (content.descV2.isNullOrEmpty) {
|
||||
return const TextSpan();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget selectableText(
|
||||
String text, {
|
||||
TextStyle? style,
|
||||
}) {
|
||||
if (Utils.isDesktop) {
|
||||
return SelectionArea(
|
||||
child: Text(
|
||||
style: style,
|
||||
text,
|
||||
),
|
||||
);
|
||||
}
|
||||
return SelectableText(
|
||||
style: style,
|
||||
text,
|
||||
);
|
||||
}
|
||||
|
||||
Widget selectableRichText(
|
||||
TextSpan textSpan, {
|
||||
TextStyle? style,
|
||||
}) {
|
||||
if (Utils.isDesktop) {
|
||||
return SelectionArea(
|
||||
child: Text.rich(
|
||||
style: style,
|
||||
textSpan,
|
||||
),
|
||||
);
|
||||
}
|
||||
return SelectableText.rich(
|
||||
style: style,
|
||||
textSpan,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user