dyn uplist

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-10-05 11:47:22 +08:00
parent 203a997583
commit 52373dc540
7 changed files with 122 additions and 56 deletions

View File

@@ -214,6 +214,8 @@ class Api {
// https://api.bilibili.com/x/polymer/web-dynamic/v1/portal
static const String followUp = '/x/polymer/web-dynamic/v1/portal';
static const String dynUplist = '/x/polymer/web-dynamic/v1/uplist';
// 关注的up动态
// https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all
// https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all?timezone_offset=-480&type=video&page=1&features=itemOpusStyle

View File

@@ -68,7 +68,13 @@ class DynamicsHttp {
}
static Future<LoadingState<FollowUpModel>> followUp() async {
var res = await Request().get(Api.followUp);
var res = await Request().get(
Api.followUp,
queryParameters: {
'up_list_more': 1,
'web_location': 333.1365,
},
);
if (res.data['code'] == 0) {
return Success(FollowUpModel.fromJson(res.data['data']));
} else {
@@ -76,6 +82,22 @@ class DynamicsHttp {
}
}
static Future<LoadingState<DynUpList>> dynUpList(String? offset) async {
var res = await Request().get(
Api.dynUplist,
queryParameters: {
'offset': offset,
'platform': 'web',
'web_location': 333.1365,
},
);
if (res.data['code'] == 0) {
return Success(DynUpList.fromJson(res.data['data']));
} else {
return Error(res.data['message']);
}
}
// 动态点赞
// static Future likeDynamic({
// required String? dynamicId,

View File

@@ -6,16 +6,34 @@ class FollowUpModel {
LiveUsers? liveUsers;
late List<UpItem> upList;
bool? hasMore;
String? offset;
FollowUpModel.fromJson(Map<String, dynamic> json) {
liveUsers = json['live_users'] != null
? LiveUsers.fromJson(json['live_users'])
: null;
upList =
(json['up_list'] as List?)
(json['up_list']?['items'] as List?)
?.map<UpItem>((e) => UpItem.fromJson(e))
.toList() ??
<UpItem>[];
hasMore = json['up_list']?['has_more'];
offset = json['up_list']?['offset'];
}
}
class DynUpList {
List<UpItem>? upList;
bool? hasMore;
String? offset;
DynUpList.fromJson(Map<String, dynamic> json) {
upList = (json['items'] as List?)
?.map<UpItem>((e) => UpItem.fromJson(e))
.toList();
hasMore = json['has_more'];
offset = json['offset'];
}
}

View File

@@ -55,27 +55,45 @@ class DynamicsController extends GetxController
@override
void onInit() {
super.onInit();
if (_showAllUp) {
scrollController.addListener(listener);
}
queryFollowUp();
}
void listener() {
if (scrollController.position.pixels >=
scrollController.position.maxScrollExtent - 300) {
void onLoadMoreUp() {
if (_showAllUp) {
queryAllUp();
} else {
queryUpList();
}
}
Future<void> queryAllUp() async {
if (isQuerying) return;
Future<void> queryUpList() async {
if (isQuerying || _upEnd) return;
isQuerying = true;
if (_upEnd) {
isQuerying = false;
return;
final res = await DynamicsHttp.dynUpList(upState.value.data.offset);
if (res.isSuccess) {
final data = res.data;
if (data.hasMore == false || data.offset.isNullOrEmpty) {
_upEnd = true;
}
final upData = upState.value.data
..hasMore = data.hasMore
..offset = data.offset;
final list = data.upList;
if (list != null && list.isNotEmpty) {
upData.upList.addAll(list);
upState.refresh();
}
}
isQuerying = false;
}
Future<void> queryAllUp() async {
if (isQuerying || _upEnd) return;
isQuerying = true;
final res = await FollowHttp.followings(
vmid: accountService.mid,
pn: _upPage,
@@ -110,6 +128,10 @@ class DynamicsController extends GetxController
return;
}
// reset
_upEnd = false;
if (_showAllUp) _upPage = 1;
final res = await Future.wait([
DynamicsHttp.followUp(),
if (_showAllUp)
@@ -138,6 +160,11 @@ class DynamicsController extends GetxController
_cacheUpList = List<UpItem>.from(list);
list.addAll(list1..removeWhere(list.contains));
}
if (!_showAllUp) {
if (data.hasMore == false || data.offset.isNullOrEmpty) {
_upEnd = true;
}
}
upState.value = Success(data);
} else {
upState.value = const Error(null);
@@ -201,9 +228,7 @@ class DynamicsController extends GetxController
@override
void onClose() {
tabController.dispose();
scrollController
..removeListener(listener)
..dispose();
scrollController.dispose();
super.onClose();
}
}

View File

@@ -61,7 +61,16 @@ class _DynamicsPageState extends State<DynamicsPage>
child: SizedBox(
width: isTop ? null : 64,
height: isTop ? 76 : null,
child: Obx(() => _buildUpPanel(_dynamicsController.upState.value)),
child: NotificationListener<ScrollEndNotification>(
onNotification: (notification) {
final metrics = notification.metrics;
if (metrics.pixels >= metrics.maxScrollExtent - 300) {
_dynamicsController.onLoadMoreUp();
}
return false;
},
child: Obx(() => _buildUpPanel(_dynamicsController.upState.value)),
),
),
);
}

View File

@@ -26,43 +26,22 @@ class _FavSortPageState extends State<FavSortPage> {
);
List<String> sort = <String>[];
final ScrollController _scrollController = ScrollController();
void listener() {
void onLoadMore() {
if (_favDetailController.isEnd) {
return;
}
if (_scrollController.position.pixels >=
_scrollController.position.maxScrollExtent - 200) {
_favDetailController.onLoadMore().whenComplete(() {
try {
if (_favDetailController.loadingState.value.isSuccess) {
List<FavDetailItemModel> list =
_favDetailController.loadingState.value.data!;
sortList.addAll(list.sublist(sortList.length));
if (mounted) {
setState(() {});
}
_favDetailController.onLoadMore().whenComplete(() {
try {
if (_favDetailController.loadingState.value.isSuccess) {
List<FavDetailItemModel> list =
_favDetailController.loadingState.value.data!;
sortList.addAll(list.sublist(sortList.length));
if (mounted) {
setState(() {});
}
} catch (_) {}
});
}
}
@override
void initState() {
super.initState();
if (!_favDetailController.isEnd) {
_scrollController.addListener(listener);
}
}
@override
void dispose() {
_scrollController
..removeListener(listener)
..dispose();
super.dispose();
}
} catch (_) {}
});
}
@override
@@ -119,9 +98,8 @@ class _FavSortPageState extends State<FavSortPage> {
}
Widget get _buildBody {
return ReorderableListView.builder(
final child = ReorderableListView.builder(
key: _key,
scrollController: _scrollController,
onReorder: onReorder,
physics: const AlwaysScrollableScrollPhysics(),
padding:
@@ -137,5 +115,18 @@ class _FavSortPageState extends State<FavSortPage> {
);
},
);
if (!_favDetailController.isEnd) {
return NotificationListener<ScrollEndNotification>(
onNotification: (notification) {
final metrics = notification.metrics;
if (metrics.pixels >= metrics.maxScrollExtent - 300) {
onLoadMore();
}
return false;
},
child: child,
);
}
return child;
}
}

View File

@@ -278,11 +278,10 @@ class LiveRoomController extends GetxController {
}
void listener() {
if (scrollController.position.userScrollDirection ==
ScrollDirection.forward) {
final userScrollDirection = scrollController.position.userScrollDirection;
if (userScrollDirection == ScrollDirection.forward) {
disableAutoScroll.value = true;
} else if (scrollController.position.userScrollDirection ==
ScrollDirection.reverse) {
} else if (userScrollDirection == ScrollDirection.reverse) {
final pos = scrollController.position;
if (pos.maxScrollExtent - pos.pixels <= 100) {
disableAutoScroll.value = false;