Skip to content

Commit

Permalink
Add the Mature Content Warning (#52)
Browse files Browse the repository at this point in the history
* bloc & repo bits for storing the shouldBypass preference

* put a toggle in the settings screen

* component with the warning on

* hijack the ChannelBloc to show the mature warning

* Show the warning on the channel page when told to
  • Loading branch information
ponkey364 authored Mar 16, 2022
1 parent 532ec30 commit bc86a58
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 6 deletions.
25 changes: 25 additions & 0 deletions lib/blocs/repos/channel_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:graphql_flutter/graphql_flutter.dart';

import 'package:glimesh_app/repository.dart';
import 'package:glimesh_app/models.dart';
import 'package:glimesh_app/blocs/repos/settings_bloc.dart';

/* Events */
@immutable
Expand All @@ -30,10 +31,25 @@ class WatchChannel extends ChannelEvent {
List<Object> get props => [this.channelId];
}

class ShowMatureWarning extends ChannelEvent {
final Channel channel;
final SettingsBloc settingsBloc;

ShowMatureWarning({required this.channel, required this.settingsBloc});

@override
List<Object?> get props => [this.channel, this.settingsBloc];
}

/* State */
@immutable
abstract class ChannelState extends Equatable {}

class ChannelShowMatureWarning extends ChannelState {
@override
List<Object?> get props => [];
}

class ChannelLoading extends ChannelState {
@override
List<Object?> get props => [];
Expand Down Expand Up @@ -79,6 +95,15 @@ class ChannelBloc extends Bloc<ChannelEvent, ChannelState> {
edgeRoute: edgeRoute,
));
});

on<ShowMatureWarning>((event, emit) async {
if (event.settingsBloc.bypassMatureWarning ||
!event.channel.matureContent) {
this.add(WatchChannel(channelId: event.channel.id));
} else {
emit(ChannelShowMatureWarning());
}
});
}

