2020-07-27 20:43:58 +00:00
|
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter/services.dart';
|
|
|
|
import 'package:flutter/widgets.dart';
|
|
|
|
import 'package:mobile_nebula/components/FormPage.dart';
|
|
|
|
import 'package:mobile_nebula/components/PlatformTextFormField.dart';
|
|
|
|
import 'package:mobile_nebula/components/config/ConfigPageItem.dart';
|
|
|
|
import 'package:mobile_nebula/components/config/ConfigItem.dart';
|
|
|
|
import 'package:mobile_nebula/components/config/ConfigSection.dart';
|
|
|
|
import 'package:mobile_nebula/models/Site.dart';
|
|
|
|
import 'package:mobile_nebula/models/UnsafeRoute.dart';
|
|
|
|
import 'package:mobile_nebula/screens/siteConfig/CipherScreen.dart';
|
2023-12-05 15:24:19 +00:00
|
|
|
import 'package:mobile_nebula/screens/siteConfig/DNSResolversScreen.dart';
|
2020-07-27 20:43:58 +00:00
|
|
|
import 'package:mobile_nebula/screens/siteConfig/LogVerbosityScreen.dart';
|
|
|
|
import 'package:mobile_nebula/screens/siteConfig/RenderedConfigScreen.dart';
|
|
|
|
import 'package:mobile_nebula/services/utils.dart';
|
|
|
|
|
|
|
|
import 'UnsafeRoutesScreen.dart';
|
|
|
|
|
|
|
|
//TODO: form validation (seconds and port)
|
|
|
|
//TODO: wire up the focus nodes, add a done/next/prev to the keyboard
|
|
|
|
//TODO: fingerprint blacklist
|
|
|
|
//TODO: show site id here
|
|
|
|
|
|
|
|
class Advanced {
|
|
|
|
int lhDuration;
|
|
|
|
int port;
|
|
|
|
String cipher;
|
|
|
|
String verbosity;
|
|
|
|
List<UnsafeRoute> unsafeRoutes;
|
|
|
|
int mtu;
|
2023-12-05 15:24:19 +00:00
|
|
|
List<String> dnsResolvers;
|
2022-09-21 20:27:35 +00:00
|
|
|
|
|
|
|
Advanced({
|
|
|
|
required this.lhDuration,
|
|
|
|
required this.port,
|
|
|
|
required this.cipher,
|
|
|
|
required this.verbosity,
|
|
|
|
required this.unsafeRoutes,
|
|
|
|
required this.mtu,
|
2023-12-05 15:24:19 +00:00
|
|
|
required this.dnsResolvers,
|
2022-09-21 20:27:35 +00:00
|
|
|
});
|
2020-07-27 20:43:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class AdvancedScreen extends StatefulWidget {
|
2022-09-21 20:27:35 +00:00
|
|
|
const AdvancedScreen({
|
|
|
|
Key? key,
|
|
|
|
required this.site,
|
|
|
|
required this.onSave,
|
|
|
|
}) : super(key: key);
|
2020-07-27 20:43:58 +00:00
|
|
|
|
|
|
|
final Site site;
|
|
|
|
final ValueChanged<Advanced> onSave;
|
|
|
|
|
|
|
|
@override
|
|
|
|
_AdvancedScreenState createState() => _AdvancedScreenState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _AdvancedScreenState extends State<AdvancedScreen> {
|
2022-09-21 20:27:35 +00:00
|
|
|
late Advanced settings;
|
2020-07-27 20:43:58 +00:00
|
|
|
var changed = false;
|
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
2022-09-21 20:27:35 +00:00
|
|
|
settings = Advanced(
|
|
|
|
lhDuration: widget.site.lhDuration,
|
|
|
|
port: widget.site.port,
|
|
|
|
cipher: widget.site.cipher,
|
|
|
|
verbosity: widget.site.logVerbosity,
|
|
|
|
unsafeRoutes: widget.site.unsafeRoutes,
|
|
|
|
mtu: widget.site.mtu,
|
2023-12-05 15:24:19 +00:00
|
|
|
dnsResolvers: widget.site.dnsResolvers,
|
2022-09-21 20:27:35 +00:00
|
|
|
);
|
2020-07-27 20:43:58 +00:00
|
|
|
super.initState();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return FormPage(
|
|
|
|
title: 'Advanced Settings',
|
|
|
|
changed: changed,
|
|
|
|
onSave: () {
|
|
|
|
Navigator.pop(context);
|
|
|
|
widget.onSave(settings);
|
|
|
|
},
|
|
|
|
child: Column(children: [
|
|
|
|
ConfigSection(
|
|
|
|
children: [
|
|
|
|
ConfigItem(
|
|
|
|
label: Text("Lighthouse interval"),
|
|
|
|
labelWidth: 200,
|
|
|
|
//TODO: Auto select on focus?
|
2022-11-17 21:43:16 +00:00
|
|
|
content: widget.site.managed ?
|
|
|
|
Text(settings.lhDuration.toString() + " seconds", textAlign: TextAlign.right) :
|
|
|
|
PlatformTextFormField(
|
|
|
|
initialValue: settings.lhDuration.toString(),
|
|
|
|
keyboardType: TextInputType.number,
|
|
|
|
suffix: Text("seconds"),
|
|
|
|
textAlign: TextAlign.right,
|
|
|
|
maxLength: 5,
|
|
|
|
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
|
|
|
onSaved: (val) {
|
|
|
|
setState(() {
|
|
|
|
if (val != null) {
|
|
|
|
settings.lhDuration = int.parse(val);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
)),
|
2020-07-27 20:43:58 +00:00
|
|
|
ConfigItem(
|
|
|
|
label: Text("Listen port"),
|
|
|
|
labelWidth: 150,
|
|
|
|
//TODO: Auto select on focus?
|
2022-11-17 21:43:16 +00:00
|
|
|
content: widget.site.managed ?
|
|
|
|
Text(settings.port.toString(), textAlign: TextAlign.right) :
|
|
|
|
PlatformTextFormField(
|
|
|
|
initialValue: settings.port.toString(),
|
|
|
|
keyboardType: TextInputType.number,
|
|
|
|
textAlign: TextAlign.right,
|
|
|
|
maxLength: 5,
|
|
|
|
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
|
|
|
onSaved: (val) {
|
|
|
|
setState(() {
|
|
|
|
if (val != null) {
|
|
|
|
settings.port = int.parse(val);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
)),
|
2020-07-27 20:43:58 +00:00
|
|
|
ConfigItem(
|
|
|
|
label: Text("MTU"),
|
|
|
|
labelWidth: 150,
|
2022-11-17 21:43:16 +00:00
|
|
|
content: widget.site.managed ?
|
|
|
|
Text(settings.mtu.toString(), textAlign: TextAlign.right) :
|
|
|
|
PlatformTextFormField(
|
|
|
|
initialValue: settings.mtu.toString(),
|
|
|
|
keyboardType: TextInputType.number,
|
|
|
|
textAlign: TextAlign.right,
|
|
|
|
maxLength: 5,
|
|
|
|
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
|
|
|
onSaved: (val) {
|
|
|
|
setState(() {
|
|
|
|
if (val != null) {
|
|
|
|
settings.mtu = int.parse(val);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
)),
|
2020-07-27 20:43:58 +00:00
|
|
|
ConfigPageItem(
|
2022-11-17 21:43:16 +00:00
|
|
|
disabled: widget.site.managed,
|
2020-07-27 20:43:58 +00:00
|
|
|
label: Text('Cipher'),
|
|
|
|
labelWidth: 150,
|
|
|
|
content: Text(settings.cipher, textAlign: TextAlign.end),
|
|
|
|
onPressed: () {
|
|
|
|
Utils.openPage(context, (context) {
|
|
|
|
return CipherScreen(
|
|
|
|
cipher: settings.cipher,
|
|
|
|
onSave: (cipher) {
|
|
|
|
setState(() {
|
|
|
|
settings.cipher = cipher;
|
|
|
|
changed = true;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}),
|
|
|
|
ConfigPageItem(
|
2022-11-17 21:43:16 +00:00
|
|
|
disabled: widget.site.managed,
|
2020-07-27 20:43:58 +00:00
|
|
|
label: Text('Log verbosity'),
|
|
|
|
labelWidth: 150,
|
|
|
|
content: Text(settings.verbosity, textAlign: TextAlign.end),
|
|
|
|
onPressed: () {
|
|
|
|
Utils.openPage(context, (context) {
|
|
|
|
return LogVerbosityScreen(
|
|
|
|
verbosity: settings.verbosity,
|
|
|
|
onSave: (verbosity) {
|
|
|
|
setState(() {
|
|
|
|
settings.verbosity = verbosity;
|
|
|
|
changed = true;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}),
|
|
|
|
ConfigPageItem(
|
|
|
|
label: Text('Unsafe routes'),
|
|
|
|
labelWidth: 150,
|
|
|
|
content: Text(Utils.itemCountFormat(settings.unsafeRoutes.length), textAlign: TextAlign.end),
|
|
|
|
onPressed: () {
|
|
|
|
Utils.openPage(context, (context) {
|
|
|
|
return UnsafeRoutesScreen(
|
|
|
|
unsafeRoutes: settings.unsafeRoutes,
|
2022-11-17 21:43:16 +00:00
|
|
|
onSave: widget.site.managed ? null : (routes) {
|
2020-07-27 20:43:58 +00:00
|
|
|
setState(() {
|
|
|
|
settings.unsafeRoutes = routes;
|
|
|
|
changed = true;
|
2021-05-03 21:58:04 +00:00
|
|
|
});
|
2020-07-27 20:43:58 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
2023-12-05 15:24:19 +00:00
|
|
|
),
|
|
|
|
ConfigPageItem(
|
|
|
|
label: Text('DNS Resolvers'),
|
|
|
|
labelWidth: 150,
|
|
|
|
content: Text(
|
|
|
|
Utils.itemCountFormat(settings.dnsResolvers.length),
|
|
|
|
textAlign: TextAlign.end),
|
|
|
|
onPressed: () {
|
|
|
|
Utils.openPage(context, (context) {
|
|
|
|
return DNSResolversScreen(
|
|
|
|
dnsResolvers: settings.dnsResolversmm
|
|
|
|
onSave: (dnsResolvers) {
|
|
|
|
setState(() {
|
|
|
|
settings.dnsResolvers = dnsResolvers;
|
|
|
|
changed = true;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
),
|
2020-07-27 20:43:58 +00:00
|
|
|
],
|
|
|
|
),
|
|
|
|
ConfigSection(
|
|
|
|
children: <Widget>[
|
|
|
|
ConfigPageItem(
|
|
|
|
content: Text('View rendered config'),
|
|
|
|
onPressed: () async {
|
|
|
|
try {
|
|
|
|
var config = await widget.site.renderConfig();
|
|
|
|
Utils.openPage(context, (context) {
|
2020-08-18 00:12:28 +00:00
|
|
|
return RenderedConfigScreen(config: config, name: widget.site.name);
|
2020-07-27 20:43:58 +00:00
|
|
|
});
|
|
|
|
} catch (err) {
|
2022-09-21 20:27:35 +00:00
|
|
|
Utils.popError(context, 'Failed to render the site config', err.toString());
|
2020-07-27 20:43:58 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
],
|
|
|
|
)
|
|
|
|
]));
|
|
|
|
}
|
|
|
|
}
|