mirror of
https://gitlab.com/openlp/openlp-mobile-remote.git
synced 2024-12-22 11:52:49 +00:00
BLoC pattern in settings page
This commit is contained in:
parent
d01d9a8965
commit
441d407005
@ -21,8 +21,10 @@
|
|||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
|
|
||||||
|
import 'src/bloc/settings_bloc.dart';
|
||||||
import 'src/openlp_mobile_remote_app.dart';
|
import 'src/openlp_mobile_remote_app.dart';
|
||||||
import 'src/configurations/app_theme.dart';
|
import 'src/configurations/app_theme.dart';
|
||||||
import 'src/configurations/app_localizations.dart';
|
import 'src/configurations/app_localizations.dart';
|
||||||
@ -60,7 +62,10 @@ void main() => runApp(
|
|||||||
},
|
},
|
||||||
routes: <String, WidgetBuilder>{
|
routes: <String, WidgetBuilder>{
|
||||||
'/': (context) => OpenLPMobileRemoteApp(),
|
'/': (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.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
|
import '../bloc/settings_bloc.dart';
|
||||||
import '../configurations/app_localizations.dart';
|
import '../configurations/app_localizations.dart';
|
||||||
|
|
||||||
class Settings extends StatefulWidget {
|
class Settings extends StatelessWidget {
|
||||||
@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';
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final SettingsBloc bloc = BlocProvider.of<SettingsBloc>(context);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(AppLocalizations.of(context).translate('settings')),
|
title: Text(AppLocalizations.of(context).translate('settings')),
|
||||||
),
|
),
|
||||||
body: ListView(
|
body: BlocBuilder<SettingsBloc, SettingsState>(
|
||||||
children: <Widget>[
|
builder: (context, state) => ListView(
|
||||||
ListTile(
|
children: <Widget>[
|
||||||
title: Text(
|
ListTile(
|
||||||
AppLocalizations.of(context).translate('settings_server_ip')),
|
title: Text(
|
||||||
subtitle: Text(serverIp),
|
AppLocalizations.of(context).translate('settings_server_ip')),
|
||||||
onTap: () {
|
subtitle: Text(state.serverIp ?? ''),
|
||||||
showDialog<String>(
|
onTap: () async {
|
||||||
context: context,
|
String title = AppLocalizations.of(context)
|
||||||
builder: (context) => _InputDialog(AppLocalizations.of(context)
|
.translate('dialog_server_ip_title');
|
||||||
.translate('dialog_server_ip_title')),
|
String serverIp = await showDialog<String>(
|
||||||
);
|
context: context,
|
||||||
},
|
builder: (context) {
|
||||||
),
|
return _InputDialog(title,
|
||||||
ListTile(
|
initialValue: state.serverIp,
|
||||||
title: Text(
|
keyboardType: TextInputType.url);
|
||||||
AppLocalizations.of(context).translate('settings_server_port')),
|
},
|
||||||
subtitle: Text('$serverPort'),
|
);
|
||||||
onTap: () {
|
bloc.setServerIp(serverIp);
|
||||||
showDialog<String>(
|
},
|
||||||
context: context,
|
),
|
||||||
builder: (context) => _InputDialog(AppLocalizations.of(context)
|
ListTile(
|
||||||
.translate('dialog_server_port_title')),
|
title: Text(AppLocalizations.of(context)
|
||||||
);
|
.translate('settings_server_port')),
|
||||||
},
|
subtitle: Text('${state.serverPort}'),
|
||||||
),
|
onTap: () async {
|
||||||
CheckboxListTile(
|
String title = AppLocalizations.of(context)
|
||||||
title: Text(
|
.translate('dialog_server_port_title');
|
||||||
AppLocalizations.of(context).translate('settings_use_https')),
|
String serverPortStr = await showDialog<String>(
|
||||||
onChanged: (value) {
|
context: context,
|
||||||
setState(() {
|
builder: (context) {
|
||||||
useHttps = value;
|
return _InputDialog(title,
|
||||||
});
|
initialValue: '${state.serverPort}',
|
||||||
},
|
keyboardType: TextInputType.numberWithOptions(
|
||||||
value: useHttps,
|
decimal: true, signed: true));
|
||||||
),
|
},
|
||||||
Divider(),
|
);
|
||||||
CheckboxListTile(
|
bloc.setServerPort(serverPortStr);
|
||||||
title: Text(
|
},
|
||||||
AppLocalizations.of(context).translate('settings_needs_auth')),
|
),
|
||||||
onChanged: (value) {
|
CheckboxListTile(
|
||||||
setState(() {
|
title: Text(
|
||||||
needsAuth = value;
|
AppLocalizations.of(context).translate('settings_use_https')),
|
||||||
});
|
value: state.useHttps,
|
||||||
},
|
onChanged: (value) {
|
||||||
value: needsAuth,
|
bloc.setUseHttps(value);
|
||||||
),
|
},
|
||||||
ListTile(
|
),
|
||||||
enabled: needsAuth,
|
Divider(),
|
||||||
title: Text(
|
CheckboxListTile(
|
||||||
AppLocalizations.of(context).translate('settings_user_id')),
|
title: Text(AppLocalizations.of(context)
|
||||||
subtitle: Text(userId),
|
.translate('settings_needs_auth')),
|
||||||
onTap: () {
|
value: state.needsAuth,
|
||||||
showDialog<String>(
|
onChanged: (value) {
|
||||||
context: context,
|
bloc.setNeedsAuth(value);
|
||||||
builder: (context) => _InputDialog(AppLocalizations.of(context)
|
},
|
||||||
.translate('dialog_server_user_id_title')),
|
),
|
||||||
);
|
ListTile(
|
||||||
},
|
enabled: state.needsAuth,
|
||||||
),
|
title: Text(
|
||||||
ListTile(
|
AppLocalizations.of(context).translate('settings_user_id')),
|
||||||
enabled: needsAuth,
|
subtitle: Text(state.userId ?? ''),
|
||||||
title: Text(
|
onTap: () async {
|
||||||
AppLocalizations.of(context).translate('settings_user_pass')),
|
String title = AppLocalizations.of(context)
|
||||||
subtitle: Text(userPassword),
|
.translate('dialog_server_user_id_title');
|
||||||
onTap: () {
|
String userId = await showDialog<String>(
|
||||||
showDialog<String>(
|
context: context,
|
||||||
context: context,
|
builder: (context) =>
|
||||||
builder: (context) => _InputDialog(AppLocalizations.of(context)
|
_InputDialog(title, initialValue: state.userId),
|
||||||
.translate('dialog_server_user_pass_title')),
|
);
|
||||||
);
|
bloc.setUserId(userId);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Divider(),
|
ListTile(
|
||||||
ListTile(
|
enabled: state.needsAuth,
|
||||||
title: Text(AppLocalizations.of(context)
|
title: Text(
|
||||||
.translate('settings_about_openlp')),
|
AppLocalizations.of(context).translate('settings_user_pass')),
|
||||||
onTap: () {
|
subtitle: Text(state.userPassword ?? ''),
|
||||||
launch('https://openlp.org/');
|
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 {
|
class _InputDialog extends StatelessWidget {
|
||||||
final String title;
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: Text(this.title),
|
title: Text(this.title),
|
||||||
contentPadding: EdgeInsets.all(15),
|
contentPadding: EdgeInsets.all(15),
|
||||||
content: TextField(autofocus: true),
|
content: TextField(
|
||||||
|
autofocus: true,
|
||||||
|
controller: _textEditingController,
|
||||||
|
keyboardType: keyboardType,
|
||||||
|
),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
FlatButton(
|
||||||
child: Text(AppLocalizations.of(context).translate('button_cancel')),
|
child: Text(AppLocalizations.of(context).translate('button_cancel')),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context, '');
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
FlatButton(
|
FlatButton(
|
||||||
child: Text(AppLocalizations.of(context).translate('button_ok')),
|
child: Text(AppLocalizations.of(context).translate('button_ok')),
|
||||||
onPressed: () {
|
onPressed: () => Navigator.pop(context, _textEditingController.text),
|
||||||
Navigator.pop(context, '');
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -34,6 +34,9 @@ dependencies:
|
|||||||
url_launcher: ^5.1.2
|
url_launcher: ^5.1.2
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
bloc: ^0.14.0
|
||||||
|
flutter_bloc: ^0.20.0
|
||||||
|
equatable: ^0.4.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Loading…
Reference in New Issue
Block a user