mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
mod: article: show list
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -1,3 +1,7 @@
|
|||||||
|
import 'package:PiliPlus/models/dynamics/opus_detail/module.dart';
|
||||||
|
import 'package:PiliPlus/models/dynamics/opus_detail/module_content.dart';
|
||||||
|
import 'package:PiliPlus/models/dynamics/opus_detail/paragraph.dart';
|
||||||
|
|
||||||
import 'author.dart';
|
import 'author.dart';
|
||||||
import 'category.dart';
|
import 'category.dart';
|
||||||
import 'media.dart';
|
import 'media.dart';
|
||||||
@@ -44,6 +48,7 @@ class ArticleData {
|
|||||||
int? versionId;
|
int? versionId;
|
||||||
String? dynIdStr;
|
String? dynIdStr;
|
||||||
int? totalArtNum;
|
int? totalArtNum;
|
||||||
|
List<OpusModule>? modules;
|
||||||
|
|
||||||
ArticleData({
|
ArticleData({
|
||||||
this.id,
|
this.id,
|
||||||
@@ -85,61 +90,77 @@ class ArticleData {
|
|||||||
this.versionId,
|
this.versionId,
|
||||||
this.dynIdStr,
|
this.dynIdStr,
|
||||||
this.totalArtNum,
|
this.totalArtNum,
|
||||||
|
this.modules,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory ArticleData.fromJson(Map<String, dynamic> json) => ArticleData(
|
factory ArticleData.fromJson(Map<String, dynamic> json) {
|
||||||
id: json['id'] as int?,
|
final data = ArticleData(
|
||||||
category: json['category'] == null
|
id: json['id'] as int?,
|
||||||
? null
|
category: json['category'] == null
|
||||||
: Category.fromJson(json['category'] as Map<String, dynamic>),
|
? null
|
||||||
categories: (json['categories'] as List<dynamic>?)
|
: Category.fromJson(json['category'] as Map<String, dynamic>),
|
||||||
?.map((e) => Category.fromJson(e as Map<String, dynamic>))
|
categories: (json['categories'] as List<dynamic>?)
|
||||||
.toList(),
|
?.map((e) => Category.fromJson(e as Map<String, dynamic>))
|
||||||
title: json['title'] as String?,
|
.toList(),
|
||||||
summary: json['summary'] as String?,
|
title: json['title'] as String?,
|
||||||
bannerUrl: json['banner_url'] as String?,
|
summary: json['summary'] as String?,
|
||||||
templateId: json['template_id'] as int?,
|
bannerUrl: json['banner_url'] as String?,
|
||||||
state: json['state'] as int?,
|
templateId: json['template_id'] as int?,
|
||||||
author: json['author'] == null
|
state: json['state'] as int?,
|
||||||
? null
|
author: json['author'] == null
|
||||||
: Author.fromJson(json['author'] as Map<String, dynamic>),
|
? null
|
||||||
reprint: json['reprint'] as int?,
|
: Author.fromJson(json['author'] as Map<String, dynamic>),
|
||||||
imageUrls: json['image_urls'],
|
reprint: json['reprint'] as int?,
|
||||||
publishTime: json['publish_time'] as int?,
|
imageUrls: json['image_urls'],
|
||||||
ctime: json['ctime'] as int?,
|
publishTime: json['publish_time'] as int?,
|
||||||
mtime: json['mtime'] as int?,
|
ctime: json['ctime'] as int?,
|
||||||
stats: json['stats'] == null
|
mtime: json['mtime'] as int?,
|
||||||
? null
|
stats: json['stats'] == null
|
||||||
: Stats.fromJson(json['stats'] as Map<String, dynamic>),
|
? null
|
||||||
tags: (json['tags'] as List<dynamic>?)
|
: Stats.fromJson(json['stats'] as Map<String, dynamic>),
|
||||||
?.map((e) => Tag.fromJson(e as Map<String, dynamic>))
|
tags: (json['tags'] as List<dynamic>?)
|
||||||
.toList(),
|
?.map((e) => Tag.fromJson(e as Map<String, dynamic>))
|
||||||
words: json['words'] as int?,
|
.toList(),
|
||||||
originImageUrls: json['origin_image_urls'],
|
words: json['words'] as int?,
|
||||||
list: json['list'] as dynamic,
|
originImageUrls: json['origin_image_urls'],
|
||||||
isLike: json['is_like'] as bool?,
|
list: json['list'] as dynamic,
|
||||||
media: json['media'] == null
|
isLike: json['is_like'] as bool?,
|
||||||
? null
|
media: json['media'] == null
|
||||||
: Media.fromJson(json['media'] as Map<String, dynamic>),
|
? null
|
||||||
applyTime: json['apply_time'] as String?,
|
: Media.fromJson(json['media'] as Map<String, dynamic>),
|
||||||
checkTime: json['check_time'] as String?,
|
applyTime: json['apply_time'] as String?,
|
||||||
original: json['original'] as int?,
|
checkTime: json['check_time'] as String?,
|
||||||
actId: json['act_id'] as int?,
|
original: json['original'] as int?,
|
||||||
dispute: json['dispute'] as dynamic,
|
actId: json['act_id'] as int?,
|
||||||
authenMark: json['authenMark'] as dynamic,
|
dispute: json['dispute'] as dynamic,
|
||||||
coverAvid: json['cover_avid'] as int?,
|
authenMark: json['authenMark'] as dynamic,
|
||||||
topVideoInfo: json['top_video_info'] as dynamic,
|
coverAvid: json['cover_avid'] as int?,
|
||||||
type: json['type'] as int?,
|
topVideoInfo: json['top_video_info'] as dynamic,
|
||||||
checkState: json['check_state'] as int?,
|
type: json['type'] as int?,
|
||||||
originTemplateId: json['origin_template_id'] as int?,
|
checkState: json['check_state'] as int?,
|
||||||
privatePub: json['private_pub'] as int?,
|
originTemplateId: json['origin_template_id'] as int?,
|
||||||
contentPicList: json['content_pic_list'] as dynamic,
|
privatePub: json['private_pub'] as int?,
|
||||||
content: json['content'] as String?,
|
contentPicList: json['content_pic_list'] as dynamic,
|
||||||
keywords: json['keywords'] as String?,
|
content: json['content'] as String?,
|
||||||
versionId: json['version_id'] as int?,
|
keywords: json['keywords'] as String?,
|
||||||
dynIdStr: json['dyn_id_str'] as String?,
|
versionId: json['version_id'] as int?,
|
||||||
totalArtNum: json['total_art_num'] as int?,
|
dynIdStr: json['dyn_id_str'] as String?,
|
||||||
);
|
totalArtNum: json['total_art_num'] as int?,
|
||||||
|
);
|
||||||
|
if (data.type == 3 && json['opus'] != null) {
|
||||||
|
data.modules = [
|
||||||
|
OpusModule(
|
||||||
|
moduleType: 'MODULE_TYPE_CONTENT',
|
||||||
|
moduleContent: ModuleContent(
|
||||||
|
paragraphs: (json['opus']?['content']?['paragraphs'] as List?)
|
||||||
|
?.map((e) => Paragraph.fromJson(e))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
'id': id,
|
'id': id,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'node.dart';
|
||||||
import 'pic.dart';
|
import 'pic.dart';
|
||||||
import 'text.dart';
|
import 'text.dart';
|
||||||
|
|
||||||
@@ -9,6 +10,7 @@ class Paragraph {
|
|||||||
Line? line;
|
Line? line;
|
||||||
LinkCard? linkCard;
|
LinkCard? linkCard;
|
||||||
Code? code;
|
Code? code;
|
||||||
|
L1st? list;
|
||||||
|
|
||||||
Paragraph({
|
Paragraph({
|
||||||
this.align,
|
this.align,
|
||||||
@@ -18,6 +20,7 @@ class Paragraph {
|
|||||||
this.line,
|
this.line,
|
||||||
this.linkCard,
|
this.linkCard,
|
||||||
this.code,
|
this.code,
|
||||||
|
this.list,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory Paragraph.fromJson(Map<String, dynamic> json) => Paragraph(
|
factory Paragraph.fromJson(Map<String, dynamic> json) => Paragraph(
|
||||||
@@ -34,6 +37,7 @@ class Paragraph {
|
|||||||
? null
|
? null
|
||||||
: LinkCard.fromJson(json['link_card']),
|
: LinkCard.fromJson(json['link_card']),
|
||||||
code: json['code'] == null ? null : Code.fromJson(json['code']),
|
code: json['code'] == null ? null : Code.fromJson(json['code']),
|
||||||
|
list: json['list'] == null ? null : L1st.fromJson(json['list']),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
@@ -44,6 +48,28 @@ class Paragraph {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class L1st {
|
||||||
|
List<Item>? items;
|
||||||
|
int? style;
|
||||||
|
|
||||||
|
L1st.fromJson(Map<String, dynamic> json) {
|
||||||
|
items = (json['items'] as List?)?.map((e) => Item.fromJson(e)).toList();
|
||||||
|
style = json['style'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Item {
|
||||||
|
int? level;
|
||||||
|
int? order;
|
||||||
|
List<Node>? nodes;
|
||||||
|
|
||||||
|
Item.fromJson(Map<String, dynamic> json) {
|
||||||
|
level = json['level'];
|
||||||
|
order = json['order'];
|
||||||
|
nodes = (json['nodes'] as List?)?.map((e) => Node.fromJson(e)).toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Code {
|
class Code {
|
||||||
String? content;
|
String? content;
|
||||||
String? lang;
|
String? lang;
|
||||||
|
|||||||
@@ -5,8 +5,15 @@ class Word {
|
|||||||
double? fontSize;
|
double? fontSize;
|
||||||
Style? style;
|
Style? style;
|
||||||
String? words;
|
String? words;
|
||||||
|
String? fontLevel;
|
||||||
|
|
||||||
Word({this.color, this.fontSize, this.style, this.words});
|
Word({
|
||||||
|
this.color,
|
||||||
|
this.fontSize,
|
||||||
|
this.style,
|
||||||
|
this.words,
|
||||||
|
this.fontLevel,
|
||||||
|
});
|
||||||
|
|
||||||
factory Word.fromJson(Map<String, dynamic> json) => Word(
|
factory Word.fromJson(Map<String, dynamic> json) => Word(
|
||||||
color: json['color'] == null
|
color: json['color'] == null
|
||||||
@@ -17,6 +24,7 @@ class Word {
|
|||||||
? null
|
? null
|
||||||
: Style.fromJson(json['style'] as Map<String, dynamic>),
|
: Style.fromJson(json['style'] as Map<String, dynamic>),
|
||||||
words: json['words'] as String?,
|
words: json['words'] as String?,
|
||||||
|
fontLevel: json['font_level'] as String?,
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
@@ -24,5 +32,6 @@ class Word {
|
|||||||
'font_size': fontSize,
|
'font_size': fontSize,
|
||||||
'style': style?.toJson(),
|
'style': style?.toJson(),
|
||||||
'words': words,
|
'words': words,
|
||||||
|
'font_level': fontLevel,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ class _ArticlePageState extends State<ArticlePage>
|
|||||||
() {
|
() {
|
||||||
if (_articleCtr.isLoaded.value) {
|
if (_articleCtr.isLoaded.value) {
|
||||||
if (_articleCtr.type == 'read') {
|
if (_articleCtr.type == 'read') {
|
||||||
var res = parser.parse(_articleCtr.articleData.content);
|
late final res = parser.parse(_articleCtr.articleData.content);
|
||||||
return SliverMainAxisGroup(
|
return SliverMainAxisGroup(
|
||||||
slivers: [
|
slivers: [
|
||||||
if (_articleCtr.articleData.title != null)
|
if (_articleCtr.articleData.title != null)
|
||||||
@@ -403,19 +403,26 @@ class _ArticlePageState extends State<ArticlePage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SliverList.separated(
|
_articleCtr.articleData.modules?.isNotEmpty == true
|
||||||
itemCount: res.body!.children.length,
|
? opusContent(
|
||||||
itemBuilder: (context, index) {
|
context: context,
|
||||||
return htmlRender(
|
modules: _articleCtr.articleData.modules,
|
||||||
context: context,
|
callback: _getImageCallback,
|
||||||
element: res.body!.children[index],
|
maxWidth: maxWidth,
|
||||||
maxWidth: maxWidth,
|
)
|
||||||
callback: _getImageCallback,
|
: SliverList.separated(
|
||||||
);
|
itemCount: res.body!.children.length,
|
||||||
},
|
itemBuilder: (context, index) {
|
||||||
separatorBuilder: (context, index) =>
|
return htmlRender(
|
||||||
const SizedBox(height: 10),
|
context: context,
|
||||||
),
|
element: res.body!.children[index],
|
||||||
|
maxWidth: maxWidth,
|
||||||
|
callback: _getImageCallback,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
separatorBuilder: (context, index) =>
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import 'package:cached_network_image/cached_network_image.dart';
|
|||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||||
import 'package:re_highlight/languages/all.dart';
|
import 'package:re_highlight/languages/all.dart';
|
||||||
import 'package:re_highlight/re_highlight.dart';
|
import 'package:re_highlight/re_highlight.dart';
|
||||||
import 'package:re_highlight/styles/all.dart';
|
import 'package:re_highlight/styles/all.dart';
|
||||||
@@ -95,7 +96,7 @@ Widget opusContent({
|
|||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final element = item.moduleContent!.paragraphs![index];
|
final element = item.moduleContent!.paragraphs![index];
|
||||||
|
|
||||||
if ((element.paraType == 1 || element.paraType == 4)) {
|
if (element.paraType == 1 || element.paraType == 4) {
|
||||||
return SelectableText.rich(
|
return SelectableText.rich(
|
||||||
textAlign: element.align == 1 ? TextAlign.center : null,
|
textAlign: element.align == 1 ? TextAlign.center : null,
|
||||||
TextSpan(
|
TextSpan(
|
||||||
@@ -117,7 +118,7 @@ Widget opusContent({
|
|||||||
),
|
),
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap = () {
|
..onTap = () {
|
||||||
if (item.rich!.jumpUrl != null) {
|
if (item.rich?.jumpUrl != null) {
|
||||||
PiliScheme.routePushFromUrl(
|
PiliScheme.routePushFromUrl(
|
||||||
item.rich!.jumpUrl!);
|
item.rich!.jumpUrl!);
|
||||||
}
|
}
|
||||||
@@ -182,6 +183,53 @@ Widget opusContent({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (element.paraType == 5) {
|
||||||
|
return SelectableText.rich(
|
||||||
|
TextSpan(
|
||||||
|
children:
|
||||||
|
element.list?.items?.asMap().entries.map((entry) {
|
||||||
|
return TextSpan(
|
||||||
|
children: [
|
||||||
|
WidgetSpan(
|
||||||
|
child: Icon(MdiIcons.circleMedium),
|
||||||
|
alignment: PlaceholderAlignment.middle,
|
||||||
|
),
|
||||||
|
...entry.value.nodes!.map((item) {
|
||||||
|
return TextSpan(
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: item.word?.words,
|
||||||
|
style: TextStyle(
|
||||||
|
decoration:
|
||||||
|
item.word?.style?.strikethrough ==
|
||||||
|
true
|
||||||
|
? TextDecoration.lineThrough
|
||||||
|
: null,
|
||||||
|
fontStyle:
|
||||||
|
item.word?.style?.italic == true
|
||||||
|
? FontStyle.italic
|
||||||
|
: null,
|
||||||
|
fontWeight: item.word?.style?.bold == true
|
||||||
|
? FontWeight.bold
|
||||||
|
: null,
|
||||||
|
color: item.word?.color != null
|
||||||
|
? Color(item.word!.color!)
|
||||||
|
: null,
|
||||||
|
fontSize: item.word?.fontSize,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
if (entry.key < element.list!.items!.length - 1)
|
||||||
|
TextSpan(text: '\n'),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (element.paraType == 6) {
|
if (element.paraType == 6) {
|
||||||
if (element.linkCard?.card?.ugc != null) {
|
if (element.linkCard?.card?.ugc != null) {
|
||||||
return Material(
|
return Material(
|
||||||
@@ -263,6 +311,33 @@ Widget opusContent({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (element.text?.nodes?.isNotEmpty == true) {
|
||||||
|
return SelectableText.rich(
|
||||||
|
textAlign: element.align == 1 ? TextAlign.center : null,
|
||||||
|
TextSpan(
|
||||||
|
children: element.text!.nodes!.map<TextSpan>((item) {
|
||||||
|
return TextSpan(
|
||||||
|
text: item.word?.words,
|
||||||
|
style: TextStyle(
|
||||||
|
decoration: item.word?.style?.strikethrough == true
|
||||||
|
? TextDecoration.lineThrough
|
||||||
|
: null,
|
||||||
|
fontStyle: item.word?.style?.italic == true
|
||||||
|
? FontStyle.italic
|
||||||
|
: null,
|
||||||
|
fontWeight: item.word?.style?.bold == true
|
||||||
|
? FontWeight.bold
|
||||||
|
: null,
|
||||||
|
color: item.word?.color != null
|
||||||
|
? Color(item.word!.color!)
|
||||||
|
: null,
|
||||||
|
fontSize: item.word?.fontSize,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
},
|
},
|
||||||
separatorBuilder: (BuildContext context, int index) =>
|
separatorBuilder: (BuildContext context, int index) =>
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ Widget _itemWidget(BuildContext context, dynamic item) {
|
|||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
Image.asset(
|
Image.asset(
|
||||||
'assets/images/lv/lv${item['author']['level']}.png',
|
'assets/images/lv/lv${item['author']['level']}.png',
|
||||||
height: 19,
|
height: 11,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user