Compare commits

...

4 commits

Author SHA1 Message Date
Caleb Jasik
5afc1ef692
Add licenses page (#227)
* Add licenses page

* Use PlatformListTile

* Use platform-specific icons

* More style fixes

* Switch back to using SimplePage

* Make title widget const

* Remove unused imports
2025-01-24 13:37:28 -06:00
Ian VanSchooten
21d8265f42
Clean up enrollment screen (#234)
## Android

Blank form:
|Before|After|
|--|--|
|<img width="395" alt="image" src="https://github.com/user-attachments/assets/5c8a8e26-d030-4b14-b91a-9cbf5e1b2e50" />|<img width="393" alt="Android Studio 2025-01-24 11 34 32" src="https://github.com/user-attachments/assets/408c8003-9bc0-4e09-af58-44f5728dcb59" />|

Text entered:
|Before|After|
|--|--|
|<img width="397" alt="Arc 2025-01-24 11 47 19" src="https://github.com/user-attachments/assets/d5e8bc70-1786-488c-aa1c-c45ddf9a92de" />|<img width="393" alt="image" src="https://github.com/user-attachments/assets/5765e9c3-cf50-4913-b4d1-78780918f35d" />|

Submitted empty:
|Before|After|
|--|--|
|<img width="395" alt="image" src="https://github.com/user-attachments/assets/37b8b9c8-760f-479e-b39f-3502367567ec" />|<img width="397" alt="Android Studio 2025-01-24 11 34 47" src="https://github.com/user-attachments/assets/c381725e-f449-43de-961f-768205b60028" />|

Submitted invalid:
|Before|After|
|--|--|
|<img width="388" alt="image" src="https://github.com/user-attachments/assets/3a3859e1-eff7-4111-9dd0-15edbd3bb998" />|<img width="389" alt="image" src="https://github.com/user-attachments/assets/1ab811df-e3ff-4a1f-9d3d-a2869cbc1877" />|


Unchanged:
<img width="388" alt="image" src="https://github.com/user-attachments/assets/f2719677-a73f-435d-b3c6-a0a4fd64759b" />


## iOS


Blank form:
|Before|After|
|--|--|
|<img width="454" alt="image" src="https://github.com/user-attachments/assets/9afed9d1-c63b-4fcf-80a8-c2a9d2c18e76" />|<img width="454" alt="image" src="https://github.com/user-attachments/assets/c185b7f1-a2b3-4e9b-a49f-fb9790214c3a" />|

Text entered:
|Before|After|
|--|--|
|<img width="452" alt="image" src="https://github.com/user-attachments/assets/d3be265d-9076-4a19-865b-413dfad79ed4" />|<img width="466" alt="image" src="https://github.com/user-attachments/assets/c23e99eb-1001-4f80-b88f-62ffa8c8f7dd" />|


Submitted empty:
(note it says invalid before)
|Before|After|
|--|--|
|<img width="463" alt="image" src="https://github.com/user-attachments/assets/e26c0642-e6cc-4e97-885d-b0309e58ace6" />|<img width="455" alt="image" src="https://github.com/user-attachments/assets/95b8f975-41b5-48a0-b75a-9cb6a9acc50e" />|

Submitted invalid:
|Before|After|
|--|--|
|<img width="484" alt="image" src="https://github.com/user-attachments/assets/1daf3c2e-5fbb-477c-b0c7-66689170d97a" />|<img width="463" alt="image" src="https://github.com/user-attachments/assets/8bef248f-a607-4373-9e9e-6ff08f402b4a" />|
2025-01-24 14:22:40 -05:00
Caleb Jasik
382e2bbbf7
Add vertical padding to ConfigPageItem in case children wrap (#233) 2025-01-24 10:48:00 -06:00
Caleb Jasik
b41054920a
Migrate from colorScheme.background to colorScheme.surface (#229) 2025-01-24 09:51:21 -06:00
11 changed files with 172 additions and 28 deletions

1
.gitignore vendored
View file

@ -45,6 +45,7 @@ lib/generated_plugin_registrant.dart
/env.sh
/lib/gen.versions.dart
/lib/.gen.versions.dart
/lib/oss_licenses.dart
/ios/Flutter/.last_build_id
/local.properties
/.gradle/

View file

@ -50,3 +50,6 @@ cd ..
# Try and avoid issues with building by moving into place after we are complete
#TODO: this might be a parallel build of deps issue in kotlin, might need to solve there
mv lib/.gen.versions.dart lib/gen.versions.dart
# Generate licenses library
flutter pub run flutter_oss_licenses:generate.dart

View file

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:mobile_nebula/services/utils.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
enum SimpleScrollable {

View file

@ -1,5 +1,3 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';

View file

@ -45,7 +45,7 @@ class ConfigPageItem extends StatelessWidget {
onPressed: this.disabled ? null : onPressed,
color: Utils.configItemBackground(context),
child: Container(
padding: EdgeInsets.only(left: 15, right: 15),
padding: EdgeInsets.symmetric(horizontal: 15, vertical: 10),
constraints: BoxConstraints(minHeight: Utils.minInteractiveSize, minWidth: double.infinity),
child: Row(
crossAxisAlignment: crossAxisAlignment,

View file

@ -5,6 +5,7 @@ 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/gen.versions.dart';
import 'package:mobile_nebula/screens/LicensesScreen.dart';
import 'package:mobile_nebula/services/utils.dart';
import 'package:package_info_plus/package_info_plus.dart';
@ -68,7 +69,12 @@ class _AboutScreenState extends State<AboutScreen> {
label: Text('Privacy policy'),
labelWidth: 300,
onPressed: () => Utils.launchUrl('https://www.defined.net/privacy/', context)),
// ConfigPageItem(label: Text('Licenses'), labelWidth: 300, onPressed: () => Utils.launchUrl('https://defined.net/mobile/license', context)),
ConfigPageItem(
label: Text('Licenses'),
labelWidth: 300,
onPressed: () => Utils.openPage(context, (context) {
return LicensesScreen();
})),
]),
Padding(
padding: EdgeInsets.only(top: 20),

View file

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
@ -6,8 +7,12 @@ import 'package:flutter/services.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:mobile_nebula/components/SimplePage.dart';
import 'package:mobile_nebula/components/buttons/PrimaryButton.dart';
import 'package:url_launcher/url_launcher.dart';
import '../components/config/ConfigItem.dart';
import '../components/config/ConfigSection.dart';
class EnrollmentScreen extends StatefulWidget {
final String? code;
final StreamController? stream;
@ -105,7 +110,7 @@ class _EnrollmentScreenState extends State<EnrollmentScreen> {
Padding(
child: SelectableText(
'There was an issue while attempting to enroll this device. Contact your administrator to obtain a new enrollment code.'),
padding: EdgeInsets.symmetric(vertical: 20)),
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 20)),
Padding(
child: SelectableText.rich(TextSpan(children: [
TextSpan(text: 'If the problem persists, please let us know at '),
@ -121,9 +126,9 @@ class _EnrollmentScreenState extends State<EnrollmentScreen> {
),
TextSpan(text: ' and provide the following error:'),
])),
padding: EdgeInsets.only(bottom: 10)),
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10)),
Container(
child: Padding(child: SelectableText(this.error!), padding: EdgeInsets.all(10)),
child: Padding(child: SelectableText(this.error!), padding: EdgeInsets.all(16)),
color: Theme.of(context).colorScheme.errorContainer,
),
],
@ -151,30 +156,59 @@ class _EnrollmentScreenState extends State<EnrollmentScreen> {
]));
}
return SimplePage(
title: Text('Enroll with Managed Nebula', style: TextStyle(fontWeight: FontWeight.bold)),
child: Padding(child: child, padding: EdgeInsets.symmetric(horizontal: 10)),
alignment: alignment);
return SimplePage(title: Text('Enroll with Managed Nebula'), child: child, alignment: alignment);
}
Widget _codeEntry() {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String? validator(String? value) {
if (value == null || value.isEmpty) {
return 'Code or link is required';
}
return null;
}
Future<void> onSubmit() async {
final bool isValid = _formKey.currentState?.validate() ?? false;
if (!isValid) {
return;
}
setState(() {
code = EnrollmentScreen.parseCode(enrollInput.text);
error = null;
_enroll();
});
}
final input = Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: PlatformTextFormField(
controller: enrollInput,
validator: validator,
hintText: 'from admin.defined.net',
cupertino: (_, __) => CupertinoTextFormFieldData(
prefix: Text("Code or link"),
),
material: (_, __) => MaterialTextFormFieldData(
decoration: const InputDecoration(labelText: 'Code or link'),
),
));
final form = Form(
key: _formKey,
child: Platform.isAndroid ? input : ConfigSection(children: [input]),
);
return Column(children: [
Padding(
padding: EdgeInsets.only(top: 20),
child: PlatformTextField(
hintText: 'defined.net enrollment code or link',
controller: enrollInput,
)),
PlatformTextButton(
child: Text('Submit'),
onPressed: () {
setState(() {
code = EnrollmentScreen.parseCode(enrollInput.text);
error = null;
_enroll();
});
},
)
padding: EdgeInsets.symmetric(vertical: 32),
child: form,
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Row(children: [Expanded(child: PrimaryButton(child: Text('Submit'), onPressed: onSubmit))]))
]);
}
}

