Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-12-03 12:41:09 +08:00
parent 001b746f65
commit 9c8e5b53e7
4 changed files with 111 additions and 81 deletions

View File

@@ -1,3 +1,5 @@
import 'dart:math';
import 'package:PiliPlus/common/skeleton/msg_feed_top.dart'; import 'package:PiliPlus/common/skeleton/msg_feed_top.dart';
import 'package:PiliPlus/common/widgets/button/more_btn.dart'; import 'package:PiliPlus/common/widgets/button/more_btn.dart';
import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart'; import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart';
@@ -46,37 +48,29 @@ class _FollowChildPageState extends State<FollowChildPage>
super.build(context); super.build(context);
final colorScheme = ColorScheme.of(context); final colorScheme = ColorScheme.of(context);
final padding = MediaQuery.viewPaddingOf(context); final padding = MediaQuery.viewPaddingOf(context);
Widget sliver = Obx( Widget child = Padding(
() => _buildBody(_followController.loadingState.value), padding: EdgeInsets.only(left: padding.left, right: padding.right),
); child: refreshIndicator(
if (_followController.loadSameFollow) { onRefresh: _followController.onRefresh,
sliver = SliverMainAxisGroup( child: CustomScrollView(
slivers: [ controller: _followController.scrollController,
Obx( physics: const AlwaysScrollableScrollPhysics(),
() => _buildSameFollowing( slivers: [
colorScheme, if (_followController.loadSameFollow)
_followController.sameState.value, Obx(
() => _buildSameFollowing(
colorScheme,
_followController.sameState.value,
),
),
SliverPadding(
padding: EdgeInsets.only(bottom: padding.bottom + 100),
sliver: Obx(
() => _buildBody(_followController.loadingState.value),
),
), ),
), ],
sliver, ),
],
);
}
Widget child = refreshIndicator(
onRefresh: _followController.onRefresh,
child: CustomScrollView(
controller: _followController.scrollController,
physics: const AlwaysScrollableScrollPhysics(),
slivers: [
SliverPadding(
padding: EdgeInsets.only(
left: padding.left,
right: padding.right,
bottom: padding.bottom + 100,
),
sliver: sliver,
),
],
), ),
); );
if (widget.onSelect != null || if (widget.onSelect != null ||
@@ -176,7 +170,7 @@ class _FollowChildPageState extends State<FollowChildPage>
), ),
), ),
SliverList.builder( SliverList.builder(
itemCount: response!.length, itemCount: min(3, response!.length),
itemBuilder: (_, index) => itemBuilder: (_, index) =>
FollowItem(item: response[index]), FollowItem(item: response[index]),
), ),

View File

