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:
parent
e7f5141aa9
commit
a3d712d11d
@ -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
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -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": {},
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
@ -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),
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user