mirror of
https://ghfast.top/https://github.com/StarCitizenToolBox/app.git
synced 2025-06-28 11:24:46 +08:00
feat:riverpod 迁移
This commit is contained in:
@ -1,197 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:starcitizen_doctor/base/ui.dart';
|
||||
import 'package:starcitizen_doctor/generated/grpc/party_room_server/index.pb.dart';
|
||||
|
||||
import 'party_room_create_dialog_ui_model.dart';
|
||||
|
||||
class PartyRoomCreateDialogUI extends BaseUI<PartyRoomCreateDialogUIModel> {
|
||||
@override
|
||||
Widget? buildBody(BuildContext context, PartyRoomCreateDialogUIModel model) {
|
||||
return ContentDialog(
|
||||
title: makeTitle(context, model),
|
||||
constraints:
|
||||
BoxConstraints(maxWidth: MediaQuery.of(context).size.width * .6),
|
||||
content: Padding(
|
||||
padding: const EdgeInsets.only(left: 12, right: 12, top: 12),
|
||||
child: AnimatedSize(
|
||||
duration: const Duration(milliseconds: 130),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (model.userName == null) ...[
|
||||
SizedBox(
|
||||
height: 200,
|
||||
child: makeLoading(context),
|
||||
)
|
||||
] else ...[
|
||||
Row(
|
||||
children: [
|
||||
const Text("请选择一种玩法"),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 36,
|
||||
child: ComboBox<RoomType>(
|
||||
value: model.selectedRoomType,
|
||||
items: [
|
||||
for (final t in model.roomTypes.entries)
|
||||
ComboBoxItem(
|
||||
value: t.value,
|
||||
child: Text(t.value.name),
|
||||
)
|
||||
],
|
||||
onChanged: model.onChangeRoomType)),
|
||||
)
|
||||
],
|
||||
),
|
||||
if (model.selectedRoomType != null &&
|
||||
(model.selectedRoomType?.subTypes.isNotEmpty ?? false))
|
||||
...makeSubTypeSelectWidgets(context, model),
|
||||
const SizedBox(height: 24),
|
||||
Row(
|
||||
children: [
|
||||
const Text("游戏用户名(自动获取)"),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: TextFormBox(
|
||||
initialValue: model.userName,
|
||||
enabled: false,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Row(
|
||||
children: [
|
||||
const Text("最大玩家数(2 ~ 32)"),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: TextFormBox(
|
||||
controller: model.playerMaxCtrl,
|
||||
onChanged: (_) => model.notifyListeners(),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly
|
||||
],
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const Text("公告(可选)"),
|
||||
const SizedBox(height: 12),
|
||||
TextFormBox(
|
||||
controller: model.announcementCtrl,
|
||||
maxLines: 5,
|
||||
placeholder: "可编写 任务简报,集合地点,船只要求,活动规则等,公告将会自动发送给进入房间的玩家。",
|
||||
placeholderStyle:
|
||||
TextStyle(color: Colors.white.withOpacity(.4)),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
for (var v in [
|
||||
"创建房间后,其他玩家可以在大厅首页看到您的房间和您选择的玩法,当一个玩家选择加入房间时,你们将可以互相看到对方的用户名。当房间人数达到最大玩家数时,将不再接受新的玩家加入。",
|
||||
"这是《SC汉化盒子》提供的公益服务,请勿滥用,我们保留拒绝服务的权力。"
|
||||
]) ...[
|
||||
Text(
|
||||
v,
|
||||
style: TextStyle(
|
||||
fontSize: 14, color: Colors.white.withOpacity(.6)),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
],
|
||||
]
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
if (model.isWorking)
|
||||
const ProgressRing()
|
||||
else
|
||||
FilledButton(
|
||||
onPressed: model.onSubmit(),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(3),
|
||||
child: Text("创建房间"),
|
||||
))
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Color generateColorFromSeed(String seed) {
|
||||
int hash = utf8
|
||||
.encode(seed)
|
||||
.fold(0, (previousValue, element) => 31 * previousValue + element);
|
||||
Random random = Random(hash);
|
||||
return Color.fromARGB(
|
||||
255, random.nextInt(256), random.nextInt(256), random.nextInt(256));
|
||||
}
|
||||
|
||||
List<Widget> makeSubTypeSelectWidgets(
|
||||
BuildContext context, PartyRoomCreateDialogUIModel model) {
|
||||
bool isItemSelected(RoomSubtype subtype) {
|
||||
return model.selectedSubType.contains(subtype);
|
||||
}
|
||||
|
||||
return [
|
||||
const SizedBox(height: 24),
|
||||
const Text("标签(可选)"),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
for (var item in model.selectedRoomType!.subTypes)
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isItemSelected(item)
|
||||
? generateColorFromSeed(item.name).withOpacity(.4)
|
||||
: FluentTheme.of(context).cardColor,
|
||||
borderRadius: BorderRadius.circular(1000)),
|
||||
padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 12),
|
||||
margin: const EdgeInsets.only(right: 12),
|
||||
child: IconButton(
|
||||
icon: Row(
|
||||
children: [
|
||||
Icon(isItemSelected(item)
|
||||
? FluentIcons.check_mark
|
||||
: FluentIcons.add),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
item.name,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: isItemSelected(item)
|
||||
? null
|
||||
: Colors.white.withOpacity(.4)),
|
||||
),
|
||||
],
|
||||
),
|
||||
onPressed: () => model.onTapSubType(item)),
|
||||
)
|
||||
],
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
Widget makeTitle(BuildContext context, PartyRoomCreateDialogUIModel model) {
|
||||
return Row(
|
||||
children: [
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
FluentIcons.back,
|
||||
size: 22,
|
||||
),
|
||||
onPressed: model.onBack()),
|
||||
const SizedBox(width: 12),
|
||||
Text(getUITitle(context, model)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String getUITitle(BuildContext context, PartyRoomCreateDialogUIModel model) =>
|
||||
"创建房间";
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
import 'package:starcitizen_doctor/base/ui_model.dart';
|
||||
import 'package:starcitizen_doctor/common/conf/app_conf.dart';
|
||||
import 'package:starcitizen_doctor/common/grpc/party_room_server.dart';
|
||||
import 'package:starcitizen_doctor/generated/grpc/party_room_server/index.pb.dart';
|
||||
import 'package:starcitizen_doctor/global_ui_model.dart';
|
||||
|
||||
class PartyRoomCreateDialogUIModel extends BaseUIModel {
|
||||
Map<String?, RoomType> roomTypes;
|
||||
|
||||
RoomType? selectedRoomType;
|
||||
|
||||
List<RoomSubtype> selectedSubType = [];
|
||||
|
||||
PartyRoomCreateDialogUIModel(this.roomTypes);
|
||||
|
||||
String? userName;
|
||||
|
||||
bool isWorking = false;
|
||||
|
||||
final playerMaxCtrl = TextEditingController(text: "8");
|
||||
final announcementCtrl = TextEditingController();
|
||||
|
||||
@override
|
||||
initModel() {
|
||||
super.initModel();
|
||||
roomTypes.removeWhere((key, value) => key == "");
|
||||
}
|
||||
|
||||
@override
|
||||
loadData() async {
|
||||
userName = await globalUIModel.getRunningGameUser();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
onBack() {
|
||||
if (isWorking) return null;
|
||||
return () {
|
||||
Navigator.pop(context!);
|
||||
};
|
||||
}
|
||||
|
||||
void onChangeRoomType(RoomType? value) {
|
||||
selectedSubType = [];
|
||||
selectedRoomType = value;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
onTapSubType(RoomSubtype item) {
|
||||
if (!selectedSubType.contains(item)) {
|
||||
selectedSubType.add(item);
|
||||
} else {
|
||||
selectedSubType.remove(item);
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
final maxPlayer = int.tryParse(playerMaxCtrl.text) ?? 0;
|
||||
if (selectedRoomType == null) return null;
|
||||
if (maxPlayer < 2 || maxPlayer > 32) return null;
|
||||
return () async {
|
||||
isWorking = true;
|
||||
notifyListeners();
|
||||
final room = await handleError(() => PartyRoomGrpcServer.createRoom(
|
||||
RoomData(
|
||||
roomTypeID: selectedRoomType?.id,
|
||||
roomSubTypeIds: [for (var value in selectedSubType) value.id],
|
||||
owner: userName,
|
||||
deviceUUID: AppConf.deviceUUID,
|
||||
maxPlayer: maxPlayer,
|
||||
announcement: announcementCtrl.text.trim())));
|
||||
isWorking = false;
|
||||
notifyListeners();
|
||||
if (room != null) {
|
||||
Navigator.pop(context!, room);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,148 +0,0 @@
|
||||
import 'package:starcitizen_doctor/base/ui.dart';
|
||||
import 'package:starcitizen_doctor/generated/grpc/party_room_server/index.pb.dart';
|
||||
import 'package:starcitizen_doctor/widgets/cache_image.dart';
|
||||
|
||||
import 'party_room_chat_ui_model.dart';
|
||||
|
||||
class PartyRoomChatUI extends BaseUI<PartyRoomChatUIModel> {
|
||||
@override
|
||||
Widget? buildBody(BuildContext context, PartyRoomChatUIModel model) {
|
||||
final roomData = model.serverResultRoomData;
|
||||
if (roomData == null) return makeLoading(context);
|
||||
final typesMap = model.partyRoomHomeUIModel.roomTypes;
|
||||
final title =
|
||||
"${roomData.owner} 的 ${typesMap?[roomData.roomTypeID]?.name ?? roomData.roomTypeID}房间";
|
||||
// final createTime =
|
||||
// DateTime.fromMillisecondsSinceEpoch(roomData.createTime.toInt());
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(color: Colors.black.withOpacity(.25)),
|
||||
child: makeTitleBar(model, title, roomData),
|
||||
),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 220,
|
||||
padding: const EdgeInsets.only(left: 12, right: 12),
|
||||
decoration: BoxDecoration(color: Colors.black.withOpacity(.07)),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 12),
|
||||
makeItemRow("玩家数量:",
|
||||
"${model.playersMap?.length ?? 0} / ${roomData.maxPlayer}"),
|
||||
const SizedBox(height: 12),
|
||||
if (model.playersMap == null)
|
||||
Expanded(child: makeLoading(context))
|
||||
else
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final item = model.playersMap!.entries
|
||||
.elementAt(index)
|
||||
.value;
|
||||
return Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(1000),
|
||||
child: CacheNetImage(
|
||||
url: item.avatar,
|
||||
width: 28,
|
||||
height: 28,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(child: Text(item.playerName)),
|
||||
const SizedBox(width: 12),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 3, bottom: 3, left: 12, right: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.green,
|
||||
borderRadius:
|
||||
BorderRadius.circular(1000)),
|
||||
child: Text(
|
||||
"${model.playerStatusMap[item.status] ?? item.status}",
|
||||
style: const TextStyle(fontSize: 13),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
itemCount: model.playersMap!.length,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget makeItemRow(String title, String value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 1, bottom: 1),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(color: Colors.white.withOpacity(.6)),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
value,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget makeTitleBar(
|
||||
PartyRoomChatUIModel model, String title, RoomData roomData) {
|
||||
return Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(1000),
|
||||
child: CacheNetImage(
|
||||
url: roomData.avatar,
|
||||
width: 32,
|
||||
height: 32,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
title,
|
||||
style: const TextStyle(fontSize: 18),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Container(
|
||||
padding:
|
||||
const EdgeInsets.only(top: 3, bottom: 3, left: 12, right: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.green, borderRadius: BorderRadius.circular(1000)),
|
||||
child: Text(
|
||||
"${model.partyRoomHomeUIModel.roomStatus[roomData.status]}")),
|
||||
const SizedBox(width: 12),
|
||||
const Spacer(),
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
FluentIcons.leave,
|
||||
size: 20,
|
||||
),
|
||||
onPressed: () => model.onClose())
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String getUITitle(BuildContext context, PartyRoomChatUIModel model) => "Chat";
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
import 'package:grpc/grpc.dart';
|
||||
import 'package:starcitizen_doctor/base/ui_model.dart';
|
||||
import 'package:starcitizen_doctor/common/conf/app_conf.dart';
|
||||
import 'package:starcitizen_doctor/common/grpc/party_room_server.dart';
|
||||
import 'package:starcitizen_doctor/generated/grpc/party_room_server/index.pb.dart';
|
||||
import 'package:starcitizen_doctor/global_ui_model.dart';
|
||||
|
||||
import 'party_room_home_ui_model.dart';
|
||||
|
||||
class PartyRoomChatUIModel extends BaseUIModel {
|
||||
PartyRoomHomeUIModel partyRoomHomeUIModel;
|
||||
|
||||
PartyRoomChatUIModel(this.partyRoomHomeUIModel);
|
||||
|
||||
RoomData? selectRoom;
|
||||
|
||||
RoomData? serverResultRoomData;
|
||||
|
||||
ResponseStream<RoomUpdateMessage>? roomStream;
|
||||
|
||||
Map<String, RoomUserData>? playersMap;
|
||||
|
||||
setRoom(RoomData? selectRoom) {
|
||||
if (this.selectRoom == null) {
|
||||
this.selectRoom = selectRoom;
|
||||
notifyListeners();
|
||||
loadRoom();
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
final playerStatusMap = {
|
||||
RoomUserStatus.RoomUserStatusJoin: "在线",
|
||||
RoomUserStatus.RoomUserStatusLostOffline: "离线",
|
||||
RoomUserStatus.RoomUserStatusLeave: "已离开",
|
||||
RoomUserStatus.RoomUserStatusWaitingConnect: "正在连接...",
|
||||
};
|
||||
|
||||
onClose() async {
|
||||
final ok = await showConfirmDialogs(
|
||||
context!, "确认离开房间?", const Text("离开房间后,您的位置将被释放。"));
|
||||
if (ok == true) {
|
||||
partyRoomHomeUIModel.pageCtrl.animateToPage(0,
|
||||
duration: const Duration(milliseconds: 130),
|
||||
curve: Curves.easeInOutSine);
|
||||
disposeRoom();
|
||||
}
|
||||
}
|
||||
|
||||
loadRoom() async {
|
||||
if (selectRoom == null) return;
|
||||
final userName = await globalUIModel.getRunningGameUser();
|
||||
if (userName == null) return;
|
||||
roomStream = PartyRoomGrpcServer.joinRoom(
|
||||
selectRoom!.id, userName, AppConf.deviceUUID);
|
||||
roomStream!.listen((value) {
|
||||
dPrint("PartyRoomChatUIModel.roomStream.listen === $value");
|
||||
if (value.roomUpdateType == RoomUpdateType.RoomClose) {
|
||||
} else if (value.roomUpdateType == RoomUpdateType.RoomUpdateData) {
|
||||
if (value.hasRoomData()) {
|
||||
serverResultRoomData = value.roomData;
|
||||
}
|
||||
if (value.usersData.isNotEmpty) {
|
||||
_updatePlayerList(value.usersData);
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
})
|
||||
..onError((err) {
|
||||
// showToast(context!, "连接到服务器出现错误:$err");
|
||||
dPrint("PartyRoomChatUIModel.roomStream onError $err");
|
||||
})
|
||||
..onDone(() {
|
||||
// showToast(context!, "房间已关闭");
|
||||
dPrint("PartyRoomChatUIModel.roomStream onDone");
|
||||
});
|
||||
}
|
||||
|
||||
disposeRoom() {
|
||||
selectRoom = null;
|
||||
roomStream?.cancel();
|
||||
roomStream = null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void _updatePlayerList(List<RoomUserData> usersData) {
|
||||
playersMap ??= {};
|
||||
for (var element in usersData) {
|
||||
playersMap![element.playerName] = element;
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
@ -1,357 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:extended_image/extended_image.dart';
|
||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||
import 'package:flutter_tilt/flutter_tilt.dart';
|
||||
import 'package:starcitizen_doctor/base/ui.dart';
|
||||
import 'package:starcitizen_doctor/generated/grpc/party_room_server/index.pb.dart';
|
||||
import 'package:starcitizen_doctor/widgets/cache_image.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
import 'party_room_home_ui_model.dart';
|
||||
|
||||
class PartyRoomHomeUI extends BaseUI<PartyRoomHomeUIModel> {
|
||||
@override
|
||||
void initState() {
|
||||
Future.delayed(const Duration(milliseconds: 16)).then((_) {
|
||||
ref.watch(provider).checkUIInit();
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// final model = ref.watch(provider);
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text(
|
||||
"联机大厅,敬请期待 !",
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
launchUrlString("https://wj.qq.com/s2/14112124/f4c8/");
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text("诚邀您参与 "),
|
||||
Text(
|
||||
"问卷调查。",
|
||||
style: TextStyle(
|
||||
color: Colors.blue,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
// return PageView(
|
||||
// controller: model.pageCtrl,
|
||||
// physics: const NeverScrollableScrollPhysics(),
|
||||
// children: [
|
||||
// super.build(context),
|
||||
// BaseUIContainer(
|
||||
// uiCreate: () => PartyRoomChatUI(),
|
||||
// modelCreate: () =>
|
||||
// model.getChildUIModelProviders<PartyRoomChatUIModel>("chat"))
|
||||
// ],
|
||||
// );
|
||||
}
|
||||
|
||||
@override
|
||||
Widget? buildBody(BuildContext context, PartyRoomHomeUIModel model) {
|
||||
if (model.pingServerMessage == null) return makeLoading(context);
|
||||
if (model.pingServerMessage!.isNotEmpty) {
|
||||
return Center(
|
||||
child: Text("${model.pingServerMessage}"),
|
||||
);
|
||||
}
|
||||
if (model.roomTypes == null) return makeLoading(context);
|
||||
return Column(
|
||||
children: [
|
||||
makeHeader(context, model),
|
||||
if (model.rooms == null)
|
||||
Expanded(child: makeLoading(context))
|
||||
else if (model.rooms!.isEmpty)
|
||||
const Expanded(
|
||||
child: Center(
|
||||
child: Text("没有符合条件的房间!"),
|
||||
))
|
||||
else
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 24, right: 24),
|
||||
child: AlignedGridView.count(
|
||||
crossAxisCount: 3,
|
||||
mainAxisSpacing: 24,
|
||||
crossAxisSpacing: 24,
|
||||
itemCount: model.rooms!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return makeRoomItemWidget(context, model, index);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget makeRoomItemWidget(
|
||||
BuildContext context,
|
||||
PartyRoomHomeUIModel model,
|
||||
int index,
|
||||
) {
|
||||
final item = model.rooms![index];
|
||||
final itemType = model.roomTypes?[item.roomTypeID];
|
||||
final itemSubTypes = {
|
||||
for (var t in itemType?.subTypes ?? <RoomSubtype>[]) t.id: t
|
||||
};
|
||||
final createTime =
|
||||
DateTime.fromMillisecondsSinceEpoch(item.createTime.toInt());
|
||||
return Tilt(
|
||||
borderRadius: BorderRadius.circular(13),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(13),
|
||||
image: DecorationImage(
|
||||
image: ExtendedNetworkImageProvider(item.avatar, cache: true),
|
||||
fit: BoxFit.cover)),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withOpacity(.4),
|
||||
borderRadius: BorderRadius.circular(13),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(13),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 16, right: 16, top: 12, bottom: 12),
|
||||
child: GestureDetector(
|
||||
onTap: () => model.onTapRoom(item),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
"${itemType?.name ?? item.roomTypeID}房间",
|
||||
style: const TextStyle(fontSize: 20),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 3, bottom: 3, left: 12, right: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.green,
|
||||
borderRadius: BorderRadius.circular(1000)),
|
||||
child: Text("${model.roomStatus[item.status]}")),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
makeItemRow("房主:", item.owner),
|
||||
makeItemRow("玩家数量:",
|
||||
"${item.curPlayer} / ${item.maxPlayer}"),
|
||||
makeItemRow("创建时间:", "${createTime.toLocal()}"),
|
||||
],
|
||||
),
|
||||
),
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(1000),
|
||||
child: CacheNetImage(
|
||||
url: item.avatar,
|
||||
width: 64,
|
||||
height: 64,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children: [
|
||||
for (var value in item.roomSubTypeIds)
|
||||
makeSubTypeTag(value, model, itemSubTypes),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget makeSubTypeTag(String id, PartyRoomHomeUIModel model,
|
||||
Map<String, RoomSubtype> itemSubTypes) {
|
||||
final name = itemSubTypes[id]?.name ?? id;
|
||||
final color = generateColorFromSeed(name).withOpacity(.6);
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(left: 12, right: 12, top: 5, bottom: 5),
|
||||
margin: const EdgeInsets.only(right: 6),
|
||||
decoration:
|
||||
BoxDecoration(color: color, borderRadius: BorderRadius.circular(12)),
|
||||
child: Text(
|
||||
name,
|
||||
style: const TextStyle(fontSize: 13),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Color generateColorFromSeed(String seed) {
|
||||
int hash = utf8
|
||||
.encode(seed)
|
||||
.fold(0, (previousValue, element) => 31 * previousValue + element);
|
||||
Random random = Random(hash);
|
||||
return Color.fromARGB(
|
||||
255, random.nextInt(256), random.nextInt(256), random.nextInt(256));
|
||||
}
|
||||
|
||||
Widget makeItemRow(String title, String value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 1, bottom: 1),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(color: Colors.white.withOpacity(.6)),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
value,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget makeHeader(BuildContext context, PartyRoomHomeUIModel model) {
|
||||
final subTypes = model.getCurRoomSubTypes();
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(left: 24, right: 24, top: 16, bottom: 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const Text("房间类型:"),
|
||||
SizedBox(
|
||||
height: 36,
|
||||
child: ComboBox<RoomType>(
|
||||
value: model.selectedRoomType,
|
||||
items: [
|
||||
for (final t in model.roomTypes!.entries)
|
||||
ComboBoxItem(
|
||||
value: t.value,
|
||||
child: Text(t.value.name),
|
||||
)
|
||||
],
|
||||
onChanged: model.onChangeRoomType)),
|
||||
if (subTypes != null) ...[
|
||||
const SizedBox(width: 24),
|
||||
const Text("子类型:"),
|
||||
SizedBox(
|
||||
height: 36,
|
||||
child: ComboBox<RoomSubtype>(
|
||||
value: model.selectedRoomSubType,
|
||||
items: [
|
||||
for (final t in subTypes.entries)
|
||||
ComboBoxItem(
|
||||
value: t.value,
|
||||
child: Text(t.value.name),
|
||||
)
|
||||
],
|
||||
onChanged: model.onChangeRoomSubType)),
|
||||
],
|
||||
const SizedBox(width: 24),
|
||||
const Text("房间状态:"),
|
||||
SizedBox(
|
||||
height: 36,
|
||||
child: ComboBox<RoomStatus>(
|
||||
value: model.selectedStatus,
|
||||
items: [
|
||||
for (final t in model.roomStatus.entries)
|
||||
ComboBoxItem(
|
||||
value: t.key,
|
||||
child: Text(t.value),
|
||||
)
|
||||
],
|
||||
onChanged: model.onChangeRoomStatus)),
|
||||
const SizedBox(width: 24),
|
||||
const Text("排序:"),
|
||||
SizedBox(
|
||||
height: 36,
|
||||
child: ComboBox<RoomSortType>(
|
||||
value: model.selectedSortType,
|
||||
items: [
|
||||
for (final t in model.roomSorts.entries)
|
||||
ComboBoxItem(
|
||||
value: t.key,
|
||||
child: Text(t.value),
|
||||
)
|
||||
],
|
||||
onChanged: model.onChangeRoomSort)),
|
||||
const Spacer(),
|
||||
Button(
|
||||
onPressed: model.onRefreshRoom,
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(6),
|
||||
child: Icon(FluentIcons.refresh),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Button(
|
||||
onPressed: () => model.onCreateRoom(),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(3),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(FluentIcons.add),
|
||||
SizedBox(width: 6),
|
||||
Text("创建房间")
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 6,
|
||||
),
|
||||
Text(
|
||||
model.selectedRoomType?.desc ?? "",
|
||||
style: TextStyle(fontSize: 13, color: Colors.white.withOpacity(.4)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String getUITitle(BuildContext context, PartyRoomHomeUIModel model) =>
|
||||
"PartyRoom";
|
||||
}
|
@ -1,204 +0,0 @@
|
||||
import 'package:starcitizen_doctor/base/ui_model.dart';
|
||||
import 'package:starcitizen_doctor/generated/grpc/party_room_server/index.pb.dart';
|
||||
import 'package:starcitizen_doctor/ui/party_room/dialogs/party_room_create_dialog_ui_model.dart';
|
||||
|
||||
import 'dialogs/party_room_create_dialog_ui.dart';
|
||||
import 'party_room_chat_ui_model.dart';
|
||||
|
||||
class PartyRoomHomeUIModel extends BaseUIModel {
|
||||
String? pingServerMessage;
|
||||
|
||||
Map<String?, RoomType>? roomTypes;
|
||||
|
||||
RoomType? selectedRoomType;
|
||||
|
||||
RoomSubtype? selectedRoomSubType;
|
||||
|
||||
final roomStatus = <RoomStatus, String>{
|
||||
RoomStatus.All: "全部",
|
||||
RoomStatus.Open: "开启中",
|
||||
RoomStatus.Full: "已满员",
|
||||
RoomStatus.Closed: "已封闭",
|
||||
RoomStatus.WillOffline: "房主离线",
|
||||
RoomStatus.Offline: "已离线",
|
||||
};
|
||||
|
||||
RoomStatus selectedStatus = RoomStatus.All;
|
||||
|
||||
final roomSorts = <RoomSortType, String>{
|
||||
RoomSortType.Default: "默认",
|
||||
RoomSortType.MostPlayerNumber: "最多玩家",
|
||||
RoomSortType.MinimumPlayerNumber: "最少玩家",
|
||||
RoomSortType.RecentlyCreated: "最近创建",
|
||||
RoomSortType.OldestCreated: "最久创建",
|
||||
};
|
||||
|
||||
RoomSortType selectedSortType = RoomSortType.Default;
|
||||
|
||||
int pageNum = 0;
|
||||
|
||||
List<RoomData>? rooms;
|
||||
|
||||
final pageCtrl = PageController();
|
||||
|
||||
@override
|
||||
BaseUIModel? onCreateChildUIModel(modelKey) {
|
||||
switch (modelKey) {
|
||||
case "chat":
|
||||
return PartyRoomChatUIModel(this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future loadData() async {
|
||||
// if (pingServerMessage != "") {
|
||||
// pingServerMessage = null;
|
||||
// notifyListeners();
|
||||
// await _pingServer();
|
||||
// }
|
||||
// await _loadPage();
|
||||
}
|
||||
|
||||
// @override
|
||||
// reloadData() async {
|
||||
// pageNum = 0;
|
||||
// rooms = null;
|
||||
// notifyListeners();
|
||||
// _touchUser();
|
||||
// return super.reloadData();
|
||||
// }
|
||||
|
||||
// _loadPage() async {
|
||||
// final r = await handleError(() => PartyRoomGrpcServer.getRoomList(
|
||||
// RoomListPageReqData(
|
||||
// pageNum: Int64.tryParseInt("$pageNum"),
|
||||
// typeID: selectedRoomType?.id ?? "",
|
||||
// subTypeID: selectedRoomSubType?.id ?? "",
|
||||
// status: selectedStatus)));
|
||||
// if (r == null) return;
|
||||
// if (r.pageData.hasNext) {
|
||||
// pageNum++;
|
||||
// } else {
|
||||
// pageNum = -1;
|
||||
// }
|
||||
// rooms = r.rooms;
|
||||
// notifyListeners();
|
||||
// }
|
||||
//
|
||||
// _pingServer() async {
|
||||
// try {
|
||||
// final r = await PartyRoomGrpcServer.pingServer();
|
||||
// dPrint(
|
||||
// "[PartyRoomHomeUIModel] Connected! serverVersion ==> ${r.serverVersion}");
|
||||
// pingServerMessage = "";
|
||||
// notifyListeners();
|
||||
// } catch (e) {
|
||||
// pingServerMessage = "服务器连接失败,请稍后重试。\n$e";
|
||||
// notifyListeners();
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Future<void> _loadTypes() async {
|
||||
// final r = await handleError(() => PartyRoomGrpcServer.getRoomTypes());
|
||||
// if (r == null) return;
|
||||
// selectedRoomType =
|
||||
// RoomType(id: "", name: "全部", desc: "查看所有类型的房间,寻找一起玩的伙伴。");
|
||||
// selectedRoomSubType = RoomSubtype(id: "", name: "全部");
|
||||
// roomTypes = {"": selectedRoomType!};
|
||||
// for (var element in r.roomTypes) {
|
||||
// roomTypes![element.id] = element;
|
||||
// }
|
||||
// notifyListeners();
|
||||
// }
|
||||
|
||||
Map<String, RoomSubtype>? getCurRoomSubTypes() {
|
||||
if (selectedRoomType?.subTypes == null) return null;
|
||||
Map<String, RoomSubtype> types = {};
|
||||
for (var element in selectedRoomType!.subTypes) {
|
||||
types[element.id] = element;
|
||||
}
|
||||
if (types.isEmpty) return null;
|
||||
final allSubType = RoomSubtype(id: "", name: "全部");
|
||||
selectedRoomSubType ??= allSubType;
|
||||
return {"all": allSubType}..addAll(types);
|
||||
}
|
||||
|
||||
void onChangeRoomType(RoomType? value) {
|
||||
selectedRoomType = value;
|
||||
selectedRoomSubType = null;
|
||||
reloadData();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void onChangeRoomStatus(RoomStatus? value) {
|
||||
if (value == null) return;
|
||||
selectedStatus = value;
|
||||
reloadData();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void onChangeRoomSort(RoomSortType? value) {
|
||||
if (value == null) return;
|
||||
selectedSortType = value;
|
||||
reloadData();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void onChangeRoomSubType(RoomSubtype? value) {
|
||||
if (value == null) return;
|
||||
selectedRoomSubType = value;
|
||||
reloadData();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
onCreateRoom() async {
|
||||
final room = await showDialog(
|
||||
context: context!,
|
||||
dismissWithEsc: false,
|
||||
builder: (BuildContext context) {
|
||||
return BaseUIContainer(
|
||||
uiCreate: () => PartyRoomCreateDialogUI(),
|
||||
modelCreate: () =>
|
||||
PartyRoomCreateDialogUIModel(Map.from(roomTypes!)));
|
||||
},
|
||||
);
|
||||
if (room == null) return;
|
||||
dPrint(room);
|
||||
reloadData();
|
||||
}
|
||||
|
||||
onRefreshRoom() {
|
||||
reloadData();
|
||||
}
|
||||
|
||||
// Future<void> _touchUser() async {
|
||||
// if (getCreatedChildUIModel<PartyRoomChatUIModel>("chat")?.selectRoom ==
|
||||
// null) {
|
||||
// final userName = await globalUIModel.getRunningGameUser();
|
||||
// if (userName == null) return;
|
||||
// // 检测用户已加入的房间
|
||||
// final room = await handleError(() =>
|
||||
// PartyRoomGrpcServer.touchUserRoom(userName, AppConf.deviceUUID));
|
||||
// dPrint("touch room == ${room?.toProto3Json()}");
|
||||
// if (room == null || room.id == "") return;
|
||||
// onTapRoom(room);
|
||||
// }
|
||||
// }
|
||||
|
||||
onTapRoom(RoomData item) {
|
||||
getCreatedChildUIModel<PartyRoomChatUIModel>("chat", create: true)
|
||||
?.setRoom(item);
|
||||
notifyListeners();
|
||||
pageCtrl.animateToPage(1,
|
||||
duration: const Duration(milliseconds: 100), curve: Curves.easeInExpo);
|
||||
}
|
||||
|
||||
void checkUIInit() {
|
||||
if (getCreatedChildUIModel<PartyRoomChatUIModel>("chat")?.selectRoom !=
|
||||
null) {
|
||||
pageCtrl.jumpToPage(1);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user