mirror of
https://gitlab.com/openlp/openlp-mobile-remote.git
synced 2024-12-22 03:42:48 +00:00
BLoC pattern in settings page
This commit is contained in:
parent
d01d9a8965
commit
441d407005
@ -21,8 +21,10 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
|
||||
import 'src/bloc/settings_bloc.dart';
|
||||
import 'src/openlp_mobile_remote_app.dart';
|
||||
import 'src/configurations/app_theme.dart';
|
||||
import 'src/configurations/app_localizations.dart';
|
||||
@ -60,7 +62,10 @@ void main() => runApp(
|
||||
},
|
||||
routes: <String, WidgetBuilder>{
|
||||
'/': (context) => OpenLPMobileRemoteApp(),
|
||||
'/settings': (context) => Settings(),
|
||||
'/settings': (context) => BlocProvider(
|
||||
builder: (context) => SettingsBloc(),
|
||||
child: Settings(),
|
||||
),
|
||||
},
|
||||
),
|
||||
);
|
||||
|
139
lib/src/bloc/settings_bloc.dart
Normal file
139
lib/src/bloc/settings_bloc.dart
Normal file
@ -0,0 +1,139 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
class SettingsState {
|
||||
String serverIp;
|
||||
int serverPort;
|
||||
bool useHttps;
|
||||
bool needsAuth;
|
||||
String userId;
|
||||
String userPassword;
|
||||
|
||||
SettingsState({
|
||||
@required this.serverIp,
|
||||
@required this.serverPort,
|
||||
@required this.useHttps,
|
||||
@required this.needsAuth,
|
||||
@required this.userId,
|
||||
@required this.userPassword,
|
||||
});
|
||||
|
||||
SettingsState copyWith({
|
||||
String serverIp,
|
||||
int serverPort,
|
||||
bool useHttps,
|
||||
bool needsAuth,
|
||||
String userId,
|
||||
String userPassword,
|
||||
}) {
|
||||
return SettingsState(
|
||||
serverIp: serverIp ?? this.serverIp,
|
||||
serverPort: serverPort ?? this.serverPort,
|
||||
useHttps: useHttps ?? this.useHttps,
|
||||
needsAuth: needsAuth ?? this.needsAuth,
|
||||
userId: userId ?? this.userId,
|
||||
userPassword: userPassword ?? this.userPassword,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class SettingsEvent<T> extends Equatable {
|
||||
final T value;
|
||||
SettingsEvent(this.value, [List props = const <dynamic>[]]) : super(props);
|
||||
}
|
||||
|
||||
class SetServerIpEvent extends SettingsEvent<String> {
|
||||
SetServerIpEvent(String value) : super(value);
|
||||
}
|
||||
|
||||
class SetServerPortEvent extends SettingsEvent<int> {
|
||||
SetServerPortEvent(int value) : super(value);
|
||||
}
|
||||
|
||||
class SetUseHttpsEvent extends SettingsEvent<bool> {
|
||||
SetUseHttpsEvent(bool value) : super(value);
|
||||
}
|
||||
|
||||
class SetNeedsAuthEvent extends SettingsEvent<bool> {
|
||||
SetNeedsAuthEvent(bool value) : super(value);
|
||||
}
|
||||
|
||||
class SetUserIdEvent extends SettingsEvent<String> {
|
||||
SetUserIdEvent(String value) : super(value);
|
||||
}
|
||||
|
||||
class SetUserPasswordEvent extends SettingsEvent<String> {
|
||||
SetUserPasswordEvent(String value) : super(value);
|
||||
}
|
||||
|
||||
class SettingsBloc extends Bloc<SettingsEvent, SettingsState> {
|
||||
@override
|
||||
SettingsState get initialState => SettingsState(
|
||||
serverIp: '192.168.1.100',
|
||||
serverPort: 4316,
|
||||
useHttps: false,
|
||||
needsAuth: false,
|
||||
userId: 'openlp',
|
||||
userPassword: 'password',
|
||||
);
|
||||
|
||||
void setServerIp(String serverIp) {
|
||||
if (serverIp == null || serverIp.isEmpty) {
|
||||
return;
|
||||
}
|
||||
dispatch(SetServerIpEvent(serverIp));
|
||||
}
|
||||
|
||||
void setServerPort(String serverPortStr) {
|
||||
if (serverPortStr == null || serverPortStr.isEmpty) {
|
||||
return;
|
||||
}
|
||||
int serverPort = int.tryParse(serverPortStr);
|
||||
dispatch(SetServerPortEvent(serverPort));
|
||||
}
|
||||
|
||||
void setUseHttps(bool useHttps) {
|
||||
dispatch(SetUseHttpsEvent(useHttps));
|
||||
}
|
||||
|
||||
void setNeedsAuth(bool needsAuth) {
|
||||
dispatch(SetNeedsAuthEvent(needsAuth));
|
||||
}
|
||||
|
||||
void setUserId(String userId) {
|
||||
if (userId == null || userId.isEmpty) {
|
||||
return;
|
||||
}
|
||||
dispatch(SetUserIdEvent(userId));
|
||||
}
|
||||
|
||||
void setUserPassword(String userPassword) {
|
||||
if (userPassword == null || userPassword.isEmpty) {
|
||||
return;
|
||||
}
|
||||
dispatch(SetUserPasswordEvent(userPassword));
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<SettingsState> mapEventToState(SettingsEvent event) async* {
|
||||
if (event is SetServerIpEvent) {
|
||||
yield this.currentState.copyWith(serverIp: event.value);
|
||||
}
|
||||
if (event is SetServerPortEvent) {
|
||||
yield this.currentState.copyWith(serverPort: event.value);
|
||||
}
|
||||
if (event is SetUseHttpsEvent) {
|
||||
yield this.currentState.copyWith(useHttps: event.value);
|
||||
}
|
||||
if (event is SetNeedsAuthEvent) {
|
||||
yield this.currentState.copyWith(needsAuth: event.value);
|
||||
}
|
||||
if (event is SetUserIdEvent) {
|
||||
yield this.currentState.copyWith(userId: event.value);
|
||||
}
|
||||
if (event is SetUserPasswordEvent) {
|
||||
yield this.currentState.copyWith(userPassword: event.value);
|
||||
}
|
||||
}
|
||||
}
|
@ -21,122 +21,119 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import '../bloc/settings_bloc.dart';
|
||||
import '../configurations/app_localizations.dart';
|
||||
|
||||
class Settings extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() => _SettingState();
|
||||
}
|
||||
|
||||
class _SettingState extends State<Settings> {
|
||||
String serverIp;
|
||||
int serverPort;
|
||||
bool useHttps;
|
||||
bool needsAuth;
|
||||
String userId;
|
||||
String userPassword;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
serverIp = '192.168.1.100';
|
||||
serverPort = 4316;
|
||||
useHttps = false;
|
||||
needsAuth = false;
|
||||
userId = 'openlp';
|
||||
userPassword = 'password';
|
||||
}
|
||||
|
||||
class Settings extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final SettingsBloc bloc = BlocProvider.of<SettingsBloc>(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(AppLocalizations.of(context).translate('settings')),
|
||||
),
|
||||
body: ListView(
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
title: Text(
|
||||
AppLocalizations.of(context).translate('settings_server_ip')),
|
||||
subtitle: Text(serverIp),
|
||||
onTap: () {
|
||||
showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => _InputDialog(AppLocalizations.of(context)
|
||||
.translate('dialog_server_ip_title')),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
AppLocalizations.of(context).translate('settings_server_port')),
|
||||
subtitle: Text('$serverPort'),
|
||||
onTap: () {
|
||||
showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => _InputDialog(AppLocalizations.of(context)
|
||||
.translate('dialog_server_port_title')),
|
||||
);
|
||||
},
|
||||
),
|
||||
CheckboxListTile(
|
||||
title: Text(
|
||||
AppLocalizations.of(context).translate('settings_use_https')),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
useHttps = value;
|
||||
});
|
||||
},
|
||||
value: useHttps,
|
||||
),
|
||||
Divider(),
|
||||
CheckboxListTile(
|
||||
title: Text(
|
||||
AppLocalizations.of(context).translate('settings_needs_auth')),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
needsAuth = value;
|
||||
});
|
||||
},
|
||||
value: needsAuth,
|
||||
),
|
||||
ListTile(
|
||||
enabled: needsAuth,
|
||||
title: Text(
|
||||
AppLocalizations.of(context).translate('settings_user_id')),
|
||||
subtitle: Text(userId),
|
||||
onTap: () {
|
||||
showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => _InputDialog(AppLocalizations.of(context)
|
||||
.translate('dialog_server_user_id_title')),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
enabled: needsAuth,
|
||||
title: Text(
|
||||
AppLocalizations.of(context).translate('settings_user_pass')),
|
||||
subtitle: Text(userPassword),
|
||||
onTap: () {
|
||||
showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => _InputDialog(AppLocalizations.of(context)
|
||||
.translate('dialog_server_user_pass_title')),
|
||||
);
|
||||
},
|
||||
),
|
||||
Divider(),
|
||||
ListTile(
|
||||
title: Text(AppLocalizations.of(context)
|
||||
.translate('settings_about_openlp')),
|
||||
onTap: () {
|
||||
launch('https://openlp.org/');
|
||||
},
|
||||
),
|
||||
],
|
||||
body: BlocBuilder<SettingsBloc, SettingsState>(
|
||||
builder: (context, state) => ListView(
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
title: Text(
|
||||
AppLocalizations.of(context).translate('settings_server_ip')),
|
||||
subtitle: Text(state.serverIp ?? ''),
|
||||
onTap: () async {
|
||||
String title = AppLocalizations.of(context)
|
||||
.translate('dialog_server_ip_title');
|
||||
String serverIp = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return _InputDialog(title,
|
||||
initialValue: state.serverIp,
|
||||
keyboardType: TextInputType.url);
|
||||
},
|
||||
);
|
||||
bloc.setServerIp(serverIp);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text(AppLocalizations.of(context)
|
||||
.translate('settings_server_port')),
|
||||
subtitle: Text('${state.serverPort}'),
|
||||
onTap: () async {
|
||||
String title = AppLocalizations.of(context)
|
||||
.translate('dialog_server_port_title');
|
||||
String serverPortStr = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return _InputDialog(title,
|
||||
initialValue: '${state.serverPort}',
|
||||
keyboardType: TextInputType.numberWithOptions(
|
||||
decimal: true, signed: true));
|
||||
},
|
||||
);
|
||||
bloc.setServerPort(serverPortStr);
|
||||
},
|
||||
),
|
||||
CheckboxListTile(
|
||||
title: Text(
|
||||
AppLocalizations.of(context).translate('settings_use_https')),
|
||||
value: state.useHttps,
|
||||
onChanged: (value) {
|
||||
bloc.setUseHttps(value);
|
||||
},
|
||||
),
|
||||
Divider(),
|
||||
CheckboxListTile(
|
||||
title: Text(AppLocalizations.of(context)
|
||||
.translate('settings_needs_auth')),
|
||||
value: state.needsAuth,
|
||||
onChanged: (value) {
|
||||
bloc.setNeedsAuth(value);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
enabled: state.needsAuth,
|
||||
title: Text(
|
||||
AppLocalizations.of(context).translate('settings_user_id')),
|
||||
subtitle: Text(state.userId ?? ''),
|
||||
onTap: () async {
|
||||
String title = AppLocalizations.of(context)
|
||||
.translate('dialog_server_user_id_title');
|
||||
String userId = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) =>
|
||||
_InputDialog(title, initialValue: state.userId),
|
||||
);
|
||||
bloc.setUserId(userId);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
enabled: state.needsAuth,
|
||||
title: Text(
|
||||
AppLocalizations.of(context).translate('settings_user_pass')),
|
||||
subtitle: Text(state.userPassword ?? ''),
|
||||
onTap: () async {
|
||||
String title = AppLocalizations.of(context)
|
||||
.translate('dialog_server_user_pass_title');
|
||||
String userPassword = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) =>
|
||||
_InputDialog(title, initialValue: state.userPassword),
|
||||
);
|
||||
bloc.setUserPassword(userPassword);
|
||||
},
|
||||
),
|
||||
Divider(),
|
||||
ListTile(
|
||||
title: Text(AppLocalizations.of(context)
|
||||
.translate('settings_about_openlp')),
|
||||
onTap: () {
|
||||
launch('https://openlp.org/');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -144,27 +141,36 @@ class _SettingState extends State<Settings> {
|
||||
|
||||
class _InputDialog extends StatelessWidget {
|
||||
final String title;
|
||||
final String initialValue;
|
||||
final TextInputType keyboardType;
|
||||
final TextEditingController _textEditingController;
|
||||
|
||||
_InputDialog(this.title);
|
||||
_InputDialog(
|
||||
this.title, {
|
||||
this.initialValue,
|
||||
this.keyboardType = TextInputType.text,
|
||||
}) : _textEditingController = TextEditingController(text: initialValue ?? '');
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(this.title),
|
||||
contentPadding: EdgeInsets.all(15),
|
||||
content: TextField(autofocus: true),
|
||||
content: TextField(
|
||||
autofocus: true,
|
||||
controller: _textEditingController,
|
||||
keyboardType: keyboardType,
|
||||
),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
child: Text(AppLocalizations.of(context).translate('button_cancel')),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
Navigator.pop(context, '');
|
||||
},
|
||||
),
|
||||
FlatButton(
|
||||
child: Text(AppLocalizations.of(context).translate('button_ok')),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, '');
|
||||
},
|
||||
onPressed: () => Navigator.pop(context, _textEditingController.text),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
@ -34,6 +34,9 @@ dependencies:
|
||||
url_launcher: ^5.1.2
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
bloc: ^0.14.0
|
||||
flutter_bloc: ^0.20.0
|
||||
equatable: ^0.4.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
Reference in New Issue
Block a user