mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
253 lines
8.9 KiB
Dart
253 lines
8.9 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:PiliPlus/common/widgets/badge.dart';
|
|
import 'package:PiliPlus/common/widgets/pendant_avatar.dart';
|
|
import 'package:PiliPlus/grpc/bilibili/app/im/v1.pb.dart'
|
|
show Session, SessionId, SessionPageType, SessionType, UnreadStyle;
|
|
import 'package:PiliPlus/models/common/badge_type.dart';
|
|
import 'package:PiliPlus/pages/whisper_secondary/view.dart';
|
|
import 'package:PiliPlus/utils/extension.dart';
|
|
import 'package:PiliPlus/utils/utils.dart';
|
|
import 'package:fixnum/fixnum.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
|
import 'package:get/get.dart';
|
|
|
|
class WhisperSessionItem extends StatelessWidget {
|
|
const WhisperSessionItem({
|
|
super.key,
|
|
required this.item,
|
|
required this.onSetTop,
|
|
required this.onSetMute,
|
|
required this.onRemove,
|
|
});
|
|
|
|
final Session item;
|
|
final Function(bool isTop, SessionId id) onSetTop;
|
|
final Function(bool isMuted, Int64 talkerUid) onSetMute;
|
|
final ValueChanged<int?> onRemove;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
Map? vipInfo = item.sessionInfo.hasVipInfo()
|
|
? jsonDecode(item.sessionInfo.vipInfo)
|
|
: null;
|
|
final ThemeData theme = Theme.of(context);
|
|
return ListTile(
|
|
tileColor: item.isPinned
|
|
? theme.colorScheme.onInverseSurface
|
|
.withOpacity(Get.isDarkMode ? 0.4 : 0.8)
|
|
: null,
|
|
onLongPress: () {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) {
|
|
return AlertDialog(
|
|
clipBehavior: Clip.hardEdge,
|
|
contentPadding: const EdgeInsets.symmetric(vertical: 12),
|
|
content: DefaultTextStyle(
|
|
style: const TextStyle(fontSize: 14),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
ListTile(
|
|
dense: true,
|
|
onTap: () {
|
|
Get.back();
|
|
onSetTop(item.isPinned, item.id);
|
|
},
|
|
title: Text(item.isPinned ? '移除置顶' : '置顶'),
|
|
),
|
|
if (item.id.privateId.hasTalkerUid())
|
|
ListTile(
|
|
dense: true,
|
|
onTap: () {
|
|
Get.back();
|
|
onSetMute(item.isMuted, item.id.privateId.talkerUid);
|
|
},
|
|
title: Text('${item.isMuted ? '关闭' : '开启'}免打扰'),
|
|
),
|
|
if (item.id.privateId.hasTalkerUid())
|
|
ListTile(
|
|
dense: true,
|
|
onTap: () {
|
|
Get.back();
|
|
onRemove(item.id.privateId.talkerUid.toInt());
|
|
},
|
|
title: const Text('删除'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
onTap: () {
|
|
if (item.hasUnread()) {
|
|
item.clearUnread();
|
|
if (context.mounted) {
|
|
(context as Element).markNeedsBuild();
|
|
}
|
|
}
|
|
if (item.id.privateId.hasTalkerUid()) {
|
|
Get.toNamed(
|
|
'/whisperDetail',
|
|
arguments: {
|
|
'talkerId': item.id.privateId.talkerUid.toInt(),
|
|
'name': item.sessionInfo.sessionName,
|
|
'face': item.sessionInfo.avatar.fallbackLayers.layers.first
|
|
.resource.resImage.imageSrc.remote.url,
|
|
if (item.sessionInfo.avatar.hasMid())
|
|
'mid': item.sessionInfo.avatar.mid.toInt(),
|
|
},
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (item.id.foldId.hasType()) {
|
|
SessionPageType? sessionPageType = switch (item.id.foldId.type) {
|
|
SessionType.SESSION_TYPE_UNKNOWN =>
|
|
SessionPageType.SESSION_PAGE_TYPE_UNKNOWN,
|
|
SessionType.SESSION_TYPE_GROUP =>
|
|
SessionPageType.SESSION_PAGE_TYPE_GROUP,
|
|
SessionType.SESSION_TYPE_GROUP_FOLD =>
|
|
SessionPageType.SESSION_PAGE_TYPE_GROUP,
|
|
SessionType.SESSION_TYPE_UNFOLLOWED =>
|
|
SessionPageType.SESSION_PAGE_TYPE_UNFOLLOWED,
|
|
SessionType.SESSION_TYPE_STRANGER =>
|
|
SessionPageType.SESSION_PAGE_TYPE_STRANGER,
|
|
SessionType.SESSION_TYPE_DUSTBIN =>
|
|
SessionPageType.SESSION_PAGE_TYPE_DUSTBIN,
|
|
SessionType.SESSION_TYPE_CUSTOMER_FOLD =>
|
|
SessionPageType.SESSION_PAGE_TYPE_CUSTOMER,
|
|
SessionType.SESSION_TYPE_AI_FOLD =>
|
|
SessionPageType.SESSION_PAGE_TYPE_AI,
|
|
SessionType.SESSION_TYPE_CUSTOMER_ACCOUNT =>
|
|
SessionPageType.SESSION_PAGE_TYPE_CUSTOMER,
|
|
_ => null,
|
|
};
|
|
if (sessionPageType != null) {
|
|
Get.to(
|
|
WhisperSecPage(
|
|
name: item.sessionInfo.sessionName,
|
|
sessionPageType: sessionPageType,
|
|
),
|
|
);
|
|
} else {
|
|
SmartDialog.showToast(item.id.foldId.type.name);
|
|
}
|
|
}
|
|
},
|
|
leading: Builder(
|
|
builder: (context) {
|
|
Widget buildAvatar() {
|
|
final pendant = item.sessionInfo.avatar.fallbackLayers.layers
|
|
.getOrNull(1)
|
|
?.resource;
|
|
final offcial = item.sessionInfo.avatar.fallbackLayers.layers
|
|
.lastOrNull?.resource.resImage.imageSrc;
|
|
return PendantAvatar(
|
|
size: 42,
|
|
badgeSize: 14,
|
|
avatar: item.sessionInfo.avatar.fallbackLayers.layers.first
|
|
.resource.resImage.imageSrc.remote.url,
|
|
garbPendantImage:
|
|
pendant?.resImage.imageSrc.remote.hasUrl() == true
|
|
? pendant!.resImage.imageSrc.remote.url
|
|
: pendant?.resAnimation.webpSrc.remote.url,
|
|
isVip: vipInfo?['status'] != null && vipInfo!['status'] > 0,
|
|
officialType: offcial?.hasLocalValue() == true
|
|
? switch (offcial!.localValue) {
|
|
3 => 0,
|
|
4 => 1,
|
|
_ => null,
|
|
}
|
|
: null,
|
|
);
|
|
}
|
|
|
|
return GestureDetector(
|
|
onTap: item.sessionInfo.avatar.hasMid()
|
|
? () {
|
|
Get.toNamed(
|
|
'/member?mid=${item.sessionInfo.avatar.mid}',
|
|
);
|
|
}
|
|
: null,
|
|
child: item.hasUnread() &&
|
|
item.unread.style != UnreadStyle.UNREAD_STYLE_NONE
|
|
? Badge(
|
|
label: item.unread.style == UnreadStyle.UNREAD_STYLE_NUMBER
|
|
? Text(" ${item.unread.number} ")
|
|
: null,
|
|
alignment: Alignment.topRight,
|
|
child: buildAvatar(),
|
|
)
|
|
: buildAvatar(),
|
|
);
|
|
},
|
|
),
|
|
title: Row(
|
|
children: [
|
|
Text(
|
|
item.sessionInfo.sessionName,
|
|
style: TextStyle(
|
|
fontSize: 15,
|
|
color: vipInfo?['status'] != null &&
|
|
vipInfo!['status'] > 0 &&
|
|
vipInfo['type'] == 2
|
|
? context.vipColor
|
|
: null,
|
|
),
|
|
),
|
|
if (item.sessionInfo.userLabel.style.borderedLabel.hasText()) ...[
|
|
const SizedBox(width: 5),
|
|
PBadge(
|
|
isStack: false,
|
|
type: PBadgeType.line_secondary,
|
|
size: PBadgeSize.small,
|
|
fontSize: 10,
|
|
isBold: false,
|
|
text: item.sessionInfo.userLabel.style.borderedLabel.text,
|
|
),
|
|
],
|
|
if (item.sessionInfo.isLive) ...[
|
|
const SizedBox(width: 5),
|
|
Image.asset('assets/images/live/live.gif', height: 15),
|
|
],
|
|
],
|
|
),
|
|
subtitle: Text(
|
|
item.msgSummary.rawMsg,
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: theme.textTheme.labelMedium!
|
|
.copyWith(color: theme.colorScheme.outline),
|
|
),
|
|
trailing: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
if (item.isMuted) ...[
|
|
Icon(
|
|
size: 16,
|
|
Icons.notifications_off,
|
|
color: theme.colorScheme.outline,
|
|
),
|
|
if (item.hasTimestamp()) const SizedBox(width: 4),
|
|
],
|
|
if (item.hasTimestamp())
|
|
Text(
|
|
Utils.dateFormat((item.timestamp ~/ 1000000).toInt(),
|
|
formatType: "day"),
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: theme.colorScheme.outline,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|