mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
refa: query data (#659)
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -27,7 +27,7 @@ abstract mixin class ScrollOrRefreshMixin {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class CommonController extends GetxController
|
||||
abstract class CommonController<R, T> extends GetxController
|
||||
with ScrollOrRefreshMixin {
|
||||
@override
|
||||
final ScrollController scrollController = ScrollController();
|
||||
@@ -35,13 +35,13 @@ abstract class CommonController extends GetxController
|
||||
late int currentPage = 1;
|
||||
bool isLoading = false;
|
||||
late bool isEnd = false;
|
||||
Rx<LoadingState> loadingState = LoadingState.loading().obs;
|
||||
Rx<LoadingState> get loadingState;
|
||||
|
||||
Future<LoadingState> customGetData();
|
||||
Future<LoadingState<R>> customGetData();
|
||||
|
||||
void handleListResponse(List dataList) {}
|
||||
|
||||
bool customHandleResponse(Success response) {
|
||||
bool customHandleResponse(bool isRefresh, Success<R> response) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -49,27 +49,36 @@ abstract class CommonController extends GetxController
|
||||
return false;
|
||||
}
|
||||
|
||||
List<T>? getDataList(R response) {
|
||||
return response as List<T>?;
|
||||
}
|
||||
|
||||
void checkIsEnd(int length) {}
|
||||
|
||||
Future queryData([bool isRefresh = true]) async {
|
||||
if (isLoading || (isRefresh.not && isEnd)) return;
|
||||
isLoading = true;
|
||||
LoadingState response = await customGetData();
|
||||
if (response is Success) {
|
||||
if (!customHandleResponse(response)) {
|
||||
List? dataList = response.response;
|
||||
LoadingState<R> response = await customGetData();
|
||||
if (response is Success<R>) {
|
||||
if (!customHandleResponse(isRefresh, response)) {
|
||||
List<T>? dataList = getDataList(response.response);
|
||||
if (dataList.isNullOrEmpty) {
|
||||
isEnd = true;
|
||||
if (isRefresh) {
|
||||
loadingState.value = response;
|
||||
loadingState.value = LoadingState<List<T>?>.success(dataList);
|
||||
}
|
||||
isLoading = false;
|
||||
return;
|
||||
}
|
||||
handleListResponse(dataList!);
|
||||
if (isRefresh) {
|
||||
loadingState.value = LoadingState.success(dataList);
|
||||
checkIsEnd(dataList.length);
|
||||
loadingState.value = LoadingState<List<T>?>.success(dataList);
|
||||
} else if (loadingState.value is Success) {
|
||||
List currentList = (loadingState.value as Success).response ?? [];
|
||||
currentList.addAll(dataList);
|
||||
loadingState.value = LoadingState.success(currentList);
|
||||
List<T> list = (loadingState.value as Success).response;
|
||||
list.addAll(dataList);
|
||||
checkIsEnd(list.length);
|
||||
loadingState.refresh();
|
||||
}
|
||||
}
|
||||
currentPage++;
|
||||
|
||||
8
lib/pages/common/common_data_controller.dart
Normal file
8
lib/pages/common/common_data_controller.dart
Normal file
@@ -0,0 +1,8 @@
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/pages/common/common_controller.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
abstract class CommonDataController<R, T> extends CommonController<R, T> {
|
||||
@override
|
||||
Rx<LoadingState<T>> loadingState = LoadingState<T>.loading().obs;
|
||||
}
|
||||
9
lib/pages/common/common_list_controller.dart
Normal file
9
lib/pages/common/common_list_controller.dart
Normal file
@@ -0,0 +1,9 @@
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/pages/common/common_controller.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
abstract class CommonListController<R, T> extends CommonController<R, T> {
|
||||
@override
|
||||
Rx<LoadingState<List<T>?>> loadingState =
|
||||
LoadingState<List<T>?>.loading().obs;
|
||||
}
|
||||
@@ -1,32 +1,43 @@
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/pages/common/common_controller.dart';
|
||||
import 'package:PiliPlus/pages/common/common_list_controller.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
|
||||
abstract class MultiSelectController extends CommonController {
|
||||
mixin class MultiSelectData {
|
||||
bool? checked;
|
||||
}
|
||||
|
||||
abstract class MultiSelectController<R, T extends MultiSelectData>
|
||||
extends CommonListController<R, T> {
|
||||
late final RxBool enableMultiSelect = false.obs;
|
||||
late final RxInt checkedCount = 0.obs;
|
||||
late final allSelected = false.obs;
|
||||
|
||||
onSelect(int index) {
|
||||
List list = (loadingState.value as Success).response;
|
||||
list[index].checked = !(list[index]?.checked ?? false);
|
||||
void onSelect(int index, [bool disableSelect = true]) {
|
||||
List<T> list = (loadingState.value as Success).response;
|
||||
list[index].checked = !(list[index].checked ?? false);
|
||||
checkedCount.value = list.where((item) => item.checked == true).length;
|
||||
loadingState.value = LoadingState.success(list);
|
||||
if (checkedCount.value == 0) {
|
||||
enableMultiSelect.value = false;
|
||||
loadingState.refresh();
|
||||
if (disableSelect) {
|
||||
if (checkedCount.value == 0) {
|
||||
enableMultiSelect.value = false;
|
||||
}
|
||||
} else {
|
||||
allSelected.value = checkedCount.value == list.length;
|
||||
}
|
||||
}
|
||||
|
||||
void handleSelect([bool checked = false]) {
|
||||
void handleSelect([bool checked = false, bool disableSelect = true]) {
|
||||
if (loadingState.value is Success) {
|
||||
List list = (loadingState.value as Success).response;
|
||||
if (list.isNotEmpty) {
|
||||
loadingState.value = LoadingState.success(
|
||||
list.map((item) => item..checked = checked).toList());
|
||||
List<T>? list = (loadingState.value as Success).response;
|
||||
if (list?.isNotEmpty == true) {
|
||||
for (T item in list!) {
|
||||
item.checked = checked;
|
||||
}
|
||||
loadingState.refresh();
|
||||
checkedCount.value = checked ? list.length : 0;
|
||||
}
|
||||
}
|
||||
if (checked.not) {
|
||||
if (disableSelect && !checked) {
|
||||
enableMultiSelect.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/http/reply.dart';
|
||||
import 'package:PiliPlus/models/common/reply_type.dart';
|
||||
import 'package:PiliPlus/models/video/reply/data.dart';
|
||||
import 'package:PiliPlus/pages/common/common_controller.dart';
|
||||
import 'package:PiliPlus/pages/common/common_list_controller.dart';
|
||||
import 'package:PiliPlus/pages/video/detail/reply_new/reply_page.dart';
|
||||
import 'package:PiliPlus/utils/accounts/account.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
@@ -16,12 +16,11 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:PiliPlus/models/common/reply_sort_type.dart';
|
||||
import 'package:PiliPlus/models/video/reply/item.dart';
|
||||
import 'package:PiliPlus/utils/feed_back.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:get/get_navigation/src/dialog/dialog_route.dart';
|
||||
|
||||
abstract class ReplyController extends CommonController {
|
||||
abstract class ReplyController<R> extends CommonListController<R, ReplyInfo> {
|
||||
String nextOffset = '';
|
||||
RxInt count = (-1).obs;
|
||||
|
||||
@@ -31,6 +30,7 @@ abstract class ReplyController extends CommonController {
|
||||
|
||||
late final bool isLogin = Accounts.main.isLogin;
|
||||
|
||||
dynamic upMid;
|
||||
CursorReply? cursor;
|
||||
late Rx<Mode> mode = Mode.MAIN_LIST_HOT.obs;
|
||||
late bool hasUpTop = false;
|
||||
@@ -59,6 +59,29 @@ abstract class ReplyController extends CommonController {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void checkIsEnd(int length) {
|
||||
if (length >= count.value) {
|
||||
isEnd = true;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool customHandleResponse(bool isRefresh, Success response) {
|
||||
MainListReply data = response.response;
|
||||
cursor = data.cursor;
|
||||
count.value = data.subjectControl.count.toInt();
|
||||
if (isRefresh) {
|
||||
upMid ??= data.subjectControl.upMid;
|
||||
hasUpTop = data.hasUpTop();
|
||||
if (data.hasUpTop()) {
|
||||
data.replies.insert(0, data.upTop);
|
||||
}
|
||||
}
|
||||
isEnd = data.cursor.isEnd;
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
Future onRefresh() {
|
||||
cursor = null;
|
||||
@@ -66,29 +89,6 @@ abstract class ReplyController extends CommonController {
|
||||
return super.onRefresh();
|
||||
}
|
||||
|
||||
@override
|
||||
bool customHandleResponse(Success response) {
|
||||
MainListReply replies = response.response;
|
||||
if (cursor == null) {
|
||||
count.value = replies.subjectControl.count.toInt();
|
||||
hasUpTop = replies.hasUpTop();
|
||||
if (replies.hasUpTop()) {
|
||||
replies.replies.insert(0, replies.upTop);
|
||||
}
|
||||
}
|
||||
cursor = replies.cursor;
|
||||
if (currentPage != 1 && loadingState.value is Success) {
|
||||
replies.replies
|
||||
.insertAll(0, (loadingState.value as Success).response.replies);
|
||||
}
|
||||
isEnd = replies.replies.isEmpty ||
|
||||
replies.cursor.isEnd ||
|
||||
replies.replies.length >= count.value;
|
||||
loadingState.value = LoadingState.success(replies);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 排序搜索评论
|
||||
queryBySort() {
|
||||
EasyThrottle.throttle('queryBySort', const Duration(seconds: 1), () {
|
||||
@@ -168,16 +168,24 @@ abstract class ReplyController extends CommonController {
|
||||
if (res != null) {
|
||||
savedReplies[key] = null;
|
||||
ReplyInfo replyInfo = Utils.replyCast(res);
|
||||
MainListReply response = loadingState.value is Success
|
||||
? (loadingState.value as Success).response
|
||||
: MainListReply();
|
||||
if (oid != null) {
|
||||
response.replies.insert(hasUpTop ? 1 : 0, replyInfo);
|
||||
if (loadingState.value is Success) {
|
||||
List<ReplyInfo>? list = (loadingState.value as Success).response;
|
||||
if (list == null) {
|
||||
loadingState.value = LoadingState.success([replyInfo]);
|
||||
} else {
|
||||
if (oid != null) {
|
||||
list.insert(hasUpTop ? 1 : 0, replyInfo);
|
||||
} else {
|
||||
list[index].replies.add(replyInfo);
|
||||
}
|
||||
loadingState.refresh();
|
||||
}
|
||||
} else {
|
||||
response.replies[index].replies.add(replyInfo);
|
||||
loadingState.value = LoadingState.success([replyInfo]);
|
||||
}
|
||||
count.value += 1;
|
||||
loadingState.value = LoadingState.success(response);
|
||||
|
||||
// check reply
|
||||
if (enableCommAntifraud && context.mounted) {
|
||||
checkReply(
|
||||
context: context,
|
||||
@@ -203,63 +211,36 @@ abstract class ReplyController extends CommonController {
|
||||
);
|
||||
}
|
||||
|
||||
onMDelete(rpid, frpid) {
|
||||
MainListReply response = (loadingState.value as Success).response;
|
||||
if (frpid == null) {
|
||||
response.replies.removeWhere((item) {
|
||||
return item.id.toInt() == rpid;
|
||||
});
|
||||
void onRemove(int index, int? subIndex) {
|
||||
List<ReplyInfo> list = (loadingState.value as Success).response;
|
||||
if (subIndex == null) {
|
||||
list.removeAt(index);
|
||||
} else {
|
||||
response.replies.map((item) {
|
||||
if (item.id == frpid) {
|
||||
return item..replies.removeWhere((reply) => reply.id.toInt() == rpid);
|
||||
} else {
|
||||
return item;
|
||||
}
|
||||
}).toList();
|
||||
list[index].replies.removeAt(subIndex);
|
||||
}
|
||||
count.value -= 1;
|
||||
loadingState.value = LoadingState.success(response);
|
||||
loadingState.refresh();
|
||||
}
|
||||
|
||||
void onCheckReply(context, item) {
|
||||
try {
|
||||
if (item is ReplyInfo) {
|
||||
checkReply(
|
||||
context: context,
|
||||
oid: item.oid.toInt(),
|
||||
rpid: item.hasRoot() ? item.root.toInt() : null,
|
||||
replyType: item.type.toInt(),
|
||||
replyId: item.id.toInt(),
|
||||
message: item.content.message,
|
||||
//
|
||||
root: item.root.toInt(),
|
||||
parent: item.parent.toInt(),
|
||||
ctime: item.ctime.toInt(),
|
||||
pictures:
|
||||
item.content.pictures.map((item) => item.toProto3Json()).toList(),
|
||||
mid: item.mid.toInt(),
|
||||
//
|
||||
isManual: true,
|
||||
);
|
||||
} else if (item is ReplyItemModel) {
|
||||
checkReply(
|
||||
context: context,
|
||||
oid: item.oid,
|
||||
rpid: item.root == 0 ? null : item.root,
|
||||
replyType: item.type!,
|
||||
replyId: item.rpid!,
|
||||
message: item.content!.message!,
|
||||
//
|
||||
root: item.root,
|
||||
parent: item.parent,
|
||||
ctime: item.ctime,
|
||||
pictures: item.content?.pictures,
|
||||
mid: item.mid,
|
||||
//
|
||||
isManual: true,
|
||||
);
|
||||
}
|
||||
checkReply(
|
||||
context: context,
|
||||
oid: item.oid.toInt(),
|
||||
rpid: item.hasRoot() ? item.root.toInt() : null,
|
||||
replyType: item.type.toInt(),
|
||||
replyId: item.id.toInt(),
|
||||
message: item.content.message,
|
||||
//
|
||||
root: item.root.toInt(),
|
||||
parent: item.parent.toInt(),
|
||||
ctime: item.ctime.toInt(),
|
||||
pictures:
|
||||
item.content.pictures.map((item) => item.toProto3Json()).toList(),
|
||||
mid: item.mid.toInt(),
|
||||
//
|
||||
isManual: true,
|
||||
);
|
||||
} catch (e) {
|
||||
SmartDialog.showToast(e.toString());
|
||||
}
|
||||
@@ -502,16 +483,14 @@ https://api.bilibili.com/x/v2/reply/reply?oid=$oid&pn=1&ps=20&root=${rpid ?? rep
|
||||
isUpTop: isUpTop,
|
||||
);
|
||||
if (res['status']) {
|
||||
final data = (loadingState.value as Success).response;
|
||||
if (data is MainListReply) {
|
||||
data.replies[index].replyControl.isUpTop = !isUpTop;
|
||||
if (!isUpTop && index != 0) {
|
||||
data.replies[0].replyControl.isUpTop = false;
|
||||
final item = data.replies.removeAt(index);
|
||||
data.replies.insert(0, item);
|
||||
}
|
||||
loadingState.value = LoadingState.success(data);
|
||||
List<ReplyInfo> list = (loadingState.value as Success).response;
|
||||
list[index].replyControl.isUpTop = !isUpTop;
|
||||
if (!isUpTop && index != 0) {
|
||||
list[0].replyControl.isUpTop = false;
|
||||
final item = list.removeAt(index);
|
||||
list.insert(0, item);
|
||||
}
|
||||
loadingState.refresh();
|
||||
SmartDialog.showToast('${isUpTop ? '取消' : ''}置顶成功');
|
||||
} else {
|
||||
SmartDialog.showToast(res['msg']);
|
||||
|
||||
Reference in New Issue
Block a user