mirror of
https://github.com/DefinedNet/mobile_nebula.git
synced 2025-01-30 17:07:02 +00:00
5a641be96f
This exploration updates the Android app to use Google's Material 3 design, and changes up the colors a bit in the process. I used a source color of #5D23DD in https://material-foundation.github.io/material-theme-builder/, which generates a full set of material colors that I imported into `lib/services/theme.dart`. It should be easy to tweak any of the colors that we want, vs previously it was somewhat more difficult because they were being generated "behind the scenes". This doesn't necessarily need to be done now, but it does align better with more modern Android design patterns and Flutter has said at some point they will stop supporting Material 2. Note: this should not have any impact on iOS, since we use the default `CupertinoThemeData` there, without any custom theming. Here are some before/after comparisons of interesting screens: Adding a new site: |Dark Before|Dark After|Light Before|Light After| |---|---|---|--- |<img width="390" alt="Android Studio 2025-01-22 10 43 55" src="https://github.com/user-attachments/assets/c7954b7f-a8eb-48a5-bd47-237877f078fd" />|<img width="405" alt="Android Studio 2025-01-22 11 16 48" src="https://github.com/user-attachments/assets/b69c1e6f-3464-44af-9f9c-f6377b5ce1d1" />|<img width="389" alt="image" src="https://github.com/user-attachments/assets/40f1e40f-a1f5-42e4-909c-c07b3f82df2b" />|<img width="393" alt="image" src="https://github.com/user-attachments/assets/09f8f8ce-668e-4e69-a4a9-233fb970655f" />| Confirmation dialog: |Before|After| |---|---| |<img width="264" alt="image" src="https://github.com/user-attachments/assets/7cae1abc-621d-4c59-bf36-0ce3be0af88c" />|<img width="278" alt="Android Studio 2025-01-22 11 43 19" src="https://github.com/user-attachments/assets/d461a97f-d252-494f-8b30-49d33a5a9cda" />| Settings page: |Dark Before|Dark After|Light Before|Light After| |---|---|---|---| |<img width="394" alt="Android Studio 2025-01-22 11 46 01" src="https://github.com/user-attachments/assets/edfc6c40-ee72-4a7c-b9b7-7c3025f0cdfe" />|<img width="393" alt="Android Studio 2025-01-22 11 46 35" src="https://github.com/user-attachments/assets/d1445041-bbc0-4994-98d5-3eb149afceea" />|<img width="391" alt="Android Studio 2025-01-22 11 46 09" src="https://github.com/user-attachments/assets/295e5cc4-74e2-422a-b478-a3e0bd577b60" />|<img width="391" alt="Android Studio 2025-01-22 11 46 28" src="https://github.com/user-attachments/assets/098339de-f2df-4269-84cf-e3ae2c09a51d" />| Site with errors: |Dark Before|Dark After|Light Before|Light After| |---|---|---|---| |<img width="395" alt="Android Studio 2025-01-22 11 48 50" src="https://github.com/user-attachments/assets/4f8dd05d-ccc7-44eb-96e0-ffec63975085" />|<img width="390" alt="Android Studio 2025-01-22 11 48 06" src="https://github.com/user-attachments/assets/751f35e2-b801-4ddf-9655-15f0097e05ca" />|<img width="395" alt="image" src="https://github.com/user-attachments/assets/15ac20c9-4d40-4e51-aed6-fd69a001588b" />|<img width="388" alt="Android Studio 2025-01-22 11 48 20" src="https://github.com/user-attachments/assets/780bf849-9add-4f91-bac8-3cdd5fd89337" />| Main page / site list: |Light Before|Light After|Light Scrolled Before|Light Scrolled After| |---|---|---|---| |<img width="387" alt="Android Studio 2025-01-22 11 53 07" src="https://github.com/user-attachments/assets/ca426470-00c2-4dc3-bd22-4a336c4ec8cf" />|<img width="403" alt="Android Studio 2025-01-22 11 53 41" src="https://github.com/user-attachments/assets/abf755e3-df10-453b-a439-0aa3b21b7ef9" />|<img width="389" alt="Android Studio 2025-01-22 11 53 22" src="https://github.com/user-attachments/assets/a6cdfabf-5288-49fe-ac29-e73678d34ccb" />|<img width="396" alt="Android Studio 2025-01-22 11 53 51" src="https://github.com/user-attachments/assets/11eda1f4-cf2f-4848-9690-6093223a9e7e" />| Certificate: |Dark Before|Dark After|Light Before|Light After| |---|---|---|---| |<img width="388" alt="Android Studio 2025-01-22 11 57 25" src="https://github.com/user-attachments/assets/5a1db1ba-a560-4aa6-8649-9b41d9ba25b6" />|<img width="390" alt="Android Studio 2025-01-22 11 56 44" src="https://github.com/user-attachments/assets/5e1b9200-ea13-42e5-a55d-51a1fda4522f" />|<img width="397" alt="Android Studio 2025-01-22 11 57 01" src="https://github.com/user-attachments/assets/65c52218-3f90-40c7-bb21-e499c2e0b08c" />|<img width="392" alt="Android Studio 2025-01-22 11 56 21" src="https://github.com/user-attachments/assets/554847cd-e825-4691-ac21-1549ab5e7d21" />|
131 lines
4.4 KiB
Dart
131 lines
4.4 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/cupertino.dart' show CupertinoThemeData, DefaultCupertinoLocalizations;
|
|
import 'package:flutter/material.dart' show DefaultMaterialLocalizations, TextTheme, ThemeMode;
|
|
import 'package:flutter/scheduler.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
|
import 'package:mobile_nebula/screens/MainScreen.dart';
|
|
import 'package:mobile_nebula/screens/EnrollmentScreen.dart';
|
|
import 'package:mobile_nebula/services/settings.dart';
|
|
import 'package:flutter_web_plugins/url_strategy.dart';
|
|
import 'package:mobile_nebula/services/theme.dart';
|
|
import 'package:mobile_nebula/services/utils.dart';
|
|
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
|
|
Future<void> main() async {
|
|
usePathUrlStrategy();
|
|
|
|
var settings = Settings();
|
|
if (settings.trackErrors) {
|
|
await SentryFlutter.init(
|
|
(options) {
|
|
options.dsn = 'https://96106df405ade3f013187dfc8e4200e7@o920269.ingest.us.sentry.io/4508132321001472';
|
|
// Capture all traces. May need to adjust if overwhelming
|
|
options.tracesSampleRate = 1.0;
|
|
// For each trace, capture all profiles
|
|
options.profilesSampleRate = 1.0;
|
|
},
|
|
appRunner: () => runApp(Main()),
|
|
);
|
|
} else {
|
|
runApp(Main());
|
|
}
|
|
}
|
|
|
|
//TODO: EventChannel might be better than the stream controller we are using now
|
|
|
|
class Main extends StatelessWidget {
|
|
// This widget is the root of your application.
|
|
@override
|
|
Widget build(BuildContext context) => App();
|
|
}
|
|
|
|
class App extends StatefulWidget {
|
|
@override
|
|
_AppState createState() => _AppState();
|
|
}
|
|
|
|
class _AppState extends State<App> {
|
|
final settings = Settings();
|
|
Brightness brightness = SchedulerBinding.instance.platformDispatcher.platformBrightness;
|
|
StreamController dnEnrolled = StreamController.broadcast();
|
|
|
|
@override
|
|
void initState() {
|
|
//TODO: wait until settings is ready?
|
|
settings.onChange().listen((_) {
|
|
setState(() {
|
|
if (settings.useSystemColors) {
|
|
brightness = SchedulerBinding.instance.platformDispatcher.platformBrightness;
|
|
} else {
|
|
brightness = settings.darkMode ? Brightness.dark : Brightness.light;
|
|
}
|
|
});
|
|
});
|
|
|
|
// Listen to changes to the system brightness mode, update accordingly
|
|
final dispatcher = SchedulerBinding.instance.platformDispatcher;
|
|
dispatcher.onPlatformBrightnessChanged = () {
|
|
if (settings.useSystemColors) {
|
|
setState(() {
|
|
brightness = dispatcher.platformBrightness;
|
|
});
|
|
}
|
|
};
|
|
|
|
super.initState();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
dnEnrolled.close();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
TextTheme textTheme = Utils.createTextTheme(context, "Public Sans", "Public Sans");
|
|
MaterialTheme theme = MaterialTheme(textTheme);
|
|
|
|
return PlatformProvider(
|
|
settings: PlatformSettingsData(iosUsesMaterialWidgets: true),
|
|
builder: (context) => PlatformApp(
|
|
debugShowCheckedModeBanner: false,
|
|
localizationsDelegates: <LocalizationsDelegate<dynamic>>[
|
|
DefaultMaterialLocalizations.delegate,
|
|
DefaultWidgetsLocalizations.delegate,
|
|
DefaultCupertinoLocalizations.delegate,
|
|
],
|
|
title: 'Nebula',
|
|
material: (_, __) {
|
|
return new MaterialAppData(
|
|
themeMode: brightness == Brightness.light ? ThemeMode.light : ThemeMode.dark,
|
|
theme: brightness == Brightness.light ? theme.light() : theme.dark(),
|
|
);
|
|
},
|
|
cupertino: (_, __) => CupertinoAppData(
|
|
theme: CupertinoThemeData(brightness: brightness),
|
|
),
|
|
onGenerateRoute: (settings) {
|
|
if (settings.name == '/') {
|
|
return platformPageRoute(context: context, builder: (context) => MainScreen(this.dnEnrolled));
|
|
}
|
|
|
|
final uri = Uri.parse(settings.name!);
|
|
if (uri.path == EnrollmentScreen.routeName) {
|
|
// 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: EnrollmentScreen.parseCode(settings.name!), stream: this.dnEnrolled),
|
|
);
|
|
}
|
|
|
|
return null;
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|