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:
parent
e7f5141aa9
commit
a3d712d11d
@ -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
|
||||
---
|
||||
|
||||
|
@ -211,6 +211,12 @@
|
||||
"damaged": "Damaged",
|
||||
"@damaged": {},
|
||||
|
||||
"darkMode": "Dark Mode",
|
||||
"@darkMode": {},
|
||||
|
||||
"darkModeEnable": "Enable dark mode",
|
||||
"@darkModeEnable": {},
|
||||
|
||||
"delete": "Delete",
|
||||
"@delete": {},
|
||||
|
||||
|
@ -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,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user