mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-01 00:28:18 +08:00
44
lib/pages/member_guard/controller.dart
Normal file
44
lib/pages/member_guard/controller.dart
Normal file
@@ -0,0 +1,44 @@
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/http/member.dart';
|
||||
import 'package:PiliPlus/models_new/member_guard/data.dart';
|
||||
import 'package:PiliPlus/models_new/member_guard/guard_top_list.dart';
|
||||
import 'package:PiliPlus/pages/common/common_list_controller.dart';
|
||||
import 'package:get/get_core/src/get_main.dart';
|
||||
import 'package:get/get_navigation/get_navigation.dart';
|
||||
|
||||
class MemberGuardController
|
||||
extends CommonListController<MemberGuardData, GuardItem> {
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
queryData();
|
||||
}
|
||||
|
||||
final Object ruid = Get.arguments['ruid'];
|
||||
|
||||
late List<GuardItem> tops;
|
||||
|
||||
@override
|
||||
List<GuardItem>? getDataList(MemberGuardData response) {
|
||||
return response.guardTopList;
|
||||
}
|
||||
|
||||
@override
|
||||
bool customHandleResponse(bool isRefresh, Success<MemberGuardData> response) {
|
||||
if (response.response.hasMore != 1) {
|
||||
isEnd = true;
|
||||
}
|
||||
if (isRefresh) {
|
||||
final list = response.response.guardTopList;
|
||||
tops = list.take(3).toList();
|
||||
if (list.length > 3) {
|
||||
list.removeRange(0, 3);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LoadingState<MemberGuardData>> customGetData() =>
|
||||
MemberHttp.memberGuard(ruid: ruid, page: page);
|
||||
}
|
||||
206
lib/pages/member_guard/view.dart
Normal file
206
lib/pages/member_guard/view.dart
Normal file
@@ -0,0 +1,206 @@
|
||||
import 'package:PiliPlus/common/widgets/flutter/list_tile.dart';
|
||||
import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart';
|
||||
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
||||
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
|
||||
import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart';
|
||||
import 'package:PiliPlus/common/widgets/view_sliver_safe_area.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models_new/member_guard/guard_top_list.dart';
|
||||
import 'package:PiliPlus/pages/member_guard/controller.dart';
|
||||
import 'package:PiliPlus/utils/extension/widget_ext.dart';
|
||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||
import 'package:flutter/material.dart' hide ListTile;
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class MemberGuard extends StatefulWidget {
|
||||
const MemberGuard({super.key});
|
||||
|
||||
@override
|
||||
State<MemberGuard> createState() => _MemberGuardState();
|
||||
|
||||
static Future<void>? toMemberGuard({
|
||||
required Object mid,
|
||||
required String name,
|
||||
required Object? count,
|
||||
}) {
|
||||
return Get.toNamed(
|
||||
'/memberGuard',
|
||||
arguments: {
|
||||
'ruid': mid,
|
||||
'name': name,
|
||||
'count': count,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _MemberGuardState extends State<MemberGuard> {
|
||||
late final String _userName;
|
||||
late final Object? _count;
|
||||
late final MemberGuardController _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final args = Get.arguments;
|
||||
_userName = args['name'];
|
||||
_count = args['count'];
|
||||
_controller = Get.put(
|
||||
MemberGuardController(),
|
||||
tag: args['ruid'].toString(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('$_userName的舰队${_count == null ? '' : '($_count)'}'),
|
||||
),
|
||||
body: refreshIndicator(
|
||||
onRefresh: _controller.onRefresh,
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
ViewSliverSafeArea(
|
||||
sliver: Obx(() => _buildBody(_controller.loadingState.value)),
|
||||
),
|
||||
],
|
||||
),
|
||||
).constraintWidth(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(LoadingState<List<GuardItem>?> state) {
|
||||
switch (state) {
|
||||
case Loading():
|
||||
return linearLoading;
|
||||
case Success<List<GuardItem>?>(:final response):
|
||||
return SliverMainAxisGroup(
|
||||
slivers: [
|
||||
_buildTopItems(),
|
||||
if (response!.isNotEmpty)
|
||||
SliverPadding(
|
||||
padding: const .only(top: 10),
|
||||
sliver: SliverList.separated(
|
||||
itemCount: response.length,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == response.length - 1) {
|
||||
_controller.onLoadMore();
|
||||
}
|
||||
|
||||
final item = response[index];
|
||||
return ListTile(
|
||||
safeArea: false,
|
||||
visualDensity: .comfortable,
|
||||
onTap: () => Get.toNamed('/member?mid=${item.uid}'),
|
||||
leading: _avatar(item.face, 32, item.guardLevel),
|
||||
title: Text(
|
||||
item.username,
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (_, _) => const SizedBox(height: 4),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
case Error(:final errMsg):
|
||||
return HttpError(errMsg: errMsg, onReload: _controller.onReload);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildTopItem(GuardItem item, double size) {
|
||||
final child = GestureDetector(
|
||||
behavior: .opaque,
|
||||
onTap: () => Get.toNamed('/member?mid=${item.uid}'),
|
||||
child: Padding(
|
||||
padding: const .symmetric(vertical: 10.0),
|
||||
child: Column(
|
||||
spacing: 5,
|
||||
mainAxisSize: .min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 67.5, // 50 * 1.35
|
||||
child: Align(
|
||||
alignment: .bottomCenter,
|
||||
child: _avatar(item.face, size, item.guardLevel),
|
||||
),
|
||||
),
|
||||
Text(item.username, maxLines: 1, overflow: .ellipsis),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
if (PlatformUtils.isDesktop) {
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
Widget _buildTopItems() {
|
||||
final Widget first;
|
||||
final Widget second;
|
||||
final Widget third;
|
||||
if (_controller.tops.firstOrNull case final item?) {
|
||||
first = _buildTopItem(item, 50);
|
||||
} else {
|
||||
first = const SizedBox.shrink();
|
||||
}
|
||||
if (_controller.tops.elementAtOrNull(1) case final item?) {
|
||||
second = _buildTopItem(item, 42);
|
||||
} else {
|
||||
second = const SizedBox.shrink();
|
||||
}
|
||||
if (_controller.tops.elementAtOrNull(2) case final item?) {
|
||||
third = _buildTopItem(item, 42);
|
||||
} else {
|
||||
third = const SizedBox.shrink();
|
||||
}
|
||||
return SliverToBoxAdapter(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(child: second),
|
||||
Expanded(child: first),
|
||||
Expanded(child: third),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static String? _pendantUrl(int guardLevel) => switch (guardLevel) {
|
||||
1 =>
|
||||
'https://i0.hdslb.com/bfs/live/a454275dea465ac15a03f121f0d7edaf96e30bcf.png',
|
||||
2 =>
|
||||
'https://i0.hdslb.com/bfs/live/3b46129e796df42ec7356fcba77c8a79d47db682.png',
|
||||
3 =>
|
||||
'https://i0.hdslb.com/bfs/live/80f732943cc3367029df65e267960d56736a82ee.png',
|
||||
_ => null,
|
||||
};
|
||||
|
||||
static Widget _avatar(String url, double size, int guardLevel) {
|
||||
final pendentSize = 1.35 * size;
|
||||
return Stack(
|
||||
clipBehavior: .none,
|
||||
alignment: .center,
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
src: url,
|
||||
width: size,
|
||||
height: size,
|
||||
type: .avatar,
|
||||
),
|
||||
NetworkImgLayer(
|
||||
type: .emote,
|
||||
width: pendentSize,
|
||||
height: pendentSize,
|
||||
src: _pendantUrl(guardLevel),
|
||||
getPlaceHolder: () => const SizedBox.shrink(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user