Guida all'Aggiornamento
Novita nella v7
Nylo Website v7 e una release principale con miglioramenti significativi all'esperienza dello sviluppatore:
Configurazione dell'Ambiente Crittografata
- Le variabili d'ambiente sono ora crittografate con XOR al momento della compilazione per maggiore sicurezza
- Il nuovo comando
metro make:keygenera la Sua APP_KEY - Il nuovo comando
metro make:envgenera il file crittografatoenv.g.dart - Supporto per l'iniezione di APP_KEY tramite
--dart-defineper le pipeline CI/CD
Processo di Avvio Semplificato
- Il nuovo pattern
BootConfigsostituisce i callback separati setup/finished Nylo.init()piu pulito con il parametroenvper l'ambiente crittografato- Hook del ciclo di vita dell'app direttamente in main.dart
Nuova API nylo.configure()
- Un singolo metodo consolida tutta la configurazione dell'app
- Sintassi piu pulita che sostituisce le chiamate individuali
nylo.add*() - Metodi separati
setup()eboot()per il ciclo di vita nei provider
NyPage per le Pagine
NyPagesostituisceNyStateper i widget delle pagine (sintassi piu pulita)view()sostituisce il metodobuild()- Il getter
get init =>sostituisce i metodiinit()eboot() NyStatee ancora disponibile per i widget stateful che non sono pagine
Sistema LoadingStyle
- Nuovo enum
LoadingStyleper stati di caricamento consistenti - Opzioni:
LoadingStyle.normal(),LoadingStyle.skeletonizer(),LoadingStyle.none() - Widget di caricamento personalizzati tramite
LoadingStyle.normal(child: ...)
Routing Type-Safe con RouteView
static RouteView pathsostituiscestatic const path- Definizioni delle route type-safe con widget factory
Supporto Multi-Theme
- Registrazione di piu theme scuri e chiari
- ID dei theme definiti nel codice invece che nel file
.env - Nuovi
NyThemeType.dark/NyThemeType.lightper la classificazione dei theme - API per theme preferiti:
NyTheme.setPreferredDark(),NyTheme.setPreferredLight() - Enumerazione dei theme:
NyTheme.lightThemes(),NyTheme.darkThemes(),NyTheme.all()
Nuovi Comandi Metro
make:key- Genera APP_KEY per la crittografiamake:env- Genera il file d'ambiente crittografatomake:bottom_sheet_modal- Crea bottom sheet modalmake:button- Crea pulsanti personalizzati
Visualizza tutte le modifiche su GitHub
Panoramica delle Modifiche Incompatibili
| Modifica | v6 | v7 |
|---|---|---|
| Widget Root dell'App | LocalizedApp(child: Main(nylo)) |
Main(nylo) (usa NyApp.materialApp()) |
| Classe State della Pagina | NyState |
NyPage per le pagine |
| Metodo View | build() |
view() |
| Metodo Init | init() async {} / boot() async {} |
get init => () async {} |
| Percorso Route | static const path = '/home' |
static RouteView path = ('/home', (_) => HomePage()) |
| Boot del Provider | boot(Nylo nylo) |
setup(Nylo nylo) + boot(Nylo nylo) |
| Configurazione | Chiamate individuali nylo.add*() |
Singola chiamata nylo.configure() |
| ID dei Theme | File .env (LIGHT_THEME_ID, DARK_THEME_ID) |
Codice (type: NyThemeType.dark) |
| Widget di Caricamento | useSkeletonizer + loading() |
Getter LoadingStyle |
| Posizione Config | lib/config/ |
lib/bootstrap/ (decoders, events, providers, theme) |
| Posizione Asset | public/ |
assets/ |
Approccio Raccomandato per la Migrazione
Per progetti piu grandi, si consiglia di creare un nuovo progetto v7 e migrare i file:
- Creare un nuovo progetto v7:
git clone https://github.com/nylo-core/nylo.git my_app_v7 -b 7.x - Copiare le Sue pagine, controller, model e service
- Aggiornare la sintassi come mostrato sopra
- Testare accuratamente
Questo garantisce di avere tutta la struttura boilerplate e le configurazioni piu recenti.
Se e interessato a visualizzare un diff delle modifiche tra v6 e v7, puo consultare il confronto su GitHub: https://github.com/nylo-core/nylo/compare/6.x...7.x
Checklist Rapida per la Migrazione
Utilizzi questa checklist per monitorare il progresso della migrazione:
- Aggiornare
pubspec.yaml(Dart >=3.10.7, Flutter >=3.24.0, nylo_framework: ^7.0.0) - Eseguire
flutter pub get - Eseguire
metro make:keyper generare APP_KEY - Eseguire
metro make:envper generare l'ambiente crittografato - Aggiornare
main.dartcon il parametro env e BootConfig - Convertire la classe
Bootper utilizzare il patternBootConfig - Spostare i file di config da
lib/config/alib/bootstrap/ - Creare nuovi file di config (
lib/config/app.dart,lib/config/storage_keys.dart,lib/config/toast_notification.dart) - Aggiornare
AppProviderper utilizzarenylo.configure() - Rimuovere
LIGHT_THEME_IDeDARK_THEME_IDda.env - Aggiungere
type: NyThemeType.darkalle configurazioni dei theme scuri - Rinominare
NyStateinNyPageper tutti i widget delle pagine - Cambiare
build()inview()in tutte le pagine - Cambiare
init()/boot()inget init =>in tutte le pagine - Aggiornare
static const pathinstatic RouteView path - Cambiare
router.route()inrouter.add()nelle route - Rinominare i widget (NyListView -> CollectionView, ecc.)
- Spostare gli asset da
public/aassets/ - Aggiornare i percorsi degli asset in
pubspec.yaml - Rimuovere gli import di Firebase (se utilizzati - aggiungere i package direttamente)
- Rimuovere l'utilizzo di NyDevPanel (utilizzare Flutter DevTools)
- Eseguire
flutter pub gete testare
Guida alla Migrazione Passo per Passo
Passo 1: Aggiornare le Dipendenze
Aggiorni il Suo pubspec.yaml:
environment:
sdk: '>=3.10.7 <4.0.0'
flutter: ">=3.24.0"
dependencies:
nylo_framework: ^7.0.0
# ... altre dipendenze
Esegua flutter pub get per aggiornare i package.
Passo 2: Configurazione dell'Ambiente
La v7 richiede variabili d'ambiente crittografate per una maggiore sicurezza.
1. Generare APP_KEY:
metro make:key
Questo aggiunge APP_KEY al Suo file .env.
2. Generare env.g.dart crittografato:
metro make:env
Questo crea lib/bootstrap/env.g.dart contenente le Sue variabili d'ambiente crittografate.
3. Rimuovere le variabili del theme deprecate da .env:
# Rimuova queste righe dal Suo file .env:
LIGHT_THEME_ID=...
DARK_THEME_ID=...
Passo 3: Aggiornare main.dart
v6:
import 'package:nylo_framework/nylo_framework.dart';
import 'bootstrap/boot.dart';
void main() async {
await Nylo.init(
setup: Boot.nylo,
setupFinished: Boot.finished,
);
}
v7:
import '/bootstrap/env.g.dart';
import 'package:nylo_framework/nylo_framework.dart';
import 'bootstrap/boot.dart';
void main() async {
await Nylo.init(
env: Env.get,
setup: Boot.nylo(),
appLifecycle: {
// Opzionale: Aggiungere hook del ciclo di vita dell'app
// AppLifecycleState.resumed: () => print("App resumed"),
// AppLifecycleState.paused: () => print("App paused"),
},
);
}
Modifiche Principali:
- Importare il file generato
env.g.dart - Passare
Env.getal parametroenv Boot.nyloe oraBoot.nylo()(restituisceBootConfig)setupFinishede stato rimosso (gestito all'interno diBootConfig)- Hook
appLifecycleopzionali per i cambiamenti di stato dell'app
Passo 4: Aggiornare boot.dart
v6:
class Boot {
static Future<Nylo> nylo() async {
WidgetsFlutterBinding.ensureInitialized();
if (getEnv('SHOW_SPLASH_SCREEN', defaultValue: false)) {
runApp(SplashScreen.app());
}
await _setup();
return await bootApplication(providers);
}
static Future<void> finished(Nylo nylo) async {
await bootFinished(nylo, providers);
runApp(Main(nylo));
}
}
v7:
class Boot {
static BootConfig nylo() => BootConfig(
setup: () async {
WidgetsFlutterBinding.ensureInitialized();
if (AppConfig.showSplashScreen) {
runApp(SplashScreen.app());
}
await _init();
return await setupApplication(providers);
},
boot: (Nylo nylo) async {
await bootFinished(nylo, providers);
runApp(Main(nylo));
},
);
}
Modifiche Principali:
- Restituisce
BootConfiginvece diFuture<Nylo> setupefinishedcombinati in un singolo oggettoBootConfiggetEnv('SHOW_SPLASH_SCREEN')->AppConfig.showSplashScreenbootApplication->setupApplication
Passo 5: Riorganizzare i File di Configurazione
La v7 riorganizza i file di configurazione per una struttura migliore:
| Posizione v6 | Posizione v7 | Azione |
|---|---|---|
lib/config/decoders.dart |
lib/bootstrap/decoders.dart |
Spostare |
lib/config/events.dart |
lib/bootstrap/events.dart |
Spostare |
lib/config/providers.dart |
lib/bootstrap/providers.dart |
Spostare |
lib/config/theme.dart |
lib/bootstrap/theme.dart |
Spostare |
lib/config/keys.dart |
lib/config/storage_keys.dart |
Rinominare e Rifattorizzare |
| (nuovo) | lib/config/app.dart |
Creare |
| (nuovo) | lib/config/toast_notification.dart |
Creare |
Creare lib/config/app.dart:
Riferimento: App Config
class AppConfig {
// Il nome dell'applicazione.
static final String appName = getEnv('APP_NAME', defaultValue: 'Nylo');
// La versione dell'applicazione.
static final String version = getEnv('APP_VERSION', defaultValue: '1.0.0');
// Aggiungere qui altre configurazioni dell'app
}
Creare lib/config/storage_keys.dart:
Riferimento: Storage Keys
final class StorageKeysConfig {
// Definire le chiavi da sincronizzare all'avvio
static syncedOnBoot() => () async {
return [
auth,
bearerToken,
// coins.defaultValue(10), // dare all'utente 10 monete per default
];
};
static StorageKey auth = 'SK_USER';
static StorageKey bearerToken = 'SK_BEARER_TOKEN';
// static StorageKey coins = 'SK_COINS';
/// Aggiungere qui le Sue storage key...
}
Creare lib/config/toast_notification.dart:
Riferimento: Toast Notification Config
import 'package:nylo_framework/nylo_framework.dart';
class ToastNotificationConfig {
static Map<ToastNotificationStyleMetaHelper, ToastMeta> styles = {
// Personalizzare gli stili dei toast qui
};
}
Passo 6: Aggiornare AppProvider
v6:
class AppProvider implements NyProvider {
@override
boot(Nylo nylo) async {
await NyLocalization.instance.init(
localeType: localeType,
languageCode: languageCode,
assetsDirectory: assetsDirectory,
);
nylo.addLoader(loader);
nylo.addLogo(logo);
nylo.addThemes(appThemes);
nylo.addToastNotification(getToastNotificationWidget);
nylo.addValidationRules(validationRules);
nylo.addModelDecoders(modelDecoders);
nylo.addControllers(controllers);
nylo.addApiDecoders(apiDecoders);
nylo.useErrorStack();
nylo.addAuthKey(Keys.auth);
await nylo.syncKeys(Keys.syncedOnBoot);
return nylo;
}
@override
afterBoot(Nylo nylo) async {}
}
v7:
class AppProvider implements NyProvider {
@override
setup(Nylo nylo) async {
await nylo.configure(
localization: NyLocalizationConfig(
languageCode: LocalizationConfig.languageCode,
localeType: LocalizationConfig.localeType,
assetsDirectory: LocalizationConfig.assetsDirectory,
),
loader: DesignConfig.loader,
logo: DesignConfig.logo,
themes: appThemes,
initialThemeId: 'light_theme',
toastNotifications: ToastNotificationConfig.styles,
modelDecoders: modelDecoders,
controllers: controllers,
apiDecoders: apiDecoders,
authKey: StorageKeysConfig.auth,
syncKeys: StorageKeysConfig.syncedOnBoot,
useErrorStack: true,
);
return nylo;
}
@override
boot(Nylo nylo) async {}
}
Modifiche Principali:
boot()e orasetup()per la configurazione inizialeboot()e ora utilizzato per la logica post-setup (precedentementeafterBoot)- Tutte le chiamate
nylo.add*()consolidate in un singolonylo.configure() - La localizzazione utilizza l'oggetto
NyLocalizationConfig
Passo 7: Aggiornare la Configurazione del Theme
v6 (file .env):
LIGHT_THEME_ID=default_light_theme
DARK_THEME_ID=default_dark_theme
v6 (theme.dart):
final List<BaseThemeConfig> appThemes = [
BaseThemeConfig(
id: getEnv('LIGHT_THEME_ID'),
description: "Light Theme",
theme: lightTheme(),
colors: LightThemeColors(),
),
BaseThemeConfig(
id: getEnv('DARK_THEME_ID'),
description: "Dark Theme",
theme: darkTheme(),
colors: DarkThemeColors(),
),
];
v7 (theme.dart):
final List<BaseThemeConfig<ColorStyles>> appThemes = [
BaseThemeConfig<ColorStyles>(
id: 'light_theme',
theme: lightTheme,
colors: LightThemeColors(),
type: NyThemeType.light,
),
BaseThemeConfig<ColorStyles>(
id: 'dark_theme',
theme: darkTheme,
colors: DarkThemeColors(),
type: NyThemeType.dark,
),
];
Modifiche Principali:
- Rimuovere
LIGHT_THEME_IDeDARK_THEME_IDda.env - Definire gli ID dei theme direttamente nel codice
- Aggiungere
type: NyThemeType.darka tutte le configurazioni dei theme scuri - I theme chiari hanno come predefinito
NyThemeType.light
Nuovi Metodi API per i Theme (v7):
// Impostare e ricordare il theme preferito
NyTheme.set(context, id: 'dark_theme', remember: true);
// Impostare i theme preferiti per seguire il sistema
NyTheme.setPreferredDark('dark_theme');
NyTheme.setPreferredLight('light_theme');
// Ottenere gli ID dei theme preferiti
String? darkId = NyTheme.preferredDarkId();
String? lightId = NyTheme.preferredLightId();
// Enumerazione dei theme
List<BaseThemeConfig> lights = NyTheme.lightThemes();
List<BaseThemeConfig> darks = NyTheme.darkThemes();
List<BaseThemeConfig> all = NyTheme.all();
BaseThemeConfig? theme = NyTheme.getById('dark_theme');
List<BaseThemeConfig> byType = NyTheme.getByType(NyThemeType.dark);
// Cancellare le preferenze salvate
NyTheme.clearSavedTheme();
Passo 10: Migrare i Widget
NyListView -> CollectionView
v6:
NyListView(
child: (context, data) {
return ListTile(title: Text(data.name));
},
data: () async => await api.getUsers(),
loading: CircularProgressIndicator(),
)
v7:
CollectionView<User>(
data: () async => await api.getUsers(),
builder: (context, item) => ListTile(
title: Text(item.data.name),
),
loadingStyle: LoadingStyle.normal(),
)
// Con paginazione (pull to refresh):
CollectionView<User>.pullable(
data: (page) async => await api.getUsers(page: page),
builder: (context, item) => ListTile(
title: Text(item.data.name),
),
)
NyFutureBuilder -> FutureWidget
v6:
NyFutureBuilder(
future: fetchData(),
child: (context, data) => Text(data),
loading: CircularProgressIndicator(),
)
v7:
FutureWidget<String>(
future: fetchData(),
child: (context, data) => Text(data ?? ''),
loadingStyle: LoadingStyle.normal(),
)
NyTextField -> InputField
v6:
NyTextField(
controller: _controller,
validationRules: "not_empty|email",
)
v7:
InputField(
controller: _controller,
formValidator: FormValidator
.notEmpty()
.email(),
),
NyRichText -> StyledText
v6:
NyRichText(children: [
Text("Hello", style: TextStyle(color: Colors.yellow)),
Text(" WORLD ", style: TextStyle(color: Colors.blue)),
Text("!", style: TextStyle(color: Colors.red)),
]),
v7:
StyledText.template(
"{{Hello}} {{WORLD}}{{!}}",
styles: {
"Hello": TextStyle(color: Colors.yellow),
"WORLD": TextStyle(color: Colors.blue),
"!": TextStyle(color: Colors.red),
},
)
NyLanguageSwitcher -> LanguageSwitcher
v6:
NyLanguageSwitcher(
onLanguageChange: (locale) => print(locale),
)
v7:
LanguageSwitcher(
onLanguageChange: (locale) => print(locale),
)
Passo 11: Aggiornare i Percorsi degli Asset
La v7 cambia la directory degli asset da public/ ad assets/:
1. Spostare le cartelle degli asset:
# Spostare le directory
mv public/fonts assets/fonts
mv public/images assets/images
mv public/app_icon assets/app_icon
2. Aggiornare pubspec.yaml:
v6:
flutter:
assets:
- public/fonts/
- public/images/
- public/app_icon/
v7:
flutter:
assets:
- assets/fonts/
- assets/images/
- assets/app_icon/
3. Aggiornare qualsiasi riferimento agli asset nel codice:
v6:
Image.asset('public/images/logo.png')
v7:
Image.asset('assets/images/logo.png')
Widget LocalizedApp - Rimosso
Riferimento: Main Widget
Migrazione: Utilizzi direttamente Main(nylo). NyApp.materialApp() gestisce la localizzazione internamente.
v6:
runApp(LocalizedApp(child: Main(nylo)));
v7:
runApp(Main(nylo));
Riferimento delle Classi Eliminate
| Classe Eliminata | Alternativa |
|---|---|
NyTextStyle |
Utilizzare direttamente TextStyle di Flutter |
NyBaseApiService |
Utilizzare DioApiService |
BaseColorStyles |
Utilizzare ThemeColor |
LocalizedApp |
Utilizzare direttamente Main(nylo) |
NyException |
Utilizzare le eccezioni standard di Dart |
PushNotification |
Utilizzare direttamente flutter_local_notifications |
PushNotificationAttachments |
Utilizzare direttamente flutter_local_notifications |
Riferimento per la Migrazione dei Widget
Widget Rinominati
| Widget v6 | Widget v7 | Note |
|---|---|---|
NyListView |
CollectionView |
Nuova API con builder invece di child |
NyFutureBuilder |
FutureWidget |
Widget asincrono semplificato |
NyTextField |
InputField |
Utilizza FormValidator |
NyLanguageSwitcher |
LanguageSwitcher |
Stessa API |
NyRichText |
StyledText |
Stessa API |
NyFader |
FadeOverlay |
Stessa API |
Widget Eliminati (Nessuna Sostituzione Diretta)
| Widget Eliminato | Alternativa |
|---|---|
NyPullToRefresh |
Utilizzare CollectionView.pullable() |
Esempi di Migrazione dei Widget
NyPullToRefresh -> CollectionView.pullable():
v6:
NyPullToRefresh(
child: (context, data) => ListTile(title: Text(data.name)),
data: (page) async => await fetchData(page),
)
v7:
CollectionView<MyModel>.pullable(
data: (page) async => await fetchData(page),
builder: (context, item) => ListTile(title: Text(item.data.name)),
)
NyFader -> FadeOverlay:
v6:
NyFader(
child: MyWidget(),
)
v7:
FadeOverlay.bottom(
child: MyWidget(),
);
Risoluzione dei Problemi
"Env.get not found" o "Env is not defined"
Soluzione: Esegua i comandi di generazione dell'ambiente:
metro make:key
metro make:env
Poi importi il file generato in main.dart:
import '/bootstrap/env.g.dart';
"Theme not applying" o "Dark theme not working"
Soluzione: Assicurarsi che i theme scuri abbiano type: NyThemeType.dark:
BaseThemeConfig(
id: 'dark_theme',
description: "Dark Theme",
theme: darkTheme(),
colors: DarkThemeColors(),
type: NyThemeType.dark, // Aggiungere questa riga
),
"LocalizedApp not found"
Riferimento: Main Widget
Soluzione: LocalizedApp e stato rimosso. Cambiare:
// Da:
runApp(LocalizedApp(child: Main(nylo)));
// A:
runApp(Main(nylo));
"router.route is not defined"
Soluzione: Utilizzare router.add() invece:
// Da:
router.route(HomePage.path, (context) => HomePage());
// A:
router.add(HomePage.path);
"NyListView not found"
Soluzione: NyListView e ora CollectionView:
// Da:
NyListView(...)
// A:
CollectionView<MyModel>(...)
Gli asset non si caricano (immagini, font)
Soluzione: Aggiornare i percorsi degli asset da public/ ad assets/:
- Spostare i file:
mv public/* assets/ - Aggiornare i percorsi in
pubspec.yaml - Aggiornare i riferimenti nel codice
"init() must return a value of type Future"
Soluzione: Cambiare alla sintassi getter:
// Da:
@override
init() async { ... }
// A:
@override
get init => () async { ... };
Ha bisogno di aiuto? Consulti la Documentazione di Nylo o apra una issue su GitHub.