Merge branch 'main' into design
This commit is contained in:
@ -5,7 +5,7 @@ import 'package:pilipala/common/constants.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/models/video_detail_res.dart';
|
||||
import 'package:pilipala/utils/utils.dart';
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
import 'package:scrollview_observer/scrollview_observer.dart';
|
||||
import '../models/common/video_episode_type.dart';
|
||||
import 'widgets/badge.dart';
|
||||
import 'widgets/stat/danmu.dart';
|
||||
@ -83,7 +83,8 @@ class PagesBottomSheet extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _PagesBottomSheetState extends State<PagesBottomSheet> {
|
||||
final ItemScrollController _itemScrollController = ItemScrollController();
|
||||
final ScrollController _listScrollController = ScrollController();
|
||||
late ListObserverController _listObserverController;
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
late int currentIndex;
|
||||
|
||||
@ -92,10 +93,17 @@ class _PagesBottomSheetState extends State<PagesBottomSheet> {
|
||||
super.initState();
|
||||
currentIndex =
|
||||
widget.episodes.indexWhere((dynamic e) => e.cid == widget.currentCid);
|
||||
_listObserverController =
|
||||
ListObserverController(controller: _listScrollController);
|
||||
if (widget.dataType == VideoEpidoesType.videoEpisode) {
|
||||
_listObserverController.initialIndexModel = ObserverIndexPositionModel(
|
||||
index: currentIndex,
|
||||
isFixedHeight: true,
|
||||
);
|
||||
}
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (widget.dataType == VideoEpidoesType.videoEpisode) {
|
||||
_itemScrollController.jumpTo(index: currentIndex);
|
||||
} else {
|
||||
if (widget.dataType != VideoEpidoesType.videoEpisode) {
|
||||
double itemHeight = (widget.isFullScreen
|
||||
? 400
|
||||
: Get.size.width - 3 * StyleString.safeSpace) /
|
||||
@ -118,6 +126,12 @@ class _PagesBottomSheetState extends State<PagesBottomSheet> {
|
||||
return '选集';
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_listObserverController.controller?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StatefulBuilder(
|
||||
@ -136,27 +150,30 @@ class _PagesBottomSheetState extends State<PagesBottomSheet> {
|
||||
Expanded(
|
||||
child: Material(
|
||||
child: widget.dataType == VideoEpidoesType.videoEpisode
|
||||
? ScrollablePositionedList.builder(
|
||||
itemScrollController: _itemScrollController,
|
||||
itemCount: widget.episodes.length + 1,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
bool isLastItem = index == widget.episodes.length;
|
||||
bool isCurrentIndex = currentIndex == index;
|
||||
return isLastItem
|
||||
? SizedBox(
|
||||
height:
|
||||
MediaQuery.of(context).padding.bottom +
|
||||
20,
|
||||
)
|
||||
: EpisodeListItem(
|
||||
episode: widget.episodes[index],
|
||||
index: index,
|
||||
isCurrentIndex: isCurrentIndex,
|
||||
dataType: widget.dataType,
|
||||
changeFucCall: widget.changeFucCall,
|
||||
isFullScreen: widget.isFullScreen,
|
||||
);
|
||||
},
|
||||
? ListViewObserver(
|
||||
controller: _listObserverController,
|
||||
child: ListView.builder(
|
||||
controller: _listScrollController,
|
||||
itemCount: widget.episodes.length + 1,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
bool isLastItem = index == widget.episodes.length;
|
||||
bool isCurrentIndex = currentIndex == index;
|
||||
return isLastItem
|
||||
? SizedBox(
|
||||
height:
|
||||
MediaQuery.of(context).padding.bottom +
|
||||
20,
|
||||
)
|
||||
: EpisodeListItem(
|
||||
episode: widget.episodes[index],
|
||||
index: index,
|
||||
isCurrentIndex: isCurrentIndex,
|
||||
dataType: widget.dataType,
|
||||
changeFucCall: widget.changeFucCall,
|
||||
isFullScreen: widget.isFullScreen,
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
|
@ -359,8 +359,8 @@ class VideoHttp {
|
||||
'plat': 1,
|
||||
'oid': oid,
|
||||
'type': type.index,
|
||||
// 'root': root == null || root == 0 ? '' : root,
|
||||
// 'parent': parent == null || parent == 0 ? '' : parent,
|
||||
'root': root == null || root == 0 ? '' : root,
|
||||
'parent': parent == null || parent == 0 ? '' : parent,
|
||||
'message': message,
|
||||
'at_name_to_mid': {},
|
||||
if (pictures != null) 'pictures': jsonEncode(pictures),
|
||||
@ -379,8 +379,8 @@ class VideoHttp {
|
||||
},
|
||||
data: formData,
|
||||
);
|
||||
log(res.toString());
|
||||
if (res.data['code'] == 0) {
|
||||
log(res.toString());
|
||||
return {'status': true, 'data': res.data['data']};
|
||||
} else {
|
||||
return {'status': false, 'data': [], 'msg': res.data['message']};
|
||||
|
@ -7,7 +7,6 @@ import 'package:hive/hive.dart';
|
||||
import 'package:pilipala/models/bangumi/info.dart';
|
||||
import 'package:pilipala/pages/video/detail/index.dart';
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
import '../../../common/pages_bottom_sheet.dart';
|
||||
import '../../../models/common/video_episode_type.dart';
|
||||
import '../introduction/controller.dart';
|
||||
@ -44,7 +43,6 @@ class _BangumiPanelState extends State<BangumiPanel> {
|
||||
late int cid;
|
||||
String heroTag = Get.arguments['heroTag'];
|
||||
late final VideoDetailController videoDetailCtr;
|
||||
final ItemScrollController itemScrollController = ItemScrollController();
|
||||
late PersistentBottomSheetController? _bottomSheetController;
|
||||
|
||||
@override
|
||||
|
@ -26,6 +26,7 @@ class DynamicDetailController extends GetxController {
|
||||
RxString sortTypeLabel = ReplySortType.time.labels.obs;
|
||||
Box setting = GStrorage.setting;
|
||||
RxInt replyReqCode = 200.obs;
|
||||
bool isEnd = false;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
@ -48,7 +49,7 @@ class DynamicDetailController extends GetxController {
|
||||
}
|
||||
|
||||
Future queryReplyList({reqType = 'init'}) async {
|
||||
if (isLoadingMore) {
|
||||
if (isLoadingMore || noMore.value == '没有更多了' || isEnd) {
|
||||
return;
|
||||
}
|
||||
isLoadingMore = true;
|
||||
@ -56,10 +57,6 @@ class DynamicDetailController extends GetxController {
|
||||
nextOffset = '';
|
||||
noMore.value = '';
|
||||
}
|
||||
if (noMore.value == '没有更多了') {
|
||||
isLoadingMore = false;
|
||||
return;
|
||||
}
|
||||
var res = await ReplyHttp.replyList(
|
||||
oid: oid!,
|
||||
nextOffset: nextOffset,
|
||||
@ -68,15 +65,14 @@ class DynamicDetailController extends GetxController {
|
||||
);
|
||||
if (res['status']) {
|
||||
List<ReplyItemModel> replies = res['data'].replies;
|
||||
isEnd = res['data'].cursor.isEnd ?? false;
|
||||
acount.value = res['data'].cursor.allCount;
|
||||
nextOffset = res['data'].cursor.paginationReply.nextOffset ?? "";
|
||||
if (replies.isNotEmpty) {
|
||||
noMore.value = '加载中...';
|
||||
if (res['data'].cursor.isEnd == true) {
|
||||
noMore.value = '没有更多了';
|
||||
}
|
||||
noMore.value = isEnd ? '没有更多了' : '加载中...';
|
||||
} else {
|
||||
noMore.value = nextOffset == "" ? '还没有评论' : '没有更多了';
|
||||
noMore.value =
|
||||
replyList.isEmpty && nextOffset == "" ? '还没有评论' : '没有更多了';
|
||||
}
|
||||
if (reqType == 'init') {
|
||||
// 添加置顶回复
|
||||
@ -122,4 +118,9 @@ class DynamicDetailController extends GetxController {
|
||||
var res = await HtmlHttp.reqHtml(id, 'opus');
|
||||
oid = res['commentId'];
|
||||
}
|
||||
|
||||
// 上拉加载
|
||||
Future onLoad() async {
|
||||
queryReplyList(reqType: 'onLoad');
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
if (scrollController.position.pixels >=
|
||||
scrollController.position.maxScrollExtent - 300) {
|
||||
EasyThrottle.throttle('replylist', const Duration(seconds: 2), () {
|
||||
_dynamicDetailController.queryReplyList(reqType: 'onLoad');
|
||||
_dynamicDetailController.onLoad();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ class VideoReplyController extends GetxController {
|
||||
|
||||
Box setting = GStrorage.setting;
|
||||
RxInt replyReqCode = 200.obs;
|
||||
bool isEnd = false;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
@ -49,8 +50,8 @@ class VideoReplyController extends GetxController {
|
||||
sortTypeLabel.value = _sortType.labels;
|
||||
}
|
||||
|
||||
Future queryReplyList({type = 'init'}) async {
|
||||
if (isLoadingMore) {
|
||||
Future<dynamic> queryReplyList({type = 'init'}) async {
|
||||
if (isLoadingMore || noMore.value == '没有更多了' || isEnd) {
|
||||
return;
|
||||
}
|
||||
isLoadingMore = true;
|
||||
@ -58,10 +59,6 @@ class VideoReplyController extends GetxController {
|
||||
nextOffset = '';
|
||||
noMore.value = '';
|
||||
}
|
||||
if (noMore.value == '没有更多了') {
|
||||
isLoadingMore = false;
|
||||
return;
|
||||
}
|
||||
final res = await ReplyHttp.replyList(
|
||||
oid: aid!,
|
||||
nextOffset: nextOffset,
|
||||
@ -70,14 +67,13 @@ class VideoReplyController extends GetxController {
|
||||
);
|
||||
if (res['status']) {
|
||||
final List<ReplyItemModel> replies = res['data'].replies;
|
||||
isEnd = res['data'].cursor.isEnd ?? false;
|
||||
nextOffset = res['data'].cursor.paginationReply.nextOffset ?? "";
|
||||
if (replies.isNotEmpty) {
|
||||
noMore.value = '加载中...';
|
||||
if (res['data'].cursor.isEnd == true) {
|
||||
noMore.value = '没有更多了';
|
||||
}
|
||||
noMore.value = isEnd ? '没有更多了' : '加载中...';
|
||||
} else {
|
||||
noMore.value = nextOffset == "" ? '还没有评论' : '没有更多了';
|
||||
noMore.value =
|
||||
replyList.isEmpty && nextOffset == "" ? '还没有评论' : '没有更多了';
|
||||
}
|
||||
if (type == 'init') {
|
||||
// 添加置顶回复
|
||||
@ -105,6 +101,14 @@ class VideoReplyController extends GetxController {
|
||||
queryReplyList(type: 'onLoad');
|
||||
}
|
||||
|
||||
// 下拉刷新
|
||||
Future onRefresh() async {
|
||||
nextOffset = "";
|
||||
noMore.value = '';
|
||||
isEnd = false;
|
||||
queryReplyList(type: 'init');
|
||||
}
|
||||
|
||||
// 排序搜索评论
|
||||
queryBySort() {
|
||||
EasyThrottle.throttle('queryBySort', const Duration(seconds: 1), () {
|
||||
@ -118,6 +122,8 @@ class VideoReplyController extends GetxController {
|
||||
break;
|
||||
default:
|
||||
}
|
||||
isLoadingMore = false;
|
||||
isEnd = false;
|
||||
sortTypeTitle.value = _sortType.titles;
|
||||
sortTypeLabel.value = _sortType.labels;
|
||||
nextOffset = "";
|
||||
|
@ -137,7 +137,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
||||
super.build(context);
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
return await _videoReplyController.queryReplyList(type: 'init');
|
||||
return await _videoReplyController.onRefresh();
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
@ -312,13 +312,13 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
||||
);
|
||||
},
|
||||
).then(
|
||||
(value) => {
|
||||
(value) {
|
||||
// 完成评论,数据添加
|
||||
if (value != null && value['data'] != null)
|
||||
{
|
||||
_videoReplyController.replyList
|
||||
.add(value['data'])
|
||||
}
|
||||
if (value != null && value['data'] != null) {
|
||||
_videoReplyController.replyList
|
||||
.add(value['data']);
|
||||
_videoReplyController.replyList.refresh();
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
|
@ -16,7 +16,7 @@ class VideoReplyReplyController extends GetxController {
|
||||
ReplyItemModel? rootReply;
|
||||
RxList<ReplyItemModel> replyList = <ReplyItemModel>[].obs;
|
||||
// 当前页
|
||||
int currentPage = 0;
|
||||
int currentPage = 1;
|
||||
bool isLoadingMore = false;
|
||||
RxString noMore = ''.obs;
|
||||
// 当前回复的回复
|
||||
@ -25,12 +25,12 @@ class VideoReplyReplyController extends GetxController {
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
currentPage = 0;
|
||||
currentPage = 1;
|
||||
}
|
||||
|
||||
Future queryReplyList({type = 'init', currentReply}) async {
|
||||
if (type == 'init') {
|
||||
currentPage = 0;
|
||||
currentPage = 1;
|
||||
}
|
||||
if (isLoadingMore) {
|
||||
return;
|
||||
@ -39,7 +39,7 @@ class VideoReplyReplyController extends GetxController {
|
||||
final res = await ReplyHttp.replyReplyList(
|
||||
oid: aid!,
|
||||
root: rpid!,
|
||||
pageNum: currentPage + 1,
|
||||
pageNum: currentPage,
|
||||
type: (replyType ?? ReplyType.video).index,
|
||||
);
|
||||
if (res['status']) {
|
||||
@ -50,12 +50,12 @@ class VideoReplyReplyController extends GetxController {
|
||||
if (replies.length == res['data'].page.count) {
|
||||
noMore.value = '没有更多了';
|
||||
}
|
||||
currentPage++;
|
||||
// currentPage++;
|
||||
} else {
|
||||
// 未登录状态replies可能返回null
|
||||
noMore.value = currentPage == 0 ? '还没有评论' : '没有更多了';
|
||||
noMore.value = currentPage == 1 ? '还没有评论' : '没有更多了';
|
||||
}
|
||||
if (type == 'init') {
|
||||
if (type == 'init' && currentPage == 1) {
|
||||
replyList.value = replies;
|
||||
} else {
|
||||
// 每次回复之后,翻页请求有且只有相同的一条回复数据
|
||||
@ -79,6 +79,7 @@ class VideoReplyReplyController extends GetxController {
|
||||
replyList.insert(0, currentReply);
|
||||
}
|
||||
}
|
||||
currentPage += 1;
|
||||
isLoadingMore = false;
|
||||
return res;
|
||||
}
|
||||
|
@ -183,8 +183,7 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
|
||||
Expanded(
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
setState(() {});
|
||||
_videoReplyReplyController.currentPage = 0;
|
||||
_videoReplyReplyController.currentPage = 1;
|
||||
return await _videoReplyReplyController.queryReplyList(
|
||||
currentReply: widget.currentReply,
|
||||
);
|
||||
|
@ -212,9 +212,9 @@ class PiliSchame {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> biliScheme(Uri value) async {
|
||||
final String host = value.host;
|
||||
final String path = value.path;
|
||||
static Future<void> biliScheme(SchemeEntity value) async {
|
||||
final String host = value.host!;
|
||||
final String path = value.path!;
|
||||
switch (host) {
|
||||
case 'root':
|
||||
Navigator.popUntil(
|
||||
|
@ -1434,14 +1434,14 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.1.3"
|
||||
scrollable_positioned_list:
|
||||
scrollview_observer:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: scrollable_positioned_list
|
||||
sha256: "1b54d5f1329a1e263269abc9e2543d90806131aa14fe7c6062a8054d57249287"
|
||||
name: scrollview_observer
|
||||
sha256: fa408bcfd41e19da841eb53fc471f8f952d5ef818b854d2505c4bb3f0c876381
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.3.8"
|
||||
version: "1.22.0"
|
||||
sentry:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -134,7 +134,7 @@ dependencies:
|
||||
# 极验
|
||||
gt3_flutter_plugin: ^0.1.0
|
||||
uuid: ^3.0.7
|
||||
scrollable_positioned_list: ^0.3.8
|
||||
scrollview_observer: ^1.22.0
|
||||
catcher_2: ^1.2.6
|
||||
logger: ^2.3.0
|
||||
path: ^1.9.0
|
||||
|
Reference in New Issue
Block a user