mobile_nebula/lib/screens/siteConfig/StaticHostmapScreen.dart

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

209 lines
6.4 KiB
Dart
Raw Normal View History

2020-07-27 20:43:58 +00:00
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:mobile_nebula/components/FormPage.dart';
import 'package:mobile_nebula/components/IPAndPortFormField.dart';
import 'package:mobile_nebula/components/IPFormField.dart';
import 'package:mobile_nebula/components/config/ConfigButtonItem.dart';
import 'package:mobile_nebula/components/config/ConfigItem.dart';
import 'package:mobile_nebula/components/config/ConfigSection.dart';
import 'package:mobile_nebula/models/Hostmap.dart';
import 'package:mobile_nebula/models/IPAndPort.dart';
import 'package:mobile_nebula/services/utils.dart';
class _IPAndPort {
final FocusNode focusNode;
IPAndPort destination;
_IPAndPort({required this.focusNode, required this.destination});
2020-07-27 20:43:58 +00:00
}
class StaticHostmapScreen extends StatefulWidget {
StaticHostmapScreen({
Key? key,
this.nebulaIp = '',
destinations,
this.lighthouse = false,
this.onDelete,
required this.onSave,
}) : this.destinations = destinations ?? [],
super(key: key);
2020-07-27 20:43:58 +00:00
final List<IPAndPort> destinations;
final String nebulaIp;
final bool lighthouse;
final ValueChanged<Hostmap> onSave;
final Function? onDelete;
2020-07-27 20:43:58 +00:00
@override
_StaticHostmapScreenState createState() => _StaticHostmapScreenState();
}
class _StaticHostmapScreenState extends State<StaticHostmapScreen> {
late Map<Key, _IPAndPort> _destinations;
late String _nebulaIp;
late bool _lighthouse;
2020-07-27 20:43:58 +00:00
bool changed = false;
@override
void initState() {
_nebulaIp = widget.nebulaIp;
_lighthouse = widget.lighthouse;
_destinations = {};
widget.destinations.forEach((dest) {
2020-07-27 20:43:58 +00:00
_destinations[UniqueKey()] = _IPAndPort(focusNode: FocusNode(), destination: dest);
});
if (_destinations.length == 0) {
_addDestination();
}
2021-04-23 21:23:06 +00:00
// _addDestination() above sets us to changed, set it back to false since we are at the default state
changed = false;
2020-07-27 20:43:58 +00:00
super.initState();
}
@override
Widget build(BuildContext context) {
return FormPage(
title: widget.onDelete == null ? 'New Static Host' : 'Edit Static Host',
changed: changed,
onSave: _onSave,
child: Column(children: [
ConfigSection(label: 'Maps a nebula ip address to multiple real world addresses', children: <Widget>[
ConfigItem(
label: Text('Nebula IP'),
labelWidth: 200,
content: IPFormField(
help: "Required",
initialValue: _nebulaIp,
ipOnly: true,
textAlign: TextAlign.end,
crossAxisAlignment: CrossAxisAlignment.end,
textInputAction: TextInputAction.next,
onSaved: (v) {
if (v != null) {
_nebulaIp = v;
}
2020-07-27 20:43:58 +00:00
})),
ConfigItem(
label: Text('Lighthouse'),
labelWidth: 200,
content: Container(
alignment: Alignment.centerRight,
child: Switch.adaptive(
value: _lighthouse,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
onChanged: (v) {
setState(() {
changed = true;
_lighthouse = v;
});
})),
),
]),
ConfigSection(
label: 'List of public ips or dns names where for this host',
children: _buildHosts(),
),
widget.onDelete != null
? Padding(
padding: EdgeInsets.only(top: 50, bottom: 10, left: 10, right: 10),
child: SizedBox(
width: double.infinity,
2022-07-27 16:38:02 +00:00
child: PlatformElevatedButton(
2020-07-27 20:43:58 +00:00
child: Text('Delete'),
color: CupertinoColors.systemRed.resolveFrom(context),
onPressed: () => Utils.confirmDelete(context, 'Delete host map?', () {
Navigator.of(context).pop();
widget.onDelete!();
2020-07-27 20:43:58 +00:00
}),
)))
: Container()
]));
}
_onSave() {
Navigator.pop(context);
var map = Hostmap(nebulaIp: _nebulaIp, destinations: [], lighthouse: _lighthouse);
2020-07-27 20:43:58 +00:00
_destinations.forEach((_, dest) {
map.destinations.add(dest.destination);
});
2020-07-27 20:43:58 +00:00
widget.onSave(map);
2020-07-27 20:43:58 +00:00
}
List<Widget> _buildHosts() {
List<Widget> items = [];
_destinations.forEach((key, dest) {
items.add(ConfigItem(
key: key,
label: Align(
alignment: Alignment.centerLeft,
child: PlatformIconButton(
padding: EdgeInsets.zero,
icon: Icon(Icons.remove_circle, color: CupertinoColors.systemRed.resolveFrom(context)),
onPressed: () => setState(() {
_removeDestination(key);
_dismissKeyboard();
}))),
labelWidth: 70,
content: Row(children: <Widget>[
Expanded(
child: IPAndPortFormField(
ipHelp: 'public ip or name',
ipTextAlign: TextAlign.end,
2021-04-23 21:23:06 +00:00
enableIPV6: true,
2020-07-27 20:43:58 +00:00
noBorder: true,
initialValue: dest.destination,
onSaved: (v) {
if (v != null) {
dest.destination = v;
}
2020-07-27 20:43:58 +00:00
},
)),
]),
));
});
items.add(ConfigButtonItem(
content: Text('Add another'),
onPressed: () => setState(() {
_addDestination();
_dismissKeyboard();
})));
return items;
}
_addDestination() {
changed = true;
_destinations[UniqueKey()] = _IPAndPort(focusNode: FocusNode(), destination: IPAndPort());
// We can't onChanged here because it causes rendering issues on first build due to ensuring there is a single destination
}
_removeDestination(Key key) {
changed = true;
_destinations.remove(key);
}
_dismissKeyboard() {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
}
@override
void dispose() {
_destinations.forEach((key, dest) {
dest.focusNode.dispose();
});
super.dispose();
}
}