View file

@ -0,0 +1,78 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:mobile_nebula/components/SimplePage.dart';
import 'package:mobile_nebula/services/utils.dart';
import '../../oss_licenses.dart';
String capitalize(String input) {
return input[0].toUpperCase() + input.substring(1);
}
class LicensesScreen extends StatelessWidget {
const LicensesScreen({super.key});
@override
Widget build(BuildContext context) {
return SimplePage(
title: const Text("Licences"),
scrollable: SimpleScrollable.none,
child: ListView.builder(
itemCount: allDependencies.length,
itemBuilder: (_, index) {
var dep = allDependencies[index];
return Padding(
padding: const EdgeInsets.all(8),
child: PlatformListTile(
onTap: () {
Utils.openPage(
context,
(_) => LicenceDetailPage(
title: capitalize(dep.name),
licence: dep.license!,
),
);
},
title: Text(
capitalize(dep.name),
),
subtitle: Text(dep.description),
trailing: Icon(context.platformIcons.forward, size: 18)),
);
},
),
);
}
}
//detail page for the licence
class LicenceDetailPage extends StatelessWidget {
final String title, licence;
const LicenceDetailPage({super.key, required this.title, required this.licence});
@override
Widget build(BuildContext context) {
return SimplePage(
title: Text(title),
scrollable: SimpleScrollable.none,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)),
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Column(
children: [
Text(
licence,
style: const TextStyle(fontSize: 15),
),
],
),
),
),
),
);
}
}

