theme work

This commit is contained in:
2026-04-05 10:06:26 +02:00
parent 0347a354ef
commit 28b2abdff3
16 changed files with 223 additions and 137 deletions

View File

@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View File

@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

43
ios/Podfile Normal file
View File

@@ -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

12
lib/data/enums.dart Normal file
View File

@@ -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;
}

View File

@@ -14,42 +14,30 @@ void main() async {
await SharedPreferences.getInstance(),
);
getIt.registerSingleton<AppSettings>(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<AppSettings>().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 BlocBuilder<ThemeBloc, ThemeState>(
builder: (context, state) {
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(),
),
theme: fluxLightTheme,
darkTheme: fluxDarkTheme,
themeMode: state.themeMode, // Applica il tema FLUX
home: const HomeScreen(),
);
},
);
}
}

View File

@@ -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<ThemeEvent, ThemeState> {
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<SharedPreferences>();
ThemeBloc() : super(ThemeState(themeMode: ThemeMode.system)) {
on<LoadThemeEvent>((event, emit) {
String savedTheme = _prefs.getString(_savedThemeKey) ?? 'system';
emit(
state.copyWith(
themeMode: AppThemeMode.values
.firstWhere((test) => test.value == savedTheme)
.themeMode,
),
);
});
on<ChangeThemeEvent>((event, emit) async {
emit(state.copyWith(appTheme: event.appTheme));
await _prefs.setString(_savedThemeKey, event.appThemeMode.value);
emit(state.copyWith(themeMode: event.appThemeMode.themeMode));
});
}
}

View File

@@ -7,11 +7,13 @@ abstract class ThemeEvent extends Equatable {
List<Object> 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<Object> get props => [appTheme];
List<Object> get props => [appThemeMode];
}

View File

@@ -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<Object?> get props => [status, appTheme];
List<Object?> 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);
}
}

View File

@@ -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'),

View File

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

View File

@@ -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,8 +29,7 @@ class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
return BlocBuilder<ThemeBloc, ThemeState>(
builder: (context, state) {
final surfaceColor = Theme.of(context).colorScheme.surface;
return Scaffold(
body: Center(child: _widgetOptions.elementAt(_selectedIndex)),
bottomNavigationBar: BottomNavigationBar(
@@ -60,17 +57,11 @@ class _HomeScreenState extends State<HomeScreen> {
],
currentIndex: _selectedIndex,
selectedItemColor: FluxColors.accentTurquoise,
unselectedItemColor: state.themeMode == ThemeMode.dark
? FluxColors.darkTextSecondary
: FluxColors.lightTextSecondary,
backgroundColor: state.themeMode == ThemeMode.dark
? FluxColors.darkSurface
: FluxColors.lightSurface,
unselectedItemColor: Theme.of(context).textTheme.bodyMedium?.color,
backgroundColor: surfaceColor,
type: BottomNavigationBarType.fixed,
onTap: _onItemTapped,
),
);
},
);
}
}

View File

@@ -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<SharedPreferences>();
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);
}
}

View File

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

View File

@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

View File

@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

42
macos/Podfile Normal file
View File

@@ -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