Skip to content

Commit

Permalink
WIP: Generate recovery key page
Browse files Browse the repository at this point in the history
  • Loading branch information
jpnurmi committed Sep 6, 2021
1 parent 1339566 commit be5c5ad
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/ubuntu_desktop_installer/lib/installer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class _UbuntuDesktopInstallerWizardState
if (model.hasBitLocker)
Routes.turnOffBitlocker: TurnOffBitLockerPage.create,
Routes.chooseSecurityKey: ChooseSecurityKeyPage.create,
Routes.generateRecoveryKey: GenerateRecoveryKeyPage.create,
Routes.allocateDiskSpace: AllocateDiskSpacePage.create,
Routes.writeChangesToDisk: WriteChangesToDiskPage.create,
Routes.whoAreYou: WhoAreYouPage.create,
Expand Down
9 changes: 9 additions & 0 deletions packages/ubuntu_desktop_installer/lib/l10n/app_en_US.arb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@
}
},

"generateRecoveryKeyTitle": "Choose a security key",
"generateRecoveryKeyHeader": "A recovery key is generated and will be temporarily saved on the live system. You can select and alternative location. Save this file and keep it in a safe place elsewhere before rebooting.",
"generateRecoveryKeyLocation": "Location:",
"generateRecoveryKeyLabel": "Show recovery key",
"generateRecoveryKeyMoreSecurity": "For more security:",
"generateRecoveryKeyOverwriteEmptyDiskSpace": "Overwrite empty disk space",
"generateRecoveryKeyLongerInstallation": "The installation may take much longer.",
"generateRecoveryKeyInstallNow": "Install now",

"allocateDiskSpace": "Allocate disk space",
"startInstallingButtonText": "Start Installing",
"diskHeadersDevice": "Device",
Expand Down
1 change: 1 addition & 0 deletions packages/ubuntu_desktop_installer/lib/pages.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export 'pages/allocate_disk_space/allocate_disk_space_page.dart';
export 'pages/choose_security_key/choose_security_key_page.dart';
export 'pages/choose_your_look_page.dart';
export 'pages/generate_recovery_key/generate_recovery_key_page.dart';
export 'pages/installation_complete/installation_complete_page.dart';
export 'pages/installation_slides/installation_slides_page.dart';
export 'pages/keyboard_layout/keyboard_layout_page.dart';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'package:flutter/foundation.dart';
import 'package:subiquity_client/subiquity_client.dart';

/// View model for [GenerateRecoveryKeyPage].
class GenerateRecoveryKeyModel extends ChangeNotifier {
/// Creates the model with the given client.
GenerateRecoveryKeyModel(this._client) {
Listenable.merge([
_recoveryKey,
_overwrite,
]).addListener(notifyListeners);
}

final SubiquityClient _client;
final _recoveryKey = ValueNotifier('');
final _overwrite = ValueNotifier(false);

/// The current recovery key.
String get recoveryKey => _recoveryKey.value;
set recoveryKey(String value) => _recoveryKey.value = value;

/// Whether empty disk space is overridden.
bool get overwriteEmptyDiskSpace => _overwrite.value;
set overwriteEmptyDiskSpace(bool value) => _overwrite.value = value;

/// Whether the current input is valid.
bool get isValid => true;

/// Loads the security key.
Future<void> loadRecoveryKey() async {}

/// Saves the security key.
Future<void> saveRecoveryKey() async {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:provider/provider.dart';
import 'package:subiquity_client/subiquity_client.dart';
import 'package:ubuntu_wizard/constants.dart';
import 'package:ubuntu_wizard/utils.dart';
import 'package:ubuntu_wizard/widgets.dart';

import '../../l10n.dart';
import '../../widgets.dart';
import 'generate_recovery_key_model.dart';

part 'generate_recovery_key_widgets.dart';

/// Choose security key page.
///
/// See also:
/// * [GenerateRecoveryKeyModel]
class GenerateRecoveryKeyPage extends StatefulWidget {
/// Use [create] instead.
@visibleForTesting
const GenerateRecoveryKeyPage({
Key? key,
}) : super(key: key);

/// Creates an instance with [GenerateRecoveryKeyModel].
static Widget create(BuildContext context) {
final client = Provider.of<SubiquityClient>(context, listen: false);
return ChangeNotifierProvider(
create: (_) => GenerateRecoveryKeyModel(client),
child: GenerateRecoveryKeyPage(),
);
}

@override
_GenerateRecoveryKeyPageState createState() =>
_GenerateRecoveryKeyPageState();
}

class _GenerateRecoveryKeyPageState extends State<GenerateRecoveryKeyPage> {
@override
void initState() {
super.initState();

final model = Provider.of<GenerateRecoveryKeyModel>(context, listen: false);
model.loadRecoveryKey();
}

@override
Widget build(BuildContext context) {
final lang = AppLocalizations.of(context);
final model = Provider.of<GenerateRecoveryKeyModel>(context);
return LocalizedView(builder: (context, lang) {
return WizardPage(
title: Text(lang.generateRecoveryKeyTitle),
header: Text(lang.generateRecoveryKeyHeader),
content: LayoutBuilder(builder: (context, constraints) {
final fieldWidth = constraints.maxWidth * kContentWidthFraction;
return ListView(
children: <Widget>[
_RecoveryKeyLocationSelector(),
const SizedBox(height: kContentSpacing),
_RecoveryKeyField(),
const SizedBox(height: kContentSpacing),
Text(lang.generateRecoveryKeyMoreSecurity),
const SizedBox(height: kContentSpacing),
CheckButton(
value: model.overwriteEmptyDiskSpace,
title: lang.generateRecoveryKeyMoreSecurity,
),
],
);
}),
actions: <WizardAction>[
WizardAction(
label: lang.backButtonText,
onActivated: Wizard.of(context).back,
),
WizardAction(
label: lang.continueButtonText,
enabled: context.select<GenerateRecoveryKeyModel, bool>(
(model) => model.isValid),
onActivated: () async {
final model =
Provider.of<GenerateRecoveryKeyModel>(context, listen: false);
await model.saveSecurityKey();

Wizard.of(context).next();
},
),
],
);
});
}
}

extension _HexColor on Color {
String toHex() =>
_formatHex(alpha.toHex(), red.toHex(), green.toHex(), blue.toHex());
String _formatHex(String a, String r, String g, String b) => '#$a$r$g$b';
}

extension _IntHex on int {
String toHex() => toRadixString(16).padLeft(2, '0');
}
1 change: 1 addition & 0 deletions packages/ubuntu_desktop_installer/lib/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ abstract class Routes {
static const installationSlides = '/installationslides';
static const turnOffBitlocker = '/turnoffbitlocker';
static const chooseSecurityKey = '/choosesecuritykey';
static const generateRecoveryKey = '/generaterecoverykey';
}

0 comments on commit be5c5ad

Please sign in to comment.