Add a manual enrollment flow to support chromeos (#99)

This commit is contained in:
Nate Brown 2022-11-22 10:12:38 -06:00 committed by GitHub
parent 17cc3477b7
commit 8fc3a40467
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 68 additions and 26 deletions

View File

@ -109,21 +109,18 @@ class _AppState extends State<App> {
),
onGenerateRoute: (settings) {
if (settings.name == '/') {
return platformPageRoute(context: context, builder: (context) => MainScreen(this.dnEnrolled.stream));
return platformPageRoute(context: context, builder: (context) => MainScreen(this.dnEnrolled));
}
final uri = Uri.parse(settings.name!);
if (uri.path == EnrollmentScreen.routeName) {
String? code;
if (uri.hasFragment) {
final qp = Uri.splitQueryString(uri.fragment);
code = qp["code"];
}
// TODO: maybe implement this as a dialog instead of a page, you can stack multiple enrollment screens which is annoying in dev
return platformPageRoute(
context: context,
builder: (context) => EnrollmentScreen(code: code, stream: this.dnEnrolled),
builder: (context) => EnrollmentScreen(
code: EnrollmentScreen.parseCode(settings.name!),
stream: this.dnEnrolled
),
);
}

View File

@ -73,7 +73,7 @@ class _AboutScreenState extends State<AboutScreen> {
Padding(
padding: EdgeInsets.only(top: 20),
child: Text(
'Copyright © 2020 Defined Networking, Inc',
'Copyright © 2022 Defined Networking, Inc',
textAlign: TextAlign.center,
)),
]),

View File

@ -1,10 +1,10 @@
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:flutter_svg/svg.dart';
import 'package:mobile_nebula/components/SimplePage.dart';
import 'package:url_launcher/url_launcher.dart';
@ -16,6 +16,22 @@ class EnrollmentScreen extends StatefulWidget {
static const routeName = '/v1/mobile-enrollment';
// Attempts to find an enrollment code in the provided url. If one is not found then assume the input was
// an enrollment code. Primarily to support manual dn enrollment where the user can input a code or a url.
static String parseCode(String url) {
final uri = Uri.parse(url);
if (uri.path != EnrollmentScreen.routeName) {
return url;
}
if (uri.hasFragment) {
final qp = Uri.splitQueryString(uri.fragment);
return qp["code"] ?? "";
}
return url;
}
const EnrollmentScreen({super.key, this.code, this.stream, this.allowCodeEntry = false});
@override
@ -138,20 +154,33 @@ class _EnrollmentScreenState extends State<EnrollmentScreen> {
));
}
return SimplePage(title: Text('DN Enrollment'), child: Padding(child: child, padding: EdgeInsets.symmetric(horizontal: 10)), alignment: alignment);
final dnIcon = Theme.of(context).brightness == Brightness.dark ? 'images/dn-logo-dark.svg' : 'images/dn-logo-light.svg';
return SimplePage(
title: Text('Enroll with DN', style: TextStyle(fontWeight: FontWeight.bold)),
child: Padding(child: child, padding: EdgeInsets.symmetric(horizontal: 10)),
alignment: alignment
);
}
Widget _codeEntry() {
return Column(children: [
Container(height: 20),
PlatformTextField(controller: enrollInput),
CupertinoButton(child: Text('Enroll'), onPressed: () {
Padding(
padding: EdgeInsets.only(top: 20),
child: PlatformTextField(
hintText: 'Enrollment code or link',
controller: enrollInput
)
),
PlatformTextButton(
child: Text('Submit'),
onPressed: () {
setState(() {
code = enrollInput.text;
code = EnrollmentScreen.parseCode(enrollInput.text);
error = null;
_enroll();
});
}),
},
)
]);
}
}

View File

@ -63,7 +63,7 @@ MAIH7gzreMGgrH/yR6rZpIHR3DxJ3E0aHtEI
class MainScreen extends StatefulWidget {
const MainScreen(this.dnEnrollStream, {Key? key}) : super(key: key);
final Stream dnEnrollStream;
final StreamController dnEnrollStream;
@override
_MainScreenState createState() => _MainScreenState();
@ -82,7 +82,7 @@ class _MainScreenState extends State<MainScreen> {
void initState() {
_loadSites();
widget.dnEnrollStream.listen((_) {
widget.dnEnrollStream.stream.listen((_) {
_loadSites();
});
@ -146,7 +146,7 @@ class _MainScreenState extends State<MainScreen> {
PlatformIconButton(
padding: EdgeInsets.zero,
icon: Icon(Icons.menu, size: 28.0),
onPressed: () => Utils.openPage(context, (_) => SettingsScreen()),
onPressed: () => Utils.openPage(context, (_) => SettingsScreen(widget.dnEnrollStream)),
),
],
bottomBar: debugSite,

View File

@ -1,18 +1,24 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:mobile_nebula/components/SimplePage.dart';
import 'package:mobile_nebula/components/config/ConfigItem.dart';
import 'package:mobile_nebula/components/config/ConfigPageItem.dart';
import 'package:mobile_nebula/components/config/ConfigSection.dart';
import 'package:mobile_nebula/screens/EnrollmentScreen.dart';
import 'package:mobile_nebula/services/settings.dart';
import 'package:mobile_nebula/services/utils.dart';
import 'AboutScreen.dart';
class SettingsScreen extends StatefulWidget {
final StreamController stream;
const SettingsScreen(this.stream, {super.key});
@override
_SettingsScreenState createState() {
return _SettingsScreenState();
}
_SettingsScreenState createState() => _SettingsScreenState();
}
class _SettingsScreenState extends State<SettingsScreen> {
@ -79,6 +85,16 @@ class _SettingsScreenState extends State<SettingsScreen> {
},
)),
));
final dnIcon = Theme.of(context).brightness == Brightness.dark ? 'images/dn-logo-dark.svg' : 'images/dn-logo-light.svg';
items.add(ConfigSection(children: [
ConfigPageItem(
label: Text('Enroll with DN'),
labelWidth: 200,
onPressed: () => Utils.openPage(context, (context) => EnrollmentScreen(stream: widget.stream, allowCodeEntry: true))
)
]));
items.add(ConfigSection(children: [
ConfigPageItem(
label: Text('About'),