mod: 动态页面视频&专栏跳转

This commit is contained in:
guozhigq
2023-06-27 16:14:04 +08:00
parent bc8be693a8
commit eca48bc77e
7 changed files with 208 additions and 45 deletions

View File

@ -1,6 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:pilipala/http/dynamics.dart';
import 'package:pilipala/http/search.dart';
import 'package:pilipala/models/dynamics/result.dart';
import 'package:pilipala/utils/utils.dart';
class DynamicsController extends GetxController {
int page = 1;
@ -8,6 +12,7 @@ class DynamicsController extends GetxController {
RxList<DynamicItemModel>? dynamicsList = [DynamicItemModel()].obs;
RxString dynamicsType = 'all'.obs;
RxString dynamicsTypeLabel = '全部'.obs;
final ScrollController scrollController = ScrollController();
Future queryFollowDynamic({type = 'init'}) async {
var res = await DynamicsHttp.followDynamic(
@ -27,16 +32,22 @@ class DynamicsController extends GetxController {
return res;
}
onSelectType(value, label) {
onSelectType(value, label) async {
dynamicsType.value = value;
dynamicsTypeLabel.value = label;
queryFollowDynamic();
await queryFollowDynamic();
scrollController.animateTo(0,
duration: const Duration(milliseconds: 500), curve: Curves.easeInOut);
}
pushDetail(item, floor) {
pushDetail(item, floor, {action = 'all'}) async {
if (action == 'comment') {
Get.toNamed('/dynamicDetail',
arguments: {'item': item, 'floor': floor, 'action': action});
return false;
}
switch (item!.type) {
case 'DYNAMIC_TYPE_FORWARD':
print('转发的动态');
Get.toNamed('/dynamicDetail',
arguments: {'item': item, 'floor': floor});
break;
@ -45,10 +56,25 @@ class DynamicsController extends GetxController {
arguments: {'item': item, 'floor': floor});
break;
case 'DYNAMIC_TYPE_AV':
print('视频');
String bvid = item.modules.moduleDynamic.major.archive.bvid;
int aid = item.modules.moduleDynamic.major.archive.aid;
String cover = item.modules.moduleDynamic.major.archive.cover;
String heroTag = Utils.makeHeroTag(aid);
try {
int cid = await SearchHttp.ab2c(bvid: bvid);
Get.toNamed('/video?bvid=$bvid&cid=$cid',
arguments: {'pic': cover, 'heroTag': heroTag});
} catch (err) {
SmartDialog.showToast(err.toString());
}
break;
case 'DYNAMIC_TYPE_ARTICLE':
print('文章/专栏');
String title = item.modules.moduleDynamic.major.opus.title;
String url = item.modules.moduleDynamic.major.opus.jumpUrl;
Get.toNamed(
'/webview',
parameters: {'url': 'https:$url', 'type': 'note', 'pageTitle': title},
);
break;
case 'DYNAMIC_TYPE_PGC':
print('番剧');

View File

@ -24,6 +24,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage> {
late StreamController<bool> titleStreamC; // appBar title
final ScrollController scrollController = ScrollController();
bool _visibleTitle = false;
String? action;
@override
void initState() {
@ -37,11 +38,16 @@ class _DynamicDetailPageState extends State<DynamicDetailPage> {
oid = Get.arguments['item'].modules.moduleDynamic.major.draw.id;
type = 11;
}
action =
Get.arguments.containsKey('action') ? Get.arguments['action'] : null;
_dynamicDetailController = Get.put(DynamicDetailController(oid, type));
_futureBuilderFuture = _dynamicDetailController!.queryReplyList();
titleStreamC = StreamController<bool>();
scrollController.addListener(_listen);
if (action == 'comment') {
_visibleTitle = true;
titleStreamC.add(true);
}
}
void _listen() async {
@ -90,12 +96,13 @@ class _DynamicDetailPageState extends State<DynamicDetailPage> {
child: CustomScrollView(
controller: scrollController,
slivers: [
SliverToBoxAdapter(
child: DynamicPanel(
item: _dynamicDetailController!.item,
source: 'detail',
if (action != 'comment')
SliverToBoxAdapter(
child: DynamicPanel(
item: _dynamicDetailController!.item,
source: 'detail',
),
),
),
SliverPersistentHeader(
delegate: _MySliverPersistentHeaderDelegate(
child: Container(

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:pilipala/common/skeleton/dynamic_card.dart';
import 'package:pilipala/common/widgets/http_error.dart';
import 'package:pilipala/models/common/dynamics_type.dart';
import 'package:pilipala/models/dynamics/result.dart';
@ -16,9 +17,9 @@ class DynamicsPage extends StatefulWidget {
class _DynamicsPageState extends State<DynamicsPage>
with AutomaticKeepAliveClientMixin {
DynamicsController _dynamicsController = Get.put(DynamicsController());
final DynamicsController _dynamicsController = Get.put(DynamicsController());
Future? _futureBuilderFuture;
final ScrollController scrollController = ScrollController();
// final ScrollController scrollController = ScrollController();
bool _isLoadingMore = false;
@override
bool get wantKeepAlive => true;
@ -28,10 +29,11 @@ class _DynamicsPageState extends State<DynamicsPage>
super.initState();
_futureBuilderFuture = _dynamicsController.queryFollowDynamic();
scrollController.addListener(
_dynamicsController.scrollController.addListener(
() async {
if (scrollController.position.pixels >=
scrollController.position.maxScrollExtent - 200) {
if (_dynamicsController.scrollController.position.pixels >=
_dynamicsController.scrollController.position.maxScrollExtent -
200) {
if (!_isLoadingMore) {
_isLoadingMore = true;
await _dynamicsController.queryFollowDynamic(type: 'onLoad');
@ -92,7 +94,7 @@ class _DynamicsPageState extends State<DynamicsPage>
List<DynamicItemModel> list = _dynamicsController.dynamicsList!;
return Obx(
() => ListView.builder(
controller: scrollController,
controller: _dynamicsController.scrollController,
shrinkWrap: true,
itemCount: list.length,
itemBuilder: (BuildContext context, index) {
@ -105,19 +107,18 @@ class _DynamicsPageState extends State<DynamicsPage>
slivers: [
HttpError(
errMsg: data['msg'],
fn: () => setState(() {}),
fn: () => _dynamicsController.queryFollowDynamic(),
)
],
);
}
} else {
// 骨架屏
// return SliverList(
// delegate: SliverChildBuilderDelegate((context, index) {
// return const VideoCardHSkeleton();
// }, childCount: 10),
// );
return Text('加载中');
return ListView.builder(
physics: const NeverScrollableScrollPhysics(),
itemCount: 5,
itemBuilder: ((context, index) => const DynamicCardSkeleton()),
);
}
},
),

View File

@ -26,7 +26,8 @@ Widget action(item, context) {
label: Text(stat.forward!.count ?? '转发'),
),
TextButton.icon(
onPressed: () => _dynamicsController.pushDetail(item, 1),
onPressed: () =>
_dynamicsController.pushDetail(item, 1, action: 'comment'),
icon: const Icon(
FontAwesomeIcons.comment,
size: 16,

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:pilipala/common/constants.dart';
import 'package:pilipala/common/widgets/badge.dart';
import 'package:pilipala/common/widgets/network_img_layer.dart';
Widget picWidget(item, context) {
@ -14,7 +15,6 @@ Widget picWidget(item, context) {
}
int len = pictures.length;
List picList = [];
List<Widget> list = [];
for (var i = 0; i < len; i++) {
picList.add(pictures[i].src ?? pictures[i].url);
@ -42,7 +42,8 @@ Widget picWidget(item, context) {
return LayoutBuilder(
builder: (context, BoxConstraints box) {
double maxWidth = box.maxWidth;
double aspectRatio = 1.1;
double aspectRatio = 1.0;
double origAspectRatio = 0.0;
double crossCount = len == 1
? 1
: len < 3
@ -51,20 +52,19 @@ Widget picWidget(item, context) {
double height = 0.0;
if (len == 1) {
aspectRatio = pictures.first.width / pictures.first.height;
origAspectRatio =
aspectRatio = pictures.first.width / pictures.first.height;
if (aspectRatio < 0.4) {
aspectRatio = 0.4;
}
height = pictures.first.height * maxWidth / pictures.first.width;
if (pictures.first.width != 1920) {
if (origAspectRatio < 0.5 || pictures.first.width < 1920) {
crossCount = 2;
height = maxWidth / 2 / aspectRatio;
}
} else {
aspectRatio = 1;
height = maxWidth /
crossCount *
(len % crossCount == 0
? len ~/ crossCount
: len ~/ crossCount + 1) +
6;
height = maxWidth / crossCount * ((len / crossCount).ceil()) + 6;
}
return Container(
padding: const EdgeInsets.only(top: 4),
@ -73,14 +73,20 @@ Widget picWidget(item, context) {
),
clipBehavior: Clip.hardEdge,
height: height,
child: GridView.count(
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
crossAxisCount: crossCount.toInt(),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
childAspectRatio: aspectRatio,
children: list,
child: Stack(
children: [
GridView.count(
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
crossAxisCount: crossCount.toInt(),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
childAspectRatio: aspectRatio,
children: list,
),
if (len == 1 && origAspectRatio < 0.4)
pBadge('长图', context, null, null, 6.0, 6.0, type: 'gray')
],
),
);
},