Merge branch 'main' into design

This commit is contained in:
guozhigq
2024-03-02 00:39:01 +08:00
7 changed files with 106 additions and 72 deletions

View File

@ -45,7 +45,9 @@ class _ContentState extends State<Content> {
if (len == 1) { if (len == 1) {
OpusPicsModel pictureItem = pics.first; OpusPicsModel pictureItem = pics.first;
picList.add(pictureItem.url!); picList.add(pictureItem.url!);
spanChilds.add(const TextSpan(text: '\n'));
/// 图片上方的空白间隔
// spanChilds.add(const TextSpan(text: '\n'));
spanChilds.add( spanChilds.add(
WidgetSpan( WidgetSpan(
child: LayoutBuilder( child: LayoutBuilder(

View File

@ -19,6 +19,17 @@ InlineSpan richNode(item, context) {
// 动态页面 richTextNodes 层级可能与主页动态层级不同 // 动态页面 richTextNodes 层级可能与主页动态层级不同
richTextNodes = richTextNodes =
item.modules.moduleDynamic.major.opus.summary.richTextNodes; item.modules.moduleDynamic.major.opus.summary.richTextNodes;
if (item.modules.moduleDynamic.major.opus.title != null) {
spanChilds.add(
TextSpan(
text: item.modules.moduleDynamic.major.opus.title + '\n',
style: Theme.of(context)
.textTheme
.titleMedium!
.copyWith(fontWeight: FontWeight.bold),
),
);
}
} }
if (richTextNodes == null || richTextNodes.isEmpty) { if (richTextNodes == null || richTextNodes.isEmpty) {
return spacer; return spacer;

View File

@ -88,36 +88,32 @@ class _UpPanelState extends State<UpPanel> {
Container( Container(
height: 90, height: 90,
color: Theme.of(context).colorScheme.background, color: Theme.of(context).colorScheme.background,
child: Row( child: Expanded(
children: [ child: ListView(
Expanded( scrollDirection: Axis.horizontal,
child: ListView( controller: scrollController,
scrollDirection: Axis.horizontal, children: [
controller: scrollController, const SizedBox(width: 10),
children: [ if (liveList.isNotEmpty) ...[
const SizedBox(width: 10), for (int i = 0; i < liveList.length; i++) ...[
if (liveList.isNotEmpty) ...[ upItemBuild(liveList[i], i)
for (int i = 0; i < liveList.length; i++) ...[
upItemBuild(liveList[i], i)
],
VerticalDivider(
indent: 20,
endIndent: 40,
width: 26,
color: Theme.of(context)
.colorScheme
.primary
.withOpacity(0.5),
),
],
for (int i = 0; i < upList.length; i++) ...[
upItemBuild(upList[i], i)
],
const SizedBox(width: 10),
], ],
), VerticalDivider(
), indent: 20,
], endIndent: 40,
width: 26,
color: Theme.of(context)
.colorScheme
.primary
.withOpacity(0.5),
),
],
for (int i = 0; i < upList.length; i++) ...[
upItemBuild(upList[i], i)
],
const SizedBox(width: 10),
],
),
), ),
), ),
Container( Container(

View File

@ -58,6 +58,9 @@ class _HomePageState extends State<HomePage>
return Scaffold( return Scaffold(
extendBody: true, extendBody: true,
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
appBar: _homeController.enableGradientBg
? null
: AppBar(toolbarHeight: 0, elevation: 0),
body: Stack( body: Stack(
children: [ children: [
// gradient background // gradient background

View File

@ -462,6 +462,9 @@ class ReplyItemRow extends StatelessWidget {
InlineSpan buildContent( InlineSpan buildContent(
BuildContext context, replyItem, replyReply, fReplyItem) { BuildContext context, replyItem, replyReply, fReplyItem) {
final String routePath = Get.currentRoute;
bool isVideoPage = routePath.startsWith('/video');
// replyItem 当前回复内容 // replyItem 当前回复内容
// replyReply 查看二楼回复(回复详情)回调 // replyReply 查看二楼回复(回复详情)回调
// fReplyItem 父级回复内容,用作二楼回复(回复详情)展示 // fReplyItem 父级回复内容,用作二楼回复(回复详情)展示
@ -503,21 +506,25 @@ InlineSpan buildContent(
.replaceAll('&quot;', '"') .replaceAll('&quot;', '"')
.replaceAll('&apos;', "'") .replaceAll('&apos;', "'")
.replaceAll('&nbsp;', ' '); .replaceAll('&nbsp;', ' ');
// print("content.jumpUrl.keys:" + content.jumpUrl.keys.toString());
// 构建正则表达式 // 构建正则表达式
final List<String> specialTokens = [ final List<String> specialTokens = [
...content.emote.keys, ...content.emote.keys,
...content.topicsMeta?.keys?.map((e) => '#$e#') ?? [], ...content.topicsMeta?.keys?.map((e) => '#$e#') ?? [],
...content.atNameToMid.keys.map((e) => '@$e'), ...content.atNameToMid.keys.map((e) => '@$e'),
...content.jumpUrl.keys.map((e) =>
e.replaceAll('?', '\\?').replaceAll('+', '\\+').replaceAll('*', '\\*')),
]; ];
List<dynamic> jumpUrlKeysList = content.jumpUrl.keys.map((e) {
return e.replaceAllMapped(
RegExp(r'[?+*]'), (match) => '\\${match.group(0)}');
}).toList();
String patternStr = specialTokens.map(RegExp.escape).join('|'); String patternStr = specialTokens.map(RegExp.escape).join('|');
if (patternStr.isNotEmpty) { if (patternStr.isNotEmpty) {
patternStr += "|"; patternStr += "|";
} }
patternStr += r'(\b(?:\d+[:])?[0-5]?[0-9][:][0-5]?[0-9]\b)'; patternStr += r'(\b(?:\d+[:])?[0-5]?[0-9][:][0-5]?[0-9]\b)';
if (jumpUrlKeysList.isNotEmpty) {
patternStr += '|${jumpUrlKeysList.join('|')}';
}
final RegExp pattern = RegExp(patternStr); final RegExp pattern = RegExp(patternStr);
List<String> matchedStrs = []; List<String> matchedStrs = [];
void addPlainTextSpan(str) { void addPlainTextSpan(str) {
@ -571,27 +578,31 @@ InlineSpan buildContent(
spanChilds.add( spanChilds.add(
TextSpan( TextSpan(
text: ' $matchStr ', text: ' $matchStr ',
style: TextStyle( style: isVideoPage
color: Theme.of(context).colorScheme.primary, ? TextStyle(
), color: Theme.of(context).colorScheme.primary,
)
: null,
recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
..onTap = () { ..onTap = () {
// 跳转到指定位置 // 跳转到指定位置
try { if (isVideoPage) {
SmartDialog.showToast('跳转至:$matchStr'); try {
Get.find<VideoDetailController>(tag: Get.arguments['heroTag']) SmartDialog.showToast('跳转至:$matchStr');
.plPlayerController Get.find<VideoDetailController>(
.seekTo( tag: Get.arguments['heroTag'])
Duration(seconds: Utils.duration(matchStr)), .plPlayerController
); .seekTo(
} catch (e) { Duration(seconds: Utils.duration(matchStr)),
SmartDialog.showToast('跳转失败: $e'); );
} catch (e) {
SmartDialog.showToast('跳转失败: $e');
}
} }
}, },
), ),
); );
} else { } else {
print("matchStr=$matchStr");
String appUrlSchema = ''; String appUrlSchema = '';
final bool enableWordRe = setting.get(SettingBoxKey.enableWordRe, final bool enableWordRe = setting.get(SettingBoxKey.enableWordRe,
defaultValue: false) as bool; defaultValue: false) as bool;

View File

@ -109,21 +109,24 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
@override @override
void didChangeMetrics() { void didChangeMetrics() {
super.didChangeMetrics(); super.didChangeMetrics();
WidgetsBinding.instance.addPostFrameCallback((_) { final String routePath = Get.currentRoute;
// 键盘高度 if (mounted && routePath.startsWith('/video')) {
final viewInsets = EdgeInsets.fromViewPadding( WidgetsBinding.instance.addPostFrameCallback((_) {
View.of(context).viewInsets, View.of(context).devicePixelRatio); // 键盘高度
_debouncer.run(() { final viewInsets = EdgeInsets.fromViewPadding(
if (mounted) { View.of(context).viewInsets, View.of(context).devicePixelRatio);
if (keyboardHeight == 0 && emoteHeight == 0) { _debouncer.run(() {
setState(() { if (mounted) {
emoteHeight = keyboardHeight = if (keyboardHeight == 0 && emoteHeight == 0) {
keyboardHeight == 0.0 ? viewInsets.bottom : keyboardHeight; setState(() {
}); emoteHeight = keyboardHeight =
keyboardHeight == 0.0 ? viewInsets.bottom : keyboardHeight;
});
}
} }
} });
}); });
}); }
} }
@override @override
@ -131,11 +134,15 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
WidgetsBinding.instance.removeObserver(this); WidgetsBinding.instance.removeObserver(this);
_replyContentController.dispose(); _replyContentController.dispose();
replyContentFocusNode.removeListener(() {}); replyContentFocusNode.removeListener(() {});
replyContentFocusNode.dispose();
super.dispose(); super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
double keyboardHeight = EdgeInsets.fromViewPadding(
View.of(context).viewInsets, View.of(context).devicePixelRatio)
.bottom;
return Container( return Container(
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
decoration: BoxDecoration( decoration: BoxDecoration(

View File

@ -51,27 +51,31 @@ class _WhisperDetailPageState extends State<WhisperDetailPage>
@override @override
void didChangeMetrics() { void didChangeMetrics() {
super.didChangeMetrics(); super.didChangeMetrics();
WidgetsBinding.instance.addPostFrameCallback((_) { final String routePath = Get.currentRoute;
// 键盘高度 if (mounted && routePath.startsWith('/whisper_detail')) {
final viewInsets = EdgeInsets.fromViewPadding( WidgetsBinding.instance.addPostFrameCallback((_) {
View.of(context).viewInsets, View.of(context).devicePixelRatio); // 键盘高度
_debouncer.run(() { final viewInsets = EdgeInsets.fromViewPadding(
if (mounted) { View.of(context).viewInsets, View.of(context).devicePixelRatio);
if (keyboardHeight == 0) { _debouncer.run(() {
setState(() { if (mounted) {
emoteHeight = keyboardHeight = if (keyboardHeight == 0) {
keyboardHeight == 0.0 ? viewInsets.bottom : keyboardHeight; setState(() {
}); emoteHeight = keyboardHeight =
keyboardHeight == 0.0 ? viewInsets.bottom : keyboardHeight;
});
}
} }
} });
}); });
}); }
} }
@override @override
void dispose() { void dispose() {
WidgetsBinding.instance.removeObserver(this); WidgetsBinding.instance.removeObserver(this);
replyContentFocusNode.removeListener(() {}); replyContentFocusNode.removeListener(() {});
replyContentFocusNode.dispose();
super.dispose(); super.dispose();
} }