Introduce themebloc and persist theme
This commit is contained in:
parent
000bd9a413
commit
8e1cf835e4
@ -4,7 +4,7 @@ import 'package:uuid/uuid.dart';
|
|||||||
|
|
||||||
class FoodEntryBloc extends Bloc<FoodEvent, FoodEntryState> {
|
class FoodEntryBloc extends Bloc<FoodEvent, FoodEntryState> {
|
||||||
final FoodEntryState initialState;
|
final FoodEntryState initialState;
|
||||||
final FoodStorage storage;
|
final AppStorage storage;
|
||||||
final DateTime forDate;
|
final DateTime forDate;
|
||||||
|
|
||||||
FoodEntryBloc(
|
FoodEntryBloc(
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:calodiary/theme_bloc.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
@ -9,34 +10,64 @@ import 'package:calodiary/storage/storage.dart';
|
|||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
var storage = await FoodStorage.create();
|
var storage = await AppStorage.create();
|
||||||
var kcalLimit = await storage.readLimit();
|
var kcalLimit = await storage.readLimit();
|
||||||
|
var brightness = await storage.readBrightness();
|
||||||
|
|
||||||
runApp(MainApp(storage: storage, kcalLimit: kcalLimit));
|
runApp(
|
||||||
|
MainApp(
|
||||||
|
storage: storage,
|
||||||
|
kcalLimit: kcalLimit,
|
||||||
|
brightness: brightness,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MainApp extends StatelessWidget {
|
class MainApp extends StatelessWidget {
|
||||||
final FoodStorage storage;
|
final AppStorage storage;
|
||||||
final double kcalLimit;
|
final double kcalLimit;
|
||||||
|
final String brightness;
|
||||||
|
|
||||||
const MainApp({required this.storage, required this.kcalLimit, super.key});
|
const MainApp(
|
||||||
|
{required this.storage,
|
||||||
|
required this.kcalLimit,
|
||||||
|
required this.brightness,
|
||||||
|
super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return MultiBlocProvider(
|
||||||
create: (context) => SettingsDataBloc(SettingsState(kcalLimit: kcalLimit),
|
providers: [
|
||||||
storage: storage),
|
BlocProvider(
|
||||||
child: MaterialApp.router(
|
create: (context) => SettingsDataBloc(
|
||||||
localizationsDelegates: const [
|
SettingsState(kcalLimit: kcalLimit),
|
||||||
GlobalMaterialLocalizations.delegate,
|
storage: storage),
|
||||||
GlobalWidgetsLocalizations.delegate,
|
),
|
||||||
GlobalCupertinoLocalizations.delegate,
|
BlocProvider(
|
||||||
],
|
create: (context) => ThemeDataBloc(ThemeState(brightness: brightness),
|
||||||
supportedLocales: const [
|
storage: storage),
|
||||||
Locale('de'),
|
),
|
||||||
],
|
],
|
||||||
theme: ThemeData.dark(),
|
child: BlocBuilder<ThemeDataBloc, ThemeState>(
|
||||||
routerConfig: router,
|
builder: (context, state) {
|
||||||
|
var switchToTheme = ThemeData.light();
|
||||||
|
if (state.brightness == 'dark') {
|
||||||
|
switchToTheme = ThemeData.dark();
|
||||||
|
}
|
||||||
|
|
||||||
|
return MaterialApp.router(
|
||||||
|
localizationsDelegates: const [
|
||||||
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
GlobalWidgetsLocalizations.delegate,
|
||||||
|
GlobalCupertinoLocalizations.delegate,
|
||||||
|
],
|
||||||
|
supportedLocales: const [
|
||||||
|
Locale('de'),
|
||||||
|
],
|
||||||
|
theme: switchToTheme,
|
||||||
|
routerConfig: router,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:calodiary/theme_bloc.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
@ -18,7 +19,7 @@ class PerDateWidget extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _PerDateWidgetState extends State<PerDateWidget> {
|
class _PerDateWidgetState extends State<PerDateWidget> {
|
||||||
late FoodStorage storage;
|
late AppStorage storage;
|
||||||
late Future<List<FoodEntry>> entriesFuture;
|
late Future<List<FoodEntry>> entriesFuture;
|
||||||
late List<FoodEntry> entries;
|
late List<FoodEntry> entries;
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ class _PerDateWidgetState extends State<PerDateWidget> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
storage = FoodStorage.getInstance();
|
storage = AppStorage.getInstance();
|
||||||
entriesFuture = storage.getEntriesForDate(widget.date);
|
entriesFuture = storage.getEntriesForDate(widget.date);
|
||||||
entriesFuture.then((val) {
|
entriesFuture.then((val) {
|
||||||
entries = val;
|
entries = val;
|
||||||
@ -39,6 +40,14 @@ class _PerDateWidgetState extends State<PerDateWidget> {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(formattedDate),
|
title: Text(formattedDate),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.lightbulb),
|
||||||
|
onPressed: () {
|
||||||
|
context.read<ThemeDataBloc>().add(ThemeToggleEvent());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
drawer: const AppDrawer(),
|
drawer: const AppDrawer(),
|
||||||
body: FutureBuilder(
|
body: FutureBuilder(
|
||||||
|
@ -2,7 +2,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:calodiary/storage/storage.dart';
|
import 'package:calodiary/storage/storage.dart';
|
||||||
|
|
||||||
class SettingsDataBloc extends Bloc<SettingsEvent, SettingsState> {
|
class SettingsDataBloc extends Bloc<SettingsEvent, SettingsState> {
|
||||||
final FoodStorage storage;
|
final AppStorage storage;
|
||||||
|
|
||||||
SettingsDataBloc(super.initialState, {required this.storage}) {
|
SettingsDataBloc(super.initialState, {required this.storage}) {
|
||||||
on<DailyKcalLimitUpdated>(persistDailyLimit);
|
on<DailyKcalLimitUpdated>(persistDailyLimit);
|
||||||
|
@ -2,22 +2,31 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:calodiary/food_entry_bloc.dart';
|
import 'package:calodiary/food_entry_bloc.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:universal_platform/universal_platform.dart';
|
||||||
|
|
||||||
class FoodStorage {
|
class AppStorage {
|
||||||
static late FoodStorage _instance;
|
static late AppStorage _instance;
|
||||||
late String path;
|
late String path;
|
||||||
FoodStorage._create();
|
AppStorage._create();
|
||||||
|
|
||||||
static Future<FoodStorage> create() async {
|
static Future<AppStorage> create() async {
|
||||||
var storage = FoodStorage._create();
|
var storage = AppStorage._create();
|
||||||
var directory = await getApplicationCacheDirectory();
|
|
||||||
storage.path = directory.path;
|
Directory dir = Directory('');
|
||||||
|
|
||||||
|
if (UniversalPlatform.isDesktop) {
|
||||||
|
dir = await getApplicationCacheDirectory();
|
||||||
|
} else if (UniversalPlatform.isAndroid) {
|
||||||
|
dir = await getApplicationDocumentsDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
storage.path = dir.path;
|
||||||
_instance = storage;
|
_instance = storage;
|
||||||
|
|
||||||
return _instance;
|
return _instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FoodStorage getInstance() => _instance;
|
static AppStorage getInstance() => _instance;
|
||||||
|
|
||||||
Future<List<FoodEntry>> getEntriesForDate(DateTime date) async {
|
Future<List<FoodEntry>> getEntriesForDate(DateTime date) async {
|
||||||
List<FoodEntry> entries = [];
|
List<FoodEntry> entries = [];
|
||||||
@ -93,4 +102,34 @@ class FoodStorage {
|
|||||||
|
|
||||||
return limit;
|
return limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<String> readBrightness() async {
|
||||||
|
var filePath = '$path/brightness';
|
||||||
|
var file = File(filePath);
|
||||||
|
var exists = await file.exists();
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
return 'dark';
|
||||||
|
}
|
||||||
|
|
||||||
|
var line = await file.readAsLines();
|
||||||
|
|
||||||
|
if (line.isEmpty || (line[0] != 'dark' && line[0] != 'light')) {
|
||||||
|
return 'dark';
|
||||||
|
}
|
||||||
|
|
||||||
|
return line[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> writeBrightness(String brightness) async {
|
||||||
|
var filePath = '$path/brightness';
|
||||||
|
var file = File(filePath);
|
||||||
|
var exists = await file.exists();
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
file.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
await file.writeAsString(brightness);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
37
lib/theme_bloc.dart
Normal file
37
lib/theme_bloc.dart
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import 'package:calodiary/storage/storage.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
class ThemeDataBloc extends Bloc<ThemeToggleEvent, ThemeState> {
|
||||||
|
final AppStorage storage;
|
||||||
|
|
||||||
|
ThemeDataBloc(super.initialState, {required this.storage}) {
|
||||||
|
on<ThemeToggleEvent>(switchTheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
void switchTheme(ThemeToggleEvent event, Emitter<ThemeState> emit) async {
|
||||||
|
String newBrightness = 'light';
|
||||||
|
if (state.brightness == 'light') newBrightness = 'dark';
|
||||||
|
|
||||||
|
persistTheme(newBrightness);
|
||||||
|
|
||||||
|
emit(ThemeState(brightness: newBrightness));
|
||||||
|
}
|
||||||
|
|
||||||
|
void persistTheme(String brightness) async {
|
||||||
|
storage.writeBrightness(brightness);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> getPersistedTheme() async {
|
||||||
|
return storage.readBrightness();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThemeToggleEvent {
|
||||||
|
ThemeToggleEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThemeState {
|
||||||
|
final String brightness;
|
||||||
|
|
||||||
|
ThemeState({required this.brightness});
|
||||||
|
}
|
@ -442,6 +442,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.2"
|
version: "1.3.2"
|
||||||
|
universal_platform:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: universal_platform
|
||||||
|
sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
uuid:
|
uuid:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -18,6 +18,7 @@ dependencies:
|
|||||||
path_provider: ^2.1.3
|
path_provider: ^2.1.3
|
||||||
quiver: ^3.2.1
|
quiver: ^3.2.1
|
||||||
settings_ui: ^2.0.2
|
settings_ui: ^2.0.2
|
||||||
|
universal_platform: ^1.1.0
|
||||||
uuid: ^4.4.0
|
uuid: ^4.4.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
Loading…
Reference in New Issue
Block a user