feat: listen to stream info on stream page

fix: disable cache read/write in RxFilter
This commit is contained in:
2025-05-13 13:25:23 +01:00
parent 3e18f7544e
commit efd95837ea
3 changed files with 42 additions and 30 deletions

View File

@ -1,10 +1,12 @@
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:chewie/chewie.dart'; import 'package:chewie/chewie.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:ndk/ndk.dart';
import 'package:video_player/video_player.dart'; import 'package:video_player/video_player.dart';
import 'package:wakelock_plus/wakelock_plus.dart'; import 'package:wakelock_plus/wakelock_plus.dart';
import 'package:zap_stream_flutter/imgproxy.dart'; import 'package:zap_stream_flutter/imgproxy.dart';
import 'package:zap_stream_flutter/main.dart'; 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/theme.dart';
import 'package:zap_stream_flutter/utils.dart'; import 'package:zap_stream_flutter/utils.dart';
import 'package:zap_stream_flutter/widgets/button.dart'; import 'package:zap_stream_flutter/widgets/button.dart';
@ -72,6 +74,23 @@ class _StreamPage extends State<StreamPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return RxFilter<Nip01Event>(
relays: widget.stream.info.relays,
filters: [
Filter(
kinds: [widget.stream.event.kind],
authors: [widget.stream.event.pubKey],
dTags: [widget.stream.event.getDtag()!],
),
],
builder: (ctx, state) {
final stream = StreamEvent(state?.firstOrNull ?? widget.stream.event);
return _buildStream(context, stream);
},
);
}
Widget _buildStream(BuildContext context, StreamEvent stream) {
return Column( return Column(
spacing: 4, spacing: 4,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -84,24 +103,21 @@ class _StreamPage extends State<StreamPage> {
: Container( : Container(
color: LAYER_1, color: LAYER_1,
child: child:
(widget.stream.info.image?.isNotEmpty ?? false) (stream.info.image?.isNotEmpty ?? false)
? CachedNetworkImage( ? CachedNetworkImage(
imageUrl: proxyImg( imageUrl: proxyImg(context, stream.info.image!),
context,
widget.stream.info.image!,
),
) )
: null, : null,
), ),
), ),
Text( Text(
widget.stream.info.title ?? "", stream.info.title ?? "",
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 18), style: TextStyle(fontWeight: FontWeight.w600, fontSize: 18),
), ),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
ProfileWidget.pubkey(widget.stream.info.host), ProfileWidget.pubkey(stream.info.host),
Row( Row(
spacing: 8, spacing: 8,
children: [ children: [
@ -118,13 +134,13 @@ class _StreamPage extends State<StreamPage> {
constraints: BoxConstraints.expand(), constraints: BoxConstraints.expand(),
builder: (ctx) { builder: (ctx) {
return ZapWidget( return ZapWidget(
pubkey: widget.stream.info.host, pubkey: stream.info.host,
target: widget.stream.event, target: stream.event,
zapTags: zapTags:
// tag goal onto zap request // tag goal onto zap request
widget.stream.info.goal != null stream.info.goal != null
? [ ? [
["e", widget.stream.info.goal!], ["e", stream.info.goal!],
] ]
: null, : null,
); );
@ -132,11 +148,11 @@ class _StreamPage extends State<StreamPage> {
); );
}, },
), ),
if (widget.stream.info.participants != null) if (stream.info.participants != null)
PillWidget( PillWidget(
color: LAYER_1, color: LAYER_1,
child: Text( child: Text(
"${widget.stream.info.participants} viewers", "${stream.info.participants} viewers",
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -147,7 +163,7 @@ class _StreamPage extends State<StreamPage> {
), ),
], ],
), ),
Expanded(child: ChatWidget(stream: widget.stream)), Expanded(child: ChatWidget(stream: stream)),
], ],
); );
} }

View File

@ -37,8 +37,6 @@ class _RxFilter<T> extends State<RxFilter<T>> {
developer.log("RX:SEDNING ${widget.filters}"); developer.log("RX:SEDNING ${widget.filters}");
_response = ndk.requests.subscription( _response = ndk.requests.subscription(
filters: widget.filters, filters: widget.filters,
cacheRead: true,
cacheWrite: true,
explicitRelays: widget.relays, explicitRelays: widget.relays,
); );
if (!widget.leaveOpen) { if (!widget.leaveOpen) {
@ -55,7 +53,6 @@ class _RxFilter<T> extends State<RxFilter<T>> {
}) })
.listen((events) { .listen((events) {
setState(() { setState(() {
_events ??= HashMap();
developer.log( developer.log(
"RX:GOT ${events.length} events for ${widget.filters}", "RX:GOT ${events.length} events for ${widget.filters}",
); );
@ -66,9 +63,10 @@ class _RxFilter<T> extends State<RxFilter<T>> {
void _replaceInto(Nip01Event ev) { void _replaceInto(Nip01Event ev) {
final evKey = _eventKey(ev); final evKey = _eventKey(ev);
final existing = _events?[evKey]; _events ??= HashMap();
final existing = _events![evKey];
if (existing == null || existing.$1 < ev.createdAt) { if (existing == null || existing.$1 < ev.createdAt) {
_events?[evKey] = ( _events![evKey] = (
ev.createdAt, ev.createdAt,
widget.mapper != null ? widget.mapper!(ev) : ev as T, widget.mapper != null ? widget.mapper!(ev) : ev as T,
); );
@ -79,7 +77,7 @@ class _RxFilter<T> extends State<RxFilter<T>> {
if ([0, 3].contains(ev.kind) || (ev.kind >= 10000 && ev.kind < 20000)) { if ([0, 3].contains(ev.kind) || (ev.kind >= 10000 && ev.kind < 20000)) {
return "${ev.kind}:${ev.pubKey}"; return "${ev.kind}:${ev.pubKey}";
} else if (ev.kind >= 30000 && ev.kind < 40000) { } else if (ev.kind >= 30000 && ev.kind < 40000) {
return "${ev.kind}:${ev.pubKey}:${ev.getDtag()}"; return "${ev.kind}:${ev.pubKey}:${ev.getDtag()!}";
} else { } else {
return ev.id; return ev.id;
} }

View File

@ -22,18 +22,16 @@ class ChatWidget extends StatelessWidget {
muteLists.add(ndk.accounts.getPublicKey()!); muteLists.add(ndk.accounts.getPublicKey()!);
} }
return RxFilter<Nip01Event>( var filters = [
key: Key("stream:chat:${stream.aTag}"),
relays: stream.info.relays,
filters: [
Filter(kinds: [1311, 9735], limit: 200, aTags: [stream.aTag]), Filter(kinds: [1311, 9735], limit: 200, aTags: [stream.aTag]),
Filter(kinds: [Nip51List.kMute], authors: muteLists), Filter(kinds: [Nip51List.kMute], authors: muteLists),
...(stream.info.goal != null ];
? [ if (stream.info.goal != null) {
Filter(kinds: [9041], ids: [stream.info.goal!]), filters.add(Filter(kinds: [9041], ids: [stream.info.goal!]));
] }
: []), return RxFilter<Nip01Event>(
], relays: stream.info.relays,
filters: filters,
builder: (ctx, state) { builder: (ctx, state) {
final mutedPubkeys = final mutedPubkeys =
(state ?? []) (state ?? [])