feat: badge awards

This commit is contained in:
2025-05-19 11:11:12 +01:00
parent 3eac1c4bfa
commit 46d60994a8
5 changed files with 88 additions and 13 deletions

View File

@ -580,3 +580,8 @@ TLVEntity decodeBech32ToTLVEntity(String input) {
return TLVEntity(data.hrp, [TLV(0, data8bit.length, data8bit)]);
}
}
Filter aTagToFilter(String tag) {
final ts = tag.split(":");
return Filter(kinds: [int.parse(ts[0])], authors: [ts[1]], dTags: [ts[2]]);
}

View File

@ -5,6 +5,7 @@ import 'package:zap_stream_flutter/main.dart';
import 'package:zap_stream_flutter/rx_filter.dart';
import 'package:zap_stream_flutter/theme.dart';
import 'package:zap_stream_flutter/utils.dart';
import 'package:zap_stream_flutter/widgets/chat_badge.dart';
import 'package:zap_stream_flutter/widgets/chat_message.dart';
import 'package:zap_stream_flutter/widgets/chat_raid.dart';
import 'package:zap_stream_flutter/widgets/chat_write.dart';
@ -27,6 +28,7 @@ class ChatWidget extends StatelessWidget {
Filter(kinds: [1311, 9735], limit: 200, aTags: [stream.aTag]),
Filter(kinds: [1312], limit: 200, aTags: [stream.aTag]),
Filter(kinds: [Nip51List.kMute], authors: muteLists),
Filter(kinds: [8], authors: [stream.info.host]),
];
return RxFilter<Nip01Event>(
Key("stream:chat:${stream.aTag}"),
@ -89,6 +91,10 @@ class ChatWidget extends StatelessWidget {
stream: stream,
zap: filteredChat[idx],
),
8 => ChatBadgeAwardWidget(
event: filteredChat[idx],
stream: stream,
),
_ => SizedBox(),
},
),

View File

@ -0,0 +1,74 @@
import 'package:flutter/widgets.dart';
import 'package:ndk/entities.dart';
import 'package:zap_stream_flutter/imgproxy.dart';
import 'package:zap_stream_flutter/main.dart';
import 'package:zap_stream_flutter/theme.dart';
import 'package:zap_stream_flutter/utils.dart';
import 'package:zap_stream_flutter/widgets/profile.dart';
class ChatBadgeAwardWidget extends StatelessWidget {
final Nip01Event event;
final StreamEvent stream;
const ChatBadgeAwardWidget({
super.key,
required this.event,
required this.stream,
});
@override
Widget build(BuildContext context) {
final aTag = event.getFirstTag("a");
if (aTag == null) return SizedBox();
return Container(
margin: EdgeInsets.symmetric(horizontal: 2, vertical: 4),
padding: EdgeInsets.all(5),
decoration: BoxDecoration(color: LAYER_1, borderRadius: DEFAULT_BR),
child: FutureBuilder(
future: ndk.requests.query(filters: [aTagToFilter(aTag)]).future,
builder: (context, state) {
final badge = state.data?.firstOrNull;
final image = badge?.getFirstTag("image");
final name = badge?.getFirstTag("name");
final title = badge?.getFirstTag("description");
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8,
children: [
Column(
spacing: 8,
children: [
if (image?.isNotEmpty ?? false)
ProxyImg(url: image, width: 64),
if (name?.isNotEmpty ?? false)
Text(
name!,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
if (title?.isNotEmpty ?? false)
Text(
title!,
style: TextStyle(color: LAYER_5),
textAlign: TextAlign.center,
),
],
),
Text(
"Awarded to: ",
style: TextStyle(fontWeight: FontWeight.w500),
),
...event
.getTags("p")
.map((e) => ProfileWidget.pubkey(e, size: 20)),
],
);
},
),
);
}
}

View File

@ -53,16 +53,9 @@ class __ChatRaidMessage extends State<ChatRaidMessage>
Widget build(BuildContext context) {
if (_from == null || _to == null) return SizedBox.shrink();
final otherLink = (_isRaiding ? _to : _from).split(":");
final otherEvent = ndk.requests.query(
filters: [
Filter(
kinds: [int.parse(otherLink[0])],
authors: [otherLink[1]],
dTags: [otherLink[2]],
),
],
);
final otherTag = _isRaiding ? _to : _from;
final otherLink = otherTag.split(":");
final otherEvent = ndk.requests.query(filters: [aTagToFilter(otherTag)]);
return Container(
padding: EdgeInsets.all(8),

View File

@ -1,14 +1,11 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_markdown_plus/flutter_markdown_plus.dart';
import 'package:flutter_svg/svg.dart';
import 'package:ndk/ndk.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:zap_stream_flutter/imgproxy.dart';
import 'package:zap_stream_flutter/rx_filter.dart';
import 'package:zap_stream_flutter/theme.dart';
import 'package:zap_stream_flutter/utils.dart';
import 'package:zap_stream_flutter/widgets/nostr_text.dart';
class StreamCardsWidget extends StatelessWidget {
final StreamEvent stream;