feat: follow button

closes #22
This commit is contained in:
2025-05-14 14:04:44 +01:00
parent 465c6f222e
commit e0e9175536
5 changed files with 111 additions and 17 deletions

View File

@ -0,0 +1,69 @@
import 'package:flutter/material.dart';
import 'package:zap_stream_flutter/main.dart';
import 'package:zap_stream_flutter/theme.dart';
import 'package:zap_stream_flutter/widgets/button.dart';
class FollowButton extends StatelessWidget {
final String pubkey;
final void Function()? onTap;
final void Function()? onFollow;
final void Function()? onUnfollow;
const FollowButton({
super.key,
required this.pubkey,
this.onTap,
this.onFollow,
this.onUnfollow,
});
@override
Widget build(BuildContext context) {
final signer = ndk.accounts.getLoggedAccount()?.signer;
if (signer == null || signer.getPublicKey() == pubkey) {
return SizedBox.shrink();
}
return FutureBuilder(
future: ndk.follows.getContactList(signer.getPublicKey()),
builder: (context, state) {
final follows = state.data?.contacts ?? [];
final isFollowing = follows.contains(pubkey);
return BasicButton(
Row(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 4,
children: [
Icon(isFollowing ? Icons.person_remove : Icons.person_add, size: 16),
Text(
isFollowing ? "Unfollow" : "Follow",
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 12),
decoration: BoxDecoration(
borderRadius: DEFAULT_BR,
color: LAYER_2,
),
onTap: () async {
if (onTap != null) {
onTap!();
}
if (isFollowing) {
await ndk.follows.broadcastRemoveContact(pubkey);
if (onUnfollow != null) {
onUnfollow!();
}
} else {
await ndk.follows.broadcastAddContact(pubkey);
if (onFollow != null) {
onFollow!();
}
}
},
);
},
);
}
}

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:ndk/ndk.dart';
import 'package:zap_stream_flutter/theme.dart';
import 'package:zap_stream_flutter/widgets/button_follow.dart';
import 'package:zap_stream_flutter/widgets/mute_button.dart';
import 'package:zap_stream_flutter/widgets/nostr_text.dart';
import 'package:zap_stream_flutter/widgets/profile.dart';
@ -75,6 +76,12 @@ class _ChatModalWidget extends State<ChatModalWidget> {
],
),
if (_showEmojiPicker) ReactionWidget(event: widget.event),
FollowButton(
pubkey: widget.event.pubKey,
onTap: () {
Navigator.pop(context);
},
),
MuteButton(
pubkey: widget.event.pubKey,
onTap: () {

View File

@ -39,7 +39,10 @@ class MuteButton extends StatelessWidget {
),
),
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 12),
decoration: BoxDecoration(color: WARNING, borderRadius: DEFAULT_BR),
decoration: BoxDecoration(
color: isMuted ? LAYER_2 : WARNING,
borderRadius: DEFAULT_BR,
),
onTap: () async {
if (onTap != null) {
onTap!();

View File

@ -60,13 +60,18 @@ class StreamCardsWidget extends StatelessWidget {
decoration: BoxDecoration(color: LAYER_2, borderRadius: DEFAULT_BR),
child: Column(
spacing: 8,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (title?.isNotEmpty ?? false)
Text(
Center(
child: Text(
title!,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
if (image?.isNotEmpty ?? false)
Center(
child:
link != null
? GestureDetector(
onTap: () {
@ -75,11 +80,14 @@ class StreamCardsWidget extends StatelessWidget {
child: CachedNetworkImage(
imageUrl: proxyImg(context, image!),
errorWidget:
(_, _, _) =>
SvgPicture.asset("assets/svg/logo.svg", height: 40),
(_, _, _) => SvgPicture.asset(
"assets/svg/logo.svg",
height: 40,
),
),
)
: CachedNetworkImage(imageUrl: proxyImg(context, image!)),
),
MarkdownBody(
data: card.content,
onTapLink: (text, href, title) {

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:zap_stream_flutter/theme.dart';
import 'package:zap_stream_flutter/utils.dart';
import 'package:zap_stream_flutter/widgets/button_follow.dart';
import 'package:zap_stream_flutter/widgets/profile.dart';
import 'package:zap_stream_flutter/widgets/stream_cards.dart';
@ -23,6 +24,12 @@ class StreamInfoWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ProfileWidget.pubkey(stream.info.host),
FollowButton(
pubkey: stream.info.host,
onTap: () {
Navigator.pop(context);
},
),
Text(
stream.info.title ?? "",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),