feat: 私信查看
This commit is contained in:
24
lib/pages/whisperDetail/controller.dart
Normal file
24
lib/pages/whisperDetail/controller.dart
Normal file
@ -0,0 +1,24 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/http/msg.dart';
|
||||
import 'package:pilipala/models/msg/session.dart';
|
||||
|
||||
class WhisperDetailController extends GetxController {
|
||||
late int talkerId;
|
||||
RxString name = ''.obs;
|
||||
RxList<MessageItem> messageList = <MessageItem>[].obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
talkerId = int.parse(Get.parameters['talkerId']!);
|
||||
name.value = Get.parameters['name']!;
|
||||
}
|
||||
|
||||
Future querySessionMsg() async {
|
||||
var res = await MsgHttp.sessionMsg(talkerId: talkerId);
|
||||
if (res['status']) {
|
||||
messageList.value = res['data'].messages;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
4
lib/pages/whisperDetail/index.dart
Normal file
4
lib/pages/whisperDetail/index.dart
Normal file
@ -0,0 +1,4 @@
|
||||
library whisper_detail;
|
||||
|
||||
export './controller.dart';
|
||||
export './view.dart';
|
||||
167
lib/pages/whisperDetail/view.dart
Normal file
167
lib/pages/whisperDetail/view.dart
Normal file
@ -0,0 +1,167 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/pages/whisperDetail/controller.dart';
|
||||
|
||||
import 'widget/chat_item.dart';
|
||||
|
||||
class WhisperDetailPage extends StatefulWidget {
|
||||
const WhisperDetailPage({super.key});
|
||||
|
||||
@override
|
||||
State<WhisperDetailPage> createState() => _WhisperDetailPageState();
|
||||
}
|
||||
|
||||
class _WhisperDetailPageState extends State<WhisperDetailPage> {
|
||||
final WhisperDetailController _whisperDetailController =
|
||||
Get.put(WhisperDetailController());
|
||||
late Future _futureBuilderFuture;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_futureBuilderFuture = _whisperDetailController.querySessionMsg();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
scrolledUnderElevation: 0,
|
||||
title: SizedBox(
|
||||
width: double.infinity,
|
||||
height: 50,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 34,
|
||||
height: 34,
|
||||
child: IconButton(
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||
backgroundColor:
|
||||
MaterialStateProperty.resolveWith((states) {
|
||||
return Theme.of(context)
|
||||
.colorScheme
|
||||
.primaryContainer
|
||||
.withOpacity(0.6);
|
||||
}),
|
||||
),
|
||||
onPressed: () => Get.back(),
|
||||
icon: Icon(
|
||||
Icons.arrow_back_outlined,
|
||||
size: 18,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => Text(
|
||||
_whisperDetailController.name.value,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 36, height: 36),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
body: FutureBuilder(
|
||||
future: _futureBuilderFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
Map data = snapshot.data as Map;
|
||||
if (data['status']) {
|
||||
List messageList = _whisperDetailController.messageList;
|
||||
return Obx(
|
||||
() => messageList.isEmpty
|
||||
? const SizedBox()
|
||||
: ListView.builder(
|
||||
itemCount: messageList.length,
|
||||
shrinkWrap: true,
|
||||
reverse: true,
|
||||
itemBuilder: (_, int i) {
|
||||
if (i == 0) {
|
||||
return Column(
|
||||
children: [
|
||||
ChatItem(item: messageList[i]),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return ChatItem(item: messageList[i]);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// 请求错误
|
||||
return const SizedBox();
|
||||
}
|
||||
} else {
|
||||
// 骨架屏
|
||||
return const SizedBox();
|
||||
}
|
||||
},
|
||||
),
|
||||
bottomNavigationBar: Container(
|
||||
width: double.infinity,
|
||||
height: MediaQuery.of(context).padding.bottom + 70,
|
||||
padding: EdgeInsets.only(
|
||||
left: 8,
|
||||
right: 12,
|
||||
bottom: MediaQuery.of(context).padding.bottom,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
width: 4,
|
||||
color: Theme.of(context).colorScheme.primary.withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
// IconButton(
|
||||
// onPressed: () {},
|
||||
// icon: Icon(
|
||||
// Icons.add_circle_outline,
|
||||
// color: Theme.of(context).colorScheme.outline,
|
||||
// ),
|
||||
// ),
|
||||
IconButton(
|
||||
onPressed: () {},
|
||||
icon: Icon(
|
||||
Icons.emoji_emotions_outlined,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
),
|
||||
// Expanded(
|
||||
// child: Container(
|
||||
// height: 42,
|
||||
// decoration: BoxDecoration(
|
||||
// color: Theme.of(context).colorScheme.primary.withOpacity(0.1),
|
||||
// borderRadius: BorderRadius.circular(40.0),
|
||||
// ),
|
||||
// child: TextField(
|
||||
// readOnly: true,
|
||||
// style: Theme.of(context).textTheme.titleMedium,
|
||||
// decoration: const InputDecoration(
|
||||
// border: InputBorder.none, // 移除默认边框
|
||||
// hintText: '请输入内容', // 提示文本
|
||||
// contentPadding: EdgeInsets.symmetric(
|
||||
// horizontal: 12.0, vertical: 12.0), // 内边距
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
const SizedBox(width: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
189
lib/pages/whisperDetail/widget/chat_item.dart
Normal file
189
lib/pages/whisperDetail/widget/chat_item.dart
Normal file
@ -0,0 +1,189 @@
|
||||
// ignore_for_file: must_be_immutable
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/utils/utils.dart';
|
||||
|
||||
class ChatItem extends StatelessWidget {
|
||||
dynamic item;
|
||||
|
||||
ChatItem({
|
||||
super.key,
|
||||
this.item,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool isOwner = item.senderUid == 17340771;
|
||||
bool isPic = item.msgType == 2;
|
||||
bool isText = item.msgType == 1;
|
||||
bool isSystem =
|
||||
item.msgType == 18 || item.msgType == 10 || item.msgType == 13;
|
||||
int msgType = item.msgType;
|
||||
Map content = item.content ?? '';
|
||||
return isSystem
|
||||
? (msgType == 10
|
||||
? SystemNotice(item: item)
|
||||
: msgType == 13
|
||||
? SystemNotice2(item: item)
|
||||
: const SizedBox())
|
||||
: Row(
|
||||
children: [
|
||||
if (!isOwner) const SizedBox(width: 12),
|
||||
if (isOwner) const Spacer(),
|
||||
Container(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 300.0, // 设置最大宽度为200.0
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: isOwner
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.secondaryContainer,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: const Radius.circular(16),
|
||||
topRight: const Radius.circular(16),
|
||||
bottomLeft: Radius.circular(isOwner ? 16 : 6),
|
||||
bottomRight: Radius.circular(isOwner ? 6 : 16),
|
||||
),
|
||||
),
|
||||
margin: const EdgeInsets.only(top: 12),
|
||||
padding: EdgeInsets.only(
|
||||
top: 8,
|
||||
bottom: 6,
|
||||
left: isPic ? 8 : 12,
|
||||
right: isPic ? 8 : 12,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: isOwner
|
||||
? CrossAxisAlignment.end
|
||||
: CrossAxisAlignment.start,
|
||||
children: [
|
||||
isText
|
||||
? Text(
|
||||
content['content'],
|
||||
style: TextStyle(
|
||||
color: isOwner
|
||||
? Theme.of(context).colorScheme.onPrimary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSecondaryContainer),
|
||||
)
|
||||
: isPic
|
||||
? NetworkImgLayer(
|
||||
width: 220,
|
||||
height:
|
||||
220 * content['height'] / content['width'],
|
||||
src: content['url'],
|
||||
)
|
||||
: const SizedBox(),
|
||||
SizedBox(height: isPic ? 7 : 2),
|
||||
Text(
|
||||
Utils.dateFormat(item.timestamp),
|
||||
style: Theme.of(context).textTheme.labelSmall!.copyWith(
|
||||
color: isOwner
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.onPrimary
|
||||
.withOpacity(0.8)
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSecondaryContainer
|
||||
.withOpacity(0.8)),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
if (!isOwner) const Spacer(),
|
||||
if (isOwner) const SizedBox(width: 12),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SystemNotice extends StatelessWidget {
|
||||
dynamic item;
|
||||
SystemNotice({super.key, this.item});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Map content = item.content ?? '';
|
||||
return Row(
|
||||
children: [
|
||||
const SizedBox(width: 12),
|
||||
Container(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 300.0, // 设置最大宽度为200.0
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(16),
|
||||
topRight: Radius.circular(16),
|
||||
bottomLeft: Radius.circular(6),
|
||||
bottomRight: Radius.circular(16),
|
||||
),
|
||||
),
|
||||
margin: const EdgeInsets.only(top: 12),
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(content['title'],
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium!
|
||||
.copyWith(fontWeight: FontWeight.bold)),
|
||||
Text(
|
||||
Utils.dateFormat(item.timestamp),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall!
|
||||
.copyWith(color: Theme.of(context).colorScheme.outline),
|
||||
)
|
||||
],
|
||||
),
|
||||
Divider(
|
||||
color: Theme.of(context).colorScheme.primary.withOpacity(0.1),
|
||||
),
|
||||
Text(
|
||||
content['text'],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SystemNotice2 extends StatelessWidget {
|
||||
dynamic item;
|
||||
SystemNotice2({super.key, this.item});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Map content = item.content ?? '';
|
||||
return Row(
|
||||
children: [
|
||||
const SizedBox(width: 12),
|
||||
Container(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 300.0, // 设置最大宽度为200.0
|
||||
),
|
||||
margin: const EdgeInsets.only(top: 12),
|
||||
padding: const EdgeInsets.only(bottom: 6),
|
||||
child: NetworkImgLayer(
|
||||
width: 320,
|
||||
height: 150,
|
||||
src: content['pic_url'],
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user