registerMagicStarterProfileRoutes function
Registers profile/settings routes provided by Magic Starter plugin.
The Settings surface is an iOS-style hub (/settings) that drills into
grouped sub-pages. Every route uses a flat absolute path and resolves its
view through the registry, so each screen stays overridable via
MagicStarter.view.register(...). Sub-routes are feature-gated: a disabled
feature means the route is never registered.
Every sub-page is .stacked() and the hub is not, which is the hub-and-
spoke shape expressed in routing terms. MagicRoute.to() calls go(),
which replaces the Navigator's whole page list, so a sub-page that replaced
left nothing to pop: no iOS edge swipe off a settings screen, and on
Android the system back button LEFT THE APP, because Flutter reports
canHandlePop: false to the platform at a stack depth of one. The hub
keeps replacing because a host commonly gives it a nav destination, and a
destination that pushes grows the stack every time its tab is tapped.
A stacked sub-page takes MagicRouter.defaultTransition rather than
naming one. That default is RouteTransition.none, so an app that sets
nothing sees exactly what it saw before; an app that sets
RouteTransition.platform gets the operating system's own animation and
its back gesture on these screens without this package deciding how a host
app should feel.
Implementation
void registerMagicStarterProfileRoutes() {
MagicRoute.group(
middleware: ['auth'],
layoutId: MagicStarterLayoutIds.app,
layout: (child) => MagicStarter.view.makeLayout('layout.app', child: child),
routes: () {
// Hub index — the default Settings destination.
MagicRoute.page(
MagicStarterConfig.settingsHubRoute(),
() => _profileSettingsView('settings.hub'),
).title('magic_starter.titles.settings').transition(RouteTransition.none);
// Profile sub-page — always available.
MagicRoute.page(
MagicStarterConfig.profileRoute(),
() => _profileSettingsView('profile.profile'),
).title('magic_starter.titles.profile').stacked();
// Appearance (theme) sub-page — always available (mirrors the hub row,
// which renders Appearance unconditionally).
MagicRoute.page(
MagicStarterConfig.settingsAppearanceRoute(),
() => _profileSettingsView('settings.appearance'),
).title('magic_starter.titles.appearance').stacked();
// Password sub-page — always available. The hub gates the Password row
// by the `starter.update-password` Gate only (no feature flag), so the
// route stays registered like a core auth action.
MagicRoute.page(
MagicStarterConfig.settingsPasswordRoute(),
() => _profileSettingsView('settings.security.password'),
).title('magic_starter.titles.password').stacked();
// Language sub-page — extended profile / locale selection.
if (MagicStarterConfig.hasExtendedProfileFeatures()) {
MagicRoute.page(
MagicStarterConfig.settingsLanguageRoute(),
() => _profileSettingsView('settings.language'),
).title('magic_starter.titles.language').stacked();
}
// Timezone sub-page.
if (MagicStarterConfig.hasTimezoneFeatures()) {
MagicRoute.page(
MagicStarterConfig.settingsTimezoneRoute(),
() => _profileSettingsView('settings.timezone'),
).title('magic_starter.titles.timezone').stacked();
}
// Newsletter sub-page.
if (MagicStarterConfig.hasNewsletterFeatures()) {
MagicRoute.page(
MagicStarterConfig.settingsNewsletterRoute(),
() => _newsletterSettingsView(),
).title('magic_starter.titles.newsletter').stacked();
}
// Changelog sub-page.
if (MagicStarterConfig.hasReleasesFeatures()) {
MagicRoute.page(
MagicStarterConfig.settingsChangelogRoute(),
() => _changelogSettingsView(),
).title('magic_starter.titles.changelog').stacked();
}
// Security — Two-Factor sub-page.
if (MagicStarterConfig.hasTwoFactorFeatures()) {
MagicRoute.page(
MagicStarterConfig.settingsTwoFactorRoute(),
() => _profileSettingsView('settings.security.two_factor'),
).title('magic_starter.titles.two_factor').stacked();
}
// Security — Active Sessions sub-page.
if (MagicStarterConfig.hasSessionsFeatures()) {
MagicRoute.page(
MagicStarterConfig.settingsSessionsRoute(),
() => _profileSettingsView('settings.security.sessions'),
).title('magic_starter.titles.sessions').stacked();
}
// Security: Connected accounts sub-page. Keyed on the feature alone: the
// app's bridge is set by a provider that boots after the one that
// registers routes, so it cannot be read here. The hub row, built later,
// is the one gated on the bridge.
if (MagicStarterConfig.hasSocialLoginFeatures()) {
MagicRoute.page(
MagicStarterConfig.settingsConnectedAccountsRoute(),
() => _profileSettingsView('settings.security.connected_accounts'),
).title('magic_starter.titles.connected_accounts').stacked();
}
},
);
}