update dark mode handling
This commit is contained in:
+14
-5
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:frontend/provider/theme_provider.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
@@ -17,10 +18,17 @@ import 'pages/leaderboard.dart';
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(
|
runApp(
|
||||||
ChangeNotifierProvider(
|
MultiProvider(
|
||||||
create: (_) => QuoteProvider(),
|
providers: [
|
||||||
child: HlaskovnikFrontendApp(),
|
ChangeNotifierProvider(
|
||||||
),
|
create: (_) => QuoteProvider()
|
||||||
|
),
|
||||||
|
ChangeNotifierProvider(
|
||||||
|
create: (_) => ThemeProvider()
|
||||||
|
)
|
||||||
|
],
|
||||||
|
child: HlaskovnikFrontendApp()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,6 +54,7 @@ class HlaskovnikFrontendApp extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final themeProvider = context.watch<ThemeProvider>();
|
||||||
return MaterialApp.router(
|
return MaterialApp.router(
|
||||||
title: Strings.appName,
|
title: Strings.appName,
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
@@ -62,7 +71,7 @@ class HlaskovnikFrontendApp extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
),
|
),
|
||||||
themeMode: ThemeMode.system,
|
themeMode: themeProvider.isDark ? ThemeMode.dark : ThemeMode.system,
|
||||||
routerConfig: _router,
|
routerConfig: _router,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
import 'package:frontend/provider/quote_provider.dart';
|
import 'package:frontend/provider/quote_provider.dart';
|
||||||
import 'package:frontend/model/quote.dart';
|
import 'package:frontend/model/quote.dart';
|
||||||
|
import 'package:frontend/provider/theme_provider.dart';
|
||||||
import 'package:frontend/values/strings.dart';
|
import 'package:frontend/values/strings.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
@@ -13,15 +14,16 @@ class ListPage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final provider = context.watch<QuoteProvider>();
|
final provider = context.watch<QuoteProvider>();
|
||||||
|
final themeProvider = context.watch<ThemeProvider>();
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
await provider.readQuotes();
|
await provider.readQuotes();
|
||||||
},
|
},
|
||||||
child: _bodyBuilder(context, provider),
|
child: _bodyBuilder(context, provider, themeProvider),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _bodyBuilder(BuildContext context, QuoteProvider provider) {
|
Widget _bodyBuilder(BuildContext context, QuoteProvider provider, ThemeProvider themeProvider) {
|
||||||
if (provider.loading) {
|
if (provider.loading) {
|
||||||
return Center(child: CircularProgressIndicator());
|
return Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
@@ -51,7 +53,7 @@ class ListPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
filterBar(context, provider),
|
filterBar(context, provider, themeProvider),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
padding: EdgeInsets.all(Constants.edgeInset),
|
padding: EdgeInsets.all(Constants.edgeInset),
|
||||||
@@ -220,7 +222,7 @@ class ListPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget filterBar(BuildContext context, QuoteProvider provider) {
|
Widget filterBar(BuildContext context, QuoteProvider provider, ThemeProvider themeProvider) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(Constants.edgeInset),
|
padding: const EdgeInsets.all(Constants.edgeInset),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -246,7 +248,7 @@ class ListPage extends StatelessWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.more_horiz),
|
icon: Icon(Icons.more_horiz),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_showOptionsBottomSheet(context, provider);
|
_showOptionsBottomSheet(context, provider, themeProvider);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -254,7 +256,7 @@ class ListPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showOptionsBottomSheet(BuildContext context, QuoteProvider provider) {
|
void _showOptionsBottomSheet(BuildContext context, QuoteProvider provider, ThemeProvider themeProvider) {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
@@ -284,6 +286,25 @@ class ListPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text(Strings.userPrefersDarkMode),
|
||||||
|
onTap: () { themeProvider.setDarkMode(!themeProvider.isDark); },
|
||||||
|
trailing: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: Constants.edgeInset),
|
||||||
|
child: Switch(
|
||||||
|
onChanged: (value) {
|
||||||
|
themeProvider.setDarkMode(value);
|
||||||
|
},
|
||||||
|
value: themeProvider.isDark
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Icon(Icons.dark_mode),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
Future<void> saveDarkMode(bool isDark) async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.setBool('darkMode', isDark);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> loadDarkMode() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
return prefs.getBool('darkMode') ?? false; // default light
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThemeProvider extends ChangeNotifier {
|
||||||
|
bool _isDark = false;
|
||||||
|
|
||||||
|
bool get isDark => _isDark;
|
||||||
|
|
||||||
|
ThemeProvider() {
|
||||||
|
_load(); // load saved value on startup
|
||||||
|
}
|
||||||
|
|
||||||
|
void _load() async {
|
||||||
|
_isDark = await loadDarkMode();
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDarkMode(bool value) async {
|
||||||
|
_isDark = value;
|
||||||
|
notifyListeners();
|
||||||
|
await saveDarkMode(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,4 +30,6 @@ class Strings {
|
|||||||
static const String filterBy = "Filtrovat podle";
|
static const String filterBy = "Filtrovat podle";
|
||||||
static const String exportSelectedQuotes = "Exportovat vybrané hlášky";
|
static const String exportSelectedQuotes = "Exportovat vybrané hlášky";
|
||||||
static const String byAttribute = "podle příznaku";
|
static const String byAttribute = "podle příznaku";
|
||||||
|
|
||||||
|
static const String userPrefersDarkMode = "Preferuji tmavý režim";
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,8 @@
|
|||||||
import FlutterMacOS
|
import FlutterMacOS
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
import shared_preferences_foundation
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -328,6 +328,62 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.2.0"
|
||||||
|
shared_preferences:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: shared_preferences
|
||||||
|
sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.5"
|
||||||
|
shared_preferences_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_android
|
||||||
|
sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.23"
|
||||||
|
shared_preferences_foundation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_foundation
|
||||||
|
sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.6"
|
||||||
|
shared_preferences_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_linux
|
||||||
|
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
|
shared_preferences_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_platform_interface
|
||||||
|
sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.2"
|
||||||
|
shared_preferences_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_web
|
||||||
|
sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.3"
|
||||||
|
shared_preferences_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_windows
|
||||||
|
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ dependencies:
|
|||||||
go_router:
|
go_router:
|
||||||
http: ^1.2.0
|
http: ^1.2.0
|
||||||
path_provider:
|
path_provider:
|
||||||
|
shared_preferences: ^2.1.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user