-
Notifications
You must be signed in to change notification settings - Fork 11
feat(EWM-511): Implement Compass Type-Safe Navigation System #889
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dart format
docs/type_safe_navigation.md
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Можем переименовать в *.instructions.md
что бы Copilot автоматом мог цеплять из папки?
https://code.visualstudio.com/docs/copilot/copilot-customization#_use-instruction-files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
На самом деле такая дока не совсем подходит для ai, это больше для людей. У меня есть набор рулсов, но я их использую с claude, там можно эмбедить в CLAUDE.md ссылки на файлы (также вроде и с копайлотом можно). Для AI рулсы выглядят вот так:
Core Principles
-
Always use type-safe navigation
- Use the Compass system for all navigation
- Never use raw GoRouter methods or Navigator directly
- Leverage type safety to prevent runtime errors
-
Route Structure
- Place route files in the same feature folder as their corresponding screens
- Use the
route.dart
naming convention for route files - Follow a consistent implementation pattern for all routes
-
DI Registration Pattern
- Register routes with
@named
and@Singleton(as: CompassBaseRoute)
- Register guards with
@named
and@Singleton(as: CompassGuard)
- Inject routes into other routes using
@Named.from(ConcreteRouteType)
- Register routes with
Route Implementation
Route Data Classes
-
DO NOT use Freezed for route data classes
- Freezed changes runtime types, breaking router resolution
- Create simple immutable classes with final fields instead
-
Route data should be immutable
- Use final fields for all properties
- Implement proper toString, equality, and hashCode methods manually
-
Type Selection
- Use
CompassRouteParameterless<T>
for routes without parameters - Use
CompassRoute<T>
for routes with parameters - Use
CompassShellRoute
for tabbed or nested navigation
- Use
Navigation Methods
-
Use the correct navigation method for each scenario
compassPoint
- Standard navigation, replacing current screencompassPush
- Adding to navigation stack with optional resultcompassContinue
- Navigation while preserving statecompassBack
- Return to previous screen, optionally with result
-
Parameter Handling
- Make route data conversions robust with proper validation
- Handle missing or invalid parameters gracefully
- Provide sensible defaults where possible
Guards and Protection
-
Leverage guards for cross-cutting concerns
- Authentication/authorization
- Feature flags
- Analytics tracking
- Deep link handling
-
Implement guards with appropriate priorities
- Use
priorityHigh
(3) for critical guards like authentication - Use
priorityMedium
(2) for feature flags - Use
priorityLow
(1) for analytics and non-blocking guards
- Use
Examples
1. Defining a Route Data Class
const _userIdQueryParam = 'userId';
const _displayNameQueryParam = 'displayName';
class ProfileRouteData implements CompassRouteDataQuery {
const ProfileRouteData({
required this.userId,
this.displayName,
});
final String userId;
final String? displayName;
@override
Map<String, String> toQueryParams() {
return {
_userIdQueryParam: userId,
if (displayName != null) _displayNameQueryParam: displayName!,
};
}
}
2. Implementing a Route Class
@named
@Singleton(as: CompassBaseRoute)
class ProfileRoute extends CompassRoute<ProfileRouteData> {
ProfileRoute() : super(
name: 'profile',
path: '/profile',
isTopLevel: true,
builder: (context, data, state) => ProfilePage(userId: data.userId),
);
@override
ProfileRouteData fromQueryParams(Map<String, String> queryParams) {
return ProfileRouteData(
userId: queryParams[_userIdQueryParam]!,
displayName: queryParams[_displayNameQueryParam],
);
}
}
/// | ||
/// Since this mixin is for parameterless routes, this method should | ||
/// return a default instance of the route data class. | ||
T dataFabric(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fabric - ткань. Название метода максимально непонятное.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Поправил
2153b23
to
994253c
Compare
…different for each route
Description
Completely redesigned the navigation system in the application to ensure type safety, improve code organization, and enhance testability.
Solution
Core Navigation Framework
Key Components
CompassRouteData
interface lib/app/router/compass/route.dartCompassRoute<T>
- For routes with query parametersCompassRouteParameterless<T>
- For routes without parametersCompassShellRoute
- For shell-based navigation (tabs, drawers)Navigation Methods
Route and Guard Organization
route.dart
files for each featureguard.dart
files for cross-cutting navigation concernsMigration
Other Changes
Splash Screen Navigation: Completely reworked splash screen navigation flow
Bootstrap Process Refactoring lib/app/service/bootstrap/bootstrap_service.dart
Navigation State Management lib/feature/root/restore_subroutes_guard.dart
Onboarding Flow Improvements lib/feature/onboarding/guard.dart
App Update Handling lib/feature/update_version/guard.dart
Navigation State Persistence: Implemented new approach to saving/restoring navigation state
Tab Navigation Enhancements lib/feature/root/view/root_tab.dart
Bottom Navigation Bar: Rewrote tab selection logic
Updated build.yaml to support feature-specific route code generation
Type of Change