feat: chat badges

closes #15
This commit is contained in:
2025-05-19 11:44:13 +01:00
parent cb1c995023
commit 86a8181aea
3 changed files with 61 additions and 1 deletions

View File

@ -64,6 +64,16 @@ class ChatWidget extends StatelessWidget {
.where((e) => e.kind == 9735)
.map((e) => ZapReceipt.fromEvent(e))
.toList();
// pubkey -> Set<badge a tag>
final badgeAwards = filteredChat
.where((e) => e.kind == 8)
.map((e) => e.getTags("p").map((p) => (p, e.getFirstTag("a")!)))
.expand((v) => v)
.groupFoldBy(
(e) => e.$1,
(Set<String>? acc, v) => (acc ?? {})..add(v.$2),
);
return Column(
spacing: 8,
crossAxisAlignment: CrossAxisAlignment.start,
@ -81,6 +91,15 @@ class ChatWidget extends StatelessWidget {
key: Key("chat:${filteredChat[idx].id}"),
stream: stream,
msg: filteredChat[idx],
badges:
badgeAwards[filteredChat[idx].pubKey]
?.map(
(a) => ChatBadgeWidget.fromATag(
a,
key: Key("${filteredChat[idx].pubKey}:$a"),
),
)
.toList(),
),
1312 => ChatRaidMessage(
event: filteredChat[idx],

View File

@ -72,3 +72,28 @@ class ChatBadgeAwardWidget extends StatelessWidget {
);
}
}
class ChatBadgeWidget extends StatelessWidget {
final Nip01Event badge;
const ChatBadgeWidget({super.key, required this.badge});
static Widget fromATag(String aTag, {Key? key}) {
return FutureBuilder(
future: ndk.requests.query(filters: [aTagToFilter(aTag)]).future,
builder: (context, state) {
final ev = state.data?.firstOrNull;
if (ev == null) return SizedBox();
return ChatBadgeWidget(badge: ev, key: key);
},
);
}
@override
Widget build(BuildContext context) {
final image = badge.getFirstTag("image");
if (image?.isEmpty ?? true) return SizedBox();
return ProxyImg(url: image, resize: 24, height: 24, key: UniqueKey());
}
}

View File

@ -13,8 +13,14 @@ import 'package:zap_stream_flutter/widgets/profile.dart';
class ChatMessageWidget extends StatelessWidget {
final StreamEvent stream;
final Nip01Event msg;
final List<Widget>? badges;
const ChatMessageWidget({super.key, required this.stream, required this.msg});
const ChatMessageWidget({
super.key,
required this.stream,
required this.msg,
this.badges,
});
@override
Widget build(BuildContext context) {
@ -60,6 +66,16 @@ class ChatMessageWidget extends StatelessWidget {
),
),
),
if (badges?.isNotEmpty ?? false) TextSpan(text: " "),
if (badges?.isNotEmpty ?? false)
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Row(
spacing: 4,
mainAxisSize: MainAxisSize.min,
children: badges!,
),
),
TextSpan(text: " "),
...textToSpans(msg.content, msg.tags, msg.pubKey),
],