From 28b2abdff31e5c297e2d870371a201ccd63198ae Mon Sep 17 00:00:00 2001 From: Mark M2 Macbook Date: Sun, 5 Apr 2026 10:06:26 +0200 Subject: [PATCH] theme work --- ios/Flutter/Debug.xcconfig | 1 + ios/Flutter/Release.xcconfig | 1 + ios/Podfile | 43 +++++++++++ lib/data/enums.dart | 12 +++ lib/main.dart | 50 +++++-------- lib/theme/theme_bloc.dart | 25 +++++-- lib/theme/theme_events.dart | 10 ++- lib/theme/theme_state.dart | 26 ++----- lib/ui/anagrafiche/anagrafiche_main_view.dart | 2 +- lib/ui/dashboard/dashboard_view.dart | 20 ++--- lib/ui/home_screen.dart | 73 ++++++++----------- lib/ui/settings/settings.dart | 24 ++---- lib/ui/settings/settings_view.dart | 29 ++++++-- macos/Flutter/Flutter-Debug.xcconfig | 1 + macos/Flutter/Flutter-Release.xcconfig | 1 + macos/Podfile | 42 +++++++++++ 16 files changed, 223 insertions(+), 137 deletions(-) create mode 100644 ios/Podfile create mode 100644 lib/data/enums.dart create mode 100644 macos/Podfile diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig index 592ceee..ec97fc6 100644 --- a/ios/Flutter/Debug.xcconfig +++ b/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig index 592ceee..c4855bf 100644 --- a/ios/Flutter/Release.xcconfig +++ b/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..620e46e --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,43 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '13.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/lib/data/enums.dart b/lib/data/enums.dart new file mode 100644 index 0000000..c8d9f29 --- /dev/null +++ b/lib/data/enums.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +enum AppThemeMode { + light('light', 'Chiaro', ThemeMode.light), + dark('dark', 'Scuro', ThemeMode.dark), + system('system', 'Sistema', ThemeMode.system); + + const AppThemeMode(this.value, this.label, this.themeMode); + final String value; + final String label; + final ThemeMode themeMode; +} diff --git a/lib/main.dart b/lib/main.dart index fe0ef6f..c8dc933 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -14,42 +14,30 @@ void main() async { await SharedPreferences.getInstance(), ); getIt.registerSingleton(AppSettings()); - runApp(const MainApp()); + runApp( + BlocProvider( + create: (context) => ThemeBloc()..add(LoadThemeEvent()), + child: const FluxApp(), + ), + ); } -class MainApp extends StatelessWidget { - const MainApp({super.key}); +class FluxApp extends StatelessWidget { + const FluxApp({super.key}); @override Widget build(BuildContext context) { - AppTheme appTheme = GetIt.I.get().appTheme; - ThemeData themeData; - switch (appTheme) { - case AppTheme.dark: - themeData = fluxDarkTheme; - break; - case AppTheme.light: - themeData = fluxLightTheme; - break; - default: - themeData = ThemeMode.system == ThemeMode.dark - ? fluxDarkTheme - : fluxLightTheme; - break; - } - return MaterialApp( - title: 'FLUX Gestionale', - debugShowCheckedModeBanner: false, - theme: themeData, // Applica il tema FLUX - home: MultiBlocProvider( - providers: [ - BlocProvider( - create: (context) => ThemeBloc(initialAppTheme: appTheme), - ), - ], - - child: const HomeScreen(), - ), + return BlocBuilder( + builder: (context, state) { + return MaterialApp( + title: 'FLUX Gestionale', + debugShowCheckedModeBanner: false, + theme: fluxLightTheme, + darkTheme: fluxDarkTheme, + themeMode: state.themeMode, // Applica il tema FLUX + home: const HomeScreen(), + ); + }, ); } } diff --git a/lib/theme/theme_bloc.dart b/lib/theme/theme_bloc.dart index 0e4a1a2..39ff8d9 100644 --- a/lib/theme/theme_bloc.dart +++ b/lib/theme/theme_bloc.dart @@ -1,17 +1,30 @@ +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:flux/data/enums.dart'; +import 'package:get_it/get_it.dart'; +import 'package:shared_preferences/shared_preferences.dart'; part 'theme_events.dart'; part 'theme_state.dart'; class ThemeBloc extends Bloc { - final AppTheme initialAppTheme; - ThemeBloc({required this.initialAppTheme}) - : super( - ThemeState(status: ThemeStatus.success, appTheme: initialAppTheme), - ) { + static const String _savedThemeKey = "themeModeSetting"; + final SharedPreferences _prefs = GetIt.I.get(); + ThemeBloc() : super(ThemeState(themeMode: ThemeMode.system)) { + on((event, emit) { + String savedTheme = _prefs.getString(_savedThemeKey) ?? 'system'; + emit( + state.copyWith( + themeMode: AppThemeMode.values + .firstWhere((test) => test.value == savedTheme) + .themeMode, + ), + ); + }); on((event, emit) async { - emit(state.copyWith(appTheme: event.appTheme)); + await _prefs.setString(_savedThemeKey, event.appThemeMode.value); + emit(state.copyWith(themeMode: event.appThemeMode.themeMode)); }); } } diff --git a/lib/theme/theme_events.dart b/lib/theme/theme_events.dart index 958e15c..680bc8a 100644 --- a/lib/theme/theme_events.dart +++ b/lib/theme/theme_events.dart @@ -7,11 +7,13 @@ abstract class ThemeEvent extends Equatable { List get props => []; } -class ChangeThemeEvent extends ThemeEvent { - const ChangeThemeEvent({required this.appTheme}); +final class LoadThemeEvent extends ThemeEvent {} - final AppTheme appTheme; +final class ChangeThemeEvent extends ThemeEvent { + final AppThemeMode appThemeMode; + + const ChangeThemeEvent(this.appThemeMode); @override - List get props => [appTheme]; + List get props => [appThemeMode]; } diff --git a/lib/theme/theme_state.dart b/lib/theme/theme_state.dart index 588ef78..b05294b 100644 --- a/lib/theme/theme_state.dart +++ b/lib/theme/theme_state.dart @@ -1,30 +1,14 @@ part of 'theme_bloc.dart'; -enum ThemeStatus { initial, success } - -enum AppTheme { - dark(name: 'dark'), - light(name: 'light'), - system(name: 'system'); - - final String name; - - const AppTheme({required this.name}); -} - class ThemeState extends Equatable { - const ThemeState({required this.status, required this.appTheme}); + const ThemeState({required this.themeMode}); - final ThemeStatus status; - final AppTheme appTheme; + final ThemeMode themeMode; @override - List get props => [status, appTheme]; + List get props => [themeMode]; - ThemeState copyWith({ThemeStatus? status, AppTheme? appTheme}) { - return ThemeState( - status: status ?? this.status, - appTheme: appTheme ?? this.appTheme, - ); + ThemeState copyWith({ThemeMode? themeMode}) { + return ThemeState(themeMode: themeMode ?? this.themeMode); } } diff --git a/lib/ui/anagrafiche/anagrafiche_main_view.dart b/lib/ui/anagrafiche/anagrafiche_main_view.dart index 39e0461..c3926ae 100644 --- a/lib/ui/anagrafiche/anagrafiche_main_view.dart +++ b/lib/ui/anagrafiche/anagrafiche_main_view.dart @@ -16,7 +16,7 @@ class AnagraficheMainView extends StatelessWidget { isScrollable: true, indicatorColor: FluxColors.accentTurquoise, labelColor: FluxColors.accentTurquoise, - unselectedLabelColor: FluxColors.textSecondary, + unselectedLabelColor: Theme.of(context).textTheme.bodyMedium?.color, tabs: [ Tab(icon: Icon(Icons.storefront), text: 'Negozi'), Tab(icon: Icon(Icons.support_agent), text: 'Gestori'), diff --git a/lib/ui/dashboard/dashboard_view.dart b/lib/ui/dashboard/dashboard_view.dart index 090b7a7..40b230e 100644 --- a/lib/ui/dashboard/dashboard_view.dart +++ b/lib/ui/dashboard/dashboard_view.dart @@ -92,26 +92,28 @@ class _RecentActivityPreview extends StatelessWidget { 'Attività Recenti', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), - const Divider(color: FluxColors.textSecondary), + Divider(color: Theme.of(context).textTheme.bodyMedium?.color), // Sostituire con BlocBuilder - _activityTile('Nuova Linea', 'Mario Rossi', '10 min fa'), - _activityTile('Assistenza Tech', 'iPhone 13', '45 min fa'), + _activityTile('Nuova Linea', 'Mario Rossi', '10 min fa', context), + _activityTile('Assistenza Tech', 'iPhone 13', '45 min fa', context), ], ), ), ); } - Widget _activityTile(String title, String subtitle, String time) { + Widget _activityTile( + String title, + String subtitle, + String time, + BuildContext context, + ) { return ListTile( contentPadding: EdgeInsets.zero, leading: const Icon(Icons.history, color: FluxColors.accentTurquoise), - title: Text(title, style: const TextStyle(color: FluxColors.textPrimary)), + title: Text(title, style: Theme.of(context).textTheme.titleLarge), subtitle: Text(subtitle), - trailing: Text( - time, - style: const TextStyle(color: FluxColors.textSecondary, fontSize: 12), - ), + trailing: Text(time, style: Theme.of(context).textTheme.bodyMedium), ); } } diff --git a/lib/ui/home_screen.dart b/lib/ui/home_screen.dart index 242120b..be4d10e 100644 --- a/lib/ui/home_screen.dart +++ b/lib/ui/home_screen.dart @@ -1,7 +1,5 @@ -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/material.dart'; import 'package:flux/theme/theme.dart'; -import 'package:flux/theme/theme_bloc.dart'; import 'package:flux/ui/anagrafiche/anagrafiche_main_view.dart'; import 'package:flux/ui/dashboard/dashboard_view.dart'; import 'package:flux/ui/settings/settings_view.dart'; @@ -31,46 +29,39 @@ class _HomeScreenState extends State { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return Scaffold( - body: Center(child: _widgetOptions.elementAt(_selectedIndex)), - bottomNavigationBar: BottomNavigationBar( - items: const [ - BottomNavigationBarItem( - icon: Icon(Icons.dashboard_outlined), - activeIcon: Icon(Icons.dashboard), - label: 'Dashboard', - ), - BottomNavigationBarItem( - icon: Icon(Icons.history_edu_outlined), - activeIcon: Icon(Icons.history_edu), - label: 'Operazioni', - ), - BottomNavigationBarItem( - icon: Icon(Icons.people_alt_outlined), - activeIcon: Icon(Icons.people_alt), - label: 'Anagrafiche', - ), - BottomNavigationBarItem( - icon: Icon(Icons.settings_outlined), - activeIcon: Icon(Icons.settings), - label: 'Impostazioni', - ), - ], - currentIndex: _selectedIndex, - selectedItemColor: FluxColors.accentTurquoise, - unselectedItemColor: state.themeMode == ThemeMode.dark - ? FluxColors.darkTextSecondary - : FluxColors.lightTextSecondary, - backgroundColor: state.themeMode == ThemeMode.dark - ? FluxColors.darkSurface - : FluxColors.lightSurface, - type: BottomNavigationBarType.fixed, - onTap: _onItemTapped, + final surfaceColor = Theme.of(context).colorScheme.surface; + return Scaffold( + body: Center(child: _widgetOptions.elementAt(_selectedIndex)), + bottomNavigationBar: BottomNavigationBar( + items: const [ + BottomNavigationBarItem( + icon: Icon(Icons.dashboard_outlined), + activeIcon: Icon(Icons.dashboard), + label: 'Dashboard', ), - ); - }, + BottomNavigationBarItem( + icon: Icon(Icons.history_edu_outlined), + activeIcon: Icon(Icons.history_edu), + label: 'Operazioni', + ), + BottomNavigationBarItem( + icon: Icon(Icons.people_alt_outlined), + activeIcon: Icon(Icons.people_alt), + label: 'Anagrafiche', + ), + BottomNavigationBarItem( + icon: Icon(Icons.settings_outlined), + activeIcon: Icon(Icons.settings), + label: 'Impostazioni', + ), + ], + currentIndex: _selectedIndex, + selectedItemColor: FluxColors.accentTurquoise, + unselectedItemColor: Theme.of(context).textTheme.bodyMedium?.color, + backgroundColor: surfaceColor, + type: BottomNavigationBarType.fixed, + onTap: _onItemTapped, + ), ); } } diff --git a/lib/ui/settings/settings.dart b/lib/ui/settings/settings.dart index 9d10d27..308d066 100644 --- a/lib/ui/settings/settings.dart +++ b/lib/ui/settings/settings.dart @@ -1,9 +1,8 @@ -import 'package:flux/theme/theme_bloc.dart'; import 'package:get_it/get_it.dart'; import 'package:shared_preferences/shared_preferences.dart'; class AppSettings { - late AppTheme _appTheme; + late String _themeModeSetting; late SharedPreferences _prefs; // Singleton @@ -16,24 +15,13 @@ class AppSettings { AppSettings._internal() { _prefs = GetIt.I.get(); - String theme = _prefs.getString('theme') ?? 'light'; - switch (theme) { - case 'dark': - _appTheme = AppTheme.dark; - break; - case 'light': - _appTheme = AppTheme.light; - break; - default: - _appTheme = AppTheme.system; - break; - } + _themeModeSetting = _prefs.getString('theme') ?? 'light'; } - AppTheme get appTheme => _appTheme; + String get themeModeSetting => _themeModeSetting; - void setAppTheme(AppTheme theme) { - _appTheme = theme; - _prefs.setString('theme', theme.name); + void setThemeModeSetting(String value) { + _themeModeSetting = value; + _prefs.setString('theme', value); } } diff --git a/lib/ui/settings/settings_view.dart b/lib/ui/settings/settings_view.dart index d5cfce4..e28159d 100644 --- a/lib/ui/settings/settings_view.dart +++ b/lib/ui/settings/settings_view.dart @@ -17,16 +17,28 @@ class SettingsView extends StatelessWidget { Icons.person, 'Profilo Utente', 'Configura i tuoi dati', + context, + ), + _settingsTile( + Icons.store, + 'Mio Negozio', + 'Piacenza Centro', + context, ), - _settingsTile(Icons.store, 'Mio Negozio', 'Piacenza Centro'), ]), const SizedBox(height: 16), _settingsSection('Applicazione', [ - _settingsTile(Icons.sync, 'Sincronizzazione', 'Ultima: 5 min fa'), + _settingsTile( + Icons.sync, + 'Sincronizzazione', + 'Ultima: 5 min fa', + context, + ), _settingsTile( Icons.dark_mode, 'Tema (FLUX Dark Active)', 'Configurazione visiva', + context, ), ]), const SizedBox(height: 24), @@ -58,14 +70,19 @@ class SettingsView extends StatelessWidget { ); } - Widget _settingsTile(IconData icon, String title, String subtitle) { + Widget _settingsTile( + IconData icon, + String title, + String subtitle, + BuildContext context, + ) { return ListTile( leading: Icon(icon, color: FluxColors.primaryBlue), - title: Text(title, style: const TextStyle(color: FluxColors.textPrimary)), + title: Text(title, style: Theme.of(context).textTheme.titleLarge), subtitle: Text(subtitle), - trailing: const Icon( + trailing: Icon( Icons.chevron_right, - color: FluxColors.textSecondary, + color: Theme.of(context).textTheme.bodyMedium?.color, ), ); } diff --git a/macos/Flutter/Flutter-Debug.xcconfig b/macos/Flutter/Flutter-Debug.xcconfig index c2efd0b..4b81f9b 100644 --- a/macos/Flutter/Flutter-Debug.xcconfig +++ b/macos/Flutter/Flutter-Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/Flutter-Release.xcconfig b/macos/Flutter/Flutter-Release.xcconfig index c2efd0b..5caa9d1 100644 --- a/macos/Flutter/Flutter-Release.xcconfig +++ b/macos/Flutter/Flutter-Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Podfile b/macos/Podfile new file mode 100644 index 0000000..ff5ddb3 --- /dev/null +++ b/macos/Podfile @@ -0,0 +1,42 @@ +platform :osx, '10.15' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end