barcode_scanner/lib/app.dart
mandreshope e963abb0ce feat: Implements app theme system
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.
2025-06-23 17:48:03 +03:00

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,
);
}
}