mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-07-06 09:10:15 +08:00
feat: cross row select (#2437)
* feat(wip): cross row select * fix patch Signed-off-by: dom <githubaccount56556@proton.me> * update Signed-off-by: dom <githubaccount56556@proton.me> --------- Co-authored-by: dom <githubaccount56556@proton.me>
This commit is contained in:
committed by
GitHub
parent
204715266f
commit
b540647222
@@ -74,21 +74,27 @@ class _ArticlePageState extends CommonDynPageState<ArticlePage> {
|
||||
if (isPortrait) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: padding),
|
||||
child: CustomScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
slivers: [
|
||||
_buildContent(
|
||||
maxWidth - this.padding.horizontal - 2 * padding - 24,
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Divider(
|
||||
thickness: 8,
|
||||
color: theme.dividerColor.withValues(alpha: 0.05),
|
||||
child: SelectionArea(
|
||||
child: CustomScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
slivers: [
|
||||
_buildContent(
|
||||
maxWidth - this.padding.horizontal - 2 * padding - 24,
|
||||
),
|
||||
),
|
||||
buildReplyHeader(),
|
||||
Obx(() => replyList(controller.loadingState.value)),
|
||||
],
|
||||
SelectionContainer.disabled(
|
||||
child: SliverToBoxAdapter(
|
||||
child: Divider(
|
||||
thickness: 8,
|
||||
color: theme.dividerColor.withValues(alpha: 0.05),
|
||||
),
|
||||
),
|
||||
),
|
||||
SelectionContainer.disabled(child: buildReplyHeader()),
|
||||
SelectionContainer.disabled(
|
||||
child: Obx(() => replyList(controller.loadingState.value)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -101,21 +107,25 @@ class _ArticlePageState extends CommonDynPageState<ArticlePage> {
|
||||
children: [
|
||||
Expanded(
|
||||
flex: flex,
|
||||
child: CustomScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
left: padding,
|
||||
bottom: this.padding.bottom + 100,
|
||||
child: SelectionArea(
|
||||
child: CustomScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
left: padding,
|
||||
bottom: this.padding.bottom + 100,
|
||||
),
|
||||
sliver: _buildContent(
|
||||
(maxWidth - this.padding.horizontal) *
|
||||
flex /
|
||||
(flex + flex1) -
|
||||
padding -
|
||||
32,
|
||||
),
|
||||
),
|
||||
sliver: _buildContent(
|
||||
(maxWidth - this.padding.horizontal) * flex / (flex + flex1) -
|
||||
padding -
|
||||
32,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
VerticalDivider(
|
||||
@@ -151,7 +161,7 @@ class _ArticlePageState extends CommonDynPageState<ArticlePage> {
|
||||
sliver: Obx(
|
||||
() {
|
||||
if (controller.isLoaded.value) {
|
||||
late Widget content;
|
||||
final Widget content;
|
||||
if (controller.opus != null) {
|
||||
// if (kDebugMode) debugPrint('json page');
|
||||
content = OpusContent(
|
||||
@@ -159,9 +169,9 @@ class _ArticlePageState extends CommonDynPageState<ArticlePage> {
|
||||
images: controller.images,
|
||||
maxWidth: maxWidth,
|
||||
);
|
||||
} else if (controller.opusData?.modules.moduleBlocked != null) {
|
||||
} else if (controller.opusData?.modules.moduleBlocked
|
||||
case final moduleBlocked?) {
|
||||
// if (kDebugMode) debugPrint('moduleBlocked');
|
||||
final moduleBlocked = controller.opusData!.modules.moduleBlocked!;
|
||||
content = SliverToBoxAdapter(
|
||||
child: moduleBlockedItem(context, theme, moduleBlocked),
|
||||
);
|
||||
@@ -201,128 +211,119 @@ class _ArticlePageState extends CommonDynPageState<ArticlePage> {
|
||||
content = const SliverToBoxAdapter(child: Text('NULL'));
|
||||
}
|
||||
|
||||
int? pubTime =
|
||||
final pubTime =
|
||||
controller.opusData?.modules.moduleAuthor?.pubTs ??
|
||||
controller.articleData?.publishTime;
|
||||
return SliverMainAxisGroup(
|
||||
slivers: [
|
||||
if (controller.type != 'read' &&
|
||||
controller
|
||||
.opusData
|
||||
?.modules
|
||||
.moduleTop
|
||||
?.display
|
||||
?.album
|
||||
?.pics
|
||||
?.isNotEmpty ==
|
||||
true)
|
||||
SliverToBoxAdapter(
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
final pics = controller
|
||||
.opusData!
|
||||
.modules
|
||||
.moduleTop!
|
||||
.display!
|
||||
.album!
|
||||
.pics!;
|
||||
final length = pics.length;
|
||||
final first = pics.first;
|
||||
double height;
|
||||
if (first.height != null && first.width != null) {
|
||||
final ratio = first.height! / first.width!;
|
||||
height = min(maxWidth * ratio, maxHeight * 0.55);
|
||||
} else {
|
||||
height = maxHeight * 0.55;
|
||||
}
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Container(
|
||||
height: height,
|
||||
width: maxWidth,
|
||||
margin: const EdgeInsets.only(bottom: 10),
|
||||
child: PageView.builder(
|
||||
physics: clampingScrollPhysics,
|
||||
onPageChanged: (value) =>
|
||||
controller.topIndex.value = value,
|
||||
itemCount: length,
|
||||
itemBuilder: (context, index) {
|
||||
final pic = pics[index];
|
||||
int? memCacheWidth, memCacheHeight;
|
||||
if (pic.isLongPic ?? false) {
|
||||
memCacheWidth = maxWidth.cacheSize(context);
|
||||
} else if (pic.width != null &&
|
||||
pic.height != null) {
|
||||
if (pic.width! > pic.height!) {
|
||||
if (controller.type != 'read')
|
||||
if (controller.opusData?.modules.moduleTop?.display?.album?.pics
|
||||
case final pics? when pics.isNotEmpty)
|
||||
SliverToBoxAdapter(
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
final length = pics.length;
|
||||
final first = pics.first;
|
||||
double height;
|
||||
if (first.height != null && first.width != null) {
|
||||
final ratio = first.height! / first.width!;
|
||||
height = min(maxWidth * ratio, maxHeight * 0.55);
|
||||
} else {
|
||||
height = maxHeight * 0.55;
|
||||
}
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Container(
|
||||
height: height,
|
||||
width: maxWidth,
|
||||
margin: const EdgeInsets.only(bottom: 10),
|
||||
child: PageView.builder(
|
||||
physics: clampingScrollPhysics,
|
||||
onPageChanged: (value) =>
|
||||
controller.topIndex.value = value,
|
||||
itemCount: length,
|
||||
itemBuilder: (context, index) {
|
||||
final pic = pics[index];
|
||||
int? memCacheWidth, memCacheHeight;
|
||||
if (pic.isLongPic ?? false) {
|
||||
memCacheWidth = maxWidth.cacheSize(context);
|
||||
} else {
|
||||
memCacheHeight = height.cacheSize(context);
|
||||
} else if (pic.width != null &&
|
||||
pic.height != null) {
|
||||
if (pic.width! > pic.height!) {
|
||||
memCacheWidth = maxWidth.cacheSize(
|
||||
context,
|
||||
);
|
||||
} else {
|
||||
memCacheHeight = height.cacheSize(
|
||||
context,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () => PageUtils.imageView(
|
||||
quality: 60,
|
||||
imgList: pics
|
||||
.map((e) => SourceModel(url: e.url!))
|
||||
.toList(),
|
||||
initialPage: index,
|
||||
),
|
||||
child: Hero(
|
||||
tag: pic.url!,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
CachedNetworkImage(
|
||||
height: height,
|
||||
width: maxWidth,
|
||||
memCacheWidth: memCacheWidth,
|
||||
memCacheHeight: memCacheHeight,
|
||||
fit: pic.isLongPic == true
|
||||
? BoxFit.cover
|
||||
: null,
|
||||
imageUrl: ImageUtils.thumbnailUrl(
|
||||
pic.url,
|
||||
60,
|
||||
),
|
||||
fadeInDuration: const Duration(
|
||||
milliseconds: 120,
|
||||
),
|
||||
fadeOutDuration: const Duration(
|
||||
milliseconds: 120,
|
||||
),
|
||||
placeholder: (_, _) =>
|
||||
const SizedBox.shrink(),
|
||||
),
|
||||
if (pic.isLongPic == true)
|
||||
const PBadge(
|
||||
right: 12,
|
||||
bottom: 12,
|
||||
text: '长图',
|
||||
type: .primary,
|
||||
),
|
||||
],
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () => PageUtils.imageView(
|
||||
quality: 60,
|
||||
imgList: pics
|
||||
.map((e) => SourceModel(url: e.url!))
|
||||
.toList(),
|
||||
initialPage: index,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Hero(
|
||||
tag: pic.url!,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
CachedNetworkImage(
|
||||
height: height,
|
||||
width: maxWidth,
|
||||
memCacheWidth: memCacheWidth,
|
||||
memCacheHeight: memCacheHeight,
|
||||
fit: pic.isLongPic == true
|
||||
? BoxFit.cover
|
||||
: null,
|
||||
imageUrl: ImageUtils.thumbnailUrl(
|
||||
pic.url,
|
||||
60,
|
||||
),
|
||||
fadeInDuration: const Duration(
|
||||
milliseconds: 120,
|
||||
),
|
||||
fadeOutDuration: const Duration(
|
||||
milliseconds: 120,
|
||||
),
|
||||
placeholder: (_, _) =>
|
||||
const SizedBox.shrink(),
|
||||
),
|
||||
if (pic.isLongPic == true)
|
||||
const PBadge(
|
||||
right: 12,
|
||||
bottom: 12,
|
||||
text: '长图',
|
||||
type: .primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => PBadge(
|
||||
top: 12,
|
||||
right: 12,
|
||||
type: PBadgeType.gray,
|
||||
text: '${controller.topIndex.value + 1}/$length',
|
||||
Obx(
|
||||
() => PBadge(
|
||||
top: 12,
|
||||
right: 12,
|
||||
type: PBadgeType.gray,
|
||||
text:
|
||||
'${controller.topIndex.value + 1}/$length',
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
if (controller.summary.title != null)
|
||||
SliverToBoxWithVisibilityAdapter(
|
||||
onVisibilityChanged: (bool visible) =>
|
||||
@@ -342,39 +343,41 @@ class _ArticlePageState extends CommonDynPageState<ArticlePage> {
|
||||
onTap: () => Get.toNamed(
|
||||
'/member?mid=${controller.summary.author?.mid}',
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
width: 40,
|
||||
height: 40,
|
||||
type: ImageType.avatar,
|
||||
src: controller.summary.author?.face,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Flexible(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
controller.summary.author?.name ?? '',
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
theme.textTheme.titleSmall!.fontSize,
|
||||
),
|
||||
),
|
||||
if (pubTime != null)
|
||||
child: SelectionContainer.disabled(
|
||||
child: Row(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
width: 40,
|
||||
height: 40,
|
||||
type: ImageType.avatar,
|
||||
src: controller.summary.author?.face,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Flexible(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
DateFormatUtils.format(pubTime),
|
||||
controller.summary.author?.name ?? '',
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize:
|
||||
theme.textTheme.labelSmall!.fontSize,
|
||||
theme.textTheme.titleSmall!.fontSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
if (pubTime != null)
|
||||
Text(
|
||||
DateFormatUtils.format(pubTime),
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize:
|
||||
theme.textTheme.labelSmall!.fontSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -382,9 +385,11 @@ class _ArticlePageState extends CommonDynPageState<ArticlePage> {
|
||||
if (controller.type != 'read' &&
|
||||
controller.opusData?.modules.moduleCollection != null)
|
||||
SliverToBoxAdapter(
|
||||
child: opusCollection(
|
||||
theme,
|
||||
controller.opusData!.modules.moduleCollection!,
|
||||
child: SelectionContainer.disabled(
|
||||
child: opusCollection(
|
||||
theme,
|
||||
controller.opusData!.modules.moduleCollection!,
|
||||
),
|
||||
),
|
||||
),
|
||||
content,
|
||||
|
||||
Reference in New Issue
Block a user