
Replaces hardcoded colors and standard Theme.of(context) accesses with a custom AppTheme. Introduces distinct light and dark themes and persists the selected theme mode using shared_preferences. Integrates the theme into the main app structure and applies it to various components and pages. Adds google_fonts dependency for theme typography.
83 lines
2.6 KiB
Dart
83 lines
2.6 KiB
Dart
import 'package:barcode_scanner/router/router.dart';
|
|
import 'package:barcode_scanner/themes/app_theme.dart';
|
|
import 'package:barcode_scanner/utils/utils.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:responsive_framework/responsive_framework.dart';
|
|
|
|
class App extends ConsumerStatefulWidget {
|
|
const App({super.key});
|
|
|
|
@override
|
|
ConsumerState<App> createState() => _AppState();
|
|
}
|
|
|
|
class _AppState extends ConsumerState<App> {
|
|
ThemeMode _themeMode = AppTheme.themeMode;
|
|
|
|
void setThemeMode(ThemeMode mode) => safeSetState(() {
|
|
_themeMode = mode;
|
|
AppTheme.saveThemeMode(mode);
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ProviderScope(
|
|
overrides: [routerProvider],
|
|
child: _InnerApp(themeMode: _themeMode),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _InnerApp extends ConsumerWidget {
|
|
const _InnerApp({required this.themeMode});
|
|
final ThemeMode themeMode;
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
return MaterialApp.router(
|
|
debugShowCheckedModeBanner: false,
|
|
title: "BarcodeScan",
|
|
locale: Locale('fr'),
|
|
supportedLocales: [Locale('fr', 'FR'), Locale('en', 'US')],
|
|
localizationsDelegates: [
|
|
GlobalMaterialLocalizations.delegate, // Support for Material widgets
|
|
GlobalWidgetsLocalizations.delegate, // Localization for widgets
|
|
GlobalCupertinoLocalizations.delegate, // Support for Cupertino widgets
|
|
],
|
|
routerConfig: ref.watch(routerProvider),
|
|
builder: (context, widget) => ResponsiveBreakpoints.builder(
|
|
child: _ResponsiveWrapper(child: widget ?? const SizedBox.shrink()),
|
|
breakpoints: [
|
|
const Breakpoint(start: 0, end: 450, name: MOBILE),
|
|
const Breakpoint(start: 451, end: 800, name: TABLET),
|
|
],
|
|
),
|
|
theme: ThemeData(brightness: Brightness.light),
|
|
darkTheme: ThemeData(brightness: Brightness.dark),
|
|
themeMode: themeMode,
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ResponsiveWrapper extends StatelessWidget {
|
|
const _ResponsiveWrapper({required this.child});
|
|
final Widget child;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ResponsiveScaledBox(
|
|
width: ResponsiveValue<double?>(
|
|
context,
|
|
conditionalValues: [
|
|
const Condition.equals(name: MOBILE, value: 450),
|
|
const Condition.between(start: 800, end: 1100, value: 800),
|
|
const Condition.between(start: 1000, end: 1200, value: 1000),
|
|
],
|
|
).value,
|
|
child: child,
|
|
);
|
|
}
|
|
}
|