mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt dyn panel
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -52,9 +52,9 @@ class RetryInterceptor extends Interceptor {
|
||||
case DioExceptionType.sendTimeout:
|
||||
case DioExceptionType.unknown:
|
||||
if ((err.requestOptions.extra['_rt'] ??= 0) < _count &&
|
||||
err.error
|
||||
is! TransportConnectionException // 网络中断, 此时请求可能已经被服务器所接收
|
||||
) {
|
||||
err.error
|
||||
is! TransportConnectionException // 网络中断, 此时请求可能已经被服务器所接收
|
||||
) {
|
||||
Future.delayed(
|
||||
Duration(
|
||||
milliseconds: ++err.requestOptions.extra['_rt'] * _delay,
|
||||
|
||||
@@ -64,7 +64,7 @@ class DynamicsDataModel {
|
||||
continue;
|
||||
}
|
||||
if (enableFilter) {
|
||||
if (item.orig case DynamicItemModel orig) {
|
||||
if (item.orig case final orig?) {
|
||||
if (banWordForDyn.hasMatch(_getMatchText(orig))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ class OpusContent extends StatelessWidget {
|
||||
if (item.word != null) {
|
||||
return _getSpan(item.word);
|
||||
}
|
||||
if (item.rich case Rich rich) {
|
||||
if (item.rich case final rich?) {
|
||||
final hasUrl = rich.jumpUrl?.isNotEmpty == true;
|
||||
return TextSpan(
|
||||
text: '${hasUrl ? '\u{1F517}' : ''}${rich.text}',
|
||||
@@ -633,6 +633,8 @@ Widget moduleBlockedItem(
|
||||
ModuleBlocked moduleBlocked,
|
||||
double maxWidth,
|
||||
) {
|
||||
late final isDarkMode = Get.isDarkMode;
|
||||
|
||||
BoxDecoration? bgImg() {
|
||||
return moduleBlocked.bgImg == null
|
||||
? null
|
||||
@@ -641,7 +643,7 @@ Widget moduleBlockedItem(
|
||||
fit: BoxFit.fill,
|
||||
image: CachedNetworkImageProvider(
|
||||
ImageUtil.thumbnailUrl(
|
||||
Get.isDarkMode
|
||||
isDarkMode
|
||||
? moduleBlocked.bgImg!.imgDark
|
||||
: moduleBlocked.bgImg!.imgDay,
|
||||
),
|
||||
@@ -655,9 +657,7 @@ Widget moduleBlockedItem(
|
||||
width: width,
|
||||
fit: BoxFit.contain,
|
||||
imageUrl: ImageUtil.thumbnailUrl(
|
||||
Get.isDarkMode
|
||||
? moduleBlocked.icon!.imgDark
|
||||
: moduleBlocked.icon!.imgDay,
|
||||
isDarkMode ? moduleBlocked.icon!.imgDark : moduleBlocked.icon!.imgDay,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -672,7 +672,7 @@ Widget moduleBlockedItem(
|
||||
padding: padding,
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
visualDensity: visualDensity,
|
||||
backgroundColor: Get.isDarkMode
|
||||
backgroundColor: isDarkMode
|
||||
? const Color(0xFF8F0030)
|
||||
: const Color(0xFFFF6699),
|
||||
foregroundColor: Colors.white,
|
||||
|
||||
@@ -61,10 +61,8 @@ abstract class CommonRichTextPubPageState<T extends CommonRichTextPubPage>
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (hasPub) {
|
||||
for (var i in pathList) {
|
||||
File(i).delSync();
|
||||
}
|
||||
for (var i in pathList) {
|
||||
File(i).delSync();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,9 +26,9 @@ import 'package:get/get.dart' hide ContextExtensionss;
|
||||
class AuthorPanel extends StatelessWidget {
|
||||
final DynamicItemModel item;
|
||||
final Function? addBannedList;
|
||||
final bool isSave;
|
||||
final bool isDetail;
|
||||
final ValueChanged? onRemove;
|
||||
final bool isSave;
|
||||
final Function(bool isTop, dynamic dynId)? onSetTop;
|
||||
final VoidCallback? onBlock;
|
||||
|
||||
@@ -43,10 +43,10 @@ class AuthorPanel extends StatelessWidget {
|
||||
this.onBlock,
|
||||
});
|
||||
|
||||
Widget _buildAvatar() {
|
||||
String? pendant = item.modules.moduleAuthor?.pendant?.image;
|
||||
Widget _buildAvatar(ModuleAuthorModel moduleAuthor) {
|
||||
String? pendant = moduleAuthor.pendant?.image;
|
||||
Widget avatar = PendantAvatar(
|
||||
avatar: item.modules.moduleAuthor?.face,
|
||||
avatar: moduleAuthor.face,
|
||||
size: pendant.isNullOrEmpty ? 40 : 34,
|
||||
officialType: null, // 已被注释
|
||||
garbPendantImage: pendant,
|
||||
@@ -60,14 +60,15 @@ class AuthorPanel extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final pubTime = item.modules.moduleAuthor?.pubTs != null
|
||||
final moduleAuthor = item.modules.moduleAuthor!;
|
||||
final pubTime = moduleAuthor.pubTs != null
|
||||
? isSave
|
||||
? DateUtil.format(
|
||||
item.modules.moduleAuthor!.pubTs,
|
||||
moduleAuthor.pubTs,
|
||||
format: DateUtil.longFormatDs,
|
||||
)
|
||||
: DateUtil.dateFormat(item.modules.moduleAuthor!.pubTs)
|
||||
: item.modules.moduleAuthor?.pubTime;
|
||||
: DateUtil.dateFormat(moduleAuthor.pubTs)
|
||||
: moduleAuthor.pubTime;
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
@@ -76,29 +77,29 @@ class AuthorPanel extends StatelessWidget {
|
||||
alignment: Alignment.centerLeft,
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: item.modules.moduleAuthor!.type == 'AUTHOR_TYPE_NORMAL'
|
||||
onTap: moduleAuthor.type == 'AUTHOR_TYPE_NORMAL'
|
||||
? () {
|
||||
feedBack();
|
||||
Get.toNamed(
|
||||
'/member?mid=${item.modules.moduleAuthor!.mid}',
|
||||
'/member?mid=${moduleAuthor.mid}',
|
||||
);
|
||||
}
|
||||
: null,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_buildAvatar(),
|
||||
_buildAvatar(moduleAuthor),
|
||||
const SizedBox(width: 10),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.modules.moduleAuthor?.name ?? '',
|
||||
moduleAuthor.name ?? '',
|
||||
style: TextStyle(
|
||||
color:
|
||||
item.modules.moduleAuthor!.vip != null &&
|
||||
item.modules.moduleAuthor!.vip!.status > 0 &&
|
||||
item.modules.moduleAuthor!.vip!.type == 2
|
||||
moduleAuthor.vip != null &&
|
||||
moduleAuthor.vip!.status > 0 &&
|
||||
moduleAuthor.vip!.type == 2
|
||||
? theme.colorScheme.vipColor
|
||||
: theme.colorScheme.onSurface,
|
||||
fontSize: theme.textTheme.titleSmall!.fontSize,
|
||||
@@ -106,7 +107,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
),
|
||||
if (pubTime != null)
|
||||
Text(
|
||||
'$pubTime${item.modules.moduleAuthor?.pubAction != null ? ' ${item.modules.moduleAuthor!.pubAction}' : ''}',
|
||||
'$pubTime${moduleAuthor.pubAction != null ? ' ${moduleAuthor.pubAction}' : ''}',
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
@@ -155,7 +156,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
_moreWidget(context),
|
||||
],
|
||||
)
|
||||
: item.modules.moduleAuthor!.decorate != null
|
||||
: moduleAuthor.decorate != null
|
||||
? Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@@ -165,48 +166,24 @@ class AuthorPanel extends StatelessWidget {
|
||||
children: [
|
||||
CachedNetworkImage(
|
||||
height: 32,
|
||||
imageUrl: item
|
||||
.modules
|
||||
.moduleAuthor!
|
||||
.decorate!
|
||||
.cardUrl
|
||||
.http2https,
|
||||
imageUrl: moduleAuthor.decorate!.cardUrl.http2https,
|
||||
),
|
||||
if (item
|
||||
.modules
|
||||
.moduleAuthor
|
||||
?.decorate
|
||||
?.fan
|
||||
?.numStr
|
||||
?.isNotEmpty ==
|
||||
if (moduleAuthor.decorate?.fan?.numStr?.isNotEmpty ==
|
||||
true)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 32),
|
||||
child: Text(
|
||||
'${item.modules.moduleAuthor!.decorate!.fan!.numStr}',
|
||||
'${moduleAuthor.decorate!.fan!.numStr}',
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
fontSize: 11,
|
||||
fontFamily: 'digital_id_num',
|
||||
color:
|
||||
item
|
||||
.modules
|
||||
.moduleAuthor!
|
||||
.decorate!
|
||||
.fan
|
||||
?.color
|
||||
moduleAuthor.decorate!.fan?.color
|
||||
?.startsWith('#') ==
|
||||
true
|
||||
? Color(
|
||||
int.parse(
|
||||
item
|
||||
.modules
|
||||
.moduleAuthor!
|
||||
.decorate!
|
||||
.fan!
|
||||
.color!
|
||||
.replaceFirst('#', '0xFF'),
|
||||
),
|
||||
? Utils.parseColor(
|
||||
moduleAuthor.decorate!.fan!.color!,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
@@ -250,7 +227,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
if (bvid == null && item.orig != null) {
|
||||
bvid = getBvid(
|
||||
item.orig!.type,
|
||||
item.orig?.modules.moduleDynamic?.major,
|
||||
item.orig!.modules.moduleDynamic?.major,
|
||||
);
|
||||
}
|
||||
} catch (_) {}
|
||||
@@ -264,6 +241,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
),
|
||||
builder: (context1) {
|
||||
final theme = Theme.of(context);
|
||||
final moduleAuthor = item.modules.moduleAuthor!;
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.viewPaddingOf(context1).bottom,
|
||||
@@ -347,32 +325,13 @@ class AuthorPanel extends StatelessWidget {
|
||||
bool isDyn = item.basic!.commentType == 17;
|
||||
String id = isDyn ? item.idStr : item.basic!.ridStr!;
|
||||
int source = isDyn ? 11 : 2;
|
||||
String title;
|
||||
if (item.modules.moduleDynamic?.desc != null) {
|
||||
title = item.modules.moduleDynamic!.desc!.text!;
|
||||
} else if (item.modules.moduleDynamic?.major != null) {
|
||||
title = item
|
||||
.modules
|
||||
.moduleDynamic!
|
||||
.major!
|
||||
.opus!
|
||||
.summary!
|
||||
.text!;
|
||||
} else {
|
||||
throw UnsupportedError(
|
||||
'error getting title: {"type": ${item.basic!.commentType}, "id": $id}',
|
||||
);
|
||||
}
|
||||
final moduleDynamic = item.modules.moduleDynamic!;
|
||||
final title =
|
||||
moduleDynamic.desc?.text ??
|
||||
moduleDynamic.major!.opus!.summary!.text!;
|
||||
String? thumb = isDyn
|
||||
? item.modules.moduleAuthor?.face
|
||||
: item
|
||||
.modules
|
||||
.moduleDynamic
|
||||
?.major
|
||||
?.opus
|
||||
?.pics
|
||||
?.firstOrNull
|
||||
?.url;
|
||||
? moduleAuthor.face
|
||||
: moduleDynamic.major?.opus?.pics?.firstOrNull?.url;
|
||||
PageUtils.pmShare(
|
||||
context,
|
||||
content: {
|
||||
@@ -381,9 +340,8 @@ class AuthorPanel extends StatelessWidget {
|
||||
"headline": "",
|
||||
"source": source,
|
||||
if (thumb?.isNotEmpty == true) "thumb": thumb,
|
||||
"author": item.modules.moduleAuthor!.name,
|
||||
"author_id": item.modules.moduleAuthor!.mid
|
||||
.toString(),
|
||||
"author": moduleAuthor.name,
|
||||
"author_id": moduleAuthor.mid.toString(),
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
@@ -394,7 +352,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
'临时屏蔽:${item.modules.moduleAuthor?.name}',
|
||||
'临时屏蔽:${moduleAuthor.name}',
|
||||
style: theme.textTheme.titleSmall,
|
||||
),
|
||||
leading: const Icon(Icons.visibility_off_outlined, size: 19),
|
||||
@@ -403,16 +361,16 @@ class AuthorPanel extends StatelessWidget {
|
||||
onBlock?.call();
|
||||
try {
|
||||
Get.find<DynamicsController>().tempBannedList.add(
|
||||
item.modules.moduleAuthor!.mid!,
|
||||
moduleAuthor.mid!,
|
||||
);
|
||||
SmartDialog.showToast(
|
||||
'已临时屏蔽${item.modules.moduleAuthor?.name}(${item.modules.moduleAuthor!.mid!}),重启恢复',
|
||||
'已临时屏蔽${moduleAuthor.name}(${moduleAuthor.mid!}),重启恢复',
|
||||
);
|
||||
} catch (_) {}
|
||||
},
|
||||
minLeadingWidth: 0,
|
||||
),
|
||||
if (item.modules.moduleAuthor?.mid == Accounts.main.mid) ...[
|
||||
if (moduleAuthor.mid == Accounts.main.mid) ...[
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
@@ -512,13 +470,13 @@ class AuthorPanel extends StatelessWidget {
|
||||
(reasonType, reasonDesc, banUid) {
|
||||
if (banUid) {
|
||||
VideoHttp.relationMod(
|
||||
mid: item.modules.moduleAuthor!.mid!,
|
||||
mid: moduleAuthor.mid!,
|
||||
act: 5,
|
||||
reSrc: 11,
|
||||
);
|
||||
}
|
||||
return UserHttp.dynamicReport(
|
||||
mid: item.modules.moduleAuthor!.mid,
|
||||
mid: moduleAuthor.mid,
|
||||
dynId: item.idStr,
|
||||
reasonType: reasonType,
|
||||
);
|
||||
|
||||
@@ -3,13 +3,13 @@ import 'package:PiliPlus/pages/article/widgets/opus_content.dart'
|
||||
show moduleBlockedItem;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget blockedItem(
|
||||
ThemeData theme,
|
||||
ModuleBlocked moduleBlocked, {
|
||||
Widget blockedItem({
|
||||
required ThemeData theme,
|
||||
required ModuleBlocked blocked,
|
||||
required double maxWidth,
|
||||
}) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 13, vertical: 1),
|
||||
child: moduleBlockedItem(theme, moduleBlocked, maxWidth - 26),
|
||||
child: moduleBlockedItem(theme, blocked, maxWidth - 26),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,19 +8,26 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
Widget content(
|
||||
ThemeData theme,
|
||||
bool isSave,
|
||||
BuildContext context,
|
||||
DynamicItemModel item,
|
||||
bool isDetail,
|
||||
Function(List<String>, int)? callback, {
|
||||
floor = 1,
|
||||
BuildContext context, {
|
||||
required int floor,
|
||||
required ThemeData theme,
|
||||
required DynamicItemModel item,
|
||||
required bool isSave,
|
||||
required bool isDetail,
|
||||
required double maxWidth,
|
||||
Function(List<String>, int)? callback,
|
||||
}) {
|
||||
if (floor == 1) {
|
||||
maxWidth -= 24;
|
||||
}
|
||||
TextSpan? richNodes = richNode(theme, item, context, maxWidth: maxWidth);
|
||||
TextSpan? richNodes = richNode(
|
||||
context,
|
||||
theme: theme,
|
||||
item: item,
|
||||
maxWidth: maxWidth,
|
||||
);
|
||||
final moduleDynamic = item.modules.moduleDynamic;
|
||||
final pics = moduleDynamic?.major?.opus?.pics;
|
||||
return Padding(
|
||||
padding: floor == 1
|
||||
? const EdgeInsets.fromLTRB(12, 0, 12, 6)
|
||||
@@ -28,13 +35,13 @@ Widget content(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (item.modules.moduleDynamic?.topic != null)
|
||||
if (moduleDynamic?.topic case final topic?)
|
||||
GestureDetector(
|
||||
onTap: () => Get.toNamed(
|
||||
'/dynTopic',
|
||||
parameters: {
|
||||
'id': item.modules.moduleDynamic!.topic!.id!.toString(),
|
||||
'name': item.modules.moduleDynamic!.topic!.name!,
|
||||
'id': topic.id!.toString(),
|
||||
'name': topic.name!,
|
||||
},
|
||||
),
|
||||
child: Text.rich(
|
||||
@@ -51,7 +58,7 @@ Widget content(
|
||||
),
|
||||
),
|
||||
),
|
||||
TextSpan(text: item.modules.moduleDynamic!.topic!.name),
|
||||
TextSpan(text: topic.name),
|
||||
],
|
||||
),
|
||||
style: TextStyle(
|
||||
@@ -79,10 +86,10 @@ Widget content(
|
||||
richNodes,
|
||||
maxLines: isSave ? null : 6,
|
||||
),
|
||||
if (item.modules.moduleDynamic?.major?.opus?.pics?.isNotEmpty == true)
|
||||
if (pics?.isNotEmpty == true)
|
||||
CustomGridView(
|
||||
maxWidth: maxWidth,
|
||||
picArr: item.modules.moduleDynamic!.major!.opus!.pics!
|
||||
picArr: pics!
|
||||
.map(
|
||||
(item) => ImageModel(
|
||||
width: item.width,
|
||||
|
||||
52
lib/pages/dynamics/widgets/dyn_content.dart
Normal file
52
lib/pages/dynamics/widgets/dyn_content.dart
Normal file
@@ -0,0 +1,52 @@
|
||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/additional_panel.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/blocked_item.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/content_panel.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/module_panel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
List<Widget> dynContent(
|
||||
BuildContext context, {
|
||||
required int floor,
|
||||
required ThemeData theme,
|
||||
required DynamicItemModel item,
|
||||
required bool isSave,
|
||||
required bool isDetail,
|
||||
required double maxWidth,
|
||||
Function(List<String>, int)? callback,
|
||||
}) {
|
||||
final moduleDynamic = item.modules.moduleDynamic;
|
||||
return [
|
||||
if (item.type != 'DYNAMIC_TYPE_NONE')
|
||||
content(
|
||||
context,
|
||||
theme: theme,
|
||||
isSave: isSave,
|
||||
isDetail: isDetail,
|
||||
item: item,
|
||||
floor: floor,
|
||||
callback: callback,
|
||||
maxWidth: maxWidth,
|
||||
),
|
||||
module(
|
||||
context,
|
||||
theme: theme,
|
||||
isSave: isSave,
|
||||
isDetail: isDetail,
|
||||
item: item,
|
||||
floor: floor,
|
||||
callback: callback,
|
||||
maxWidth: maxWidth,
|
||||
),
|
||||
if (moduleDynamic?.additional case final additional?)
|
||||
addWidget(
|
||||
theme: theme,
|
||||
context,
|
||||
idStr: item.idStr,
|
||||
additional: additional,
|
||||
floor: floor,
|
||||
),
|
||||
if (moduleDynamic?.major?.blocked case final blocked?)
|
||||
blockedItem(theme: theme, blocked: blocked, maxWidth: maxWidth),
|
||||
];
|
||||
}
|
||||
@@ -2,11 +2,8 @@ import 'package:PiliPlus/common/widgets/dyn/ink_well.dart';
|
||||
import 'package:PiliPlus/common/widgets/image/image_save.dart';
|
||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/action_panel.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/additional_panel.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/author_panel.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/blocked_item.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/content_panel.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/module_panel.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/dyn_content.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:flutter/material.dart' hide InkWell;
|
||||
|
||||
@@ -76,37 +73,20 @@ class DynamicPanel extends StatelessWidget {
|
||||
padding: const EdgeInsets.fromLTRB(12, 12, 12, 6),
|
||||
child: authorWidget,
|
||||
),
|
||||
if (item.type != 'DYNAMIC_TYPE_NONE')
|
||||
content(
|
||||
theme,
|
||||
isSave,
|
||||
context,
|
||||
item,
|
||||
isDetail,
|
||||
callback,
|
||||
maxWidth: maxWidth,
|
||||
),
|
||||
module(
|
||||
theme,
|
||||
isSave,
|
||||
item,
|
||||
...dynContent(
|
||||
context,
|
||||
isDetail,
|
||||
callback,
|
||||
theme: theme,
|
||||
isSave: isSave,
|
||||
isDetail: isDetail,
|
||||
item: item,
|
||||
floor: 1,
|
||||
callback: callback,
|
||||
maxWidth: maxWidth,
|
||||
),
|
||||
if (item.modules.moduleDynamic?.additional != null)
|
||||
addWidget(theme, item, context),
|
||||
if (item.modules.moduleDynamic?.major?.blocked != null)
|
||||
blockedItem(
|
||||
theme,
|
||||
item.modules.moduleDynamic!.major!.blocked!,
|
||||
maxWidth: maxWidth,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
if (!isDetail) ...[
|
||||
ActionPanel(item: item),
|
||||
if (item.modules.moduleFold case ModuleFold moduleFold) ...[
|
||||
if (item.modules.moduleFold case final moduleFold?) ...[
|
||||
Divider(
|
||||
height: 1,
|
||||
color: theme.dividerColor.withValues(alpha: 0.1),
|
||||
|
||||
135
lib/pages/dynamics/widgets/forward_panel.dart
Normal file
135
lib/pages/dynamics/widgets/forward_panel.dart
Normal file
@@ -0,0 +1,135 @@
|
||||
import 'package:PiliPlus/common/widgets/dyn/ink_well.dart';
|
||||
import 'package:PiliPlus/common/widgets/image/image_save.dart';
|
||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/dyn_content.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/module_panel.dart';
|
||||
import 'package:PiliPlus/utils/date_util.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:flutter/material.dart' hide InkWell;
|
||||
import 'package:get/get.dart';
|
||||
|
||||
Widget forwardPanel(
|
||||
BuildContext context, {
|
||||
required int floor,
|
||||
required ThemeData theme,
|
||||
required DynamicItemModel orig,
|
||||
required bool isSave,
|
||||
required bool isDetail,
|
||||
required double maxWidth,
|
||||
Function(List<String>, int)? callback,
|
||||
}) {
|
||||
final moduleDynamic = orig.modules.moduleDynamic;
|
||||
final major = moduleDynamic?.major;
|
||||
final isNoneMajor = major?.type == 'MAJOR_TYPE_NONE';
|
||||
|
||||
Widget child;
|
||||
|
||||
if (isNoneMajor) {
|
||||
child = noneWidget(theme, major?.none?.tips);
|
||||
} else {
|
||||
child = Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_forwardAuthor(
|
||||
theme: theme,
|
||||
moduleAuthor: orig.modules.moduleAuthor!,
|
||||
isSave: isSave,
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
...dynContent(
|
||||
context,
|
||||
theme: theme,
|
||||
isSave: isSave,
|
||||
isDetail: isDetail,
|
||||
item: orig,
|
||||
floor: floor + 1,
|
||||
callback: callback,
|
||||
maxWidth: maxWidth - 30,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
child = Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8),
|
||||
color: theme.dividerColor.withValues(alpha: 0.08),
|
||||
child: child,
|
||||
);
|
||||
|
||||
if (isNoneMajor) {
|
||||
return child;
|
||||
}
|
||||
|
||||
return InkWell(
|
||||
onTap: () => PageUtils.pushDynDetail(orig),
|
||||
onLongPress: () {
|
||||
String? title, cover, bvid;
|
||||
switch (orig.type) {
|
||||
case 'DYNAMIC_TYPE_AV':
|
||||
title = major?.archive?.title;
|
||||
cover = major?.archive?.cover;
|
||||
bvid = major?.archive?.bvid;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_UGC_SEASON':
|
||||
title = major?.ugcSeason?.title;
|
||||
cover = major?.ugcSeason?.cover;
|
||||
bvid = major?.ugcSeason?.bvid;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_PGC' || 'DYNAMIC_TYPE_PGC_UNION':
|
||||
title = major?.pgc?.title;
|
||||
cover = major?.pgc?.cover;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_LIVE_RCMD':
|
||||
title = major?.liveRcmd?.title;
|
||||
cover = major?.liveRcmd?.cover;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_LIVE':
|
||||
title = major?.live?.title;
|
||||
cover = major?.live?.cover;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (cover != null) {
|
||||
imageSaveDialog(
|
||||
title: title,
|
||||
cover: cover,
|
||||
bvid: bvid,
|
||||
);
|
||||
}
|
||||
},
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _forwardAuthor({
|
||||
required ThemeData theme,
|
||||
required ModuleAuthorModel moduleAuthor,
|
||||
required bool isSave,
|
||||
}) {
|
||||
final isNormalAuth = moduleAuthor.type == 'AUTHOR_TYPE_NORMAL';
|
||||
return Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: isNormalAuth
|
||||
? () => Get.toNamed('/member?mid=${moduleAuthor.mid}')
|
||||
: null,
|
||||
child: Text(
|
||||
'${isNormalAuth ? '@' : ''}${moduleAuthor.name}',
|
||||
style: TextStyle(color: theme.colorScheme.primary),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
isSave
|
||||
? DateUtil.format(moduleAuthor.pubTs, format: DateUtil.longFormatDs)
|
||||
: DateUtil.dateFormat(moduleAuthor.pubTs),
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -1,73 +1,65 @@
|
||||
import 'package:PiliPlus/common/widgets/image/image_save.dart';
|
||||
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget livePanel(
|
||||
ThemeData theme,
|
||||
bool isDetail,
|
||||
DynamicItemModel item,
|
||||
BuildContext context, {
|
||||
int floor = 1,
|
||||
required int floor,
|
||||
required ThemeData theme,
|
||||
required DynamicItemModel item,
|
||||
required bool isDetail,
|
||||
required double maxWidth,
|
||||
Function(List<String>, int)? callback,
|
||||
}) {
|
||||
DynamicMajorModel? content = item.modules.moduleDynamic!.major;
|
||||
if (content == null) {
|
||||
DynamicLive2Model? live = item.modules.moduleDynamic!.major!.live;
|
||||
if (live == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () => PageUtils.toLiveRoom(content.live?.id),
|
||||
onLongPress: () {
|
||||
Feedback.forLongPress(context);
|
||||
imageSaveDialog(
|
||||
title: content.live!.title,
|
||||
cover: content.live!.cover,
|
||||
);
|
||||
},
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
width: 120,
|
||||
height: 75,
|
||||
src: content.live!.cover,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
content.live!.title!,
|
||||
maxLines: isDetail ? null : 2,
|
||||
overflow: isDetail ? null : TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
if (content.live?.descFirst != null)
|
||||
Text(
|
||||
content.live!.descFirst!,
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (content.live!.badge?.text != null)
|
||||
Text(
|
||||
content.live!.badge!.text!,
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
return Padding(
|
||||
padding: floor == 1
|
||||
? const EdgeInsets.symmetric(horizontal: 12)
|
||||
: EdgeInsets.zero,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
width: 120,
|
||||
height: 75,
|
||||
src: live.cover,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
live.title!,
|
||||
maxLines: isDetail ? null : 2,
|
||||
overflow: isDetail ? null : TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
if (live.descFirst case final descFirst?)
|
||||
Text(
|
||||
descFirst,
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (live.badge?.text case final badge?)
|
||||
Text(
|
||||
badge,
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: live.liveState == 1
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,117 +3,116 @@ import 'package:PiliPlus/common/widgets/badge.dart';
|
||||
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
||||
import 'package:PiliPlus/models/common/badge_type.dart';
|
||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget livePanelSub(
|
||||
ThemeData theme,
|
||||
bool isDetail,
|
||||
DynamicItemModel item,
|
||||
BuildContext context, {
|
||||
int floor = 1,
|
||||
required int floor,
|
||||
required ThemeData theme,
|
||||
required DynamicItemModel item,
|
||||
required bool isDetail,
|
||||
required double maxWidth,
|
||||
Function(List<String>, int)? callback,
|
||||
}) {
|
||||
maxWidth -= 24;
|
||||
SubscriptionNew? subItem = item.modules.moduleDynamic!.major?.subscriptionNew;
|
||||
LivePlayInfo? content = subItem?.liveRcmd?.content?.livePlayInfo;
|
||||
if (subItem == null || content == null) {
|
||||
LivePlayInfo? live = item
|
||||
.modules
|
||||
.moduleDynamic!
|
||||
.major
|
||||
?.subscriptionNew
|
||||
?.liveRcmd
|
||||
?.content
|
||||
?.livePlayInfo;
|
||||
if (live == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
|
||||
child: GestureDetector(
|
||||
onTap: () => PageUtils.toLiveRoom(content.roomId),
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
width: maxWidth,
|
||||
height: maxWidth / StyleString.aspectRatio,
|
||||
src: content.cover,
|
||||
quality: 40,
|
||||
),
|
||||
PBadge(
|
||||
text: content.watchedShow?.textLarge,
|
||||
EdgeInsets padding;
|
||||
if (floor == 1) {
|
||||
maxWidth -= 24;
|
||||
padding = const EdgeInsets.symmetric(horizontal: 12);
|
||||
} else {
|
||||
padding = EdgeInsets.zero;
|
||||
}
|
||||
return Padding(
|
||||
padding: padding,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
width: maxWidth,
|
||||
height: maxWidth / StyleString.aspectRatio,
|
||||
src: live.cover,
|
||||
quality: 40,
|
||||
),
|
||||
PBadge(
|
||||
text: live.watchedShow?.textLarge,
|
||||
top: 6,
|
||||
right: 65,
|
||||
fontSize: 10.5,
|
||||
type: PBadgeType.gray,
|
||||
),
|
||||
if (live.liveStatus == 1)
|
||||
Positioned(
|
||||
right: 6,
|
||||
top: 6,
|
||||
right: 65,
|
||||
fontSize: 10.5,
|
||||
type: PBadgeType.gray,
|
||||
child: Image.asset(
|
||||
height: 16,
|
||||
'assets/images/live/live.gif',
|
||||
filterQuality: FilterQuality.low,
|
||||
),
|
||||
)
|
||||
else
|
||||
const PBadge(
|
||||
text: '直播结束',
|
||||
top: 6,
|
||||
right: 6,
|
||||
),
|
||||
if (content.liveStatus == 1)
|
||||
Positioned(
|
||||
right: 6,
|
||||
top: 6,
|
||||
child: Image.asset(
|
||||
height: 16,
|
||||
'assets/images/live/live.gif',
|
||||
filterQuality: FilterQuality.low,
|
||||
),
|
||||
)
|
||||
else
|
||||
const PBadge(
|
||||
text: '直播结束',
|
||||
top: 6,
|
||||
right: 6,
|
||||
),
|
||||
if (content.areaName != null)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
height: 80,
|
||||
alignment: Alignment.bottomLeft,
|
||||
padding: const EdgeInsets.fromLTRB(12, 0, 10, 10),
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: <Color>[
|
||||
Colors.transparent,
|
||||
Colors.black45,
|
||||
],
|
||||
),
|
||||
borderRadius: floor == 1
|
||||
? const BorderRadius.only(
|
||||
bottomLeft: StyleString.imgRadius,
|
||||
bottomRight: StyleString.imgRadius,
|
||||
)
|
||||
: const BorderRadius.only(
|
||||
bottomLeft: Radius.circular(6),
|
||||
bottomRight: Radius.circular(6),
|
||||
),
|
||||
if (live.areaName case final areaName?)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
height: 80,
|
||||
alignment: Alignment.bottomLeft,
|
||||
padding: const EdgeInsets.fromLTRB(12, 0, 10, 10),
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: <Color>[
|
||||
Colors.transparent,
|
||||
Colors.black45,
|
||||
],
|
||||
),
|
||||
child: Text(
|
||||
content.areaName!,
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: Colors.white,
|
||||
),
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: StyleString.imgRadius,
|
||||
bottomRight: StyleString.imgRadius,
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
areaName,
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
if (content.title != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: StyleString.safeSpace,
|
||||
),
|
||||
child: Text(
|
||||
content.title!,
|
||||
const SizedBox(height: 6),
|
||||
if (live.title case final title?)
|
||||
Text(
|
||||
title,
|
||||
maxLines: isDetail ? null : 1,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
overflow: isDetail ? null : TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
],
|
||||
const SizedBox(height: 2),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,117 +3,110 @@ import 'package:PiliPlus/common/widgets/badge.dart';
|
||||
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
||||
import 'package:PiliPlus/models/common/badge_type.dart';
|
||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget liveRcmdPanel(
|
||||
ThemeData theme,
|
||||
bool isDetail,
|
||||
DynamicItemModel item,
|
||||
BuildContext context, {
|
||||
int floor = 1,
|
||||
required int floor,
|
||||
required ThemeData theme,
|
||||
required DynamicItemModel item,
|
||||
required bool isDetail,
|
||||
required double maxWidth,
|
||||
Function(List<String>, int)? callback,
|
||||
}) {
|
||||
maxWidth -= 24;
|
||||
DynamicLiveModel? liveRcmd = item.modules.moduleDynamic?.major?.liveRcmd;
|
||||
if (liveRcmd == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
|
||||
child: GestureDetector(
|
||||
onTap: () => PageUtils.pushDynDetail(item),
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
width: maxWidth,
|
||||
height: maxWidth / StyleString.aspectRatio,
|
||||
src: liveRcmd.cover,
|
||||
quality: 40,
|
||||
),
|
||||
PBadge(
|
||||
text: liveRcmd.watchedShow?.textLarge,
|
||||
EdgeInsets padding;
|
||||
if (floor == 1) {
|
||||
maxWidth -= 24;
|
||||
padding = const EdgeInsets.symmetric(horizontal: 12);
|
||||
} else {
|
||||
padding = EdgeInsets.zero;
|
||||
}
|
||||
return Padding(
|
||||
padding: padding,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
width: maxWidth,
|
||||
height: maxWidth / StyleString.aspectRatio,
|
||||
src: liveRcmd.cover,
|
||||
quality: 40,
|
||||
),
|
||||
PBadge(
|
||||
text: liveRcmd.watchedShow?.textLarge,
|
||||
top: 6,
|
||||
right: 65,
|
||||
fontSize: 10.5,
|
||||
type: PBadgeType.gray,
|
||||
),
|
||||
if (liveRcmd.liveStatus == 1)
|
||||
Positioned(
|
||||
right: 6,
|
||||
top: 6,
|
||||
right: 65,
|
||||
fontSize: 10.5,
|
||||
child: Image.asset(
|
||||
height: 16,
|
||||
'assets/images/live/live.gif',
|
||||
filterQuality: FilterQuality.low,
|
||||
),
|
||||
)
|
||||
else
|
||||
const PBadge(
|
||||
text: '直播结束',
|
||||
top: 6,
|
||||
right: 6,
|
||||
type: PBadgeType.gray,
|
||||
),
|
||||
if (liveRcmd.liveStatus == 1)
|
||||
Positioned(
|
||||
right: 6,
|
||||
top: 6,
|
||||
child: Image.asset(
|
||||
height: 16,
|
||||
'assets/images/live/live.gif',
|
||||
filterQuality: FilterQuality.low,
|
||||
),
|
||||
)
|
||||
else
|
||||
const PBadge(
|
||||
text: '直播结束',
|
||||
top: 6,
|
||||
right: 6,
|
||||
type: PBadgeType.gray,
|
||||
),
|
||||
if (liveRcmd.areaName != null)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
height: 80,
|
||||
alignment: Alignment.bottomLeft,
|
||||
padding: const EdgeInsets.fromLTRB(12, 0, 10, 10),
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: <Color>[
|
||||
Colors.transparent,
|
||||
Colors.black45,
|
||||
],
|
||||
),
|
||||
borderRadius: floor == 1
|
||||
? const BorderRadius.only(
|
||||
bottomLeft: StyleString.imgRadius,
|
||||
bottomRight: StyleString.imgRadius,
|
||||
)
|
||||
: const BorderRadius.only(
|
||||
bottomLeft: Radius.circular(6),
|
||||
bottomRight: Radius.circular(6),
|
||||
),
|
||||
if (liveRcmd.areaName case final areaName?)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
height: 80,
|
||||
alignment: Alignment.bottomLeft,
|
||||
padding: const EdgeInsets.fromLTRB(12, 0, 10, 10),
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: <Color>[
|
||||
Colors.transparent,
|
||||
Colors.black45,
|
||||
],
|
||||
),
|
||||
child: Text(
|
||||
liveRcmd.areaName!,
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: Colors.white,
|
||||
),
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: StyleString.imgRadius,
|
||||
bottomRight: StyleString.imgRadius,
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
areaName,
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
if (liveRcmd.title != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: StyleString.safeSpace,
|
||||
),
|
||||
child: Text(
|
||||
liveRcmd.title!,
|
||||
const SizedBox(height: 6),
|
||||
if (liveRcmd.title case final title?)
|
||||
Text(
|
||||
title,
|
||||
maxLines: isDetail ? null : 1,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
overflow: isDetail ? null : TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
],
|
||||
const SizedBox(height: 2),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,36 +1,60 @@
|
||||
// 转发
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/common/widgets/badge.dart';
|
||||
import 'package:PiliPlus/common/widgets/dyn/ink_well.dart';
|
||||
import 'package:PiliPlus/common/widgets/image/image_save.dart';
|
||||
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/additional_panel.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/blocked_item.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/content_panel.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/forward_panel.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/live_panel.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/live_panel_sub.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/live_rcmd_panel.dart';
|
||||
import 'package:PiliPlus/pages/dynamics/widgets/video_panel.dart';
|
||||
import 'package:PiliPlus/utils/date_util.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart' hide InkWell;
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
Widget noneWidget(ThemeData theme, String? tips) => Row(
|
||||
spacing: 5,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.error,
|
||||
size: 18,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
Text(
|
||||
tips ?? '已失效',
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
Widget module(
|
||||
ThemeData theme,
|
||||
bool isSave,
|
||||
DynamicItemModel item,
|
||||
BuildContext context,
|
||||
bool isDetail,
|
||||
Function(List<String>, int)? callback, {
|
||||
floor = 1,
|
||||
BuildContext context, {
|
||||
required int floor,
|
||||
required ThemeData theme,
|
||||
required DynamicItemModel item,
|
||||
required bool isSave,
|
||||
required bool isDetail,
|
||||
required double maxWidth,
|
||||
Function(List<String>, int)? callback,
|
||||
}) {
|
||||
final moduleDynamic = item.modules.moduleDynamic;
|
||||
final major = moduleDynamic?.major;
|
||||
|
||||
if (major?.type == 'MAJOR_TYPE_NONE') {
|
||||
return noneWidget(theme, major?.none?.tips);
|
||||
}
|
||||
|
||||
switch (item.type) {
|
||||
case 'DYNAMIC_TYPE_NONE':
|
||||
return Row(
|
||||
spacing: 4,
|
||||
children: [
|
||||
const Icon(FontAwesomeIcons.ghost, size: 14),
|
||||
Text(major!.none!.tips!),
|
||||
],
|
||||
);
|
||||
// 图文
|
||||
case 'DYNAMIC_TYPE_DRAW':
|
||||
// 文章
|
||||
@@ -44,173 +68,46 @@ Widget module(
|
||||
case 'DYNAMIC_TYPE_PGC_UNION':
|
||||
case 'DYNAMIC_TYPE_COURSES_SEASON':
|
||||
return videoSeasonWidget(
|
||||
theme,
|
||||
isSave,
|
||||
isDetail,
|
||||
item,
|
||||
context,
|
||||
callback,
|
||||
theme: theme,
|
||||
item: item,
|
||||
floor: floor,
|
||||
isSave: isSave,
|
||||
isDetail: isDetail,
|
||||
callback: callback,
|
||||
maxWidth: maxWidth,
|
||||
);
|
||||
// 转发
|
||||
case 'DYNAMIC_TYPE_FORWARD':
|
||||
final orig = item.orig!;
|
||||
final isNoneMajor =
|
||||
orig.modules.moduleDynamic?.major?.type == 'MAJOR_TYPE_NONE';
|
||||
late final isNormalAuth =
|
||||
orig.modules.moduleAuthor!.type == 'AUTHOR_TYPE_NORMAL';
|
||||
if (isNoneMajor) {
|
||||
if (orig.modules.moduleDynamic?.major?.none?.tips?.isNotEmpty == true) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8),
|
||||
color: theme.dividerColor.withValues(alpha: 0.08),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.error,
|
||||
size: 18,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
orig.modules.moduleDynamic!.major!.none!.tips!,
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
maxWidth -= 30;
|
||||
return InkWell(
|
||||
onTap: () => PageUtils.pushDynDetail(orig),
|
||||
onLongPress: () {
|
||||
String? title, cover, bvid;
|
||||
late var origMajor = orig.modules.moduleDynamic?.major;
|
||||
late var major = item.modules.moduleDynamic?.major;
|
||||
switch (orig.type) {
|
||||
case 'DYNAMIC_TYPE_AV':
|
||||
title = origMajor?.archive?.title;
|
||||
cover = origMajor?.archive?.cover;
|
||||
bvid = origMajor?.archive?.bvid;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_UGC_SEASON':
|
||||
title = origMajor?.ugcSeason?.title;
|
||||
cover = origMajor?.ugcSeason?.cover;
|
||||
bvid = origMajor?.ugcSeason?.bvid;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_PGC' || 'DYNAMIC_TYPE_PGC_UNION':
|
||||
title = origMajor?.pgc?.title;
|
||||
cover = origMajor?.pgc?.cover;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_LIVE_RCMD':
|
||||
title = major?.liveRcmd?.title;
|
||||
cover = major?.liveRcmd?.cover;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_LIVE':
|
||||
title = major?.live?.title;
|
||||
cover = major?.live?.cover;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
imageSaveDialog(
|
||||
title: title,
|
||||
cover: cover,
|
||||
bvid: bvid,
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8),
|
||||
color: theme.dividerColor.withValues(alpha: 0.08),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: isNormalAuth
|
||||
? () => Get.toNamed(
|
||||
'/member?mid=${orig.modules.moduleAuthor!.mid}',
|
||||
)
|
||||
: null,
|
||||
child: Text(
|
||||
'${isNormalAuth ? '@' : ''}${orig.modules.moduleAuthor!.name}',
|
||||
style: TextStyle(color: theme.colorScheme.primary),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
isSave
|
||||
? DateUtil.format(
|
||||
orig.modules.moduleAuthor!.pubTs,
|
||||
format: DateUtil.longFormatDs,
|
||||
)
|
||||
: DateUtil.dateFormat(orig.modules.moduleAuthor!.pubTs),
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
content(
|
||||
theme,
|
||||
isSave,
|
||||
context,
|
||||
orig,
|
||||
isDetail,
|
||||
callback,
|
||||
floor: floor + 1,
|
||||
maxWidth: maxWidth,
|
||||
),
|
||||
module(
|
||||
theme,
|
||||
isSave,
|
||||
orig,
|
||||
context,
|
||||
isDetail,
|
||||
callback,
|
||||
floor: floor + 1,
|
||||
maxWidth: maxWidth,
|
||||
),
|
||||
if (orig.modules.moduleDynamic?.additional != null)
|
||||
addWidget(theme, orig, context, floor: floor + 1),
|
||||
if (orig.modules.moduleDynamic?.major?.blocked != null)
|
||||
blockedItem(
|
||||
theme,
|
||||
orig.modules.moduleDynamic!.major!.blocked!,
|
||||
maxWidth: maxWidth,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
return forwardPanel(
|
||||
context,
|
||||
theme: theme,
|
||||
isSave: isSave,
|
||||
orig: item.orig!,
|
||||
isDetail: isDetail,
|
||||
callback: callback,
|
||||
floor: floor + 1,
|
||||
maxWidth: maxWidth,
|
||||
);
|
||||
// 直播
|
||||
case 'DYNAMIC_TYPE_LIVE_RCMD':
|
||||
return liveRcmdPanel(
|
||||
theme,
|
||||
isDetail,
|
||||
item,
|
||||
context,
|
||||
theme: theme,
|
||||
isDetail: isDetail,
|
||||
item: item,
|
||||
floor: floor,
|
||||
maxWidth: maxWidth,
|
||||
);
|
||||
// 直播
|
||||
case 'DYNAMIC_TYPE_LIVE':
|
||||
return livePanel(theme, isDetail, item, context, floor: floor);
|
||||
case 'DYNAMIC_TYPE_NONE':
|
||||
return Row(
|
||||
spacing: 4,
|
||||
children: [
|
||||
const Icon(FontAwesomeIcons.ghost, size: 14),
|
||||
Text(item.modules.moduleDynamic!.major!.none!.tips!),
|
||||
],
|
||||
return livePanel(
|
||||
context,
|
||||
theme: theme,
|
||||
item: item,
|
||||
floor: floor,
|
||||
isDetail: isDetail,
|
||||
maxWidth: maxWidth,
|
||||
);
|
||||
// 活动
|
||||
case 'DYNAMIC_TYPE_COMMON_SQUARE':
|
||||
@@ -225,7 +122,7 @@ Widget module(
|
||||
borderRadius: floor == 1 ? null : StyleString.mdRadius,
|
||||
onTap: () {
|
||||
try {
|
||||
String url = item.modules.moduleDynamic!.major!.common!.jumpUrl!;
|
||||
String url = major.common!.jumpUrl!;
|
||||
if (url.contains('bangumi/play') &&
|
||||
PageUtils.viewPgcFromUri(url)) {
|
||||
return;
|
||||
@@ -272,7 +169,7 @@ Widget module(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.modules.moduleDynamic!.major!.common!.title!,
|
||||
major!.common!.title!,
|
||||
style: TextStyle(color: theme.colorScheme.primary),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
@@ -286,7 +183,7 @@ Widget module(
|
||||
?.isNotEmpty ==
|
||||
true)
|
||||
Text(
|
||||
item.modules.moduleDynamic!.major!.common!.desc!,
|
||||
major.common!.desc!,
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
@@ -303,7 +200,7 @@ Widget module(
|
||||
),
|
||||
);
|
||||
case 'DYNAMIC_TYPE_MUSIC':
|
||||
final Map music = item.modules.moduleDynamic!.major!.music!;
|
||||
final Map music = major!.music!;
|
||||
return InkWell(
|
||||
onTap: () => PageUtils.handleWebview("https:${music['jump_url']}"),
|
||||
child: Container(
|
||||
@@ -355,24 +252,22 @@ Widget module(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (floor == 1) const SizedBox(width: 12),
|
||||
if (item.modules.moduleDynamic!.major!.medialist!.cover?.isNotEmpty ==
|
||||
true) ...[
|
||||
if (major?.medialist?.cover?.isNotEmpty == true) ...[
|
||||
Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Hero(
|
||||
tag: item.modules.moduleDynamic!.major!.medialist!.cover!,
|
||||
tag: major!.medialist!.cover!,
|
||||
child: NetworkImgLayer(
|
||||
width: 180,
|
||||
height: 110,
|
||||
src: item.modules.moduleDynamic!.major!.medialist!.cover,
|
||||
src: major.medialist!.cover,
|
||||
),
|
||||
),
|
||||
PBadge(
|
||||
right: 6,
|
||||
top: 6,
|
||||
text:
|
||||
item.modules.moduleDynamic!.major!.medialist!.badge?.text,
|
||||
text: major.medialist!.badge?.text,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -387,17 +282,16 @@ Widget module(
|
||||
children: [
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
item.modules.moduleDynamic!.major!.medialist!.title!,
|
||||
major!.medialist!.title!,
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.titleMedium!.fontSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
if (item.modules.moduleDynamic?.major?.medialist?.subTitle !=
|
||||
null) ...[
|
||||
if (major.medialist?.subTitle != null) ...[
|
||||
const Spacer(),
|
||||
Text(
|
||||
item.modules.moduleDynamic!.major!.medialist!.subTitle!,
|
||||
major.medialist!.subTitle!,
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.labelLarge!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
@@ -413,14 +307,14 @@ Widget module(
|
||||
);
|
||||
|
||||
case 'DYNAMIC_TYPE_SUBSCRIPTION_NEW'
|
||||
when item.modules.moduleDynamic?.major?.type ==
|
||||
'MAJOR_TYPE_SUBSCRIPTION_NEW':
|
||||
when major?.type == 'MAJOR_TYPE_SUBSCRIPTION_NEW':
|
||||
return livePanelSub(
|
||||
theme,
|
||||
isDetail,
|
||||
item,
|
||||
context,
|
||||
theme: theme,
|
||||
isDetail: isDetail,
|
||||
item: item,
|
||||
floor: floor,
|
||||
callback: callback,
|
||||
maxWidth: maxWidth,
|
||||
);
|
||||
|
||||
|
||||
@@ -19,31 +19,32 @@ import 'package:get/get.dart';
|
||||
|
||||
// 富文本
|
||||
TextSpan? richNode(
|
||||
ThemeData theme,
|
||||
DynamicItemModel item,
|
||||
BuildContext context, {
|
||||
required ThemeData theme,
|
||||
required DynamicItemModel item,
|
||||
required double maxWidth,
|
||||
}) {
|
||||
try {
|
||||
late final style = TextStyle(color: theme.colorScheme.primary);
|
||||
List<InlineSpan> spanChildren = [];
|
||||
|
||||
final moduleDynamic = item.modules.moduleDynamic;
|
||||
List<RichTextNodeItem>? richTextNodes;
|
||||
if (item.modules.moduleDynamic?.desc != null) {
|
||||
richTextNodes = item.modules.moduleDynamic!.desc!.richTextNodes;
|
||||
} else if (item.modules.moduleDynamic?.major != null) {
|
||||
if (moduleDynamic?.desc case final desc?) {
|
||||
richTextNodes = desc.richTextNodes;
|
||||
} else if (moduleDynamic?.major?.opus case final opus?) {
|
||||
// 动态页面 richTextNodes 层级可能与主页动态层级不同
|
||||
richTextNodes =
|
||||
item.modules.moduleDynamic!.major!.opus?.summary?.richTextNodes;
|
||||
if (item.modules.moduleDynamic?.major?.opus?.title != null) {
|
||||
richTextNodes = opus.summary?.richTextNodes;
|
||||
if (opus.title case final title?) {
|
||||
spanChildren.add(
|
||||
TextSpan(
|
||||
text: '${item.modules.moduleDynamic!.major!.opus!.title!}\n',
|
||||
text: '$title\n',
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (richTextNodes == null || richTextNodes.isEmpty) {
|
||||
return null;
|
||||
} else {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:PiliPlus/common/widgets/dyn/ink_well.dart';
|
||||
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
||||
import 'package:PiliPlus/models/common/dynamic/up_panel_position.dart';
|
||||
import 'package:PiliPlus/models/common/image_type.dart';
|
||||
@@ -6,7 +7,7 @@ import 'package:PiliPlus/pages/dynamics/controller.dart';
|
||||
import 'package:PiliPlus/pages/live_follow/view.dart';
|
||||
import 'package:PiliPlus/utils/feed_back.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/material.dart' hide InkWell;
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class UpPanel extends StatefulWidget {
|
||||
|
||||
@@ -8,43 +8,20 @@ import 'package:PiliPlus/utils/num_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget videoSeasonWidget(
|
||||
ThemeData theme,
|
||||
bool isSave,
|
||||
bool isDetail,
|
||||
DynamicItemModel item,
|
||||
BuildContext context,
|
||||
Function(List<String>, int)? callback, {
|
||||
floor = 1,
|
||||
BuildContext context, {
|
||||
required int floor,
|
||||
required ThemeData theme,
|
||||
required DynamicItemModel item,
|
||||
required bool isSave,
|
||||
required bool isDetail,
|
||||
required double maxWidth,
|
||||
Function(List<String>, int)? callback,
|
||||
}) {
|
||||
if (item.modules.moduleDynamic?.major?.type == 'MAJOR_TYPE_NONE') {
|
||||
return item.modules.moduleDynamic?.major?.none?.tips != null
|
||||
? Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.error,
|
||||
size: 18,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
item.modules.moduleDynamic!.major!.none!.tips!,
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
],
|
||||
)
|
||||
: const SizedBox.shrink();
|
||||
}
|
||||
|
||||
// type archive ugcSeason
|
||||
// archive 视频/显示发布人
|
||||
// ugcSeason 合集/不显示发布人
|
||||
|
||||
// floor 1 2
|
||||
// 1 投稿视频 铺满 borderRadius 0
|
||||
// 2 转发视频 铺满 borderRadius 6
|
||||
|
||||
DynamicArchiveModel? itemContent = switch (item.type) {
|
||||
DynamicArchiveModel? video = switch (item.type) {
|
||||
'DYNAMIC_TYPE_AV' => item.modules.moduleDynamic?.major?.archive,
|
||||
'DYNAMIC_TYPE_UGC_SEASON' => item.modules.moduleDynamic?.major?.ugcSeason,
|
||||
'DYNAMIC_TYPE_PGC' ||
|
||||
@@ -53,121 +30,117 @@ Widget videoSeasonWidget(
|
||||
_ => null,
|
||||
};
|
||||
|
||||
if (itemContent == null) {
|
||||
if (video == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
Widget buildCover() {
|
||||
if (floor == 1) {
|
||||
maxWidth -= 24;
|
||||
}
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
width: maxWidth,
|
||||
height: maxWidth / StyleString.aspectRatio,
|
||||
src: itemContent.cover,
|
||||
quality: 40,
|
||||
),
|
||||
if (itemContent.badge?.text != null)
|
||||
PBadge(
|
||||
text: itemContent.badge!.text,
|
||||
top: 8.0,
|
||||
right: 10.0,
|
||||
bottom: null,
|
||||
left: null,
|
||||
type: switch (itemContent.badge!.text) {
|
||||
'充电专属' => PBadgeType.error,
|
||||
_ => PBadgeType.primary,
|
||||
},
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
height: 70,
|
||||
alignment: Alignment.bottomLeft,
|
||||
padding: const EdgeInsets.fromLTRB(10, 0, 8, 8),
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Colors.transparent,
|
||||
Colors.black54,
|
||||
],
|
||||
),
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: StyleString.imgRadius,
|
||||
bottomRight: StyleString.imgRadius,
|
||||
),
|
||||
),
|
||||
child: DefaultTextStyle.merge(
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
if (itemContent.durationText != null) ...[
|
||||
DecoratedBox(
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.black45,
|
||||
borderRadius: BorderRadius.all(Radius.circular(4)),
|
||||
),
|
||||
child: Text(' ${itemContent.durationText} '),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
],
|
||||
if (itemContent.stat != null) ...[
|
||||
Text('${NumUtil.numFormat(itemContent.stat!.play)}次围观'),
|
||||
const SizedBox(width: 6),
|
||||
Text('${NumUtil.numFormat(itemContent.stat!.danmu)}条弹幕'),
|
||||
],
|
||||
const Spacer(),
|
||||
Image.asset(
|
||||
'assets/images/play.png',
|
||||
width: 50,
|
||||
height: 50,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
EdgeInsets padding;
|
||||
if (floor == 1) {
|
||||
maxWidth -= 24;
|
||||
padding = const EdgeInsets.symmetric(horizontal: 12);
|
||||
} else {
|
||||
padding = EdgeInsets.zero;
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (itemContent.cover != null)
|
||||
if (floor == 1)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: StyleString.safeSpace,
|
||||
),
|
||||
child: buildCover(),
|
||||
)
|
||||
else
|
||||
buildCover(),
|
||||
const SizedBox(height: 6),
|
||||
if (itemContent.title != null)
|
||||
Padding(
|
||||
padding: floor == 1
|
||||
? const EdgeInsets.only(left: 12, right: 12)
|
||||
: EdgeInsets.zero,
|
||||
child: Text(
|
||||
itemContent.title!,
|
||||
return Padding(
|
||||
padding: padding,
|
||||
child: Column(
|
||||
spacing: 6,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (video.cover case final cover?)
|
||||
Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
width: maxWidth,
|
||||
height: maxWidth / StyleString.aspectRatio,
|
||||
src: cover,
|
||||
quality: 40,
|
||||
),
|
||||
if (video.badge?.text case final badge?)
|
||||
PBadge(
|
||||
text: badge,
|
||||
top: 8.0,
|
||||
right: 10.0,
|
||||
bottom: null,
|
||||
left: null,
|
||||
type: switch (badge) {
|
||||
'充电专属' => PBadgeType.error,
|
||||
_ => PBadgeType.primary,
|
||||
},
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
height: 70,
|
||||
alignment: Alignment.bottomLeft,
|
||||
padding: const EdgeInsets.fromLTRB(10, 0, 8, 8),
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Colors.transparent,
|
||||
Colors.black54,
|
||||
],
|
||||
),
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: StyleString.imgRadius,
|
||||
bottomRight: StyleString.imgRadius,
|
||||
),
|
||||
),
|
||||
child: DefaultTextStyle.merge(
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
if (video.durationText case final durationText?) ...[
|
||||
DecoratedBox(
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.black45,
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(4),
|
||||
),
|
||||
),
|
||||
child: Text(' $durationText '),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
],
|
||||
if (video.stat case final stat?) ...[
|
||||
Text(
|
||||
'${NumUtil.numFormat(stat.play)}次围观',
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
'${NumUtil.numFormat(stat.danmu)}条弹幕',
|
||||
),
|
||||
],
|
||||
const Spacer(),
|
||||
Image.asset(
|
||||
'assets/images/play.png',
|
||||
width: 50,
|
||||
height: 50,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (video.title case final title?)
|
||||
Text(
|
||||
title,
|
||||
maxLines: isDetail ? null : 1,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
overflow: isDetail ? null : TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -50,21 +50,33 @@ class _RepostPanelState extends CommonRichTextPubPageState<RepostPanel> {
|
||||
|
||||
late final _key = GlobalKey();
|
||||
|
||||
late final _pic =
|
||||
widget.pic ??
|
||||
widget.item?.modules.moduleDynamic?.major?.archive?.cover ??
|
||||
widget.item?.modules.moduleDynamic?.major?.pgc?.cover ??
|
||||
widget.item?.modules.moduleDynamic?.major?.opus?.pics?.firstOrNull?.url;
|
||||
late final String? _pic;
|
||||
late final String _text;
|
||||
late final String? _uname;
|
||||
|
||||
late final _text =
|
||||
widget.title ??
|
||||
widget.item?.modules.moduleDynamic?.major?.opus?.summary?.text ??
|
||||
widget.item?.modules.moduleDynamic?.desc?.text ??
|
||||
widget.item?.modules.moduleDynamic?.major?.archive?.title ??
|
||||
widget.item?.modules.moduleDynamic?.major?.pgc?.title ??
|
||||
'';
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
late final modules = widget.item?.modules;
|
||||
late final moduleDynamic = modules?.moduleDynamic;
|
||||
late final major = moduleDynamic?.major;
|
||||
|
||||
late final _uname = widget.uname ?? widget.item?.modules.moduleAuthor?.name;
|
||||
_pic =
|
||||
widget.pic ??
|
||||
major?.archive?.cover ??
|
||||
major?.pgc?.cover ??
|
||||
major?.opus?.pics?.firstOrNull?.url;
|
||||
|
||||
_text =
|
||||
widget.title ??
|
||||
major?.opus?.summary?.text ??
|
||||
major?.archive?.title ??
|
||||
major?.pgc?.title ??
|
||||
moduleDynamic?.desc?.text ??
|
||||
'';
|
||||
|
||||
_uname = widget.uname ?? modules?.moduleAuthor?.name;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
|
||||
@@ -105,11 +105,11 @@ class _MemberShopState extends State<MemberShop>
|
||||
child: Center(
|
||||
child: FilledButton.tonal(
|
||||
onPressed: () {
|
||||
if (_controller.clickUrl case String clickUrl) {
|
||||
if (_controller.clickUrl case final clickUrl?) {
|
||||
final url = Uri.parse(
|
||||
clickUrl,
|
||||
).queryParameters['url'];
|
||||
if (url case String url) {
|
||||
if (url case final url?) {
|
||||
Get.toNamed(
|
||||
'/webview',
|
||||
parameters: {'url': url},
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'package:PiliPlus/common/widgets/badge.dart';
|
||||
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
||||
import 'package:PiliPlus/models/common/badge_type.dart';
|
||||
import 'package:PiliPlus/models_new/space/space_shop/item.dart';
|
||||
import 'package:PiliPlus/models_new/space/space_shop/net_price.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -28,7 +27,7 @@ class MemberShopItem extends StatelessWidget {
|
||||
),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
if (item.cardUrl case String cardUrl) {
|
||||
if (item.cardUrl case final cardUrl?) {
|
||||
Get.toNamed('/webview', parameters: {'url': cardUrl});
|
||||
}
|
||||
},
|
||||
@@ -69,7 +68,7 @@ class MemberShopItem extends StatelessWidget {
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (item.netPrice case NetPrice netPrice)
|
||||
if (item.netPrice case final netPrice?)
|
||||
Text.rich(
|
||||
style: TextStyle(color: colorScheme.vipColor),
|
||||
TextSpan(
|
||||
|
||||
@@ -417,14 +417,14 @@ class PageUtils {
|
||||
// pgc
|
||||
if (archive.type == 2) {
|
||||
// jumpUrl
|
||||
if (archive.jumpUrl case String jumpUrl) {
|
||||
if (archive.jumpUrl case final jumpUrl?) {
|
||||
if (viewPgcFromUri(jumpUrl)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// redirectUrl from intro
|
||||
final res = await VideoHttp.videoIntro(bvid: archive.bvid!);
|
||||
if (res.dataOrNull?.redirectUrl case String redirectUrl) {
|
||||
if (res.dataOrNull?.redirectUrl case final redirectUrl?) {
|
||||
if (viewPgcFromUri(redirectUrl)) {
|
||||
return;
|
||||
}
|
||||
@@ -434,7 +434,7 @@ class PageUtils {
|
||||
archive.jumpUrl.http2https,
|
||||
false,
|
||||
)
|
||||
case String redirectUrl) {
|
||||
case final redirectUrl?) {
|
||||
if (viewPgcFromUri(redirectUrl)) {
|
||||
return;
|
||||
}
|
||||
@@ -479,6 +479,18 @@ class PageUtils {
|
||||
toLiveRoom(liveRcmd.roomId);
|
||||
break;
|
||||
|
||||
case 'DYNAMIC_TYPE_SUBSCRIPTION_NEW':
|
||||
LivePlayInfo live = item
|
||||
.modules
|
||||
.moduleDynamic!
|
||||
.major!
|
||||
.subscriptionNew!
|
||||
.liveRcmd!
|
||||
.content!
|
||||
.livePlayInfo!;
|
||||
toLiveRoom(live.roomId);
|
||||
break;
|
||||
|
||||
/// 合集查看
|
||||
case 'DYNAMIC_TYPE_UGC_SEASON':
|
||||
DynamicArchiveModel ugcSeason =
|
||||
@@ -508,7 +520,7 @@ class PageUtils {
|
||||
|
||||
case 'DYNAMIC_TYPE_MEDIALIST':
|
||||
if (item.modules.moduleDynamic?.major?.medialist
|
||||
case Medialist medialist) {
|
||||
case final medialist?) {
|
||||
final String? url = medialist.jumpUrl;
|
||||
if (url != null) {
|
||||
if (url.contains('medialist/detail/ml')) {
|
||||
|
||||
Reference in New Issue
Block a user