Future<JanusEdgeRoute> watchChannel(int channelId) async {
Expand Down
47 changes: 44 additions & 3 deletions lib/blocs/repos/settings_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,27 @@ class ChangeLocale extends SettingsEvent {
List<Object> get props => [this.locale];
}

class ChangeBypassMatureWarning extends SettingsEvent {
final bool shouldBypass;

ChangeBypassMatureWarning({required this.shouldBypass});

@override
List<Object> get props => [this.shouldBypass];
}

@immutable
abstract class SettingsState extends Equatable {}

class InitialState extends SettingsState {
final ThemeMode theme;
final Locale locale;
final bool bypassMatureWarning;

InitialState({required this.theme, required this.locale});
InitialState(
{required this.theme,
required this.locale,
required this.bypassMatureWarning});

@override
List<Object> get props => [theme, locale];
Expand All @@ -62,30 +75,58 @@ class LocaleChanged extends SettingsState {
List<Object> get props => [newLocale];
}

class BypassMatureWarningChanged extends SettingsState {
final bool shouldBypass;

BypassMatureWarningChanged(this.shouldBypass);

@override
List<Object> get props => [this.shouldBypass];
}

class SettingsBloc extends Bloc<SettingsEvent, SettingsState> {
late SettingsRepository repo;

ThemeMode currentTheme = ThemeMode.system;
Locale currentLocale = Locale("en");
bool bypassMatureWarning = false;

SettingsBloc()
: super(InitialState(theme: ThemeMode.system, locale: Locale('en'))) {
: super(InitialState(
theme: ThemeMode.system,
locale: Locale('en'),
bypassMatureWarning: false)) {
on<InitSettingsData>((_, emit) async {
var prefs = await SharedPreferences.getInstance();

repo = SettingsRepository(prefs: prefs);

currentTheme = await repo.getTheme();
currentLocale = await repo.getLocale() ?? Locale('en');
emit(InitialState(theme: currentTheme, locale: currentLocale));
bypassMatureWarning = await repo.getShouldBypassMatureWarning();

emit(InitialState(
theme: currentTheme,
locale: currentLocale,
bypassMatureWarning: bypassMatureWarning));
});

on<ChangeTheme>((event, emit) async {
currentTheme = event.appTheme;
await repo.setTheme(currentTheme);
emit(ThemeChanged(currentTheme));
});

on<ChangeLocale>((event, emit) async {
currentLocale = event.locale;
await repo.setLocale(currentLocale);
emit(LocaleChanged(currentLocale));
});

on<ChangeBypassMatureWarning>((event, emit) async {
bypassMatureWarning = event.shouldBypass;
await repo.setShouldBypassMatureWarning(bypassMatureWarning);
emit(BypassMatureWarningChanged(bypassMatureWarning));
});
}
}
42 changes: 42 additions & 0 deletions lib/components/MatureWarning.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import 'package:flutter/material.dart';
import 'package:gettext_i18n/gettext_i18n.dart';

class MatureWarning extends StatelessWidget {
final void Function() onAccept;

MatureWarning({required this.onAccept});

@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
context.t("Mature Content Warning"),
style: Theme.of(context).textTheme.headline4,
),
Text(
context.t(
"The streamer has flagged this channel as only appropriate for Mature Audiences."),
style: Theme.of(context).textTheme.subtitle1,
),
Text(
context.t("Do you wish to continue?"),
style: Theme.of(context).textTheme.subtitle1,
),
Padding(
child: OutlinedButton(
child: Text(context.t("Agree & View Channel")),
onPressed: onAccept,
),
padding: EdgeInsets.symmetric(vertical: 8),
),
ElevatedButton(
child: Text(context.t("Go Back")),
onPressed: () => Navigator.pop(context),
)
],
));
}
}
6 changes: 4 additions & 2 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,10 @@ class GlimeshApp extends StatelessWidget {
providers: [
// Channel Bloc
BlocProvider<ChannelBloc>(
create: (context) =>
bloc..add(WatchChannel(channelId: channel.id)),
create: (context) => bloc
..add(ShowMatureWarning(
channel: channel,
settingsBloc: context.read<SettingsBloc>())),
),
// ChatMessagesBloc
BlocProvider<ChatMessagesBloc>(
Expand Down
8 changes: 8 additions & 0 deletions lib/repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,12 @@ class SettingsRepository {
? prefs.remove("settings.locale.country")
: prefs.setString("settings.locale.country", locale_country);
}

Future<bool> getShouldBypassMatureWarning() async {
return prefs.getBool("settings.bypassMatureWarning") ?? false;
}

setShouldBypassMatureWarning(bool value) async {
prefs.setBool("settings.bypassMatureWarning", value);
}
}
13 changes: 13 additions & 0 deletions lib/screens/ChannelScreen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:glimesh_app/components/Chat.dart';
import 'package:glimesh_app/components/FTLPlayer.dart';
import 'package:glimesh_app/components/StreamTitle.dart';
import 'package:glimesh_app/components/Loading.dart';
import 'package:glimesh_app/components/MatureWarning.dart';
import 'package:glimesh_app/models.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:gettext_i18n/gettext_i18n.dart';
Expand All @@ -27,6 +28,18 @@ class ChannelScreen extends StatelessWidget {
);
}

if (state is ChannelShowMatureWarning) {
return Scaffold(
body: SafeArea(
child: MatureWarning(onAccept: () {
context
.read<ChannelBloc>()
.add(WatchChannel(channelId: channel.id));
}),
),
);
}

if (state is ChannelNotLoaded) {
return Scaffold(
body: SafeArea(
Expand Down
17 changes: 16 additions & 1 deletion lib/screens/SettingsScreen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ class _SettingsWidgetState extends State<SettingsWidget> {
body: Container(
child: Column(children: [
_buildThemeSelector(context),
_buildLocaleSelector(context)
_buildLocaleSelector(context),
_buildMatureWarningToggle(context),
]),
margin: EdgeInsets.all(4),
),
Expand Down Expand Up @@ -79,4 +80,18 @@ class _SettingsWidgetState extends State<SettingsWidget> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
);
}

Widget _buildMatureWarningToggle(BuildContext context) {
return Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text(context.t("Bypass Mature Content Warning")),
Switch(
value: context.select((SettingsBloc bloc) => bloc.bypassMatureWarning),
onChanged: (newVal) {
context
.read<SettingsBloc>()
.add(ChangeBypassMatureWarning(shouldBypass: newVal));
},
),
]);
}
}

0 comments on commit bc86a58

Please sign in to comment.