Skip to content

Commit a3d712d

Browse files
Adds "dark mode" support (#317)
* Adds "dark mode" support - Uses adaptive_theme package * CI fixes * More fixes * Update release notes
1 parent e7f5141 commit a3d712d

File tree

7 files changed

+99
-29
lines changed

7 files changed

+99
-29
lines changed

assets/release_notes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
### 0.11.2 - April 2023
55
---
66

7+
- Adds "dark mode" display option
78
- Add action to issue a purchase order
89
- Add action to cancel a purchase order
910
- Reimplement periodic checks for notifications
1011

12+
1113
### 0.11.1 - April 2023
1214
---
1315

lib/l10n/app_en.arb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,12 @@
211211
"damaged": "Damaged",
212212
"@damaged": {},
213213

214+
"darkMode": "Dark Mode",
215+
"@darkMode": {},
216+
217+
"darkModeEnable": "Enable dark mode",
218+
"@darkModeEnable": {},
219+
214220
"delete": "Delete",
215221
"@delete": {},
216222

lib/main.dart

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import "dart:async";
33
import "package:flutter/material.dart";
44
import "package:flutter/services.dart";
55

6+
import "package:adaptive_theme/adaptive_theme.dart";
67
import "package:flutter_gen/gen_l10n/app_localizations.dart";
78
import "package:flutter_localizations/flutter_localizations.dart";
89
import "package:flutter_localized_locales/flutter_localized_locales.dart";
@@ -22,6 +23,8 @@ Future<void> main() async {
2223

2324
WidgetsFlutterBinding.ensureInitialized();
2425

26+
final savedThemeMode = await AdaptiveTheme.getThemeMode();
27+
2528
await runZonedGuarded<Future<void>>(() async {
2629

2730
PackageInfo info = await PackageInfo.fromPlatform();
@@ -53,7 +56,7 @@ Future<void> main() async {
5356
};
5457

5558
runApp(
56-
InvenTreeApp()
59+
InvenTreeApp(savedThemeMode)
5760
);
5861

5962
}, (Object error, StackTrace stackTrace) async {
@@ -65,8 +68,12 @@ Future<void> main() async {
6568
class InvenTreeApp extends StatefulWidget {
6669
// This widget is the root of your application.
6770

71+
const InvenTreeApp(this.savedThemeMode);
72+
73+
final AdaptiveThemeMode? savedThemeMode;
74+
6875
@override
69-
InvenTreeAppState createState() => InvenTreeAppState();
76+
InvenTreeAppState createState() => InvenTreeAppState(savedThemeMode);
7077

7178
static InvenTreeAppState? of(BuildContext context) => context.findAncestorStateOfType<InvenTreeAppState>();
7279

@@ -75,9 +82,13 @@ class InvenTreeApp extends StatefulWidget {
7582

7683
class InvenTreeAppState extends State<StatefulWidget> {
7784

85+
InvenTreeAppState(this.savedThemeMode) : super();
86+
7887
// Custom _locale (default = null; use system default)
7988
Locale? _locale;
8089

90+
final AdaptiveThemeMode? savedThemeMode;
91+
8192
@override
8293
void initState() {
8394
super.initState();
@@ -122,25 +133,36 @@ class InvenTreeAppState extends State<StatefulWidget> {
122133
@override
123134
Widget build(BuildContext context) {
124135

125-
return MaterialApp(
126-
debugShowCheckedModeBanner: false,
127-
builder: OneContext().builder,
128-
navigatorKey: OneContext().key,
129-
onGenerateTitle: (BuildContext context) => "InvenTree",
130-
theme: ThemeData(
136+
return AdaptiveTheme(
137+
light: ThemeData(
138+
brightness: Brightness.light,
139+
primarySwatch: Colors.lightBlue,
140+
secondaryHeaderColor: Colors.blueGrey
141+
),
142+
dark: ThemeData(
143+
brightness: Brightness.dark,
131144
primarySwatch: Colors.lightBlue,
132145
secondaryHeaderColor: Colors.blueGrey,
133146
),
134-
home: InvenTreeHomePage(),
135-
localizationsDelegates: [
136-
I18N.delegate,
137-
LocaleNamesLocalizationsDelegate(),
138-
GlobalMaterialLocalizations.delegate,
139-
GlobalCupertinoLocalizations.delegate,
140-
GlobalWidgetsLocalizations.delegate,
141-
],
142-
supportedLocales: supported_locales,
143-
locale: _locale,
147+
initial: savedThemeMode ?? AdaptiveThemeMode.light,
148+
builder: (light, dark) => MaterialApp(
149+
theme: light,
150+
darkTheme: dark,
151+
debugShowCheckedModeBanner: false,
152+
builder: OneContext().builder,
153+
navigatorKey: OneContext().key,
154+
onGenerateTitle: (BuildContext context) => "InvenTree",
155+
home: InvenTreeHomePage(),
156+
localizationsDelegates: [
157+
I18N.delegate,
158+
LocaleNamesLocalizationsDelegate(),
159+
GlobalMaterialLocalizations.delegate,
160+
GlobalCupertinoLocalizations.delegate,
161+
GlobalWidgetsLocalizations.delegate,
162+
],
163+
supportedLocales: supported_locales,
164+
locale: _locale,
165+
)
144166
);
145167
}
146168
}

lib/settings/app_settings.dart

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
21
import "package:flutter/material.dart";
2+
3+
import "package:adaptive_theme/adaptive_theme.dart";
34
import "package:font_awesome_flutter/font_awesome_flutter.dart";
45
import "package:flutter_localized_locales/flutter_localized_locales.dart";
6+
import "package:one_context/one_context.dart";
57

68
import "package:inventree/api_form.dart";
79
import "package:inventree/l10.dart";
810
import "package:inventree/l10n/supported_locales.dart";
911
import "package:inventree/main.dart";
1012
import "package:inventree/preferences.dart";
1113

14+
import "package:inventree/widget/progress.dart";
15+
1216

1317
class InvenTreeAppSettingsWidget extends StatefulWidget {
1418
@override
@@ -28,23 +32,32 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
2832
bool reportErrors = true;
2933
bool strictHttps = false;
3034

35+
bool darkMode = false;
36+
3137
Locale? locale;
3238

3339
@override
3440
void initState() {
3541
super.initState();
3642

37-
loadSettings();
43+
loadSettings(OneContext().context!);
3844
}
3945

40-
Future <void> loadSettings() async {
46+
Future <void> loadSettings(BuildContext context) async {
47+
48+
showLoadingOverlay(context);
49+
4150
barcodeSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_BARCODE, true) as bool;
4251
serverSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_SERVER, true) as bool;
4352
reportErrors = await InvenTreeSettingsManager().getValue(INV_REPORT_ERRORS, true) as bool;
4453
strictHttps = await InvenTreeSettingsManager().getValue(INV_STRICT_HTTPS, false) as bool;
4554

55+
darkMode = AdaptiveTheme.of(context).mode.isDark;
56+
4657
locale = await InvenTreeSettingsManager().getSelectedLocale();
4758

59+
hideLoadingOverlay();
60+
4861
if (mounted) {
4962
setState(() {});
5063
}
@@ -168,6 +181,24 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
168181
),
169182
leading: FaIcon(FontAwesomeIcons.mobile),
170183
),
184+
ListTile(
185+
title: Text(L10().darkMode),
186+
subtitle: Text(L10().darkModeEnable),
187+
leading: FaIcon(FontAwesomeIcons.moon),
188+
trailing: Switch(
189+
value: darkMode,
190+
onChanged: (bool value) {
191+
if (value) {
192+
AdaptiveTheme.of(context).setDark();
193+
} else {
194+
AdaptiveTheme.of(context).setLight();
195+
}
196+
setState(() {
197+
darkMode = value;
198+
});
199+
}
200+
)
201+
),
171202
ListTile(
172203
title: Text(L10().strictHttps),
173204
subtitle: Text(L10().strictHttpsDetails),

lib/settings/settings.dart

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ class _InvenTreeSettingsState extends State<InvenTreeSettingsWidget> {
5252
Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeLoginSettingsWidget()));
5353
},
5454
),
55+
ListTile(
56+
title: Text(L10().appSettings),
57+
subtitle: Text(L10().appSettingsDetails),
58+
leading: FaIcon(FontAwesomeIcons.gears, color: COLOR_CLICK),
59+
onTap: () {
60+
Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeAppSettingsWidget()));
61+
}
62+
),
5563
ListTile(
5664
title: Text(L10().homeScreen),
5765
subtitle: Text(L10().homeScreenSettings),
@@ -60,14 +68,6 @@ class _InvenTreeSettingsState extends State<InvenTreeSettingsWidget> {
6068
Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreenSettingsWidget()));
6169
}
6270
),
63-
ListTile(
64-
title: Text(L10().appSettings),
65-
subtitle: Text(L10().appSettingsDetails),
66-
leading: FaIcon(FontAwesomeIcons.gears, color: COLOR_CLICK),
67-
onTap: () {
68-
Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeAppSettingsWidget()));
69-
}
70-
),
7171
ListTile(
7272
title: Text(L10().part),
7373
subtitle: Text(L10().partSettings),

pubspec.lock

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ packages:
99
url: "https://pub.dev"
1010
source: hosted
1111
version: "52.0.0"
12+
adaptive_theme:
13+
dependency: "direct main"
14+
description:
15+
name: adaptive_theme
16+
sha256: "61bde10390e937d11d05c6cf0d5cf378a73d49f9a442262e43613dae60ed0b3f"
17+
url: "https://pub.dev"
18+
source: hosted
19+
version: "3.2.0"
1220
analyzer:
1321
dependency: transitive
1422
description:

pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ environment:
77
sdk: ">=2.16.0 <3.0.0"
88

99
dependencies:
10+
adaptive_theme: ^3.2.0 # Theme management (e.g. dark mode)
1011
audioplayers: ^3.0.1 # Play audio files
1112
cached_network_image: ^3.2.0 # Download and cache remote images
1213
camera: ^0.10.3 # Camera

0 commit comments

Comments
 (0)