@@ -24,6 +24,18 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart' hide ContextExtensionss; import 'package:get/get.dart' hide ContextExtensionss;
enum _UserInfoType {
fan('粉丝', .centerLeft),
follow('关注', .center),
like('获赞', .centerRight),
;
final String title;
final Alignment alignment;
const _UserInfoType(this.title, this.alignment);
}
class UserInfoCard extends StatelessWidget { class UserInfoCard extends StatelessWidget {
const UserInfoCard({ const UserInfoCard({
super.key, super.key,
@@ -59,29 +71,49 @@ class UserInfoCard extends StatelessWidget {
Widget _countWidget({ Widget _countWidget({
required ColorScheme colorScheme, required ColorScheme colorScheme,
required String title, required _UserInfoType type,
required int? count,
required VoidCallback onTap,
}) { }) {
int? count;
VoidCallback? onTap;
switch (type) {
case _UserInfoType.fan:
count = card.fans;
onTap = () => FansPage.toFansPage(
mid: card.mid,
name: card.name,
);
case _UserInfoType.follow:
count = card.attention;
onTap = () => FollowPage.toFollowPage(
mid: card.mid,
name: card.name,
);
case _UserInfoType.like:
count = card.likes?.likeNum;
}
return GestureDetector( return GestureDetector(
behavior: .opaque,
onTap: onTap, onTap: onTap,
behavior: HitTestBehavior.opaque, child: Align(
child: Column( alignment: type.alignment,
mainAxisSize: MainAxisSize.min, widthFactor: 1.0,
children: [ child: Column(
Text( mainAxisSize: .min,
NumUtils.numFormat(count), children: [
style: const TextStyle(fontSize: 14), Text(
), NumUtils.numFormat(count),
Text( style: const TextStyle(fontSize: 14),
title,
style: TextStyle(
height: 1.2,
fontSize: 12,
color: colorScheme.outline,
), ),
), Text(
], type.title,
style: TextStyle(
height: 1.2,
fontSize: 12,
color: colorScheme.outline,
),
),
],
),
), ),
); );
} }
@@ -320,33 +352,25 @@ class UserInfoCard extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Row( Row(
children: List.generate( children: _UserInfoType.values
5, .map(
(index) => index.isEven (e) => Expanded(
? _countWidget( child: _countWidget(
colorScheme: colorScheme, colorScheme: colorScheme,
title: ['粉丝', '关注', '获赞'][index ~/ 2], type: e,
count: index == 0
? card.fans
: index == 2
? card.attention
: card.likes?.likeNum,
onTap: () {
if (index == 0) {
FansPage.toFansPage(mid: card.mid, name: card.name);
} else if (index == 2) {
FollowPage.toFollowPage(mid: card.mid, name: card.name);
}
},
)
: const Expanded(
child: SizedBox(
height: 15,
width: 1,
child: VerticalDivider(),
),
), ),
), ),
)
.expand((child) sync* {
yield const SizedBox(
height: 15,
width: 1,
child: VerticalDivider(),
);
yield child;
})
.skip(1)
.toList(),
), ),
const SizedBox(height: 5), const SizedBox(height: 5),
Row( Row(

View File

@@ -1,3 +1,4 @@
import 'package:PiliPlus/common/widgets/scroll_physics.dart' show ReloadMixin;
import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/http/video.dart'; import 'package:PiliPlus/http/video.dart';
import 'package:PiliPlus/models/model_hot_video_item.dart'; import 'package:PiliPlus/models/model_hot_video_item.dart';
@@ -9,7 +10,8 @@ import 'package:PiliPlus/utils/extension.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
class PopularSeriesController class PopularSeriesController
extends CommonListController<PopularSeriesOneData, HotVideoItemModel> { extends CommonListController<PopularSeriesOneData, HotVideoItemModel>
with ReloadMixin {
late int number; late int number;
final Rx<PopularSeriesConfig?> config = Rx<PopularSeriesConfig?>(null); final Rx<PopularSeriesConfig?> config = Rx<PopularSeriesConfig?>(null);
@@ -54,6 +56,7 @@ class PopularSeriesController
if (seriesList.isNullOrEmpty) { if (seriesList.isNullOrEmpty) {
return _getSeriesList(); return _getSeriesList();
} }
reload = true;
return super.onReload(); return super.onReload();
} }
} }

View File

@@ -1,7 +1,9 @@
import 'dart:math'; import 'dart:math';
import 'package:PiliPlus/common/widgets/custom_sliver_persistent_header_delegate.dart';
import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart'; import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart';
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
import 'package:PiliPlus/common/widgets/scroll_physics.dart';
import 'package:PiliPlus/common/widgets/video_card/video_card_h.dart'; import 'package:PiliPlus/common/widgets/video_card/video_card_h.dart';
import 'package:PiliPlus/common/widgets/view_sliver_safe_area.dart'; import 'package:PiliPlus/common/widgets/view_sliver_safe_area.dart';
import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/loading_state.dart';
@@ -40,7 +42,7 @@ class _PopularSeriesPageState extends State<PopularSeriesPage> with GridMixin {
body: refreshIndicator( body: refreshIndicator(
onRefresh: _controller.onRefresh, onRefresh: _controller.onRefresh,
child: CustomScrollView( child: CustomScrollView(
physics: const AlwaysScrollableScrollPhysics(), physics: ReloadScrollPhysics(controller: _controller),
slivers: [ slivers: [
ViewSliverSafeArea( ViewSliverSafeArea(
sliver: Obx(() => _buildBody(_controller.loadingState.value)), sliver: Obx(() => _buildBody(_controller.loadingState.value)),
@@ -205,10 +207,17 @@ class _PopularSeriesPageState extends State<PopularSeriesPage> with GridMixin {
], ],
); );
} }
return SliverToBoxAdapter( final height = MediaQuery.textScalerOf(context).scale(27);
child: Padding( return SliverPersistentHeader(
padding: const EdgeInsets.only(left: 14, bottom: 7), floating: true,
child: child, delegate: CustomSliverPersistentHeaderDelegate(
extent: height,
child: Container(
height: height,
padding: const EdgeInsets.only(left: 14, bottom: 7),
child: child,
),
bgColor: colorScheme.surface,
), ),
); );
} }