2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-27 21:16:48 +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
---
- Adds "dark mode" display option
- Add action to issue a purchase order
- Add action to cancel a purchase order
- Reimplement periodic checks for notifications
### 0.11.1 - April 2023
---

View File

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

View File

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

View File

@ -1,7 +1,9 @@
import "package:flutter/material.dart";
import "package:adaptive_theme/adaptive_theme.dart";
import "package:font_awesome_flutter/font_awesome_flutter.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/l10.dart";
@ -9,6 +11,8 @@ import "package:inventree/l10n/supported_locales.dart";
import "package:inventree/main.dart";
import "package:inventree/preferences.dart";
import "package:inventree/widget/progress.dart";
class InvenTreeAppSettingsWidget extends StatefulWidget {
@override
@ -28,23 +32,32 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
bool reportErrors = true;
bool strictHttps = false;
bool darkMode = false;
Locale? locale;
@override
void 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;
serverSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_SERVER, true) as bool;
reportErrors = await InvenTreeSettingsManager().getValue(INV_REPORT_ERRORS, true) as bool;
strictHttps = await InvenTreeSettingsManager().getValue(INV_STRICT_HTTPS, false) as bool;
darkMode = AdaptiveTheme.of(context).mode.isDark;
locale = await InvenTreeSettingsManager().getSelectedLocale();
hideLoadingOverlay();
if (mounted) {
setState(() {});
}
@ -168,6 +181,24 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
),
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(
title: Text(L10().strictHttps),
subtitle: Text(L10().strictHttpsDetails),

View File

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

View File

@ -9,6 +9,14 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: transitive
description:

View File

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