View file

@ -346,7 +346,7 @@ class MaterialTheme {
bodyColor: colorScheme.onSurface,
displayColor: colorScheme.onSurface,
),
scaffoldBackgroundColor: colorScheme.background,
scaffoldBackgroundColor: colorScheme.surface,
canvasColor: colorScheme.surface,
);

View file

@ -89,6 +89,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.8"
dart_pubspec_licenses:
dependency: transitive
description:
name: dart_pubspec_licenses
sha256: "23ddb78ff9204d08e3109ced67cd3c6c6a066f581b0edf5ee092fc3e1127f4ea"
url: "https://pub.dev"
source: hosted
version: "3.0.4"
fake_async:
dependency: transitive
description:
@ -134,6 +142,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_oss_licenses:
dependency: "direct dev"
description:
name: flutter_oss_licenses
sha256: e4bbaeb00bc768e8430ee0c95ad304d2f256fb15194d30b912cea269871c8885
url: "https://pub.dev"
source: hosted
version: "3.0.4"
flutter_platform_widgets:
dependency: "direct main"
description:
@ -216,6 +232,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.19.0"
json_annotation:
dependency: transitive
description:
name: json_annotation
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
url: "https://pub.dev"
source: hosted
version: "4.9.0"
leak_tracker:
dependency: transitive
description:

View file

@ -41,6 +41,7 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
flutter_oss_licenses: ^3.0.4
# For information on the generic Dart part of this file, see the