Upgrade-Leitfaden
Was ist neu in v7
Nylo Website v7 ist ein Major Release mit bedeutenden Verbesserungen fuer die Entwicklererfahrung:
Verschluesselte Umgebungskonfiguration
- Umgebungsvariablen werden jetzt zur Build-Zeit XOR-verschluesselt fuer mehr Sicherheit
- Neuer Befehl
metro make:keygeneriert Ihren APP_KEY - Neuer Befehl
metro make:envgeneriert die verschluesselteenv.g.dart - Unterstuetzung fuer
--dart-defineAPP_KEY-Injektion fuer CI/CD-Pipelines
Vereinfachter Boot-Prozess
- Neues
BootConfig-Muster ersetzt separate setup/finished-Callbacks - Saubereres
Nylo.init()mitenv-Parameter fuer verschluesselte Umgebung - App-Lifecycle-Hooks direkt in main.dart
Neue nylo.configure() API
- Eine einzelne Methode konsolidiert die gesamte App-Konfiguration
- Sauberere Syntax ersetzt einzelne
nylo.add*()-Aufrufe - Separate
setup()- undboot()-Lifecycle-Methoden in Providern
NyPage fuer Pages
NyPageersetztNyStatefuer Page-Widgets (sauberere Syntax)view()ersetzt diebuild()-Methodeget init =>-Getter ersetztinit()- undboot()-MethodenNyStateist weiterhin verfuegbar fuer Nicht-Page Stateful Widgets
LoadingStyle-System
- Neues
LoadingStyle-Enum fuer konsistente Ladezustaende - Optionen:
LoadingStyle.normal(),LoadingStyle.skeletonizer(),LoadingStyle.none() - Benutzerdefinierte Lade-Widgets ueber
LoadingStyle.normal(child: ...)
RouteView Typsicheres Routing
static RouteView pathersetztstatic const path- Typsichere Route-Definitionen mit Widget-Factory
Multi-Theme-Unterstuetzung
- Registrieren Sie mehrere dunkle und helle Themes
- Theme-IDs werden im Code statt in der
.env-Datei definiert - Neu:
NyThemeType.dark/NyThemeType.lightfuer Theme-Klassifizierung - Bevorzugtes Theme API:
NyTheme.setPreferredDark(),NyTheme.setPreferredLight() - Theme-Aufzaehlung:
NyTheme.lightThemes(),NyTheme.darkThemes(),NyTheme.all()
Neue Metro-Befehle
make:key- APP_KEY fuer Verschluesselung generierenmake:env- Verschluesselte Umgebungsdatei generierenmake:bottom_sheet_modal- Bottom Sheet Modals erstellenmake:button- Benutzerdefinierte Buttons erstellen
Alle Aenderungen auf GitHub ansehen
Uebersicht der Breaking Changes
| Aenderung | v6 | v7 |
|---|---|---|
| App Root Widget | LocalizedApp(child: Main(nylo)) |
Main(nylo) (verwendet NyApp.materialApp()) |
| Page State Klasse | NyState |
NyPage fuer Pages |
| View-Methode | build() |
view() |
| Init-Methode | init() async {} / boot() async {} |
get init => () async {} |
| Route-Pfad | static const path = '/home' |
static RouteView path = ('/home', (_) => HomePage()) |
| Provider Boot | boot(Nylo nylo) |
setup(Nylo nylo) + boot(Nylo nylo) |
| Konfiguration | Einzelne nylo.add*()-Aufrufe |
Ein einzelner nylo.configure()-Aufruf |
| Theme-IDs | .env-Datei (LIGHT_THEME_ID, DARK_THEME_ID) |
Code (type: NyThemeType.dark) |
| Lade-Widget | useSkeletonizer + loading() |
LoadingStyle-Getter |
| Konfig-Speicherort | lib/config/ |
lib/bootstrap/ (decoders, events, providers, theme) |
| Asset-Speicherort | public/ |
assets/ |
Empfohlener Migrations-Ansatz
Fuer groessere Projekte empfehlen wir, ein neues v7-Projekt zu erstellen und Dateien zu migrieren:
- Neues v7-Projekt erstellen:
git clone https://github.com/nylo-core/nylo.git my_app_v7 -b 7.x - Kopieren Sie Ihre Pages, Controller, Models und Services
- Aktualisieren Sie die Syntax wie oben gezeigt
- Testen Sie gruendlich
Dies stellt sicher, dass Sie alle aktuellen Boilerplate-Strukturen und Konfigurationen haben.
Wenn Sie einen Diff der Aenderungen zwischen v6 und v7 sehen moechten, koennen Sie den Vergleich auf GitHub ansehen: https://github.com/nylo-core/nylo/compare/6.x...7.x
Schnelle Migrations-Checkliste
Verwenden Sie diese Checkliste, um Ihren Migrationsfortschritt zu verfolgen:
-
pubspec.yamlaktualisieren (Dart >=3.10.7, Flutter >=3.24.0, nylo_framework: ^7.0.0) -
flutter pub getausfuehren -
metro make:keyausfuehren, um APP_KEY zu generieren -
metro make:envausfuehren, um verschluesselte Umgebung zu generieren -
main.dartmit env-Parameter und BootConfig aktualisieren -
Boot-Klasse aufBootConfig-Muster umstellen - Konfigurationsdateien von
lib/config/nachlib/bootstrap/verschieben - Neue Konfigurationsdateien erstellen (
lib/config/app.dart,lib/config/storage_keys.dart,lib/config/toast_notification.dart) -
AppProvideraufnylo.configure()aktualisieren -
LIGHT_THEME_IDundDARK_THEME_IDaus.enventfernen -
type: NyThemeType.darkzu Dark-Theme-Konfigurationen hinzufuegen -
NyStatezuNyPagefuer alle Page-Widgets umbenennen -
build()zuview()in allen Pages aendern -
init()/boot()zuget init =>in allen Pages aendern -
static const pathzustatic RouteView pathaktualisieren -
router.route()zurouter.add()in Routes aendern - Widgets umbenennen (NyListView -> CollectionView, etc.)
- Assets von
public/nachassets/verschieben - Asset-Pfade in
pubspec.yamlaktualisieren - Firebase-Imports entfernen (falls verwendet - Packages direkt hinzufuegen)
- NyDevPanel-Verwendung entfernen (Flutter DevTools verwenden)
-
flutter pub getausfuehren und testen
Schritt-fuer-Schritt Migrationsleitfaden
Schritt 1: Abhaengigkeiten aktualisieren
Aktualisieren Sie Ihre pubspec.yaml:
environment:
sdk: '>=3.10.7 <4.0.0'
flutter: ">=3.24.0"
dependencies:
nylo_framework: ^7.0.0
# ... weitere Abhaengigkeiten
Fuehren Sie flutter pub get aus, um die Packages zu aktualisieren.
Schritt 2: Umgebungskonfiguration
v7 erfordert verschluesselte Umgebungsvariablen fuer verbesserte Sicherheit.
1. APP_KEY generieren:
metro make:key
Dies fuegt APP_KEY zu Ihrer .env-Datei hinzu.
2. Verschluesselte env.g.dart generieren:
metro make:env
Dies erstellt lib/bootstrap/env.g.dart mit Ihren verschluesselten Umgebungsvariablen.
3. Veraltete Theme-Variablen aus .env entfernen:
# Entfernen Sie diese Zeilen aus Ihrer .env-Datei:
LIGHT_THEME_ID=...
DARK_THEME_ID=...
Schritt 3: main.dart aktualisieren
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: {
// Optional: App-Lifecycle-Hooks hinzufuegen
// AppLifecycleState.resumed: () => print("App resumed"),
// AppLifecycleState.paused: () => print("App paused"),
},
);
}
Wichtige Aenderungen:
- Importieren Sie die generierte
env.g.dart - Uebergeben Sie
Env.getan denenv-Parameter Boot.nyloist jetztBoot.nylo()(gibtBootConfigzurueck)setupFinishedwurde entfernt (wird innerhalb vonBootConfigbehandelt)- Optionale
appLifecycle-Hooks fuer App-Zustandsaenderungen
Schritt 4: boot.dart aktualisieren
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));
},
);
}
Wichtige Aenderungen:
- Gibt
BootConfigzurueck stattFuture<Nylo> setupundfinishedwerden in einem einzelnenBootConfig-Objekt kombiniertgetEnv('SHOW_SPLASH_SCREEN')->AppConfig.showSplashScreenbootApplication->setupApplication
Schritt 5: Konfigurationsdateien reorganisieren
v7 reorganisiert Konfigurationsdateien fuer eine bessere Struktur:
| v6 Speicherort | v7 Speicherort | Aktion |
|---|---|---|
lib/config/decoders.dart |
lib/bootstrap/decoders.dart |
Verschieben |
lib/config/events.dart |
lib/bootstrap/events.dart |
Verschieben |
lib/config/providers.dart |
lib/bootstrap/providers.dart |
Verschieben |
lib/config/theme.dart |
lib/bootstrap/theme.dart |
Verschieben |
lib/config/keys.dart |
lib/config/storage_keys.dart |
Umbenennen & Refaktorisieren |
| (neu) | lib/config/app.dart |
Erstellen |
| (neu) | lib/config/toast_notification.dart |
Erstellen |
lib/config/app.dart erstellen:
Referenz: App Config
class AppConfig {
// Der Name der Anwendung.
static final String appName = getEnv('APP_NAME', defaultValue: 'Nylo');
// Die Version der Anwendung.
static final String version = getEnv('APP_VERSION', defaultValue: '1.0.0');
// Weitere App-Konfiguration hier hinzufuegen
}
lib/config/storage_keys.dart erstellen:
Referenz: Storage Keys
final class StorageKeysConfig {
// Definieren Sie die Keys, die beim Boot synchronisiert werden sollen
static syncedOnBoot() => () async {
return [
auth,
bearerToken,
// coins.defaultValue(10), // dem Benutzer standardmaessig 10 Coins geben
];
};
static StorageKey auth = 'SK_USER';
static StorageKey bearerToken = 'SK_BEARER_TOKEN';
// static StorageKey coins = 'SK_COINS';
/// Fuegen Sie hier Ihre Storage Keys hinzu...
}
lib/config/toast_notification.dart erstellen:
Referenz: Toast Notification Config
import 'package:nylo_framework/nylo_framework.dart';
class ToastNotificationConfig {
static Map<ToastNotificationStyleMetaHelper, ToastMeta> styles = {
// Passen Sie hier die Toast-Styles an
};
}
Schritt 6: AppProvider aktualisieren
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 {}
}
Wichtige Aenderungen:
boot()ist jetztsetup()fuer die initiale Konfigurationboot()wird jetzt fuer Post-Setup-Logik verwendet (frueherafterBoot)- Alle
nylo.add*()-Aufrufe werden in einem einzelnennylo.configure()konsolidiert - Lokalisierung verwendet das
NyLocalizationConfig-Objekt
Schritt 7: Theme-Konfiguration aktualisieren
v6 (.env-Datei):
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,
),
];
Wichtige Aenderungen:
- Entfernen Sie
LIGHT_THEME_IDundDARK_THEME_IDaus.env - Definieren Sie Theme-IDs direkt im Code
- Fuegen Sie
type: NyThemeType.darkzu allen Dark-Theme-Konfigurationen hinzu - Light Themes verwenden standardmaessig
NyThemeType.light
Neue Theme-API-Methoden (v7):
// Bevorzugtes Theme setzen und merken
NyTheme.set(context, id: 'dark_theme', remember: true);
// Bevorzugte Themes fuer Systemverfolgung setzen
NyTheme.setPreferredDark('dark_theme');
NyTheme.setPreferredLight('light_theme');
// Bevorzugte Theme-IDs abrufen
String? darkId = NyTheme.preferredDarkId();
String? lightId = NyTheme.preferredLightId();
// Theme-Aufzaehlung
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);
// Gespeicherte Einstellungen loeschen
NyTheme.clearSavedTheme();
Schritt 10: Widgets migrieren
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(),
)
// Mit Paginierung (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),
)
Schritt 11: Asset-Pfade aktualisieren
v7 aendert das Asset-Verzeichnis von public/ zu assets/:
1. Verschieben Sie Ihre Asset-Ordner:
# Verzeichnisse verschieben
mv public/fonts assets/fonts
mv public/images assets/images
mv public/app_icon assets/app_icon
2. pubspec.yaml aktualisieren:
v6:
flutter:
assets:
- public/fonts/
- public/images/
- public/app_icon/
v7:
flutter:
assets:
- assets/fonts/
- assets/images/
- assets/app_icon/
3. Asset-Referenzen im Code aktualisieren:
v6:
Image.asset('public/images/logo.png')
v7:
Image.asset('assets/images/logo.png')
LocalizedApp Widget - Entfernt
Referenz: Main Widget
Migration: Verwenden Sie Main(nylo) direkt. Das NyApp.materialApp() behandelt die Lokalisierung intern.
v6:
runApp(LocalizedApp(child: Main(nylo)));
v7:
runApp(Main(nylo));
Geloeschte Klassen Referenz
| Geloeschte Klasse | Alternative |
|---|---|
NyTextStyle |
Verwenden Sie Flutters TextStyle direkt |
NyBaseApiService |
Verwenden Sie DioApiService |
BaseColorStyles |
Verwenden Sie ThemeColor |
LocalizedApp |
Verwenden Sie Main(nylo) direkt |
NyException |
Verwenden Sie Standard-Dart-Exceptions |
PushNotification |
Verwenden Sie flutter_local_notifications direkt |
PushNotificationAttachments |
Verwenden Sie flutter_local_notifications direkt |
Widget-Migrations-Referenz
Umbenannte Widgets
| v6 Widget | v7 Widget | Hinweise |
|---|---|---|
NyListView |
CollectionView |
Neue API mit builder statt child |
NyFutureBuilder |
FutureWidget |
Vereinfachtes Async-Widget |
NyTextField |
InputField |
Verwendet FormValidator |
NyLanguageSwitcher |
LanguageSwitcher |
Gleiche API |
NyRichText |
StyledText |
Gleiche API |
NyFader |
FadeOverlay |
Gleiche API |
Geloeschte Widgets (Kein direkter Ersatz)
| Geloeschtes Widget | Alternative |
|---|---|
NyPullToRefresh |
Verwenden Sie CollectionView.pullable() |
Widget-Migrations-Beispiele
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(),
);
Fehlerbehebung
"Env.get not found" oder "Env is not defined"
Loesung: Fuehren Sie die Befehle zur Umgebungsgenerierung aus:
metro make:key
metro make:env
Importieren Sie dann die generierte Datei in main.dart:
import '/bootstrap/env.g.dart';
"Theme not applying" oder "Dark theme not working"
Loesung: Stellen Sie sicher, dass Dark Themes type: NyThemeType.dark haben:
BaseThemeConfig(
id: 'dark_theme',
description: "Dark Theme",
theme: darkTheme(),
colors: DarkThemeColors(),
type: NyThemeType.dark, // Diese Zeile hinzufuegen
),
"LocalizedApp not found"
Referenz: Main Widget
Loesung: LocalizedApp wurde entfernt. Aendern Sie:
// Von:
runApp(LocalizedApp(child: Main(nylo)));
// Zu:
runApp(Main(nylo));
"router.route is not defined"
Loesung: Verwenden Sie router.add() stattdessen:
// Von:
router.route(HomePage.path, (context) => HomePage());
// Zu:
router.add(HomePage.path);
"NyListView not found"
Loesung: NyListView ist jetzt CollectionView:
// Von:
NyListView(...)
// Zu:
CollectionView<MyModel>(...)
Assets werden nicht geladen (Bilder, Schriftarten)
Loesung: Aktualisieren Sie Asset-Pfade von public/ zu assets/:
- Dateien verschieben:
mv public/* assets/ pubspec.yaml-Pfade aktualisieren- Code-Referenzen aktualisieren
"init() must return a value of type Future"
Loesung: Wechseln Sie zur Getter-Syntax:
// Von:
@override
init() async { ... }
// Zu:
@override
get init => () async { ... };
Benoetigen Sie Hilfe? Schauen Sie in die Nylo-Dokumentation oder eroeffnen Sie ein Issue auf GitHub.