2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-28 05:26:47 +00:00

Adds "dark mode" support (#317)

* Adds "dark mode" support

- Uses adaptive_theme package

* CI fixes

* More fixes

* Update release notes
This commit is contained in:
Oliver 2023-04-16 21:10:57 +10:00 committed by GitHub
parent e7f5141aa9
commit a3d712d11d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 99 additions and 29 deletions

View File

@ -4,10 +4,12 @@
### 0.11.2 - April 2023 ### 0.11.2 - April 2023
--- ---
- Adds "dark mode" display option
- Add action to issue a purchase order - Add action to issue a purchase order
- Add action to cancel a purchase order - Add action to cancel a purchase order
- Reimplement periodic checks for notifications - Reimplement periodic checks for notifications
### 0.11.1 - April 2023 ### 0.11.1 - April 2023
--- ---

View File

@ -211,6 +211,12 @@
"damaged": "Damaged", "damaged": "Damaged",
"@damaged": {}, "@damaged": {},
"darkMode": "Dark Mode",
"@darkMode": {},
"darkModeEnable": "Enable dark mode",
"@darkModeEnable": {},
"delete": "Delete", "delete": "Delete",
"@delete": {}, "@delete": {},

View File

@ -3,6 +3,7 @@ import "dart:async";
import "package:flutter/material.dart"; import "package:flutter/material.dart";
import "package:flutter/services.dart"; import "package:flutter/services.dart";
import "package:adaptive_theme/adaptive_theme.dart";
import "package:flutter_gen/gen_l10n/app_localizations.dart"; import "package:flutter_gen/gen_l10n/app_localizations.dart";
import "package:flutter_localizations/flutter_localizations.dart"; import "package:flutter_localizations/flutter_localizations.dart";
import "package:flutter_localized_locales/flutter_localized_locales.dart"; import "package:flutter_localized_locales/flutter_localized_locales.dart";
@ -22,6 +23,8 @@ Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
final savedThemeMode = await AdaptiveTheme.getThemeMode();
await runZonedGuarded<Future<void>>(() async { await runZonedGuarded<Future<void>>(() async {
PackageInfo info = await PackageInfo.fromPlatform(); PackageInfo info = await PackageInfo.fromPlatform();
@ -53,7 +56,7 @@ Future<void> main() async {
}; };
runApp( runApp(
InvenTreeApp() InvenTreeApp(savedThemeMode)
); );
}, (Object error, StackTrace stackTrace) async { }, (Object error, StackTrace stackTrace) async {
@ -65,8 +68,12 @@ Future<void> main() async {
class InvenTreeApp extends StatefulWidget { class InvenTreeApp extends StatefulWidget {
// This widget is the root of your application. // This widget is the root of your application.
const InvenTreeApp(this.savedThemeMode);
final AdaptiveThemeMode? savedThemeMode;
@override @override
InvenTreeAppState createState() => InvenTreeAppState(); InvenTreeAppState createState() => InvenTreeAppState(savedThemeMode);
static InvenTreeAppState? of(BuildContext context) => context.findAncestorStateOfType<InvenTreeAppState>(); static InvenTreeAppState? of(BuildContext context) => context.findAncestorStateOfType<InvenTreeAppState>();
@ -75,9 +82,13 @@ class InvenTreeApp extends StatefulWidget {
class InvenTreeAppState extends State<StatefulWidget> { class InvenTreeAppState extends State<StatefulWidget> {
InvenTreeAppState(this.savedThemeMode) : super();
// Custom _locale (default = null; use system default) // Custom _locale (default = null; use system default)
Locale? _locale; Locale? _locale;
final AdaptiveThemeMode? savedThemeMode;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -122,15 +133,25 @@ class InvenTreeAppState extends State<StatefulWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return AdaptiveTheme(
light: ThemeData(
brightness: Brightness.light,
primarySwatch: Colors.lightBlue,
secondaryHeaderColor: Colors.blueGrey
),
dark: ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.lightBlue,
secondaryHeaderColor: Colors.blueGrey,
),
initial: savedThemeMode ?? AdaptiveThemeMode.light,
builder: (light, dark) => MaterialApp(
theme: light,
darkTheme: dark,
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
builder: OneContext().builder, builder: OneContext().builder,
navigatorKey: OneContext().key, navigatorKey: OneContext().key,
onGenerateTitle: (BuildContext context) => "InvenTree", onGenerateTitle: (BuildContext context) => "InvenTree",
theme: ThemeData(
primarySwatch: Colors.lightBlue,
secondaryHeaderColor: Colors.blueGrey,
),
home: InvenTreeHomePage(), home: InvenTreeHomePage(),
localizationsDelegates: [ localizationsDelegates: [
I18N.delegate, I18N.delegate,
@ -141,6 +162,7 @@ class InvenTreeAppState extends State<StatefulWidget> {
], ],
supportedLocales: supported_locales, supportedLocales: supported_locales,
locale: _locale, locale: _locale,
)
); );
} }
} }

View File

@ -1,7 +1,9 @@
import "package:flutter/material.dart"; import "package:flutter/material.dart";
import "package:adaptive_theme/adaptive_theme.dart";
import "package:font_awesome_flutter/font_awesome_flutter.dart"; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import "package:flutter_localized_locales/flutter_localized_locales.dart"; import "package:flutter_localized_locales/flutter_localized_locales.dart";
import "package:one_context/one_context.dart";
import "package:inventree/api_form.dart"; import "package:inventree/api_form.dart";
import "package:inventree/l10.dart"; import "package:inventree/l10.dart";
@ -9,6 +11,8 @@ import "package:inventree/l10n/supported_locales.dart";
import "package:inventree/main.dart"; import "package:inventree/main.dart";
import "package:inventree/preferences.dart"; import "package:inventree/preferences.dart";
import "package:inventree/widget/progress.dart";
class InvenTreeAppSettingsWidget extends StatefulWidget { class InvenTreeAppSettingsWidget extends StatefulWidget {
@override @override
@ -28,23 +32,32 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
bool reportErrors = true; bool reportErrors = true;
bool strictHttps = false; bool strictHttps = false;
bool darkMode = false;
Locale? locale; Locale? locale;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
loadSettings(); loadSettings(OneContext().context!);
} }
Future <void> loadSettings() async { Future <void> loadSettings(BuildContext context) async {
showLoadingOverlay(context);
barcodeSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_BARCODE, true) as bool; barcodeSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_BARCODE, true) as bool;
serverSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_SERVER, true) as bool; serverSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_SERVER, true) as bool;
reportErrors = await InvenTreeSettingsManager().getValue(INV_REPORT_ERRORS, true) as bool; reportErrors = await InvenTreeSettingsManager().getValue(INV_REPORT_ERRORS, true) as bool;
strictHttps = await InvenTreeSettingsManager().getValue(INV_STRICT_HTTPS, false) as bool; strictHttps = await InvenTreeSettingsManager().getValue(INV_STRICT_HTTPS, false) as bool;
darkMode = AdaptiveTheme.of(context).mode.isDark;
locale = await InvenTreeSettingsManager().getSelectedLocale(); locale = await InvenTreeSettingsManager().getSelectedLocale();
hideLoadingOverlay();
if (mounted) { if (mounted) {
setState(() {}); setState(() {});
} }
@ -168,6 +181,24 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
), ),
leading: FaIcon(FontAwesomeIcons.mobile), leading: FaIcon(FontAwesomeIcons.mobile),
), ),
ListTile(
title: Text(L10().darkMode),
subtitle: Text(L10().darkModeEnable),
leading: FaIcon(FontAwesomeIcons.moon),
trailing: Switch(
value: darkMode,
onChanged: (bool value) {
if (value) {
AdaptiveTheme.of(context).setDark();
} else {
AdaptiveTheme.of(context).setLight();
}
setState(() {
darkMode = value;
});
}
)
),
ListTile( ListTile(
title: Text(L10().strictHttps), title: Text(L10().strictHttps),
subtitle: Text(L10().strictHttpsDetails), subtitle: Text(L10().strictHttpsDetails),

View File

@ -52,14 +52,6 @@ class _InvenTreeSettingsState extends State<InvenTreeSettingsWidget> {
Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeLoginSettingsWidget())); Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeLoginSettingsWidget()));
}, },
), ),
ListTile(
title: Text(L10().homeScreen),
subtitle: Text(L10().homeScreenSettings),
leading: FaIcon(FontAwesomeIcons.house, color: COLOR_CLICK),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreenSettingsWidget()));
}
),
ListTile( ListTile(
title: Text(L10().appSettings), title: Text(L10().appSettings),
subtitle: Text(L10().appSettingsDetails), subtitle: Text(L10().appSettingsDetails),
@ -68,6 +60,14 @@ class _InvenTreeSettingsState extends State<InvenTreeSettingsWidget> {
Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeAppSettingsWidget())); Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeAppSettingsWidget()));
} }
), ),
ListTile(
title: Text(L10().homeScreen),
subtitle: Text(L10().homeScreenSettings),
leading: FaIcon(FontAwesomeIcons.house, color: COLOR_CLICK),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreenSettingsWidget()));
}
),
ListTile( ListTile(
title: Text(L10().part), title: Text(L10().part),
subtitle: Text(L10().partSettings), subtitle: Text(L10().partSettings),

View File

@ -9,6 +9,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "52.0.0" version: "52.0.0"
adaptive_theme:
dependency: "direct main"
description:
name: adaptive_theme
sha256: "61bde10390e937d11d05c6cf0d5cf378a73d49f9a442262e43613dae60ed0b3f"
url: "https://pub.dev"
source: hosted
version: "3.2.0"
analyzer: analyzer:
dependency: transitive dependency: transitive
description: description:

View File

@ -7,6 +7,7 @@ environment:
sdk: ">=2.16.0 <3.0.0" sdk: ">=2.16.0 <3.0.0"
dependencies: dependencies:
adaptive_theme: ^3.2.0 # Theme management (e.g. dark mode)
audioplayers: ^3.0.1 # Play audio files audioplayers: ^3.0.1 # Play audio files
cached_network_image: ^3.2.0 # Download and cache remote images cached_network_image: ^3.2.0 # Download and cache remote images
camera: ^0.10.3 # Camera camera: ^0.10.3 # Camera