Add ability to block and report in search results

This commit is contained in:
tommyxchow 2022-02-09 17:54:43 -05:00
parent 97a742f74c
commit 8eeed4e716
7 changed files with 103 additions and 60 deletions

View file

@ -37,7 +37,7 @@ abstract class _UserStoreBase with Store {
final success = await twitchApi.blockUser(userId: targetId, headers: headers);
// Add a slight delay between requests, otherwise the blocked list won't properly update.
// Weird behavior, might be something to do with PUT request and time to create and update resource?
await Future.delayed(const Duration(milliseconds: 200));
await Future.delayed(const Duration(milliseconds: 300));
if (success) await refreshBlockedUsers(headers: headers);
}

View file

@ -31,7 +31,7 @@ class ChatDetails extends StatelessWidget {
chatDetails: chatDetails,
userLogin: userLogin,
),
)
),
],
),
),

View file

@ -126,8 +126,8 @@ class _ChattersListState extends State<ChattersList> {
),
),
...chatDetailStore.filteredUsers.expandIndexed(
(index, type) => [
if (type.isNotEmpty) ...[
(index, users) => [
if (users.isNotEmpty) ...[
SliverPadding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0, top: 20.0),
sliver: SliverToBoxAdapter(
@ -141,8 +141,8 @@ class _ChattersListState extends State<ChattersList> {
padding: const EdgeInsets.only(left: 10.0, right: 10.0, top: 5.0),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => Text(type[index]),
childCount: type.length,
(context, index) => Text(users[index]),
childCount: users.length,
),
),
),

View file

@ -4,6 +4,7 @@ import 'package:frosty/constants/constants.dart';
import 'package:frosty/models/channel.dart';
import 'package:frosty/screens/channel/video_chat.dart';
import 'package:frosty/screens/home/stores/search_store.dart';
import 'package:frosty/widgets/block_report_modal.dart';
import 'package:frosty/widgets/loading_indicator.dart';
import 'package:frosty/widgets/profile_picture.dart';
import 'package:mobx/mobx.dart';
@ -60,42 +61,56 @@ class SearchResultsChannels extends StatelessWidget {
),
);
case FutureStatus.fulfilled:
final List<ChannelQuery> results = future.result;
final results = (future.result as List<ChannelQuery>)
.where((channel) => !searchStore.authStore.user.blockedUsers.map((blockedUser) => blockedUser.userId).contains(channel.id));
return SliverList(
delegate: SliverChildListDelegate.fixed([
...results.map(
(channel) => ListTile(
title: Text(
regexEnglish.hasMatch(channel.displayName) ? channel.displayName : channel.displayName + ' (${channel.broadcasterLogin})'),
leading: ProfilePicture(userLogin: channel.broadcasterLogin),
trailing: channel.isLive
? ClipRRect(
borderRadius: BorderRadius.circular(5.0),
child: Container(
color: const Color(0xFFF44336),
padding: const EdgeInsets.all(10.0),
child: const Text(
'LIVE',
style: TextStyle(fontWeight: FontWeight.bold),
(channel) {
final displayName =
regexEnglish.hasMatch(channel.displayName) ? channel.displayName : channel.displayName + ' (${channel.broadcasterLogin})';
return ListTile(
title: Text(displayName),
leading: ProfilePicture(userLogin: channel.broadcasterLogin),
trailing: channel.isLive
? ClipRRect(
borderRadius: BorderRadius.circular(5.0),
child: Container(
color: const Color(0xFFF44336),
padding: const EdgeInsets.all(10.0),
child: const Text(
'LIVE',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
),
)
: null,
subtitle: channel.isLive
? Text('Uptime: ${DateTime.now().difference(DateTime.parse(channel.startedAt)).toString().split('.')[0]}')
: null,
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => VideoChat(
userId: channel.id,
userName: channel.displayName,
userLogin: channel.broadcasterLogin,
)
: null,
subtitle: channel.isLive
? Text('Uptime: ${DateTime.now().difference(DateTime.parse(channel.startedAt)).toString().split('.')[0]}')
: null,
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => VideoChat(
userId: channel.id,
userName: channel.displayName,
userLogin: channel.broadcasterLogin,
),
),
),
),
),
onLongPress: () => showModalBottomSheet(
context: context,
builder: (context) => BlockReportModal(
authStore: searchStore.authStore,
name: displayName,
userLogin: channel.broadcasterLogin,
userId: channel.id,
),
),
);
},
),
ListTile(
title: Text('Go to channel "$query"'),

View file

@ -4,10 +4,9 @@ import 'package:frosty/constants/constants.dart';
import 'package:frosty/models/stream.dart';
import 'package:frosty/screens/channel/video_chat.dart';
import 'package:frosty/screens/home/stores/list_store.dart';
import 'package:frosty/widgets/block_button.dart';
import 'package:frosty/widgets/block_report_modal.dart';
import 'package:frosty/widgets/loading_indicator.dart';
import 'package:frosty/widgets/profile_picture.dart';
import 'package:frosty/widgets/report_button.dart';
import 'package:intl/intl.dart';
/// A tappable card widget that displays a stream's thumbnail and details.
@ -56,28 +55,11 @@ class StreamCard extends StatelessWidget {
),
onLongPress: () => showModalBottomSheet(
context: context,
builder: (context) => Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
width: double.infinity,
child: BlockButton(
authStore: listStore.authStore,
targetUser: streamerName,
targetUserId: streamInfo.userId,
simple: false,
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
width: double.infinity,
child: ReportButton(
userLogin: streamInfo.userLogin,
name: streamerName,
),
),
],
builder: (context) => BlockReportModal(
authStore: listStore.authStore,
name: streamerName,
userLogin: streamInfo.userLogin,
userId: streamInfo.userId,
),
),
child: Padding(

View file

@ -27,7 +27,7 @@ class BlockButton extends StatelessWidget {
builder: (context) => AlertDialog(
title: isBlocked ? const Text('Unblock') : const Text('Block'),
content: Text(
'Are you sure you want to ${isBlocked ? 'unblock $targetUser?' : 'block $targetUser? This will hide them from channel lists and chat messages.'}'),
'Are you sure you want to ${isBlocked ? 'unblock $targetUser?' : 'block $targetUser? This will remove them from channel lists, search results, and chat messages.'}'),
actions: [
TextButton(
onPressed: Navigator.of(context).pop,

View file

@ -0,0 +1,46 @@
import 'package:flutter/widgets.dart';
import 'package:frosty/core/auth/auth_store.dart';
import 'package:frosty/widgets/block_button.dart';
import 'package:frosty/widgets/report_button.dart';
class BlockReportModal extends StatelessWidget {
final AuthStore authStore;
final String name;
final String userLogin;
final String userId;
const BlockReportModal({
Key? key,
required this.authStore,
required this.name,
required this.userLogin,
required this.userId,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
width: double.infinity,
child: BlockButton(
authStore: authStore,
targetUser: name,
targetUserId: userId,
simple: false,
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
width: double.infinity,
child: ReportButton(
userLogin: userLogin,
name: name,
),
),
],
);
}
}